From 19e60ad937af50843a653fa19c8be6a83a64f24f Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 16 Sep 2010 06:57:56 +0000 Subject: [PATCH] Right, there are *two* cases of pr-value class-type expressions that don't 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 | 11 ++++++++--- test/CodeGenCXX/temporaries.cpp | 34 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index f3285ec390..4c6822c041 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -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(E)) { switch (cast(E)->getCastKind()) { case CK_DerivedToBase: @@ -1672,6 +1673,10 @@ bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const { } } + // - member expressions (all) + if (isa(E)) + return false; + return true; } diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp index fb6f2160b8..7996ed656d 100644 --- a/test/CodeGenCXX/temporaries.cpp +++ b/test/CodeGenCXX/temporaries.cpp @@ -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]]) + } } -- 2.40.0