diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2012-02-11 23:51:47 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2012-02-11 23:51:47 +0000 |
commit | 5b9cc5df25c2198f270dd1d5c438fdce70d4051d (patch) | |
tree | 8d2c36bd9fe0e47cc5ce4e5a2fd02d8dd0e31f7f /lib | |
parent | ecfcd5655758955d8958dc2a7a7b2c8eff2395b7 (diff) |
Represent C++ direct initializers as ParenListExprs before semantic analysis
instead of having a special-purpose function.
- ActOnCXXDirectInitializer, which was mostly duplication of
AddInitializerToDecl (leading e.g. to PR10620, which Eli fixed a few days
ago), is dropped completely.
- MultiInitializer, which was an ugly hack I added, is dropped again.
- We now have the infrastructure in place to distinguish between
int x = {1};
int x({1});
int x{1};
-- VarDecl now has getInitStyle(), which indicates which of the above was used.
-- CXXConstructExpr now has a flag to indicate that it represents list-
initialization, although this is not yet used.
- InstantiateInitializer was renamed to SubstInitializer and simplified.
- ActOnParenOrParenListExpr has been replaced by ActOnParenListExpr, which
always produces a ParenListExpr. Placed that so far failed to convert that
back to a ParenExpr containing comma operators have been fixed. I'm pretty
sure I could have made a crashing test case before this.
The end result is a (I hope) considerably cleaner design of initializers.
More importantly, the fact that I can now distinguish between the various
initialization kinds means that I can get the tricky generalized initializer
test cases Johannes Schaub supplied to work. (This is not yet done.)
This commit passed self-host, with the resulting compiler passing the tests. I
hope it doesn't break more complicated code. It's a pretty big change, but one
that I feel is necessary.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150318 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 22 | ||||
-rw-r--r-- | lib/AST/DumpXML.cpp | 8 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 5 | ||||
-rw-r--r-- | lib/AST/ExprCXX.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 9 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Sema/MultiInitializer.cpp | 93 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 122 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 345 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 170 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 7 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 6 |
18 files changed, 310 insertions, 540 deletions
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 5a6686d164..32bdba1a0b 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -621,16 +621,20 @@ void DeclPrinter::VisitVarDecl(VarDecl *D) { Out << Name; Expr *Init = D->getInit(); if (!Policy.SuppressInitializers && Init) { - if (D->hasCXXDirectInitializer()) - Out << "("; - else { - CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init); - if (!CCE || CCE->getConstructor()->isCopyOrMoveConstructor()) - Out << " = "; + bool ImplicitInit = false; + if (CXXConstructExpr *Construct = dyn_cast<CXXConstructExpr>(Init)) + ImplicitInit = D->getInitStyle() == VarDecl::CallInit && + Construct->getNumArgs() == 0 && !Construct->isListInitialization(); + if (!ImplicitInit) { + if (D->getInitStyle() == VarDecl::CallInit) + Out << "("; + else if (D->getInitStyle() == VarDecl::CInit) { + Out << " = "; + } + Init->printPretty(Out, Context, 0, Policy, Indentation); + if (D->getInitStyle() == VarDecl::CallInit) + Out << ")"; } - Init->printPretty(Out, Context, 0, Policy, Indentation); - if (D->hasCXXDirectInitializer()) - Out << ")"; } prettyPrintAttributes(D); } diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp index dcbc5180a0..b4038ddaf9 100644 --- a/lib/AST/DumpXML.cpp +++ b/lib/AST/DumpXML.cpp @@ -461,7 +461,13 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>, if (D->getStorageClass() != SC_None) set("storage", VarDecl::getStorageClassSpecifierString(D->getStorageClass())); - setFlag("directinit", D->hasCXXDirectInitializer()); + StringRef initStyle = ""; + switch (D->getInitStyle()) { + case VarDecl::CInit: initStyle = "c"; break; + case VarDecl::CallInit: initStyle = "call"; break; + case VarDecl::ListInit: initStyle = "list"; break; + } + set("initstyle", initStyle); setFlag("nrvo", D->isNRVOVariable()); // TODO: instantiation, etc. } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 398e27ea97..5d22d144f4 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -3414,11 +3414,10 @@ void DesignatedInitExpr::ExpandDesignator(ASTContext &C, unsigned Idx, ParenListExpr::ParenListExpr(ASTContext& C, SourceLocation lparenloc, Expr **exprs, unsigned nexprs, - SourceLocation rparenloc, QualType T) - : Expr(ParenListExprClass, T, VK_RValue, OK_Ordinary, + SourceLocation rparenloc) + : Expr(ParenListExprClass, QualType(), VK_RValue, OK_Ordinary, false, false, false, false), NumExprs(nexprs), LParenLoc(lparenloc), RParenLoc(rparenloc) { - assert(!T.isNull() && "ParenListExpr must have a valid type"); Exprs = new (C) Stmt*[nexprs]; for (unsigned i = 0; i != nexprs; ++i) { if (exprs[i]->isTypeDependent()) diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 51dd57cfe3..a38488b877 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -653,7 +653,7 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(ASTContext &C, Type->getType().getNonReferenceType(), Type->getTypeLoc().getBeginLoc(), Cons, false, Args, NumArgs, - HadMultipleCandidates, ZeroInitialization, + HadMultipleCandidates, /*FIXME*/false, ZeroInitialization, CXXConstructExpr::CK_Complete, parenRange), Type(Type) { } @@ -668,13 +668,15 @@ CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T, CXXConstructorDecl *D, bool Elidable, Expr **Args, unsigned NumArgs, bool HadMultipleCandidates, + bool ListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenRange) { return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D, Elidable, Args, NumArgs, - HadMultipleCandidates, ZeroInitialization, - ConstructKind, ParenRange); + HadMultipleCandidates, ListInitialization, + ZeroInitialization, ConstructKind, + ParenRange); } CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, @@ -682,6 +684,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, CXXConstructorDecl *D, bool elidable, Expr **args, unsigned numargs, bool HadMultipleCandidates, + bool ListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, SourceRange ParenRange) @@ -691,6 +694,7 @@ CXXConstructExpr::CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, T->containsUnexpandedParameterPack()), Constructor(D), Loc(Loc), ParenRange(ParenRange), NumArgs(numargs), Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates), + ListInitialization(ListInitialization), ZeroInitialization(ZeroInitialization), ConstructKind(ConstructKind), Args(0) { diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index dc68605555..94bad92180 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -2740,7 +2740,8 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction( CXXConstExpr->getConstructor(), CXXConstExpr->isElidable(), &ConstructorArgs[0], ConstructorArgs.size(), - CXXConstExpr->hadMultipleCandidates(), + CXXConstExpr->hadMultipleCandidates(), + CXXConstExpr->isListInitialization(), CXXConstExpr->requiresZeroInitialization(), CXXConstExpr->getConstructionKind(), SourceRange()); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 0c8a647f65..914a5acd09 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1344,10 +1344,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, ExitScope(); } - Actions.AddCXXDirectInitializerToDecl(ThisDecl, T.getOpenLocation(), - move_arg(Exprs), - T.getCloseLocation(), - TypeContainsAuto); + ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(), + T.getCloseLocation(), + move_arg(Exprs)); + Actions.AddInitializerToDecl(ThisDecl, Initializer.take(), + /*DirectInit=*/true, TypeContainsAuto); } } else if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { // Parse C++0x braced-init-list. diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 3660b01816..b5e4a5f620 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -2006,8 +2006,8 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, if (!ParseExpressionList(ArgExprs, CommaLocs)) { ExprType = SimpleExpr; - Result = Actions.ActOnParenOrParenListExpr(OpenLoc, Tok.getLocation(), - move_arg(ArgExprs)); + Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(), + move_arg(ArgExprs)); } } else { InMessageExpressionRAIIObject InMessage(*this, false); diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index dece5bd998..c576d765b2 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -8,7 +8,6 @@ add_clang_library(clangSema DelayedDiagnostic.cpp IdentifierResolver.cpp JumpDiagnostics.cpp - MultiInitializer.cpp Scope.cpp Sema.cpp SemaAccess.cpp diff --git a/lib/Sema/MultiInitializer.cpp b/lib/Sema/MultiInitializer.cpp deleted file mode 100644 index d8944efba3..0000000000 --- a/lib/Sema/MultiInitializer.cpp +++ /dev/null @@ -1,93 +0,0 @@ -//===--- MultiInitializer.cpp - Initializer expression group ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the MultiInitializer class, which can represent a list -// initializer or a parentheses-wrapped group of expressions in a C++ member -// initializer. -// -//===----------------------------------------------------------------------===// - -#include "clang/Sema/MultiInitializer.h" -#include "clang/Sema/Initialization.h" -#include "clang/Sema/Sema.h" -#include "clang/AST/Expr.h" - -using namespace clang; - -InitListExpr *MultiInitializer::getInitList() const { - return cast<InitListExpr>(InitListOrExpressions.get<Expr*>()); -} - -SourceLocation MultiInitializer::getStartLoc() const { - return isInitializerList() ? getInitList()->getLBraceLoc() : LParenLoc; -} - -SourceLocation MultiInitializer::getEndLoc() const { - return isInitializerList() ? getInitList()->getRBraceLoc() : RParenLoc; -} - -MultiInitializer::iterator MultiInitializer::begin() const { - return isInitializerList() ? getInitList()->getInits() : getExpressions(); -} - -MultiInitializer::iterator MultiInitializer::end() const { - if (isInitializerList()) { - InitListExpr *ILE = getInitList(); - return ILE->getInits() + ILE->getNumInits(); - } - return getExpressions() + NumInitializers; -} - -bool MultiInitializer::isTypeDependent() const { - if (isInitializerList()) - return getInitList()->isTypeDependent(); - for (iterator I = begin(), E = end(); I != E; ++I) { - if ((*I)->isTypeDependent()) - return true; - } - return false; -} - -bool MultiInitializer::DiagnoseUnexpandedParameterPack(Sema &SemaRef) const { - if (isInitializerList()) - return SemaRef.DiagnoseUnexpandedParameterPack(getInitList(), - Sema::UPPC_Initializer); - for (iterator I = begin(), E = end(); I != E; ++I) { - if (SemaRef.DiagnoseUnexpandedParameterPack(*I, Sema::UPPC_Initializer)) - return true; - } - return false; -} - -Expr *MultiInitializer::CreateInitExpr(ASTContext &Ctx, QualType T) const { - if (isInitializerList()) - return InitListOrExpressions.get<Expr*>(); - - return new (Ctx) ParenListExpr(Ctx, LParenLoc, getExpressions(), - NumInitializers, RParenLoc, T); -} - -ExprResult MultiInitializer::PerformInit(Sema &SemaRef, - InitializedEntity Entity, - InitializationKind Kind) const { - Expr *Single; - Expr **Args; - unsigned NumArgs; - if (isInitializerList()) { - Single = InitListOrExpressions.get<Expr*>(); - Args = &Single; - NumArgs = 1; - } else { - Args = getExpressions(); - NumArgs = NumInitializers; - } - InitializationSequence InitSeq(SemaRef, Entity, Kind, Args, NumArgs); - return InitSeq.Perform(SemaRef, Entity, Kind, - MultiExprArg(SemaRef, Args, NumArgs), 0); -} diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 6ba3228b08..feffaf13fa 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2139,9 +2139,8 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, /// emitting diagnostics as appropriate. /// /// Declarations using the auto type specifier (C++ [decl.spec.auto]) call back -/// to here in AddInitializerToDecl and AddCXXDirectInitializerToDecl. We can't -/// check them before the initializer is attached. -/// +/// to here in AddInitializerToDecl. We can't check them before the initializer +/// is attached. void Sema::MergeVarDeclTypes(VarDecl *New, VarDecl *Old) { if (New->isInvalidDecl() || Old->isInvalidDecl()) return; @@ -5983,17 +5982,6 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (RealDecl == 0 || RealDecl->isInvalidDecl()) return; - // Check for self-references within variable initializers. - if (VarDecl *vd = dyn_cast<VarDecl>(RealDecl)) { - // Variables declared within a function/method body are handled - // by a dataflow analysis. - if (!vd->hasLocalStorage() && !vd->isStaticLocal()) - CheckSelfReference(RealDecl, Init); - } - else { - CheckSelfReference(RealDecl, Init); - } - if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(RealDecl)) { // With declarators parsed the way they are, the parser cannot // distinguish between a normal initializer and a pure-specifier. @@ -6018,12 +6006,44 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } + // Check for self-references within variable initializers. + // Variables declared within a function/method body are handled + // by a dataflow analysis. + if (!VDecl->hasLocalStorage() && !VDecl->isStaticLocal()) + CheckSelfReference(RealDecl, Init); + + ParenListExpr *CXXDirectInit = dyn_cast<ParenListExpr>(Init); + // C++11 [decl.spec.auto]p6. Deduce the type which 'auto' stands in for. if (TypeMayContainAuto && VDecl->getType()->getContainedAutoType()) { + Expr *DeduceInit = Init; + // Initializer could be a C++ direct-initializer. Deduction only works if it + // contains exactly one expression. + if (CXXDirectInit) { + if (CXXDirectInit->getNumExprs() == 0) { + // It isn't possible to write this directly, but it is possible to + // end up in this situation with "auto x(some_pack...);" + Diag(CXXDirectInit->getSourceRange().getBegin(), + diag::err_auto_var_init_no_expression) + << VDecl->getDeclName() << VDecl->getType() + << VDecl->getSourceRange(); + RealDecl->setInvalidDecl(); + return; + } else if (CXXDirectInit->getNumExprs() > 1) { + Diag(CXXDirectInit->getExpr(1)->getSourceRange().getBegin(), + diag::err_auto_var_init_multiple_expressions) + << VDecl->getDeclName() << VDecl->getType() + << VDecl->getSourceRange(); + RealDecl->setInvalidDecl(); + return; + } else { + DeduceInit = CXXDirectInit->getExpr(0); + } + } TypeSourceInfo *DeducedType = 0; - if (DeduceAutoType(VDecl->getTypeSourceInfo(), Init, DeducedType) == + if (DeduceAutoType(VDecl->getTypeSourceInfo(), DeduceInit, DeducedType) == DAR_Failed) - DiagnoseAutoDeductionFailure(VDecl, Init); + DiagnoseAutoDeductionFailure(VDecl, DeduceInit); if (!DeducedType) { RealDecl->setInvalidDecl(); return; @@ -6048,25 +6068,26 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, return; } + if (!VDecl->getType()->isDependentType()) { + // A definition must end up with a complete type, which means it must be + // complete with the restriction that an array type might be completed by + // the initializer; note that later code assumes this restriction. + QualType BaseDeclType = VDecl->getType(); + if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType)) + BaseDeclType = Array->getElementType(); + if (RequireCompleteType(VDecl->getLocation(), BaseDeclType, + diag::err_typecheck_decl_incomplete_type)) { + RealDecl->setInvalidDecl(); + return; + } - // A definition must end up with a complete type, which means it must be - // complete with the restriction that an array type might be completed by the - // initializer; note that later code assumes this restriction. - QualType BaseDeclType = VDecl->getType(); - if (const ArrayType *Array = Context.getAsIncompleteArrayType(BaseDeclType)) - BaseDeclType = Array->getElementType(); - if (RequireCompleteType(VDecl->getLocation(), BaseDeclType, - diag::err_typecheck_decl_incomplete_type)) { - RealDecl->setInvalidDecl(); - return; + // The variable can not have an abstract class type. + if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), + diag::err_abstract_type_in_decl, + AbstractVariableType)) + VDecl->setInvalidDecl(); } - // The variable can not have an abstract class type. - if (RequireNonAbstractType(VDecl->getLocation(), VDecl->getType(), - diag::err_abstract_type_in_decl, - AbstractVariableType)) - VDecl->setInvalidDecl(); - const VarDecl *Def; if ((Def = VDecl->getDefinition()) && Def != VDecl) { Diag(VDecl->getLocation(), diag::err_redefinition) @@ -6128,9 +6149,15 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, : InitializationKind::CreateCopy(VDecl->getLocation(), Init->getLocStart()); - InitializationSequence InitSeq(*this, Entity, Kind, &Init, 1); + Expr **Args = &Init; + unsigned NumArgs = 1; + if (CXXDirectInit) { + Args = CXXDirectInit->getExprs(); + NumArgs = CXXDirectInit->getNumExprs(); + } + InitializationSequence InitSeq(*this, Entity, Kind, Args, NumArgs); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, - MultiExprArg(*this, &Init, 1), + MultiExprArg(*this, Args,NumArgs), &DclT); if (Result.isInvalid()) { VDecl->setInvalidDecl(); @@ -6266,6 +6293,28 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, CheckForConstantInitializer(Init, DclT); } + // We will represent direct-initialization similarly to copy-initialization: + // int x(1); -as-> int x = 1; + // ClassType x(a,b,c); -as-> ClassType x = ClassType(a,b,c); + // + // Clients that want to distinguish between the two forms, can check for + // direct initializer using VarDecl::getInitStyle(). + // A major benefit is that clients that don't particularly care about which + // exactly form was it (like the CodeGen) can handle both cases without + // special case code. + + // C++ 8.5p11: + // The form of initialization (using parentheses or '=') is generally + // insignificant, but does matter when the entity being initialized has a + // class type. + if (CXXDirectInit) { + assert(DirectInit && "Call-style initializer must be direct init."); + VDecl->setInitStyle(VarDecl::CallInit); + } else if (DirectInit) { + // This must be list-initialization. No other way is direct-initialization. + VDecl->setInitStyle(VarDecl::ListInit); + } + CheckCompleteVariableDeclaration(VDecl); } @@ -6496,8 +6545,11 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl, MultiExprArg(*this, 0, 0)); if (Init.isInvalid()) Var->setInvalidDecl(); - else if (Init.get()) + else if (Init.get()) { Var->setInit(MaybeCreateExprWithCleanups(Init.get())); + // This is important for template substitution. + Var->setInitStyle(VarDecl::CallInit); + } CheckCompleteVariableDeclaration(Var); } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index a6d7d63b3a..72a8de2b71 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1768,7 +1768,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, Expr *InitList, SourceLocation EllipsisLoc) { return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, - DS, IdLoc, MultiInitializer(InitList), + DS, IdLoc, InitList, EllipsisLoc); } @@ -1785,10 +1785,10 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { + Expr *List = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, + RParenLoc); return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, - DS, IdLoc, MultiInitializer(LParenLoc, Args, - NumArgs, RParenLoc), - EllipsisLoc); + DS, IdLoc, List, EllipsisLoc); } namespace { @@ -1825,7 +1825,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, ParsedType TemplateTypeTy, const DeclSpec &DS, SourceLocation IdLoc, - const MultiInitializer &Args, + Expr *Init, SourceLocation EllipsisLoc) { if (!ConstructorD) return true; @@ -1864,9 +1864,10 @@ Sema::BuildMemInitializer(Decl *ConstructorD, (Member = dyn_cast<IndirectFieldDecl>(*Result.first))) { if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_pack_expansion_member_init) - << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); + << MemberOrBase + << SourceRange(IdLoc, Init->getSourceRange().getEnd()); - return BuildMemberInitializer(Member, Args, IdLoc); + return BuildMemberInitializer(Member, Init, IdLoc); } } } @@ -1927,7 +1928,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, Diag(Member->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr; - return BuildMemberInitializer(Member, Args, IdLoc); + return BuildMemberInitializer(Member, Init, IdLoc); } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) { const CXXBaseSpecifier *DirectBaseSpec; const CXXBaseSpecifier *VirtualBaseSpec; @@ -1955,7 +1956,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (!TyD && BaseType.isNull()) { Diag(IdLoc, diag::err_mem_init_not_member_or_class) - << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); + << MemberOrBase << SourceRange(IdLoc,Init->getSourceRange().getEnd()); return true; } } @@ -1975,7 +1976,7 @@ Sema::BuildMemInitializer(Decl *ConstructorD, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); - return BuildBaseInitializer(BaseType, TInfo, Args, ClassDecl, EllipsisLoc); + return BuildBaseInitializer(BaseType, TInfo, Init, ClassDecl, EllipsisLoc); } /// Checks a member initializer expression for cases where reference (or @@ -2102,15 +2103,14 @@ static bool InitExprContainsUninitializedFields(const Stmt *S, } MemInitResult -Sema::BuildMemberInitializer(ValueDecl *Member, - const MultiInitializer &Args, +Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, SourceLocation IdLoc) { FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member); IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member); assert((DirectMember || IndirectMember) && "Member must be a FieldDecl or IndirectFieldDecl"); - if (Args.DiagnoseUnexpandedParameterPack(*this)) + if (DiagnoseUnexpandedParameterPack(Init, UPPC_Initializer)) return true; if (Member->isInvalidDecl()) @@ -2120,13 +2120,19 @@ Sema::BuildMemberInitializer(ValueDecl *Member, // foo(foo) // where foo is not also a parameter to the constructor. // TODO: implement -Wuninitialized and fold this into that framework. - for (MultiInitializer::iterator I = Args.begin(), E = Args.end(); - I != E; ++I) { + Expr **Args; + unsigned NumArgs; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } else { + InitListExpr *InitList = cast<InitListExpr>(Init); + Args = InitList->getInits(); + NumArgs = InitList->getNumInits(); + } + for (unsigned i = 0; i < NumArgs; ++i) { SourceLocation L; - Expr *Arg = *I; - if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Arg)) - Arg = DIE->getInit(); - if (InitExprContainsUninitializedFields(Arg, Member, &L)) { + if (InitExprContainsUninitializedFields(Args[i], Member, &L)) { // FIXME: Return true in the case when other fields are used before being // uninitialized. For example, let this field be the i'th field. When // initializing the i'th field, throw a warning if any of the >= i'th @@ -2137,14 +2143,11 @@ Sema::BuildMemberInitializer(ValueDecl *Member, } } - bool HasDependentArg = Args.isTypeDependent(); + SourceRange InitRange = Init->getSourceRange(); - Expr *Init; - if (Member->getType()->isDependentType() || HasDependentArg) { + if (Member->getType()->isDependentType() || Init->isTypeDependent()) { // Can't check initialization for a member of dependent type or when // any of the arguments are type-dependent expressions. - Init = Args.CreateInitExpr(Context,Member->getType().getNonReferenceType()); - DiscardCleanupsInEvaluationContext(); } else { // Initialize the member. @@ -2152,14 +2155,22 @@ Sema::BuildMemberInitializer(ValueDecl *Member, DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0) : InitializedEntity::InitializeMember(IndirectMember, 0); InitializationKind Kind = - InitializationKind::CreateDirect(IdLoc, Args.getStartLoc(), - Args.getEndLoc()); + InitializationKind::CreateDirect(IdLoc, InitRange.getBegin(), + InitRange.getEnd()); - ExprResult MemberInit = Args.PerformInit(*this, MemberEntity, Kind); + if (isa<InitListExpr>(Init)) { + Args = &Init; + NumArgs = 1; + } + InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); + ExprResult MemberInit = InitSeq.Perform(*this, MemberEntity, Kind, + MultiExprArg(*this, Args, NumArgs), + 0); if (MemberInit.isInvalid()) return true; - CheckImplicitConversions(MemberInit.get(), Args.getStartLoc()); + CheckImplicitConversions(MemberInit.get(), + InitRange.getBegin()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -2170,14 +2181,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, // If we are in a dependent context, template instantiation will // perform this type-checking again. Just save the arguments that we - // received in a ParenListExpr. + // received. // FIXME: This isn't quite ideal, since our ASTs don't capture all // of the information that we have about the member // initializer. However, deconstructing the ASTs is a dicey process, // and this approach is far more likely to get the corner cases right. if (CurContext->isDependentContext()) { - Init = Args.CreateInitExpr(Context, - Member->getType().getNonReferenceType()); + // The existing Init will do fine. } else { Init = MemberInit.get(); CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); @@ -2185,19 +2195,18 @@ Sema::BuildMemberInitializer(ValueDecl *Member, } if (DirectMember) { - return new (Context) CXXCtorInitializer(Context, DirectMember, - IdLoc, Args.getStartLoc(), - Init, Args.getEndLoc()); + return new (Context) CXXCtorInitializer(Context, DirectMember, IdLoc, + InitRange.getBegin(), Init, + InitRange.getEnd()); } else { - return new (Context) CXXCtorInitializer(Context, IndirectMember, - IdLoc, Args.getStartLoc(), - Init, Args.getEndLoc()); + return new (Context) CXXCtorInitializer(Context, IndirectMember, IdLoc, + InitRange.getBegin(), Init, + InitRange.getEnd()); } } MemInitResult -Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, - const MultiInitializer &Args, +Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr *Init, CXXRecordDecl *ClassDecl) { SourceLocation NameLoc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus0x) @@ -2205,21 +2214,31 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, << TInfo->getTypeLoc().getLocalSourceRange(); Diag(NameLoc, diag::warn_cxx98_compat_delegating_ctor); + SourceRange InitRange = Init->getSourceRange(); // Initialize the object. InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( QualType(ClassDecl->getTypeForDecl(), 0)); InitializationKind Kind = - InitializationKind::CreateDirect(NameLoc, Args.getStartLoc(), - Args.getEndLoc()); - - ExprResult DelegationInit = Args.PerformInit(*this, DelegationEntity, Kind); + InitializationKind::CreateDirect(NameLoc, InitRange.getBegin(), + InitRange.getEnd()); + + Expr **Args = &Init; + unsigned NumArgs = 1; + if (ParenListExpr *ParenList = dyn_cast<ParenListExpr>(Init)) { + Args = ParenList->getExprs(); + NumArgs = ParenList->getNumExprs(); + } + InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + ExprResult DelegationInit = InitSeq.Perform(*this, DelegationEntity, Kind, + MultiExprArg(*this, Args,NumArgs), + 0); if (DelegationInit.isInvalid()) return true; assert(cast<CXXConstructExpr>(DelegationInit.get())->getConstructor() && "Delegating constructor with no target?"); - CheckImplicitConversions(DelegationInit.get(), Args.getStartLoc()); + CheckImplicitConversions(DelegationInit.get(), InitRange.getBegin()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -2228,18 +2247,15 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, if (DelegationInit.isInvalid()) |