<div dir="ltr">This fixes a bug marked as being a release blocker and should be put on the 3.5 branch.</div><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Jul 30, 2014 at 11:31 PM, Richard Smith <span dir="ltr"><<a href="mailto:richard-llvm@metafoo.co.uk" target="_blank">richard-llvm@metafoo.co.uk</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Thu Jul 31 01:31:19 2014<br>
New Revision: 214390<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=214390&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=214390&view=rev</a><br>
Log:<br>
PR18097: Support initializing an _Atomic(T) from an object of C++ class type T<br>
or a class derived from T. We already supported this when initializing<br>
_Atomic(T) from T for most (and maybe all) other reasonable values of T.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Sema/Initialization.h<br>
    cfe/trunk/lib/AST/ExprConstant.cpp<br>
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp<br>
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp<br>
    cfe/trunk/lib/Sema/SemaInit.cpp<br>
    cfe/trunk/test/CodeGen/c11atomics.c<br>
    cfe/trunk/test/CodeGenCXX/atomicinit.cpp<br>
    cfe/trunk/test/SemaCXX/atomic-type.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Sema/Initialization.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=214390&r1=214389&r2=214390&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=214390&r1=214389&r2=214390&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/include/clang/Sema/Initialization.h (original)<br>
+++ cfe/trunk/include/clang/Sema/Initialization.h Thu Jul 31 01:31:19 2014<br>
@@ -663,6 +663,8 @@ public:<br>
     SK_QualificationConversionXValue,<br>
     /// \brief Perform a qualification conversion, producing an lvalue.<br>
     SK_QualificationConversionLValue,<br>
+    /// \brief Perform a conversion adding _Atomic to a type.<br>
+    SK_AtomicConversion,<br>
     /// \brief Perform a load from a glvalue, producing an rvalue.<br>
     SK_LValueToRValue,<br>
     /// \brief Perform an implicit conversion sequence.<br>
@@ -999,7 +1001,11 @@ public:<br>
   /// given type.<br>
   void AddQualificationConversionStep(QualType Ty,<br>
                                      ExprValueKind Category);<br>
-<br>
+<br>
+  /// \brief Add a new step that performs conversion from non-atomic to atomic<br>
+  /// type.<br>
+  void AddAtomicConversionStep(QualType Ty);<br>
+<br>
   /// \brief Add a new step that performs a load of the given type.<br>
   ///<br>
   /// Although the term "LValueToRValue" is conventional, this applies to both<br>
<br>
Modified: cfe/trunk/lib/AST/ExprConstant.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=214390&r1=214389&r2=214390&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=214390&r1=214389&r2=214390&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)<br>
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Jul 31 01:31:19 2014<br>
@@ -1353,6 +1353,11 @@ static bool CheckConstantExpression(Eval<br>
     return false;<br>
   }<br>
<br>
+  // We allow _Atomic(T) to be initialized from anything that T can be<br>
+  // initialized from.<br>
+  if (const AtomicType *AT = Type->getAs<AtomicType>())<br>
+    Type = AT->getValueType();<br>
+<br>
   // Core issue 1454: For a literal constant expression of array or class type,<br>
   // each subobject of its value shall have been initialized by a constant<br>
   // expression.<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=214390&r1=214389&r2=214390&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=214390&r1=214389&r2=214390&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Thu Jul 31 01:31:19 2014<br>
@@ -1137,6 +1137,16 @@ void AggExprEmitter::VisitInitListExpr(I<br>
     return;<br>
   }<br>
<br>
+  if (E->getType()->isAtomicType()) {<br>
+    // An _Atomic(T) object can be list-initialized from an expression<br>
+    // of the same type.<br>
+    assert(E->getNumInits() == 1 &&<br>
+           CGF.getContext().hasSameUnqualifiedType(E->getInit(0)->getType(),<br>
+                                                   E->getType()) &&<br>
+           "unexpected list initialization for atomic object");<br>
+    return Visit(E->getInit(0));<br>
+  }<br>
+<br>
   assert(E->getType()->isRecordType() && "Only support structs/unions here!");<br>
<br>
   // Do struct initialization; this code just sets each individual member<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=214390&r1=214389&r2=214390&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=214390&r1=214389&r2=214390&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Thu Jul 31 01:31:19 2014<br>
