]> granicus.if.org Git - clang/commitdiff
Strip off parens and no-op casts when deciding if an expr can be devirtualized. Fixes...
authorAnders Carlsson <andersca@mac.com>
Sun, 10 Apr 2011 18:20:53 +0000 (18:20 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 10 Apr 2011 18:20:53 +0000 (18:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129253 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprCXX.cpp
test/CodeGenCXX/devirtualize-virtual-function-calls.cpp

index 777036bc3b3741e286bce2be558e34cfd1f15679..075fdc30a8b40637de44702aa8d961872d660335 100644 (file)
@@ -77,6 +77,31 @@ static const CXXRecordDecl *getMostDerivedClassDecl(const Expr *Base) {
   return cast<CXXRecordDecl>(DerivedType->castAs<RecordType>()->getDecl());
 }
 
+// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do
+// quite what we want.
+static const Expr *skipNoOpCastsAndParens(const Expr *E) {
+  while (true) {
+    if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) {
+      E = PE->getSubExpr();
+      continue;
+    }
+
+    if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
+      if (CE->getCastKind() == CK_NoOp) {
+        E = CE->getSubExpr();
+        continue;
+      }
+    }
+    if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) {
+      if (UO->getOpcode() == UO_Extension) {
+        E = UO->getSubExpr();
+        continue;
+      }
+    }
+    return E;
+  }
+}
+
 /// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given
 /// expr can be devirtualized.
 static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context,
@@ -112,6 +137,7 @@ static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context,
   if (MD->getParent()->hasAttr<FinalAttr>())
     return true;
 
+  Base = skipNoOpCastsAndParens(Base);
   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
     if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
       // This is a record decl. We know the type and can devirtualize it.
index 74795b5dfb0efab96b889836de86468c65092985..5eede66cd7b47501159b2342207b5c0e2ae50296 100644 (file)
@@ -2,7 +2,8 @@
 
 struct A {
   virtual void f();
-  
+  virtual void f_const() const;
+
   A h();
 };
 
@@ -28,6 +29,12 @@ void f(A a, A *ap, A& ar) {
   
   // CHECK: call void @_ZN1A1fEv
   a.h().f();
+
+  // CHECK: call void @_ZNK1A7f_constEv
+  a.f_const();
+
+  // CHECK: call void @_ZN1A1fEv
+  (a).f();
 }
 
 struct B {
@@ -45,3 +52,4 @@ void f() {
   // CHECK: call void @_ZN1B1fEv
   B().h().f();
 }
+