diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-07-16 21:33:43 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2014-07-16 21:33:43 +0000 |
commit | 5332411cd7464979fe6ee2e7bf48f87fb8055f96 (patch) | |
tree | b3392abbf3cc422004cf545934c16d6d83df5e3f | |
parent | c8491d3d838c3bbc272bf80cb0d0d8e5c0bbab3e (diff) | |
download | bcm5719-llvm-5332411cd7464979fe6ee2e7bf48f87fb8055f96.tar.gz bcm5719-llvm-5332411cd7464979fe6ee2e7bf48f87fb8055f96.zip |
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.
llvm-svn: 213201
-rw-r--r-- | clang/include/clang/Sema/Initialization.h | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 41 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp | 16 |
3 files changed, 45 insertions, 19 deletions
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h index 1b59d2d921e..76644250a59 100644 --- a/clang/include/clang/Sema/Initialization.h +++ b/clang/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/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a33724a2970..f6d0b80f5c6 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/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/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp b/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp index db6614de037..eda4e44b773 100644 --- a/clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp +++ b/clang/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<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; +} |