summaryrefslogtreecommitdiffstats
path: root/clang
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
commit48c15319f7db4349c8da663145a223db915a7452 (patch)
tree34236ca9f86cc348ba3ad024ce85fb0c1ac33fa2 /clang
parent19c722d61df804a31aa093cff3ebf89ce9c9c0da (diff)
downloadbcm5719-llvm-48c15319f7db4349c8da663145a223db915a7452.tar.gz
bcm5719-llvm-48c15319f7db4349c8da663145a223db915a7452.zip
Devirtualize calls on glvalues produced by class member access expressions.
Based on a patch by Yin Ma! llvm-svn: 161998
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/CGExprCXX.cpp9
-rw-r--r--clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp17
2 files changed, 25 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index 7c2c9f1ecb4..31ea1b5448a 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/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/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
index c5a4094a53c..7ef4864c836 100644
--- a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
+++ b/clang/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();
+ }
+}
OpenPOWER on IntegriCloud