aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-04 00:32:56 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-04 00:32:56 +0000
commit3fb9e4b89f72823f162096086f0f964e6dcf66d6 (patch)
tree8b942b275d55cca992e80812dede111dd8d856fc /lib/Sema
parentb162054ba8f5b64fe87fbc4837933ab23eebd52b (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.cpp51
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp2
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp66
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(),