diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-08-15 22:59:28 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-08-15 22:59:28 +0000 |
commit | ac45293276030400195133225d54ddcb3644ea20 (patch) | |
tree | 0f714afc99697a3995afd23fcf881934728f0a12 | |
parent | 95526a480f252514d63a00bb032a2cb205dbf021 (diff) |
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
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 9 | ||||
-rw-r--r-- | test/CodeGenCXX/devirtualize-virtual-function-calls.cpp | 17 |
2 files changed, 25 insertions, 1 deletions
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<MemberExpr>(Base)) + if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl())) + return VD->getType()->isRecordType(); + // We can always devirtualize calls on temporary object expressions. if (isa<CXXConstructExpr>(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(); + } +} |