diff options
| author | Douglas Gregor <dgregor@apple.com> | 2011-01-04 00:32:56 +0000 |
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2011-01-04 00:32:56 +0000 |
| commit | 44e7df67d963de48125873d82eed90821c8a370d (patch) | |
| tree | 17d6e34b294f0c7d7fa2c2bca2e0ff4a443e7c11 /clang/lib | |
| parent | bd9dfb2e297bb29f33d631566bcf0b6db6e3f61e (diff) | |
| download | bcm5719-llvm-44e7df67d963de48125873d82eed90821c8a370d.tar.gz bcm5719-llvm-44e7df67d963de48125873d82eed90821c8a370d.zip | |
Implement pack expansion of base initializers, so that we can
initialize those lovely mixins that come from pack expansions of base
specifiers.
llvm-svn: 122793
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 51 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 66 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 14 |
6 files changed, 132 insertions, 23 deletions
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 3304ad9a293..13a25321d4b 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1002,8 +1002,9 @@ bool CXXMethodDecl::hasInlineBody() const { CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, - SourceLocation L, Expr *Init, SourceLocation R) - : BaseOrMember(TInfo), Init(Init), + SourceLocation L, Expr *Init, SourceLocation R, + SourceLocation EllipsisLoc) + : BaseOrMember(TInfo), MemberOrEllipsisLocation(EllipsisLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsVirtual(IsVirtual), IsWritten(false), SourceOrderOrNumArrayIndices(0) { @@ -1013,7 +1014,7 @@ CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) - : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), + : BaseOrMember(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { @@ -1023,7 +1024,7 @@ CXXBaseOrMemberInitializer:: CXXBaseOrMemberInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R) - : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), + : BaseOrMember(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(0) { @@ -1035,7 +1036,7 @@ CXXBaseOrMemberInitializer(ASTContext &Context, SourceLocation L, Expr *Init, SourceLocation R, VarDecl **Indices, unsigned NumIndices) - : BaseOrMember(Member), MemberLocation(MemberLoc), Init(Init), + : BaseOrMember(Member), MemberOrEllipsisLocation(MemberLoc), Init(Init), LParenLoc(L), RParenLoc(R), IsVirtual(false), IsWritten(false), SourceOrderOrNumArrayIndices(NumIndices) { diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index adbecdc4a94..bc3f977bfc7 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1739,8 +1739,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, /// ':' mem-initializer-list /// /// [C++] mem-initializer-list: -/// mem-initializer -/// mem-initializer , mem-initializer-list +/// mem-initializer ...[opt] +/// mem-initializer ...[opt] , mem-initializer-list void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'"); @@ -1839,10 +1839,15 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + SourceLocation EllipsisLoc; + if (Tok.is(tok::ellipsis)) + EllipsisLoc = ConsumeToken(); + return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy, IdLoc, LParenLoc, ArgExprs.take(), - ArgExprs.size(), RParenLoc); + ArgExprs.size(), RParenLoc, + EllipsisLoc); } /// ParseExceptionSpecification - Parse a C++ exception-specification diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 10d04fa9a31..e2067de9645 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1057,7 +1057,8 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, SourceLocation IdLoc, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, - SourceLocation RParenLoc) { + SourceLocation RParenLoc, + SourceLocation EllipsisLoc) { if (!ConstructorD) return true; @@ -1093,15 +1094,26 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, if (Result.first != Result.second) { Member = dyn_cast<FieldDecl>(*Result.first); - if (Member) + 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); + } + // Handle anonymous union case. if (IndirectFieldDecl* IndirectField - = dyn_cast<IndirectFieldDecl>(*Result.first)) + = dyn_cast<IndirectFieldDecl>(*Result.first)) { + if (EllipsisLoc.isValid()) + Diag(EllipsisLoc, diag::err_pack_expansion_member_init) + << MemberOrBase << SourceRange(IdLoc, RParenLoc); + return BuildMemberInitializer(IndirectField, (Expr**)Args, NumArgs, IdLoc, LParenLoc, RParenLoc); + } } } // It didn't name a member, so see if it names a class. @@ -1210,7 +1222,7 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, TInfo = Context.getTrivialTypeSourceInfo(BaseType, IdLoc); return BuildBaseInitializer(BaseType, TInfo, (Expr **)Args, NumArgs, - LParenLoc, RParenLoc, ClassDecl); + LParenLoc, RParenLoc, ClassDecl, EllipsisLoc); } /// Checks an initializer expression for use of uninitialized fields, such as @@ -1383,7 +1395,8 @@ MemInitResult Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, Expr **Args, unsigned NumArgs, SourceLocation LParenLoc, SourceLocation RParenLoc, - CXXRecordDecl *ClassDecl) { + CXXRecordDecl *ClassDecl, + SourceLocation EllipsisLoc) { bool HasDependentArg = false; for (unsigned i = 0; i < NumArgs; i++) HasDependentArg |= Args[i]->isTypeDependent(); @@ -1403,6 +1416,24 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, // name that denotes that base class type. bool Dependent = BaseType->isDependentType() || HasDependentArg; + if (EllipsisLoc.isValid()) { + // This is a pack expansion. + if (!BaseType->containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(BaseLoc, RParenLoc); + + 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; + } + // Check for direct and virtual base classes. const CXXBaseSpecifier *DirectBaseSpec = 0; const CXXBaseSpecifier *VirtualBaseSpec = 0; @@ -1447,7 +1478,8 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, /*IsVirtual=*/false, LParenLoc, BaseInit.takeAs<Expr>(), - RParenLoc); + RParenLoc, + EllipsisLoc); } // C++ [base.class.init]p2: @@ -1501,14 +1533,16 @@ Sema::BuildBaseInitializer(QualType BaseType, TypeSourceInfo *BaseTInfo, BaseSpec->isVirtual(), LParenLoc, Init.takeAs<Expr>(), - RParenLoc); + RParenLoc, + EllipsisLoc); } return new (Context) CXXBaseOrMemberInitializer(Context, BaseTInfo, BaseSpec->isVirtual(), LParenLoc, BaseInit.takeAs<Expr>(), - RParenLoc); + RParenLoc, + EllipsisLoc); } /// ImplicitInitializerKind - How an implicit base or member initializer should @@ -1586,6 +1620,7 @@ BuildImplicitBaseInitializer(Sema &SemaRef, CXXConstructorDecl *Constructor, BaseSpec->isVirtual(), SourceLocation(), BaseInit.takeAs<Expr>(), + SourceLocation(), SourceLocation()); return false; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 77d3e64a157..16500d4207a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1169,8 +1169,8 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation, Unexpanded.data(), Unexpanded.size(), TemplateArgs, ShouldExpand, NumExpansions)) { - continue; Invalid = true; + continue; } // If we should expand this pack expansion now, do so. diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9db3a8cacfe..60a942ac2fa 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2362,6 +2362,69 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, SourceLocation LParenLoc, RParenLoc; ASTOwningVector<Expr*> NewArgs(*this); + SourceLocation EllipsisLoc; + + if (Init->isPackExpansion()) { + // This is a pack expansion. We should expand it now. + TypeLoc BaseTL = Init->getBaseClassInfo()->getTypeLoc(); + llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded; + collectUnexpandedParameterPacks(BaseTL, Unexpanded); + bool ShouldExpand = false; + unsigned NumExpansions = 0; + if (CheckParameterPacksForExpansion(Init->getEllipsisLoc(), + BaseTL.getSourceRange(), + Unexpanded.data(), + Unexpanded.size(), + TemplateArgs, ShouldExpand, + NumExpansions)) { + AnyErrors = true; + New->setInvalidDecl(); + continue; + } + assert(ShouldExpand && "Partial instantiation of base initializer?"); + + // Loop over all of the arguments in the argument pack(s), + for (unsigned I = 0; I != NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I); + + // Instantiate the initializer. + if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, + LParenLoc, NewArgs, RParenLoc)) { + AnyErrors = true; + break; + } + + // Instantiate the base type. + TypeSourceInfo *BaseTInfo = SubstType(Init->getBaseClassInfo(), + TemplateArgs, + Init->getSourceLocation(), + New->getDeclName()); + if (!BaseTInfo) { + AnyErrors = true; + break; + } + + // Build the initializer. + MemInitResult NewInit = BuildBaseInitializer(BaseTInfo->getType(), + BaseTInfo, + (Expr **)NewArgs.data(), + NewArgs.size(), + Init->getLParenLoc(), + Init->getRParenLoc(), + New->getParent(), + SourceLocation()); + if (NewInit.isInvalid()) { + AnyErrors = true; + break; + } + + NewInits.push_back(NewInit.get()); + NewArgs.clear(); + } + + continue; + } + // Instantiate the initializer. if (InstantiateInitializer(*this, Init->getInit(), TemplateArgs, LParenLoc, NewArgs, RParenLoc)) { @@ -2386,7 +2449,8 @@ Sema::InstantiateMemInitializers(CXXConstructorDecl *New, NewArgs.size(), Init->getLParenLoc(), Init->getRParenLoc(), - New->getParent()); + New->getParent(), + EllipsisLoc); } else if (Init->isMemberInitializer()) { FieldDecl *Member = cast<FieldDecl>(FindInstantiatedDecl( Init->getMemberLocation(), diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index dd8807fb004..f3320a04158 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -4325,7 +4325,7 @@ ASTReader::ReadCXXBaseOrMemberInitializers(PerFileData &F, else Member = cast<FieldDecl>(GetDecl(Record[Idx++])); } - SourceLocation MemberLoc = ReadSourceLocation(F, Record, Idx); + SourceLocation MemberOrEllipsisLoc = ReadSourceLocation(F, Record, Idx); Expr *Init = ReadExpr(F); SourceLocation LParenLoc = ReadSourceLocation(F, Record, Idx); SourceLocation RParenLoc = ReadSourceLocation(F, Record, Idx); @@ -4345,18 +4345,22 @@ ASTReader::ReadCXXBaseOrMemberInitializers(PerFileData &F, if (IsBaseInitializer) { BOMInit = new (C) CXXBaseOrMemberInitializer(C, BaseClassInfo, IsBaseVirtual, LParenLoc, - Init, RParenLoc); + Init, RParenLoc, + MemberOrEllipsisLoc); } else if (IsWritten) { if (Member) - BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, MemberLoc, + BOMInit = new (C) CXXBaseOrMemberInitializer(C, Member, + MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc); else BOMInit = new (C) CXXBaseOrMemberInitializer(C, IndirectMember, - MemberLoc, LParenLoc, + MemberOrEllipsisLoc, + LParenLoc, Init, RParenLoc); } else { - BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, MemberLoc, + BOMInit = CXXBaseOrMemberInitializer::Create(C, Member, + MemberOrEllipsisLoc, LParenLoc, Init, RParenLoc, Indices.data(), Indices.size()); |