@@ -1045,6 +1045,25 @@ llvm::Constant *CodeGenModule::EmitConst<br>
 llvm::Constant *CodeGenModule::EmitConstantValue(const APValue &Value,<br>
                                                  QualType DestType,<br>
                                                  CodeGenFunction *CGF) {<br>
+  // For an _Atomic-qualified constant, we may need to add tail padding.<br>
+  if (auto *AT = DestType->getAs<AtomicType>()) {<br>
+    QualType InnerType = AT->getValueType();<br>
+    auto *Inner = EmitConstantValue(Value, InnerType, CGF);<br>
+<br>
+    uint64_t InnerSize = Context.getTypeSize(InnerType);<br>
+    uint64_t OuterSize = Context.getTypeSize(DestType);<br>
+    if (InnerSize == OuterSize)<br>
+      return Inner;<br>
+<br>
+    assert(InnerSize < OuterSize && "emitted over-large constant for atomic");<br>
+    llvm::Constant *Elts[] = {<br>
+      Inner,<br>
+      llvm::ConstantAggregateZero::get(<br>
+          llvm::ArrayType::get(Int8Ty, (OuterSize - InnerSize) / 8))<br>
+    };<br>
+    return llvm::ConstantStruct::getAnon(Elts);<br>
+  }<br>
+<br>
   switch (Value.getKind()) {<br>
   case APValue::Uninitialized:<br>
     llvm_unreachable("Constant expressions should be initialized.");<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaInit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=214390&r1=214389&r2=214390&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=214390&r1=214389&r2=214390&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jul 31 01:31:19 2014<br>
@@ -2767,6 +2767,7 @@ void InitializationSequence::Step::Destr<br>
   case SK_QualificationConversionRValue:<br>
   case SK_QualificationConversionXValue:<br>
   case SK_QualificationConversionLValue:<br>
+  case SK_AtomicConversion:<br>
   case SK_LValueToRValue:<br>
   case SK_ListInitialization:<br>
   case SK_UnwrapInitList:<br>
@@ -2919,6 +2920,13 @@ void InitializationSequence::AddQualific<br>
   Steps.push_back(S);<br>
 }<br>
<br>
+void InitializationSequence::AddAtomicConversionStep(QualType Ty) {<br>
+  Step S;<br>
+  S.Kind = SK_AtomicConversion;<br>
+  S.Type = Ty;<br>
+  Steps.push_back(S);<br>
+}<br>
+<br>
 void InitializationSequence::AddLValueToRValueStep(QualType Ty) {<br>
   assert(!Ty.hasQualifiers() && "rvalues may not have qualifiers");<br>
<br>
@@ -4174,12 +4182,11 @@ static void TryDefaultInitialization(Sem<br>
 /// which enumerates all conversion functions and performs overload resolution<br>
 /// to select the best.<br>
 static void TryUserDefinedConversion(Sema &S,<br>
-                                     const InitializedEntity &Entity,<br>
+                                     QualType DestType,<br>
                                      const InitializationKind &Kind,<br>
                                      Expr *Initializer,<br>
                                      InitializationSequence &Sequence,<br>
                                      bool TopLevelOfInitList) {<br>
-  QualType DestType = Entity.getType();<br>
   assert(!DestType->isReferenceType() && "References are handled elsewhere");<br>
   QualType SourceType = Initializer->getType();<br>
   assert((DestType->isRecordType() || SourceType->isRecordType()) &&<br>
@@ -4596,7 +4603,6 @@ void InitializationSequence::InitializeF<br>
                                               Initializer) ||<br>
           S.ConversionToObjCStringLiteralCheck(DestType, Initializer))<br>
         Args[0] = Initializer;<br>
-<br>
     }<br>
     if (!isa<InitListExpr>(Initializer))<br>
       SourceType = Initializer->getType();<br>
@@ -4741,7 +4747,7 @@ void InitializationSequence::InitializeF<br>
          (Context.hasSameUnqualifiedType(SourceType, DestType) ||<br>
           S.IsDerivedFrom(SourceType, DestType))))<br>
       TryConstructorInitialization(S, Entity, Kind, Args,<br>
-                                   Entity.getType(), *this);<br>
+                                   DestType, *this);<br>
     //     - Otherwise (i.e., for the remaining copy-initialization cases),<br>
     //       user-defined conversion sequences that can convert from the source<br>
     //       type to the destination type or (when a conversion function is<br>
