Author: rsmith Date: Thu Jul 17 00:12:35 2014 New Revision: 213224 URL: http://llvm.org/viewvc/llvm-project?rev=213224&view=rev Log: Track the difference between
-- a constructor list initialization that unpacked an initializer list into constructor arguments and -- a list initialization that created as std::initializer_list and passed it as the first argument to a constructor in the AST. Use this flag while instantiating templates to provide the right semantics for the resulting initialization. Modified: cfe/trunk/include/clang/AST/ExprCXX.h cfe/trunk/include/clang/Sema/Initialization.h cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/AST/ExprCXX.cpp cfe/trunk/lib/CodeGen/CGObjC.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/lib/Sema/SemaInit.cpp cfe/trunk/lib/Sema/TreeTransform.h cfe/trunk/lib/Serialization/ASTReaderStmt.cpp cfe/trunk/lib/Serialization/ASTWriterStmt.cpp cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Modified: cfe/trunk/include/clang/AST/ExprCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h (original) +++ cfe/trunk/include/clang/AST/ExprCXX.h Thu Jul 17 00:12:35 2014 @@ -1077,6 +1077,7 @@ private: bool Elidable : 1; bool HadMultipleCandidates : 1; bool ListInitialization : 1; + bool StdInitListInitialization : 1; bool ZeroInitialization : 1; unsigned ConstructKind : 2; Stmt **Args; @@ -1088,6 +1089,7 @@ protected: ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); @@ -1114,6 +1116,7 @@ public: ArrayRef<Expr *> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); @@ -1137,6 +1140,13 @@ public: bool isListInitialization() const { return ListInitialization; } void setListInitialization(bool V) { ListInitialization = V; } + /// \brief Whether this constructor call was written as list-initialization, + /// but was interpreted as forming a std::initializer_list<T> from the list + /// and passing that as a single constructor argument. + /// See C++11 [over.match.list]p1 bullet 1. + bool isStdInitListInitialization() const { return StdInitListInitialization; } + void setStdInitListInitialization(bool V) { StdInitListInitialization = V; } + /// \brief Whether this construction first requires /// zero-initialization before the initializer is called. bool requiresZeroInitialization() const { return ZeroInitialization; } @@ -1272,6 +1282,7 @@ public: SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization); explicit CXXTemporaryObjectExpr(EmptyShell Empty) : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty), Type() { } Modified: cfe/trunk/include/clang/Sema/Initialization.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Initialization.h?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Initialization.h (original) +++ cfe/trunk/include/clang/Sema/Initialization.h Thu Jul 17 00:12:35 2014 @@ -671,8 +671,6 @@ public: SK_ConversionSequenceNoNarrowing, /// \brief Perform list-initialization without a constructor. SK_ListInitialization, - /// \brief Perform list-initialization with an initializer list constructor. - SK_ListConstructorCall, /// \brief Unwrap the single-element initializer list for a reference. SK_UnwrapInitList, /// \brief Rewrap the single-element initializer list for a reference. @@ -705,6 +703,9 @@ public: SK_ProduceObjCObject, /// \brief Construct a std::initializer_list from an initializer list. SK_StdInitializerList, + /// \brief Perform initialization via a constructor taking a single + /// std::initializer_list argument. + SK_StdInitializerListConstructorCall, /// \brief Initialize an OpenCL sampler from an integer. SK_OCLSamplerInit, /// \brief Passing zero to a function where OpenCL event_t is expected. Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Thu Jul 17 00:12:35 2014 @@ -3858,16 +3858,18 @@ public: BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, MultiExprArg Exprs, bool HadMultipleCandidates, bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange); - // FIXME: Can re remove this and have the above BuildCXXConstructExpr check if + // FIXME: Can we remove this and have the above BuildCXXConstructExpr check if // the constructor can be elidable? ExprResult BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType, CXXConstructorDecl *Constructor, bool Elidable, MultiExprArg Exprs, bool HadMultipleCandidates, - bool IsListInitialization, bool RequiresZeroInit, + bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange); /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating Modified: cfe/trunk/lib/AST/ExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExprCXX.cpp (original) +++ cfe/trunk/lib/AST/ExprCXX.cpp Thu Jul 17 00:12:35 2014 @@ -806,13 +806,16 @@ CXXTemporaryObjectExpr::CXXTemporaryObje SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization) : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), Cons, false, Args, HadMultipleCandidates, - ListInitialization, ZeroInitialization, + ListInitialization, + StdInitListInitialization, + ZeroInitialization, CXXConstructExpr::CK_Complete, ParenOrBraceRange), Type(Type) { } @@ -834,12 +837,14 @@ CXXConstructExpr *CXXConstructExpr::Crea ArrayRef<Expr*> Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, Elidable, Args, HadMultipleCandidates, ListInitialization, + StdInitListInitialization, ZeroInitialization, ConstructKind, ParenOrBraceRange); } @@ -850,6 +855,7 @@ CXXConstructExpr::CXXConstructExpr(const ArrayRef<Expr*> args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenOrBraceRange) @@ -861,6 +867,7 @@ CXXConstructExpr::CXXConstructExpr(const NumArgs(args.size()), Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), ListInitialization(ListInitialization), + StdInitListInitialization(StdInitListInitialization), ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), Args(nullptr) { Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjC.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjC.cpp Thu Jul 17 00:12:35 2014 @@ -3021,6 +3021,7 @@ CodeGenFunction::GenerateObjCAtomicGette ConstructorArgs, CXXConstExpr->hadMultipleCandidates(), CXXConstExpr->isListInitialization(), + CXXConstExpr->isStdInitListInitialization(), CXXConstExpr->requiresZeroInitialization(), CXXConstExpr->getConstructionKind(), SourceRange()); Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Jul 17 00:12:35 2014 @@ -10709,6 +10709,7 @@ Sema::BuildCXXConstructExpr(SourceLocati MultiExprArg ExprArgs, bool HadMultipleCandidates, bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { @@ -10732,7 +10733,8 @@ Sema::BuildCXXConstructExpr(SourceLocati return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor, Elidable, ExprArgs, HadMultipleCandidates, - IsListInitialization, RequiresZeroInit, + IsListInitialization, + IsStdInitListInitialization, RequiresZeroInit, ConstructKind, ParenRange); } @@ -10744,13 +10746,15 @@ Sema::BuildCXXConstructExpr(SourceLocati MultiExprArg ExprArgs, bool HadMultipleCandidates, bool IsListInitialization, + bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange) { MarkFunctionReferenced(ConstructLoc, Constructor); return CXXConstructExpr::Create( Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs, - HadMultipleCandidates, IsListInitialization, RequiresZeroInit, + HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, + RequiresZeroInit, static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind), ParenRange); } Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Thu Jul 17 00:12:35 2014 @@ -2560,11 +2560,11 @@ static ExprResult BuildCXXCastArgument(S InitializedEntity::InitializeTemporary(Ty), Constructor->getAccess()); - ExprResult Result - = S.BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method), - ConstructorArgs, HadMultipleCandidates, - /*ListInit*/ false, /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, SourceRange()); + ExprResult Result = S.BuildCXXConstructExpr( + CastLoc, Ty, cast<CXXConstructorDecl>(Method), + ConstructorArgs, HadMultipleCandidates, + /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, SourceRange()); if (Result.isInvalid()) return ExprError(); @@ -2709,20 +2709,17 @@ Sema::PerformImplicitConversion(Expr *Fr From, /*FIXME:ConstructLoc*/SourceLocation(), ConstructorArgs)) return ExprError(); - return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - ToType, SCS.CopyConstructor, - ConstructorArgs, - /*HadMultipleCandidates*/ false, - /*ListInit*/ false, /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, - SourceRange()); + return BuildCXXConstructExpr( + /*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor, + ConstructorArgs, /*HadMultipleCandidates*/ false, + /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, SourceRange()); } - return BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(), - ToType, SCS.CopyConstructor, - From, /*HadMultipleCandidates*/ false, - /*ListInit*/ false, /*ZeroInit*/ false, - CXXConstructExpr::CK_Complete, - SourceRange()); + return BuildCXXConstructExpr( + /*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor, + From, /*HadMultipleCandidates*/ false, + /*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false, + CXXConstructExpr::CK_Complete, SourceRange()); } // Resolve overloaded function references. Modified: cfe/trunk/lib/Sema/SemaInit.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaInit.cpp (original) +++ cfe/trunk/lib/Sema/SemaInit.cpp Thu Jul 17 00:12:35 2014 @@ -2760,7 +2760,6 @@ void InitializationSequence::Step::Destr case SK_QualificationConversionLValue: case SK_LValueToRValue: case SK_ListInitialization: - case SK_ListConstructorCall: case SK_UnwrapInitList: case SK_RewrapInitList: case SK_ConstructorInitialization: @@ -2775,6 +2774,7 @@ void InitializationSequence::Step::Destr case SK_PassByIndirectRestore: case SK_ProduceObjCObject: case SK_StdInitializerList: + case SK_StdInitializerListConstructorCall: case SK_OCLSamplerInit: case SK_OCLZeroEvent: break; @@ -2945,7 +2945,7 @@ InitializationSequence bool HadMultipleCandidates, bool FromInitList, bool AsInitList) { Step S; - S.Kind = FromInitList ? AsInitList ? SK_ListConstructorCall + S.Kind = FromInitList ? AsInitList ? SK_StdInitializerListConstructorCall : SK_ConstructorInitializationFromList : SK_ConstructorInitialization; S.Type = T; @@ -5148,6 +5148,7 @@ static ExprResult CopyObject(Sema &S, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, + /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -5269,6 +5270,7 @@ PerformConstructorInitialization(Sema &S const InitializationSequence::Step& Step, bool &ConstructorInitRequiresZeroInit, bool IsListInitialization, + bool IsStdInitListInitialization, SourceLocation LBraceLoc, SourceLocation RBraceLoc) { unsigned NumArgs = Args.size(); @@ -5330,7 +5332,7 @@ PerformConstructorInitialization(Sema &S CurInit = new (S.Context) CXXTemporaryObjectExpr( S.Context, Constructor, TSInfo, ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, IsListInitialization, - ConstructorInitRequiresZeroInit); + IsStdInitListInitialization, ConstructorInitRequiresZeroInit); } else { CXXConstructExpr::ConstructionKind ConstructKind = CXXConstructExpr::CK_Complete; @@ -5359,6 +5361,7 @@ PerformConstructorInitialization(Sema &S ConstructorArgs, HadMultipleCandidates, IsListInitialization, + IsStdInitListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, ParenOrBraceRange); @@ -5368,6 +5371,7 @@ PerformConstructorInitialization(Sema &S ConstructorArgs, HadMultipleCandidates, IsListInitialization, + IsStdInitListInitialization, ConstructorInitRequiresZeroInit, ConstructKind, ParenOrBraceRange); @@ -5784,7 +5788,7 @@ InitializationSequence::Perform(Sema &S, case SK_ConstructorInitialization: case SK_ConstructorInitializationFromList: - case SK_ListConstructorCall: + case SK_StdInitializerListConstructorCall: case SK_ZeroInitialization: break; } @@ -5959,6 +5963,7 @@ InitializationSequence::Perform(Sema &S, ConstructorArgs, HadMultipleCandidates, /*ListInit*/ false, + /*StdInitListInit*/ false, /*ZeroInit*/ false, CXXConstructExpr::CK_Complete, SourceRange()); @@ -6132,6 +6137,7 @@ InitializationSequence::Perform(Sema &S, Kind, Arg, *Step, ConstructorInitRequiresZeroInit, /*IsListInitialization*/true, + /*IsStdInitListInit*/false, InitList->getLBraceLoc(), InitList->getRBraceLoc()); break; @@ -6154,7 +6160,7 @@ InitializationSequence::Perform(Sema &S, } case SK_ConstructorInitialization: - case SK_ListConstructorCall: { + case SK_StdInitializerListConstructorCall: { // 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. @@ -6164,10 +6170,13 @@ InitializationSequence::Perform(Sema &S, InitializedEntity TempEntity = InitializedEntity::InitializeTemporary( Entity.getType().getNonReferenceType()); bool UseTemporary = Entity.getType()->isReferenceType(); + bool IsStdInitListInit = + Step->Kind == SK_StdInitializerListConstructorCall; CurInit = PerformConstructorInitialization( S, UseTemporary ? TempEntity : Entity, Kind, Args, *Step, ConstructorInitRequiresZeroInit, - /*IsListInitialization*/Step->Kind == SK_ListConstructorCall, + /*IsListInitialization*/IsStdInitListInit, + /*IsStdInitListInitialization*/IsStdInitListInit, /*LBraceLoc*/SourceLocation(), /*RBraceLoc*/SourceLocation()); break; @@ -7030,10 +7039,6 @@ void InitializationSequence::dump(raw_os OS << "list initialization via constructor"; break; - case SK_ListConstructorCall: - OS << "list initialization via initializer list constructor"; - break; - case SK_ZeroInitialization: OS << "zero initialization"; break; @@ -7074,6 +7079,10 @@ void InitializationSequence::dump(raw_os OS << "std::initializer_list from initializer list"; break; + case SK_StdInitializerListConstructorCall: + OS << "list initialization from std::initializer_list"; + break; + case SK_OCLSamplerInit: OS << "OpenCL sampler_t from integer constant"; break; Modified: cfe/trunk/lib/Sema/TreeTransform.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/lib/Sema/TreeTransform.h (original) +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jul 17 00:12:35 2014 @@ -2375,6 +2375,7 @@ public: MultiExprArg Args, bool HadMultipleCandidates, bool ListInitialization, + bool StdInitListInitialization, bool RequiresZeroInit, CXXConstructExpr::ConstructionKind ConstructKind, SourceRange ParenRange) { @@ -2387,6 +2388,7 @@ public: ConvertedArgs, HadMultipleCandidates, ListInitialization, + StdInitListInitialization, RequiresZeroInit, ConstructKind, ParenRange); } @@ -2877,6 +2879,11 @@ ExprResult TreeTransform<Derived>::Trans if (!Construct || isa<CXXTemporaryObjectExpr>(Construct)) return getDerived().TransformExpr(Init); + // If the initialization implicitly converted an initializer list to a + // std::initializer_list object, unwrap the std::initializer_list too. + if (Construct && Construct->isStdInitListInitialization()) + return TransformInitializer(Construct->getArg(0), CXXDirectInit); + SmallVector<Expr*, 8> NewArgs; bool ArgChanged = false; if (getDerived().TransformExprs(Construct->getArgs(), Construct->getNumArgs(), @@ -8571,6 +8578,7 @@ TreeTransform<Derived>::TransformCXXCons Args, E->hadMultipleCandidates(), E->isListInitialization(), + E->isStdInitListInitialization(), E->requiresZeroInitialization(), E->getConstructionKind(), E->getParenOrBraceRange()); Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Thu Jul 17 00:12:35 2014 @@ -1196,6 +1196,7 @@ void ASTStmtReader::VisitCXXConstructExp E->setElidable(Record[Idx++]); E->setHadMultipleCandidates(Record[Idx++]); E->setListInitialization(Record[Idx++]); + E->setStdInitListInitialization(Record[Idx++]); E->setRequiresZeroInitialization(Record[Idx++]); E->setConstructionKind((CXXConstructExpr::ConstructionKind)Record[Idx++]); E->ParenOrBraceRange = ReadSourceRange(Record, Idx); Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Thu Jul 17 00:12:35 2014 @@ -1150,6 +1150,7 @@ void ASTStmtWriter::VisitCXXConstructExp Record.push_back(E->isElidable()); Record.push_back(E->hadMultipleCandidates()); Record.push_back(E->isListInitialization()); + Record.push_back(E->isStdInitListInitialization()); Record.push_back(E->requiresZeroInitialization()); Record.push_back(E->getConstructionKind()); // FIXME: stable encoding Writer.AddSourceRange(E->getParenOrBraceRange(), Record); 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=213224&r1=213223&r2=213224&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Thu Jul 17 00:12:35 2014 @@ -242,6 +242,7 @@ namespace DR1070 { namespace ListInitInstantiate { struct A { A(std::initializer_list<A>); + A(std::initializer_list<int>); }; struct B : A { B(int); @@ -253,4 +254,8 @@ namespace ListInitInstantiate { template<typename T> X<T>::X() : a{B{0}, B{1}} {} X<int> x; + + int f(const A&); + template<typename T> void g() { int k = f({0}); } + template void g<int>(); } _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits