From: Richard Smith Date: Wed, 16 Jul 2014 21:33:43 +0000 (+0000) Subject: When list-initializing an object of class type, if we pick an initializer list X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cb743254ce3efc0883e4f4a91ab64614bfce18cd;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@213201 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index 1b59d2d921..76644250a5 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -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 diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index a33724a297..f6d0b80f5c 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -2764,6 +2764,7 @@ void InitializationSequence::Step::Destroy() { 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_ostream &OS) const { 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_ostream &OS) const { 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; diff --git a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index db6614de03..eda4e44b77 100644 --- a/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp @@ -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); + }; + struct B : A { + B(int); + }; + template struct X { + X(); + A a; + }; + template X::X() : a{B{0}, B{1}} {} + + X x; +}