Author: rsmith Date: Thu Feb 23 16:41:47 2017 New Revision: 296033 URL: http://llvm.org/viewvc/llvm-project?rev=296033&view=rev Log: PR32044: Fix some cases where we would confuse a transparent init-list expression with an aggregate init.
Modified: cfe/trunk/lib/AST/Expr.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp cfe/trunk/test/CodeGenCXX/reference-init.cpp Modified: cfe/trunk/lib/AST/Expr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=296033&r1=296032&r2=296033&view=diff ============================================================================== --- cfe/trunk/lib/AST/Expr.cpp (original) +++ cfe/trunk/lib/AST/Expr.cpp Thu Feb 23 16:41:47 2017 @@ -1882,6 +1882,11 @@ bool InitListExpr::isTransparent() const if (getNumInits() != 1 || !getInit(0)) return false; + // Don't confuse aggregate initialization of a struct X { X &x; }; with a + // transparent struct copy. + if (!getInit(0)->isRValue() && getType()->isRecordType()) + return false; + return getType().getCanonicalType() == getInit(0)->getType().getCanonicalType(); } Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=296033&r1=296032&r2=296033&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Feb 23 16:41:47 2017 @@ -623,6 +623,11 @@ InitListChecker::FillInEmptyInitializati assert((ILE->getType() != SemaRef.Context.VoidTy) && "Should not have void type"); + // A transparent ILE is not performing aggregate initialization and should + // not be filled in. + if (ILE->isTransparent()) + return; + if (const RecordType *RType = ILE->getType()->getAs<RecordType>()) { const RecordDecl *RDecl = RType->getDecl(); if (RDecl->isUnion() && ILE->getInitializedFieldInUnion()) Modified: cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp?rev=296033&r1=296032&r2=296033&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp (original) +++ cfe/trunk/test/CodeGenCXX/cxx11-initializer-aggregate.cpp Thu Feb 23 16:41:47 2017 @@ -2,7 +2,16 @@ struct A { int a, b; int f(); }; -// CHECK: define {{.*}}@_Z3fn1i( +namespace NonAggregateCopyInAggregateInit { // PR32044 + struct A { constexpr A(int n) : x(n), y() {} int x, y; } extern a; + // CHECK-DAG: @_ZN31NonAggregateCopyInAggregateInit1bE = global %{{.*}} { %[[A:.*]]* @_ZN31NonAggregateCopyInAggregateInit1aE } + struct B { A &p; } b{{a}}; + // CHECK-DAG: @_ZGRN31NonAggregateCopyInAggregateInit1cE_ = internal global %[[A]] { i32 1, i32 0 } + // CHECK-DAG: @_ZN31NonAggregateCopyInAggregateInit1cE = global %{{.*}} { %{{.*}}* @_ZGRN31NonAggregateCopyInAggregateInit1cE_ } + struct C { A &&p; } c{{1}}; +} + +// CHECK-LABEL: define {{.*}}@_Z3fn1i( int fn1(int x) { // CHECK: %[[INITLIST:.*]] = alloca %struct.A // CHECK: %[[A:.*]] = getelementptr inbounds %struct.A, %struct.A* %[[INITLIST]], i32 0, i32 0 @@ -15,7 +24,7 @@ int fn1(int x) { struct B { int &r; int &f() { return r; } }; -// CHECK: define {{.*}}@_Z3fn2Ri( +// CHECK-LABEL: define {{.*}}@_Z3fn2Ri( int &fn2(int &v) { // CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8 // CHECK: %[[R:.*]] = getelementptr inbounds %struct.B, %struct.B* %[[INITLIST2:.*]], i32 0, i32 0 @@ -24,7 +33,7 @@ int &fn2(int &v) { return B{v}.f(); } -// CHECK: define {{.*}}@__cxx_global_var_init( +// CHECK-LABEL: define {{.*}}@__cxx_global_var_init( // // CHECK: call {{.*}}@_ZN14NonTrivialInit1AC1Ev( // CHECK: getelementptr inbounds {{.*}}, i64 1 Modified: cfe/trunk/test/CodeGenCXX/reference-init.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/reference-init.cpp?rev=296033&r1=296032&r2=296033&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/reference-init.cpp (original) +++ cfe/trunk/test/CodeGenCXX/reference-init.cpp Thu Feb 23 16:41:47 2017 @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 -emit-llvm-only -triple %itanium_abi_triple -verify %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -verify %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -std=c++98 | FileCheck %s --check-prefix=CHECK-CXX98 +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - -std=c++11 | FileCheck %s --check-prefix=CHECK-CXX11 // expected-no-diagnostics struct XPTParamDescriptor {}; @@ -23,3 +25,12 @@ Foo& ignoreSetMutex = *(new Foo); // Binding to a bit-field that requires a temporary. struct { int bitfield : 3; } s = { 3 }; const int &s2 = s.bitfield; + +// In C++98, this forms a reference to itself. In C++11 onwards, this performs +// copy-construction. +struct SelfReference { SelfReference &r; }; +extern SelfReference self_reference_1; +SelfReference self_reference_2 = {self_reference_1}; +// CHECK-CXX98: @self_reference_2 = global %[[SELF_REF:.*]] { %[[SELF_REF]]* @self_reference_1 } +// CHECK-CXX11: @self_reference_2 = global %[[SELF_REF:.*]] zeroinitializer +// CHECK-CXX11: call {{.*}}memcpy{{.*}} @self_reference_2 {{.*}} @self_reference_1 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits