r296033 - PR32044: Fix some cases where we would confuse a transparent init-list expression with an aggregate init.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 23 14:41:48 PST 2017


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




More information about the cfe-commits mailing list