@@ -4749,7 +4755,7 @@ void InitializationSequence::InitializeF<br>
     //       13.3.1.4, and the best one is chosen through overload resolution<br>
     //       (13.3).<br>
     else<br>
-      TryUserDefinedConversion(S, Entity, Kind, Initializer, *this,<br>
+      TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,<br>
                                TopLevelOfInitList);<br>
     return;<br>
   }<br>
@@ -4763,9 +4769,22 @@ void InitializationSequence::InitializeF<br>
   //    - Otherwise, if the source type is a (possibly cv-qualified) class<br>
   //      type, conversion functions are considered.<br>
   if (!SourceType.isNull() && SourceType->isRecordType()) {<br>
-    TryUserDefinedConversion(S, Entity, Kind, Initializer, *this,<br>
+    // For a conversion to _Atomic(T) from either T or a class type derived<br>
+    // from T, initialize the T object then convert to _Atomic type.<br>
+    bool NeedAtomicConversion = false;<br>
+    if (const AtomicType *Atomic = DestType->getAs<AtomicType>()) {<br>
+      if (Context.hasSameUnqualifiedType(SourceType, Atomic->getValueType()) ||<br>
+          S.IsDerivedFrom(SourceType, Atomic->getValueType())) {<br>
+        DestType = Atomic->getValueType();<br>
+        NeedAtomicConversion = true;<br>
+      }<br>
+    }<br>
+<br>
+    TryUserDefinedConversion(S, DestType, Kind, Initializer, *this,<br>
                              TopLevelOfInitList);<br>
     MaybeProduceObjCObject(S, *this, Entity);<br>
+    if (!Failed() && NeedAtomicConversion)<br>
+      AddAtomicConversionStep(Entity.getType());<br>
     return;<br>
   }<br>
<br>
@@ -4774,16 +4793,16 @@ void InitializationSequence::InitializeF<br>
   //      conversions (Clause 4) will be used, if necessary, to convert the<br>
   //      initializer expression to the cv-unqualified version of the<br>
   //      destination type; no user-defined conversions are considered.<br>
-<br>
+<br>
   ImplicitConversionSequence ICS<br>
-    = S.TryImplicitConversion(Initializer, Entity.getType(),<br>
+    = S.TryImplicitConversion(Initializer, DestType,<br>
                               /*SuppressUserConversions*/true,<br>
                               /*AllowExplicitConversions*/ false,<br>
                               /*InOverloadResolution*/ false,<br>
                               /*CStyle=*/Kind.isCStyleOrFunctionalCast(),<br>
                               allowObjCWritebackConversion);<br>
-<br>
-  if (ICS.isStandard() &&<br>
+<br>
+  if (ICS.isStandard() &&<br>
       ICS.Standard.Second == ICK_Writeback_Conversion) {<br>
     // Objective-C ARC writeback conversion.<br>
<br>
@@ -4804,7 +4823,7 @@ void InitializationSequence::InitializeF<br>
       AddConversionSequenceStep(LvalueICS, ICS.Standard.getToType(0));<br>
     }<br>
<br>
-    AddPassByIndirectCopyRestoreStep(Entity.getType(), ShouldCopy);<br>
+    AddPassByIndirectCopyRestoreStep(DestType, ShouldCopy);<br>
   } else if (ICS.isBad()) {<br>
     DeclAccessPair dap;<br>
     if (isLibstdcxxPointerReturnFalseHack(S, Entity, Initializer)) {<br>
@@ -4816,7 +4835,7 @@ void InitializationSequence::InitializeF<br>
     else<br>
       SetFailed(InitializationSequence::FK_ConversionFailed);<br>
   } else {<br>
-    AddConversionSequenceStep(ICS, Entity.getType(), TopLevelOfInitList);<br>
+    AddConversionSequenceStep(ICS, DestType, TopLevelOfInitList);<br>
<br>
     MaybeProduceObjCObject(S, *this, Entity);<br>
   }<br>
@@ -5772,6 +5791,7 @@ InitializationSequence::Perform(Sema &S,<br>
   case SK_QualificationConversionLValue:<br>
   case SK_QualificationConversionXValue:<br>
   case SK_QualificationConversionRValue:<br>
+  case SK_AtomicConversion:<br>
   case SK_LValueToRValue:<br>
   case SK_ConversionSequence:<br>
   case SK_ConversionSequenceNoNarrowing:<br>
@@ -6062,6 +6082,13 @@ InitializationSequence::Perform(Sema &S,<br>
       break;<br>
     }<br>
<br>
+    case SK_AtomicConversion: {<br>
+      assert(CurInit.get()->isRValue() && "cannot convert glvalue to atomic");<br>
+      CurInit = S.ImpCastExprToType(CurInit.get(), Step->Type,<br>
+                                    CK_NonAtomicToAtomic, VK_RValue);<br>
+      break;<br>
+    }<br>
+<br>
     case SK_LValueToRValue: {<br>
       assert(CurInit.get()->isGLValue() && "cannot load from a prvalue");<br>
       CurInit = ImplicitCastExpr::Create(S.Context, Step->Type,<br>
@@ -7033,6 +7060,10 @@ void InitializationSequence::dump(raw_os<br>
       OS << "qualification conversion (lvalue)";<br>
       break;<br>
<br>
+    case SK_AtomicConversion:<br>
+      OS << "non-atomic-to-atomic conversion";<br>
+      break;<br>
+<br>
     case SK_LValueToRValue:<br>
       OS << "load (lvalue to rvalue)";<br>
       break;<br>
<br>
Modified: cfe/trunk/test/CodeGen/c11atomics.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/c11atomics.c?rev=214390&r1=214389&r2=214390&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/c11atomics.c?rev=214390&r1=214389&r2=214390&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGen/c11atomics.c (original)<br>
+++ cfe/trunk/test/CodeGen/c11atomics.c Thu Jul 31 01:31:19 2014<br>
@@ -12,6 +12,9 @@<br>
 // they're sufficiently rare that it's not worth making sure that the semantics<br>
 // are correct.<br>
<br>
+// CHECK: @testStructGlobal = global {{.*}} { i16 1, i16 2, i16 3, i16 4 }<br>
+// CHECK: @testPromotedStructGlobal = global {{.*}} { %{{.*}} { i16 1, i16 2, i16 3 }, [2 x i8] zeroinitializer }<br>
+<br>
 typedef int __attribute__((vector_size(16))) vector;<br>
<br>
 _Atomic(_Bool) b;<br>
@@ -224,6 +227,7 @@ void testComplexFloat(_Atomic(_Complex f<br>
 }<br>
<br>
 typedef struct { short x, y, z, w; } S;<br>
+_Atomic S testStructGlobal = (S){1, 2, 3, 4};<br>
 // CHECK: define arm_aapcscc void @testStruct([[S:.*]]*<br>
 void testStruct(_Atomic(S) *fp) {<br>
 // CHECK:      [[FP:%.*]] = alloca [[S]]*, align 4<br>
@@ -272,6 +276,7 @@ void testStruct(_Atomic(S) *fp) {<br>
 }<br>
<br>
 typedef struct { short x, y, z; } PS;<br>
+_Atomic PS testPromotedStructGlobal = (PS){1, 2, 3};<br>
 // CHECK: define arm_aapcscc void @testPromotedStruct([[APS:.*]]*<br>
 void testPromotedStruct(_Atomic(PS) *fp) {<br>
 // CHECK:      [[FP:%.*]] = alloca [[APS]]*, align 4<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/atomicinit.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/atomicinit.cpp?rev=214390&r1=214389&r2=214390&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/atomicinit.cpp?rev=214390&r1=214389&r2=214390&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/atomicinit.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/atomicinit.cpp Thu Jul 31 01:31:19 2014<br>
@@ -1,4 +1,10 @@<br>
-// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 | FileCheck %s<br>
+// RUN: %clang_cc1 %s -emit-llvm -O1 -o - -triple=i686-apple-darwin9 -std=c++11 | FileCheck %s<br>
+<br>
+// CHECK-DAG: @_ZN7PR180978constant1aE = global {{.*}} { i16 1, i8 6, i8 undef }, align 4<br>
+// CHECK-DAG: @_ZN7PR180978constant1bE = global {{.*}} { i16 2, i8 6, i8 undef }, align 4<br>
+// CHECK-DAG: @_ZN7PR180978constant1cE = global {{.*}} { i16 3, i8 6, i8 undef }, align 4<br>
+// CHECK-DAG: @_ZN7PR180978constant1yE = global {{.*}} { {{.*}} { i16 4, i8 6, i8 undef }, i32 5 }, align 4<br>
+<br>
 struct A {<br>
   _Atomic(int) i;<br>
   A(int j);<br>
@@ -46,3 +52,51 @@ struct AtomicBoolMember {<br>
 // CHECK-NEXT: ret void<br>
 AtomicBoolMember::AtomicBoolMember(bool b) : ab(b) { }<br>
<br>
+namespace PR18097 {<br>
+  namespace dynamic {<br>
+    struct X {<br>
+      X(int);<br>
+      short n;<br>
+      char c;<br>
+    };<br>
+<br>
+    // CHECK-LABEL: define {{.*}} @__cxx_global_var_init<br>
+    // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1aE, i32 1)<br>
+    _Atomic(X) a = X(1);<br>
+<br>
+    // CHECK-LABEL: define {{.*}} @__cxx_global_var_init<br>
+    // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1bE, i32 2)<br>
+    _Atomic(X) b(X(2));<br>
+<br>
+    // CHECK-LABEL: define {{.*}} @__cxx_global_var_init<br>
+    // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* @_ZN7PR180977dynamic1cE, i32 3)<br>
+    _Atomic(X) c{X(3)};<br>
+<br>
+    struct Y {<br>
+      _Atomic(X) a;<br>
+      _Atomic(int) b;<br>
+    };<br>
+    // CHECK-LABEL: define {{.*}} @__cxx_global_var_init<br>
+    // CHECK: call void @_ZN7PR180977dynamic1XC1Ei({{.*}}* getelementptr inbounds ({{.*}}* @_ZN7PR180977dynamic1yE, i32 0, i32 0), i32 4)<br>
+    // CHECK: store i32 5, i32* getelementptr inbounds ({{.*}}* @_ZN7PR180977dynamic1yE, i32 0, i32 1)<br>
+    Y y = { X(4), 5 };<br>
+  }<br>
+<br>
+  // CHECKs at top of file.<br>
+  namespace constant {<br>
+    struct X {<br>
+      constexpr X(int n) : n(n) {}<br>
+      short n;<br>
+      char c = 6;<br>
+    };<br>
+    _Atomic(X) a = X(1);<br>
+    _Atomic(X) b(X(2));<br>
+    _Atomic(X) c{X(3)};<br>
+<br>
+    struct Y {<br>
+      _Atomic(X) a;<br>
+      _Atomic(int) b;<br>
+    };<br>
+    Y y = { X(4), 5 };<br>
+  }<br>
+}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/atomic-type.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/atomic-type.cpp?rev=214390&r1=214389&r2=214390&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/atomic-type.cpp?rev=214390&r1=214389&r2=214390&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/SemaCXX/atomic-type.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/atomic-type.cpp Thu Jul 31 01:31:19 2014<br>
@@ -1,4 +1,5 @@<br>
-// RUN: %clang_cc1 -verify -pedantic %s<br>
+// RUN: %clang_cc1 -verify -pedantic %s -std=c++98<br>
+// RUN: %clang_cc1 -verify -pedantic %s -std=c++11<br>
<br>
 template<typename T> struct atomic {<br>
   _Atomic(T) value;<br>
@@ -56,3 +57,29 @@ typedef _Atomic(int &) atomic_reference_<br>
 struct S {<br>
   _Atomic union { int n; }; // expected-warning {{anonymous union cannot be '_Atomic'}}<br>
 };<br>
+<br>
+namespace copy_init {<br>
+  struct X {<br>
+    X(int);<br>
+    int n;<br>
+  };<br>
+  _Atomic(X) y = X(0);<br>
+  _Atomic(X) z(X(0));<br>
+  void f() { y = X(0); }<br>
+<br>
+  _Atomic(X) e1(0); // expected-error {{cannot initialize}}<br>
+#if __cplusplus >= 201103L<br>
+  _Atomic(X) e2{0}; // expected-error {{illegal initializer}}<br>
+  _Atomic(X) a{X(0)};<br>
+#endif<br>
+<br>
+  struct Y {<br>
+    _Atomic(X) a;<br>
+    _Atomic(int) b;<br>
+  };<br>
+  Y y1 = { X(0), 4 };<br>
+  Y y2 = { 0, 4 }; // expected-error {{cannot initialize}}<br>
+  // FIXME: It's not really clear if we should allow these. Generally, C++11<br>
+  // allows extraneous braces around initializers.<br>
+  Y y3 = { { X(0) }, { 4 } }; // expected-error 2{{illegal initializer type}}<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>