diff options
-rw-r--r-- | include/clang/Parse/Parser.h | 1 | ||||
-rw-r--r-- | include/clang/Sema/MultiInitializer.h | 72 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 34 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 52 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 14 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/MultiInitializer.cpp | 92 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 200 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 54 | ||||
-rw-r--r-- | test/SemaCXX/cxx0x-initializer-scalars.cpp | 34 | ||||
-rw-r--r-- | test/SemaCXX/generalized-initializers.cpp | 21 |
11 files changed, 410 insertions, 166 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index ee2dbd5519..2234920597 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -1060,6 +1060,7 @@ private: void ParseLexedMemberInitializers(ParsingClass &Class); void ParseLexedMemberInitializer(LateParsedMemberInitializer &MI); Decl *ParseLexedObjCMethodDefs(LexedMethod &LM); + bool ConsumeAndStoreTryAndInitializers(CachedTokens &Toks); bool ConsumeAndStoreUntil(tok::TokenKind T1, CachedTokens &Toks, bool StopAtSemi = true, diff --git a/include/clang/Sema/MultiInitializer.h b/include/clang/Sema/MultiInitializer.h new file mode 100644 index 0000000000..c44e3934db --- /dev/null +++ b/include/clang/Sema/MultiInitializer.h @@ -0,0 +1,72 @@ +//===--- MultiInitializer.h - 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 defines the MultiInitializer class, which can represent a list +// initializer or a parentheses-wrapped group of expressions in a C++ member +// initializer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_MULTIINITIALIZER_H +#define LLVM_CLANG_SEMA_MULTIINITIALIZER_H + +#include "clang/Sema/Ownership.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/PointerUnion.h" + +namespace clang { + class ASTContext; + class Expr; + class InitializationKind; + class InitializedEntity; + class InitListExpr; + class Sema; + +class MultiInitializer { + llvm::PointerUnion<Expr*, Expr**> InitListOrExpressions; + unsigned NumInitializers; + SourceLocation LParenLoc; + SourceLocation RParenLoc; + + InitListExpr *getInitList() const; + Expr **getExpressions() const { return InitListOrExpressions.get<Expr**>(); } + +public: + MultiInitializer(Expr* InitList) + : InitListOrExpressions(InitList) + {} + + MultiInitializer(SourceLocation LParenLoc, Expr **Exprs, unsigned NumInits, + SourceLocation RParenLoc) + : InitListOrExpressions(Exprs), NumInitializers(NumInits), + LParenLoc(LParenLoc), RParenLoc(RParenLoc) + {} + + bool isInitializerList() const { return InitListOrExpressions.is<Expr*>(); } + + SourceLocation getStartLoc() const; + SourceLocation getEndLoc() const; + + typedef Expr **iterator; + iterator begin() const; + iterator end() const; + + bool isTypeDependent() const; + + bool DiagnoseUnexpandedParameterPack(Sema &SemaRef) const; + + // Return the InitListExpr or create a ParenListExpr. + Expr *CreateInitExpr(ASTContext &Ctx, QualType T) const; + + ExprResult PerformInit(Sema &SemaRef, InitializedEntity Entity, + InitializationKind Kind) const; +}; +} + +#endif diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a7a0c2f7ae..e52d2fefbc 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -22,6 +22,7 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/LocInfoType.h" +#include "clang/Sema/MultiInitializer.h" #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.h" #include "clang/AST/Expr.h" @@ -3398,24 +3399,37 @@ public: SourceLocation RParenLoc, SourceLocation EllipsisLoc); - MemInitResult BuildMemberInitializer(ValueDecl *Member, Expr **Args, - unsigned NumArgs, SourceLocation IdLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc); + MemInitResult ActOnMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + SourceLocation IdLoc, + Expr *InitList, + SourceLocation EllipsisLoc); + + MemInitResult BuildMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + SourceLocation IdLoc, + const MultiInitializer &Init, + SourceLocation EllipsisLoc); + + MemInitResult BuildMemberInitializer(ValueDecl *Member, + const MultiInitializer &Args, + SourceLocation IdLoc); MemInitResult BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, - Expr **Args, unsigned NumArgs, - SourceLocation LParenLoc, - SourceLocation RParenLoc, + const MultiInitializer &Args, CXXRecordDecl *ClassDecl, SourceLocation EllipsisLoc); MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, - Expr **Args, unsigned NumArgs, + const MultiInitializer &Args, SourceLocation BaseLoc, - SourceLocation RParenLoc, - SourceLocation LParenLoc, CXXRecordDecl *ClassDecl); bool SetDelegatingInitializer(CXXConstructorDecl *Constructor, diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 1b364537cc..0ca249fd1a 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -125,8 +125,9 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D, tok::TokenKind kind = Tok.getKind(); // We may have a constructor initializer or function-try-block here. if (kind == tok::colon || kind == tok::kw_try) { - // Consume everything up to (and including) the left brace. - if (!ConsumeAndStoreUntil(tok::l_brace, Toks)) { + // Consume everything up to (and including) the left brace of the + // function body. + if (ConsumeAndStoreTryAndInitializers(Toks)) { // We didn't find the left-brace we expected after the // constructor initializer. if (Tok.is(tok::semi)) { @@ -579,3 +580,50 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, isFirstTokenConsumed = false; } } + +/// \brief Consume tokens and store them in the passed token container until +/// we've passed the try keyword and constructor initializers and have consumed +/// the opening brace of the function body. +/// +/// \return True on error. +bool Parser::ConsumeAndStoreTryAndInitializers(CachedTokens &Toks) { + if (Tok.is(tok::kw_try)) { + Toks.push_back(Tok); + ConsumeToken(); + } + if (Tok.is(tok::colon)) { + // Initializers can contain braces too. + Toks.push_back(Tok); + ConsumeToken(); + + while (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) { + if (Tok.is(tok::eof) || Tok.is(tok::semi)) + return true; + + // Grab the identifier. + if (!ConsumeAndStoreUntil(tok::l_paren, tok::l_brace, Toks, + /*StopAtSemi=*/true, + /*ConsumeFinalToken=*/false)) + return true; + + tok::TokenKind kind = Tok.getKind(); + Toks.push_back(Tok); + if (kind == tok::l_paren) + ConsumeParen(); + else { + assert(kind == tok::l_brace && "Must be left paren or brace here."); + ConsumeBrace(); + } + + // Grab the initializer + if (!ConsumeAndStoreUntil(kind == tok::l_paren ? tok::r_paren : + tok::r_brace, + Toks, /*StopAtSemi=*/true)) + return true; + } + } + + // Grab any remaining garbage to be diagnosed later, and the opening + // brace of the function body. + return !ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/true); +} diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 0fcc863b12..21cf3a1e1c 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -2292,9 +2292,17 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // Parse the '('. if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { - // FIXME: Do something with the braced-init-list. - ParseBraceInitializer(); - return true; + ExprResult InitList = ParseBraceInitializer(); + if (InitList.isInvalid()) + return true; + + SourceLocation EllipsisLoc; + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); + + return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, + TemplateTypeTy, IdLoc, InitList.take(), + EllipsisLoc); } else if(Tok.is(tok::l_paren)) { SourceLocation LParenLoc = ConsumeParen(); diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 5cc604bde1..5ffd535337 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -1252,7 +1252,7 @@ void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) { tok::TokenKind kind = Tok.getKind(); // We may have a constructor initializer or function-try-block here. if (kind == tok::colon || kind == tok::kw_try) - ConsumeAndStoreUntil(tok::l_brace, Toks); + ConsumeAndStoreTryAndInitializers(Toks); else { Toks.push_back(Tok); ConsumeBrace(); diff --git a/lib/Sema/MultiInitializer.cpp b/lib/Sema/MultiInitializer.cpp new file mode 100644 index 0000000000..8bd2213b57 --- /dev/null +++ b/lib/Sema/MultiInitializer.cpp @@ -0,0 +1,92 @@ +//===--- 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()); + for (iterator I = begin(), E = end(); I != E; ++I) { + if (SemaRef.DiagnoseUnexpandedParameterPack(*I)) + 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/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 23b128db59..72c74084b2 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1342,7 +1342,21 @@ static bool FindBaseInitializer(Sema &SemaRef, return DirectBaseSpec || VirtualBaseSpec; } -/// ActOnMemInitializer - Handle a C++ member initializer. +/// \brief Handle a C++ member initializer using braced-init-list syntax. +MemInitResult +Sema::ActOnMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + SourceLocation IdLoc, + Expr *InitList, + SourceLocation EllipsisLoc) { + return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, + IdLoc, MultiInitializer(InitList), EllipsisLoc); +} + +/// \brief Handle a C++ member initializer using parentheses syntax. MemInitResult Sema::ActOnMemInitializer(Decl *ConstructorD, Scope *S, @@ -1354,6 +1368,22 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, Expr **Args, unsigned NumArgs, SourceLocation RParenLoc, SourceLocation EllipsisLoc) { + return BuildMemInitializer(ConstructorD, S, SS, MemberOrBase, TemplateTypeTy, + IdLoc, MultiInitializer(LParenLoc, Args, NumArgs, + RParenLoc), + EllipsisLoc); +} + +/// \brief Handle a C++ member initializer. +MemInitResult +Sema::BuildMemInitializer(Decl *ConstructorD, + Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *MemberOrBase, + ParsedType TemplateTypeTy, + SourceLocation IdLoc, + const MultiInitializer &Args, + SourceLocation EllipsisLoc) { if (!ConstructorD) return true; @@ -1388,26 +1418,23 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, = ClassDecl->lookup(MemberOrBase); if (Result.first != Result.second) { Member = dyn_cast<FieldDecl>(*Result.first); - + if (Member) { if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_pack_expansion_member_init) - << MemberOrBase << SourceRange(IdLoc, RParenLoc); - - return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, - LParenLoc, RParenLoc); + << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); + + return BuildMemberInitializer(Member, Args, IdLoc); } - + // Handle anonymous union case. if (IndirectFieldDecl* IndirectField = dyn_cast<IndirectFieldDecl>(*Result.first)) { if (EllipsisLoc.isValid()) Diag(EllipsisLoc, diag::err_pack_expansion_member_init) - << MemberOrBase << SourceRange(IdLoc, RParenLoc); + << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); - return BuildMemberInitializer(IndirectField, (Expr**)Args, - NumArgs, IdLoc, - LParenLoc, RParenLoc); + return BuildMemberInitializer(IndirectField, Args, IdLoc); } } } @@ -1466,8 +1493,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, Diag(Member->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr; - return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, - LParenLoc, RParenLoc); + return BuildMemberInitializer(Member, Args, IdLoc); } } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) { const CXXBaseSpecifier *DirectBaseSpec; @@ -1496,7 +1522,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, if (!TyD && BaseType.isNull()) { Diag(IdLoc, diag::err_mem_init_not_member_or_class) - << MemberOrBase << SourceRange(IdLoc, RParenLoc); + << MemberOrBase << SourceRange(IdLoc, Args.getEndLoc()); return true; } } @@ -1516,8 +1542,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, if (!TInfo) TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); - return BuildBaseInitializer(BaseType, TInfo, (Expr **)Args, NumArgs, - LParenLoc, RParenLoc, ClassDecl, EllipsisLoc); + return BuildBaseInitializer(BaseType, TInfo, Args, ClassDecl, EllipsisLoc); } /// Checks a member initializer expression for cases where reference (or @@ -1644,10 +1669,9 @@ static bool InitExprContainsUninitializedFields(const Stmt *S, } MemInitResult -Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, - unsigned NumArgs, SourceLocation IdLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc) { +Sema::BuildMemberInitializer(ValueDecl *Member, + const MultiInitializer &Args, + SourceLocation IdLoc) { FieldDecl *DirectMember = dyn_cast<FieldDecl>(Member); IndirectFieldDecl *IndirectMember = dyn_cast<IndirectFieldDecl>(Member); assert((DirectMember || IndirectMember) && @@ -1660,9 +1684,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, // foo(foo) // where foo is not also a parameter to the constructor. // TODO: implement -Wuninitialized and fold this into that framework. - for (unsigned i = 0; i < NumArgs; ++i) { + for (MultiInitializer::iterator I = Args.begin(), E = Args.end(); + I != E; ++I) { SourceLocation L; - if (InitExprContainsUninitializedFields(Args[i], Member, &L)) { + Expr *Arg = *I; + if (DesignatedInitExpr *DIE = dyn_cast<DesignatedInitExpr>(Arg)) + Arg = DIE->getInit(); + if (InitExprContainsUninitializedFields(Arg, 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 @@ -1673,17 +1701,13 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, } } - bool HasDependentArg = false; - for (unsigned i = 0; i < NumArgs; i++) - HasDependentArg |= Args[i]->isTypeDependent(); + bool HasDependentArg = Args.isTypeDependent(); Expr *Init; if (Member->getType()->isDependentType() || HasDependentArg) { // Can't check initialization for a member of dependent type or when // any of the arguments are type-dependent expressions. - Init = new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, - RParenLoc, - Member->getType().getNonReferenceType()); + Init = Args.CreateInitExpr(Context,Member->getType().getNonReferenceType()); DiscardCleanupsInEvaluationContext(); } else { @@ -1692,17 +1716,14 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, DirectMember ? InitializedEntity::InitializeMember(DirectMember, 0) : InitializedEntity::InitializeMember(IndirectMember, 0); InitializationKind Kind = - InitializationKind::CreateDirect(IdLoc, LParenLoc, RParenLoc); + InitializationKind::CreateDirect(IdLoc, Args.getStartLoc(), + Args.getEndLoc()); - InitializationSequence InitSeq(*this, MemberEntity, Kind, Args, NumArgs); - - ExprResult MemberInit = - InitSeq.Perform(*this, MemberEntity, Kind, - MultiExprArg(*this, Args, NumArgs), 0); + ExprResult MemberInit = Args.PerformInit(*this, MemberEntity, Kind); if (MemberInit.isInvalid()) return true; - CheckImplicitConversions(MemberInit.get(), LParenLoc); + CheckImplicitConversions(MemberInit.get(), Args.getStartLoc()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -1719,9 +1740,8 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, // 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 = new (Context) ParenListExpr( - Context, LParenLoc, Args, NumArgs, RParenLoc, - Member->getType().getNonReferenceType()); + Init = Args.CreateInitExpr(Context, + Member->getType().getNonReferenceType()); } else { Init = MemberInit.get(); CheckForDanglingReferenceOrPointer(*this, Member, Init, IdLoc); @@ -1730,21 +1750,19 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr **Args, if (DirectMember) { return new (Context) CXXCtorInitializer(Context, DirectMember, - IdLoc, LParenLoc, Init, - RParenLoc); + IdLoc, Args.getStartLoc(), + Init, Args.getEndLoc()); } else { return new (Context) CXXCtorInitializer(Context, IndirectMember, - IdLoc, LParenLoc, Init, - RParenLoc); + IdLoc, Args.getStartLoc(), + Init, Args.getEndLoc()); } } MemInitResult Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, - Expr **Args, unsigned NumArgs, + const MultiInitializer &Args, SourceLocation NameLoc, - SourceLocation LParenLoc, - SourceLocation RParenLoc, CXXRecordDecl *ClassDecl) { SourceLocation Loc = TInfo->getTypeLoc().getLocalSourceRange().getBegin(); if (!LangOpts.CPlusPlus0x) @@ -1755,13 +1773,10 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, InitializedEntity DelegationEntity = InitializedEntity::InitializeDelegation( QualType(ClassDecl->getTypeForDecl(), 0)); InitializationKind Kind = - InitializationKind::CreateDirect(NameLoc, LParenLoc, RParenLoc); - - InitializationSequence InitSeq(*this, DelegationEntity, Kind, Args, NumArgs); + InitializationKind::CreateDirect(NameLoc, Args.getStartLoc(), + Args.getEndLoc()); - ExprResult DelegationInit = - InitSeq.Perform(*this, DelegationEntity, Kind, - MultiExprArg(*this, Args, NumArgs), 0); + ExprResult DelegationInit = Args.PerformInit(*this, DelegationEntity, Kind); if (DelegationInit.isInvalid()) return true; @@ -1770,7 +1785,7 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, = ConExpr->getConstructor(); assert(Constructor && "Delegating constructor with no target?"); - CheckImplicitConversions(DelegationInit.get(), LParenLoc); + CheckImplicitConversions(DelegationInit.get(), Args.getStartLoc()); // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a @@ -1780,24 +1795,22 @@ Sema::BuildDelegatingInitializer(TypeSourceInfo *TInfo, return true; assert(!CurContext->isDependentContext()); - return new (Context) CXXCtorInitializer(Context, Loc, LParenLoc, Constructor, + return new (Context) CXXCtorInitializer(Context, Loc, Args.getStartLoc(), + Constructor, DelegationInit.takeAs<Expr>(), - RParenLoc); + Args.getEndLoc()); } MemInitResult Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, - Expr **Args, unsigned NumArgs, - SourceLocation LParenLoc, SourceLocation RParenLoc, + const MultiInitializer &Args, CXXRecordDecl *ClassDecl, SourceLocation EllipsisLoc) { - bool HasDependentArg = false; - for (unsigned i = 0; i < NumArgs; i++) - HasDependentArg |= Args[i]->isTypeDependent(); + bool HasDependentArg = Args.isTypeDependent(); SourceLocation BaseLoc = BaseTInfo->getTypeLoc().getLocalSourceRange().getBegin(); - + if (!BaseType->isDependentType() && !BaseType->isRecordType()) return Diag(BaseLoc, diag::err_base_init_does_not_name_class) << BaseType << BaseTInfo->getTypeLoc().getLocalSourceRange(); @@ -1814,28 +1827,26 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // This is a pack expansion. if (!BaseType->containsUnexpandedParameterPack()) { Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) - << SourceRange(BaseLoc, RParenLoc); - + << SourceRange(BaseLoc, Args.getEndLoc()); + EllipsisLoc = SourceLocation(); } } else { // Check for any unexpanded parameter packs. if (DiagnoseUnexpandedParameterPack(BaseLoc, BaseTInfo, UPPC_Initializer)) return true; - - for (unsigned I = 0; I != NumArgs; ++I) - if (DiagnoseUnexpandedParameterPack(Args[I])) - return true; + + if (Args.DiagnoseUnexpandedParameterPack(*this)) + return true; } - + // Check for direct and virtual base classes. const CXXBaseSpecifier *DirectBaseSpec = 0; const CXXBaseSpecifier *VirtualBaseSpec = 0; if (!Dependent) { if (Context.hasSameUnqualifiedType(QualType(ClassDecl->getTypeForDecl(),0), BaseType)) - return BuildDelegatingInitializer(BaseTInfo, Args, NumArgs, BaseLoc, - LParenLoc, RParenLoc, ClassDecl); + return BuildDelegatingInitializer(BaseTInfo, Args, BaseLoc, ClassDecl); FindBaseInitializer(*this, ClassDecl, BaseType, DirectBaseSpec, VirtualBaseSpec); @@ -1862,18 +1873,14 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, if (Dependent) { // Can't check initialization for a base of dependent type or when // any of the arguments are type-dependent expressions. - ExprResult BaseInit - = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, - RParenLoc, BaseType)); + Expr *BaseInit = Args.CreateInitExpr(Context, BaseType); DiscardCleanupsInEvaluationContext(); - return new (Context) CXXCtorInitializer(Context, BaseTInfo, - /*IsVirtual=*/false, - LParenLoc, - BaseInit.takeAs<Expr>(), - RParenLoc, - EllipsisLoc); + return new (Context) CXXCtorInitializer(Context, BaseTInfo, + /*IsVirtual=*/false, + Args.getStartLoc(), BaseInit, + Args.getEndLoc(), EllipsisLoc); } // C++ [base.class.init]p2: @@ -1893,18 +1900,15 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, InitializedEntity BaseEntity = InitializedEntity::InitializeBase(Context, BaseSpec, VirtualBaseSpec); InitializationKind Kind = - InitializationKind::CreateDirect(BaseLoc, LParenLoc, RParenLoc); - - InitializationSequence InitSeq(*this, BaseEntity, Kind, Args, NumArgs); - - ExprResult BaseInit = - InitSeq.Perform(*this, BaseEntity, Kind, - MultiExprArg(*this, Args, NumArgs), 0); + InitializationKind::CreateDirect(BaseLoc, Args.getStartLoc(), + Args.getEndLoc()); + + ExprResult BaseInit = Args.PerformInit(*this, BaseEntity, Kind); if (BaseInit.isInvalid()) return true; - CheckImplicitConversions(BaseInit.get(), LParenLoc); - + CheckImplicitConversions(BaseInit.get(), Args.getStartLoc()); + // C++0x [class.base.init]p7: // The initialization of each base and member constitutes a // full-expression. @@ -1919,24 +1923,14 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // of the information that we have about the base // 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()) { - ExprResult Init - = Owned(new (Context) ParenListExpr(Context, LParenLoc, Args, NumArgs, - RParenLoc, BaseType)); - return new (Context) CXXCtorInitializer(Context, BaseTInfo, - BaseSpec->isVirtual(), - LParenLoc, - Init.takeAs<Expr>(), - RParenLoc, - EllipsisLoc); - } + if (CurContext->isDependentContext()) + BaseInit = Owned(Args.CreateInitExpr(Context, BaseType)); return new (Context) CXXCtorInitializer(Context, BaseTInfo, - BaseSpec->isVirtual(), - LParenLoc, - BaseInit.takeAs<Expr>(), - RParenLoc, - EllipsisLoc); + BaseSpec->isVirtual(), + Args.getStartLoc(), + BaseInit.takeAs<Expr>(), + Args.getEndLoc(), EllipsisLoc); } // Create a static_cast\<T&&>(expr). diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 43db5cbbd6..e29b75a2c2 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2670,6 +2670,19 @@ void Sema::InstantiateStaticDataMemberDefinition( } } +static MultiInitializer CreateMultiInitializer( + const SmallVectorImpl<Expr*> &Args, + const CXXCtorInitializer *Init) { + // FIXME: This is a hack that will do slightly the wrong thing for an + // initializer of the form foo({...}). + // The right thing to do would be to modify InstantiateInitializer to create + // the MultiInitializer. + if (Args.size() == 1 && isa<InitListExpr>(Args[0])) + return MultiInitializer(Args[0]); + return MultiInitializer(Init->getLParenLoc(), (Expr **)Args.data(), + Args.size(), Init->getRParenLoc()); +} + void Sema::InstantiateMemInitializers(CXXConstructorDecl *New, const CXXConstructorDecl *Tmpl, @@ -2736,12 +2749,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, } // Build the initializer. - MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), - BaseTInfo, - (Expr **)NewArgs.data(), - NewArgs.size(), - Init->getLParenLoc(), - Init->getRParenLoc(), + MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); + MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), + BaseTInfo, MultiInit, New->getParent(), SourceLocation()); if (NewInit.isInvalid()) { @@ -2774,14 +2784,10 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, New->setInvalidDecl(); continue; } - - NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, - (Expr **)NewArgs.data(), - NewArgs.size(), - Init->getLParenLoc(), - Init->getRParenLoc(), - New->getParent(), - EllipsisLoc); + + MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); + NewInit = BuildBaseInitializer(BaseTInfo->getType(), BaseTInfo, MultiInit, + New->getParent(), EllipsisLoc); } else if (Init->isMemberInitializer()) { FieldDecl *Member = cast_or_null<FieldDecl>(FindInstantiatedDecl( Init->getMemberLocation(), @@ -2793,11 +2799,9 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, continue; } - NewInit = BuildMemberInitializer(Member, (Expr **)NewArgs.data(), - NewArgs.size(), - Init->getSourceLocation(), - Init->getLParenLoc(), - Init->getRParenLoc()); + MultiInitializer MultiInit(CreateMultiInitializer(NewArgs, Init)); + NewInit = BuildMemberInitializer(Member, MultiInit, + Init->getSourceLocation()); } else if (Init->isIndirectMemberInitializer()) { IndirectFieldDecl *IndirectMember = cast_or_null<IndirectFieldDecl>(FindInstantiatedDecl( @@ -2807,14 +2811,12 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, if (!IndirectMember) { AnyErrors = true; New->setInvalidDecl(); - continue; + continue; } - |