]> granicus.if.org Git - clang/commitdiff
Right, there are *two* cases of pr-value class-type expressions that don't
authorJohn McCall <rjmccall@apple.com>
Thu, 16 Sep 2010 06:57:56 +0000 (06:57 +0000)
committerJohn McCall <rjmccall@apple.com>
Thu, 16 Sep 2010 06:57:56 +0000 (06:57 +0000)
derive from temporaries of the same type.  Black-list member expressions
as well.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114071 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/Expr.cpp
test/CodeGenCXX/temporaries.cpp

index f3285ec390b85e0530166602696c806f755e78c7..4c6822c041ff08aa72e13dd311be43511bb31793 100644 (file)
@@ -1659,9 +1659,10 @@ bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const {
   // Temporaries are by definition pr-values of class type.
   if (!E->Classify(C).isPRValue()) return false;
 
-  // Black-list implicit derived-to-base conversions, which are the
-  // only way we can get a pr-value of class type that doesn't refer
-  // to a temporary of that type.
+  // Black-list a few cases which yield pr-values of class type that don't
+  // refer to temporaries of that type:
+
+  // - implicit derived-to-base conversions
   if (isa<ImplicitCastExpr>(E)) {
     switch (cast<ImplicitCastExpr>(E)->getCastKind()) {
     case CK_DerivedToBase:
@@ -1672,6 +1673,10 @@ bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const {
     }
   }
 
+  // - member expressions (all)
+  if (isa<MemberExpr>(E))
+    return false;
+
   return true;
 }
 
index fb6f2160b8f8cc01c0d858370f407b545875bd2d..7996ed656d426f2ab8fc57ffa19316046a10dc7b 100644 (file)
@@ -344,6 +344,7 @@ namespace Elision {
 
   void foo();
   A fooA();
+  void takeA(A a);
 
   // CHECK: define void @_ZN7Elision5test0Ev()
   void test0() {
@@ -441,4 +442,37 @@ namespace Elision {
 
     // CHECK:      call void @_ZN7Elision1AD1Ev([[A]]* [[X]])
   }
+
+  // rdar://problem/8433352
+  // CHECK: define void @_ZN7Elision5test5Ev([[A]]* sret
+  struct B { A a; B(); };
+  A test5() {
+    // CHECK:      [[AT0:%.*]] = alloca [[A]], align 8
+    // CHECK-NEXT: [[BT0:%.*]] = alloca [[B:%.*]], align 8
+    // CHECK-NEXT: [[X:%.*]] = alloca [[A]], align 8
+    // CHECK-NEXT: [[BT1:%.*]] = alloca [[B]], align 8
+    // CHECK-NEXT: [[BT2:%.*]] = alloca [[B]], align 8
+
+    // CHECK:      call void @_ZN7Elision1BC1Ev([[B]]* [[BT0]])
+    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT0]], i32 0, i32 0
+    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* [[AM]])
+    // CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE([[A]]* [[AT0]])
+    // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[AT0]])
+    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT0]])
+    takeA(B().a);
+
+    // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT1]])
+    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT1]], i32 0, i32 0
+    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* [[AM]])
+    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT1]])
+    A x = B().a;
+
+    // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT2]])
+    // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT2]], i32 0, i32 0
+    // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* [[AM]])
+    // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT2]])
+    return B().a;
+
+    // CHECK:      call void @_ZN7Elision1AD1Ev([[A]]* [[X]])
+  }
 }