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 | 3fb9e4b89f72823f162096086f0f964e6dcf66d6 (patch) | |
tree | 8b942b275d55cca992e80812dede111dd8d856fc /lib/Sema | |
parent | b162054ba8f5b64fe87fbc4837933ab23eebd52b (diff) |
Implement pack expansion of base initializers, so that we can
initialize those lovely mixins that come from pack expansions of base
specifiers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122793 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 51 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 66 |
3 files changed, 109 insertions, 10 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 10d04fa9a3..e2067de964 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/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/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 77d3e64a15..16500d4207 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/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/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9db3a8cacf..60a942ac2f 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/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(), |