From: Richard Smith Date: Wed, 15 Aug 2012 22:59:28 +0000 (+0000) Subject: Devirtualize calls on glvalues produced by class member access expressions. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ac45293276030400195133225d54ddcb3644ea20;p=clang Devirtualize calls on glvalues produced by class member access expressions. Based on a patch by Yin Ma! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161998 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 7c2c9f1ecb..31ea1b5448 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -123,7 +123,14 @@ static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context, return false; } - + + // We can devirtualize calls on an object accessed by a class member access + // expression, since by C++11 [basic.life]p6 we know that it can't refer to + // a derived class object constructed in the same location. + if (const MemberExpr *ME = dyn_cast(Base)) + if (const ValueDecl *VD = dyn_cast(ME->getMemberDecl())) + return VD->getType()->isRecordType(); + // We can always devirtualize calls on temporary object expressions. if (isa(Base)) return true; diff --git a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp index c5a4094a53..7ef4864c83 100644 --- a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp +++ b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp @@ -83,3 +83,20 @@ namespace test3 { d.B::~B(); } } + +namespace test4 { + struct Animal { + virtual void eat(); + }; + struct Fish : Animal { + virtual void eat(); + }; + struct Wrapper { + Fish fish; + }; + extern Wrapper *p; + void test() { + // CHECK: call void @_ZN5test44Fish3eatEv + p->fish.eat(); + } +}