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 7c2c9f1..31ea1b5 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -123,7 +123,14 @@
     
     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 c5a4094..7ef4864 100644
--- a/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
+++ b/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
@@ -83,3 +83,20 @@
     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();
+  }
+}