aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-08-15 22:59:28 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-08-15 22:59:28 +0000
commitac45293276030400195133225d54ddcb3644ea20 (patch)
tree0f714afc99697a3995afd23fcf881934728f0a12
parent95526a480f252514d63a00bb032a2cb205dbf021 (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.cpp9
-rw-r--r--test/CodeGenCXX/devirtualize-virtual-function-calls.cpp17
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();
+ }
+}