diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-02-05 07:02:11 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-02-05 07:02:11 +0000 |
commit | ed83ebd77e12e561d435574fbe093a220f270e4e (patch) | |
tree | e3650f69e384d49e014b196a97e44923ccd09407 /clang/lib | |
parent | 6956e2e68338f62bd19d54b82f0791a8f626c84d (diff) | |
download | bcm5719-llvm-ed83ebd77e12e561d435574fbe093a220f270e4e.tar.gz bcm5719-llvm-ed83ebd77e12e561d435574fbe093a220f270e4e.zip |
PR22465: when performing list-initialization for a class type C, if we see an
initializer of the form {x}, where x is of type C or a type derived from C,
perform *non-list* initialization of the entity from x, but create a
CXXConstructExpr that knows that we used list-initialization syntax.
Plus some fixes to ensure we mangle correctly in this and related cases.
llvm-svn: 228276
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 16 | ||||
-rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 35 |
3 files changed, 40 insertions, 23 deletions
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 96d4db75e5a..eae82a28273 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -2864,7 +2864,7 @@ recurse: case Expr::CXXConstructExprClass: { const auto *CE = cast<CXXConstructExpr>(E); - if (!CE->isListInitialization()) { + if (!CE->isListInitialization() || CE->isStdInitListInitialization()) { assert( CE->getNumArgs() >= 1 && (CE->getNumArgs() == 1 || isa<CXXDefaultArgExpr>(CE->getArg(1))) && @@ -2890,8 +2890,18 @@ recurse: mangleType(CE->getType()); if (!List && N != 1) Out << '_'; - for (auto *E : CE->arguments()) - mangleExpression(E); + if (CE->isStdInitListInitialization()) { + // We implicitly created a std::initializer_list<T> for the first argument + // of a constructor of type U in an expression of the form U{a, b, c}. + // Strip all the semantic gunk off the initializer list. + auto *SILE = + cast<CXXStdInitializerListExpr>(CE->getArg(0)->IgnoreImplicit()); + auto *ILE = cast<InitListExpr>(SILE->getSubExpr()->IgnoreImplicit()); + mangleInitListElements(ILE); + } else { + for (auto *E : CE->arguments()) + mangleExpression(E); + } if (List || N != 1) Out << 'E'; break; diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 621c7a5e7eb..d6e0debee14 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1694,7 +1694,9 @@ void StmtPrinter::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { Node->getType().print(OS, Policy); - if (Node->isListInitialization()) + if (Node->isStdInitListInitialization()) + /* Nothing to do; braces are part of creating the std::initializer_list. */; + else if (Node->isListInitialization()) OS << "{"; else OS << "("; @@ -1707,7 +1709,9 @@ void StmtPrinter::VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *Node) { OS << ", "; PrintExpr(*Arg); } - if (Node->isListInitialization()) + if (Node->isStdInitListInitialization()) + /* See above. */; + else if (Node->isListInitialization()) OS << "}"; else OS << ")"; @@ -1876,7 +1880,7 @@ void StmtPrinter::VisitCXXPseudoDestructorExpr(CXXPseudoDestructorExpr *E) { } void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { - if (E->isListInitialization()) + if (E->isListInitialization() && !E->isStdInitListInitialization()) OS << "{"; for (unsigned i = 0, e = E->getNumArgs(); i != e; ++i) { @@ -1889,7 +1893,7 @@ void StmtPrinter::VisitCXXConstructExpr(CXXConstructExpr *E) { PrintExpr(E->getArg(i)); } - if (E->isListInitialization()) + if (E->isListInitialization() && !E->isStdInitListInitialization()) OS << "}"; } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 1068b3e7e13..bb0a9c11474 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -3174,16 +3174,19 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc, /// \brief Attempt initialization by constructor (C++ [dcl.init]), which /// enumerates the constructors of the initialized entity and performs overload /// resolution to select the best. -/// If InitListSyntax is true, this is list-initialization of a non-aggregate -/// class type. +/// \param InitListSyntax Is this list-initialization? +/// \param IsInitListCopy Is this non-list-initialization resulting from a +/// list-initialization from {x} where x is the same +/// type as the entity? static void TryConstructorInitialization(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType DestType, InitializationSequence &Sequence, - bool InitListSyntax = false) { - assert((!InitListSyntax || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) && - "InitListSyntax must come with a single initializer list argument."); + bool IsListInit = false, + bool IsInitListCopy = false) { + assert((!IsListInit || (Args.size() == 1 && isa<InitListExpr>(Args[0]))) && + "IsListInit must come with a single initializer list argument."); // The type we're constructing needs to be complete. if (S.RequireCompleteType(Kind.getLocation(), DestType, 0)) { @@ -3202,7 +3205,7 @@ static void TryConstructorInitialization(Sema &S, // Determine whether we are allowed to call explicit constructors or // explicit conversion operators. - bool AllowExplicit = Kind.AllowExplicit() || InitListSyntax; + bool AllowExplicit = Kind.AllowExplicit() || IsListInit; bool CopyInitialization = Kind.getKind() == InitializationKind::IK_Copy; // - Otherwise, if T is a class type, constructors are considered. The @@ -3227,7 +3230,7 @@ static void TryConstructorInitialization(Sema &S, // - Initially, the candidate functions are the initializer-list // constructors of the class T and the argument list consists of the // initializer list as a single argument. - if (InitListSyntax) { + if (IsListInit) { InitListExpr *ILE = cast<InitListExpr>(Args[0]); AsInitializerList = true; @@ -3256,7 +3259,7 @@ static void TryConstructorInitialization(Sema &S, /*OnlyListConstructors=*/false); } if (Result) { - Sequence.SetOverloadFailure(InitListSyntax ? + Sequence.SetOverloadFailure(IsListInit ? InitializationSequence::FK_ListConstructorOverloadFailed : InitializationSequence::FK_ConstructorOverloadFailed, Result); @@ -3278,7 +3281,7 @@ static void TryConstructorInitialization(Sema &S, // In copy-list-initialization, if an explicit constructor is chosen, the // initializer is ill-formed. CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); - if (InitListSyntax && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { + if (IsListInit && !Kind.AllowExplicit() && CtorDecl->isExplicit()) { Sequence.SetFailed(InitializationSequence::FK_ExplicitConstructor); return; } @@ -3286,10 +3289,9 @@ static void TryConstructorInitialization(Sema &S, // Add the constructor initialization step. Any cv-qualification conversion is // subsumed by the initialization. bool HadMultipleCandidates = (CandidateSet.size() > 1); - Sequence.AddConstructorInitializationStep(CtorDecl, - Best->FoundDecl.getAccess(), - DestType, HadMultipleCandidates, - InitListSyntax, AsInitializerList); + Sequence.AddConstructorInitializationStep( + CtorDecl, Best->FoundDecl.getAccess(), DestType, HadMultipleCandidates, + IsListInit | IsInitListCopy, AsInitializerList); } static bool @@ -3445,9 +3447,10 @@ static void TryListInitialization(Sema &S, QualType InitType = InitList->getInit(0)->getType(); if (S.Context.hasSameUnqualifiedType(InitType, DestType) || S.IsDerivedFrom(InitType, DestType)) { - Expr *InitListAsExpr = InitList; - TryConstructorInitialization(S, Entity, Kind, InitListAsExpr, DestType, - Sequence, /*InitListSyntax*/true); + Expr *InitAsExpr = InitList->getInit(0); + TryConstructorInitialization(S, Entity, Kind, InitAsExpr, DestType, + Sequence, /*InitListSyntax*/ false, + /*IsInitListCopy*/ true); return; } } |