summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-07-16 21:33:43 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-07-16 21:33:43 +0000
commit5332411cd7464979fe6ee2e7bf48f87fb8055f96 (patch)
treeb3392abbf3cc422004cf545934c16d6d83df5e3f
parentc8491d3d838c3bbc272bf80cb0d0d8e5c0bbab3e (diff)
downloadbcm5719-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.h7
-rw-r--r--clang/lib/Sema/SemaInit.cpp41
-rw-r--r--clang/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp16
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;
+}
OpenPOWER on IntegriCloud