summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2015-02-05 07:02:11 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2015-02-05 07:02:11 +0000
commited83ebd77e12e561d435574fbe093a220f270e4e (patch)
treee3650f69e384d49e014b196a97e44923ccd09407 /clang/lib
parent6956e2e68338f62bd19d54b82f0791a8f626c84d (diff)
downloadbcm5719-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.cpp16
-rw-r--r--clang/lib/AST/StmtPrinter.cpp12
-rw-r--r--clang/lib/Sema/SemaInit.cpp35
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;
}
}
OpenPOWER on IntegriCloud