r213201 - When list-initializing an object of class type, if we pick an initializer list

Richard Smith richard-llvm at metafoo.co.uk
Wed Jul 16 14:33:43 PDT 2014


Author: rsmith
Date: Wed Jul 16 16:33:43 2014
New Revision: 213201

URL: http://llvm.org/viewvc/llvm-project?rev=213201&view=rev
Log:
When list-initializing an object of class type, if we pick an initializer list
constructor (and pass it an implicitly-generated std::initializer_list object),
be sure to mark the resulting construction as list-initialization. This fixes
an assert in template instantiation where we previously thought we'd got direct
non-list initialization without any parentheses.

Modified:
    cfe/trunk/include/clang/Sema/Initialization.h
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp

Modified: cfe/trunk/include/clang/Sema/Initialization.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=213201&r1=213200&r2=213201&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Initialization.h (original)
+++ cfe/trunk/include/clang/Sema/Initialization.h Wed Jul 16 16:33:43 2014
@@ -669,9 +669,9 @@ public:
     SK_ConversionSequence,
     /// \brief Perform an implicit conversion sequence without narrowing.
     SK_ConversionSequenceNoNarrowing,
-    /// \brief Perform list-initialization without a constructor
+    /// \brief Perform list-initialization without a constructor.
     SK_ListInitialization,
-    /// \brief Perform list-initialization with a constructor.
+    /// \brief Perform list-initialization with an initializer list constructor.
     SK_ListConstructorCall,
     /// \brief Unwrap the single-element initializer list for a reference.
     SK_UnwrapInitList,
@@ -679,6 +679,9 @@ public:
     SK_RewrapInitList,
     /// \brief Perform initialization via a constructor.
     SK_ConstructorInitialization,
+    /// \brief Perform initialization via a constructor, taking arguments from
+    /// a single InitListExpr.
+    SK_ConstructorInitializationFromList,
     /// \brief Zero-initialize the object
     SK_ZeroInitialization,
     /// \brief C assignment

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=213201&r1=213200&r2=213201&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Wed Jul 16 16:33:43 2014
@@ -2764,6 +2764,7 @@ void InitializationSequence::Step::Destr
   case SK_UnwrapInitList:
   case SK_RewrapInitList:
   case SK_ConstructorInitialization:
+  case SK_ConstructorInitializationFromList:
   case SK_ZeroInitialization:
   case SK_CAssignment:
   case SK_StringInit:
@@ -2944,8 +2945,9 @@ InitializationSequence
                                    bool HadMultipleCandidates,
                                    bool FromInitList, bool AsInitList) {
   Step S;
-  S.Kind = FromInitList && !AsInitList ? SK_ListConstructorCall
-                                       : SK_ConstructorInitialization;
+  S.Kind = FromInitList ? AsInitList ? SK_ListConstructorCall
+                                     : SK_ConstructorInitializationFromList
+                        : SK_ConstructorInitialization;
   S.Type = T;
   S.Function.HadMultipleCandidates = HadMultipleCandidates;
   S.Function.Function = Constructor;
@@ -5781,6 +5783,7 @@ InitializationSequence::Perform(Sema &S,
   }
 
   case SK_ConstructorInitialization:
+  case SK_ConstructorInitializationFromList:
   case SK_ListConstructorCall:
   case SK_ZeroInitialization:
     break;
@@ -6109,7 +6112,7 @@ InitializationSequence::Perform(Sema &S,
       break;
     }
 
-    case SK_ListConstructorCall: {
+    case SK_ConstructorInitializationFromList: {
       // When an initializer list is passed for a parameter of type "reference
       // to object", we don't get an EK_Temporary entity, but instead an
       // EK_Parameter entity with reference type.
@@ -6128,7 +6131,7 @@ InitializationSequence::Perform(Sema &S,
                                                                    Entity,
                                                  Kind, Arg, *Step,
                                                ConstructorInitRequiresZeroInit,
-                                               /*IsListInitialization*/ true,
+                                               /*IsListInitialization*/true,
                                                InitList->getLBraceLoc(),
                                                InitList->getRBraceLoc());
       break;
@@ -6150,7 +6153,8 @@ InitializationSequence::Perform(Sema &S,
       break;
     }
 
-    case SK_ConstructorInitialization: {
+    case SK_ConstructorInitialization:
+    case SK_ListConstructorCall: {
       // When an initializer list is passed for a parameter of type "reference
       // to object", we don't get an EK_Temporary entity, but instead an
       // EK_Parameter entity with reference type.
@@ -6160,13 +6164,12 @@ InitializationSequence::Perform(Sema &S,
       InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(
                                         Entity.getType().getNonReferenceType());
       bool UseTemporary = Entity.getType()->isReferenceType();
-      CurInit = PerformConstructorInitialization(S, UseTemporary ? TempEntity
-                                                                 : Entity,
-                                                 Kind, Args, *Step,
-                                               ConstructorInitRequiresZeroInit,
-                                               /*IsListInitialization*/ false,
-                                               /*LBraceLoc*/ SourceLocation(),
-                                               /*RBraceLoc*/ SourceLocation());
+      CurInit = PerformConstructorInitialization(
+          S, UseTemporary ? TempEntity : Entity, Kind, Args, *Step,
+          ConstructorInitRequiresZeroInit,
+          /*IsListInitialization*/Step->Kind == SK_ListConstructorCall,
+          /*LBraceLoc*/SourceLocation(),
+          /*RBraceLoc*/SourceLocation());
       break;
     }
 
@@ -6175,7 +6178,7 @@ InitializationSequence::Perform(Sema &S,
       ++NextStep;
       if (NextStep != StepEnd &&
           (NextStep->Kind == SK_ConstructorInitialization ||
-           NextStep->Kind == SK_ListConstructorCall)) {
+           NextStep->Kind == SK_ConstructorInitializationFromList)) {
         // The need for zero-initialization is recorded directly into
         // the call to the object's constructor within the next step.
         ConstructorInitRequiresZeroInit = true;
@@ -7011,10 +7014,6 @@ void InitializationSequence::dump(raw_os
       OS << "list aggregate initialization";
       break;
 
-    case SK_ListConstructorCall:
-      OS << "list initialization via constructor";
-      break;
-
     case SK_UnwrapInitList:
       OS << "unwrap reference initializer list";
       break;
@@ -7027,6 +7026,14 @@ void InitializationSequence::dump(raw_os
       OS << "constructor initialization";
       break;
 
+    case SK_ConstructorInitializationFromList:
+      OS << "list initialization via constructor";
+      break;
+
+    case SK_ListConstructorCall:
+      OS << "list initialization via initializer list constructor";
+      break;
+
     case SK_ZeroInitialization:
       OS << "zero initialization";
       break;

Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=213201&r1=213200&r2=213201&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Wed Jul 16 16:33:43 2014
@@ -238,3 +238,19 @@ namespace DR1070 {
   S s[3] = { {1, 2, 3}, {4, 5} }; // ok
   S *p = new S[3] { {1, 2, 3}, {4, 5} }; // ok
 }
+
+namespace ListInitInstantiate {
+  struct A {
+    A(std::initializer_list<A>);
+  };
+  struct B : A {
+    B(int);
+  };
+  template<typename T> struct X {
+    X();
+    A a;
+  };
+  template<typename T> X<T>::X() : a{B{0}, B{1}} {}
+
+  X<int> x;
+}





More information about the cfe-commits mailing list