Implement pack expansions whose pattern is a base-specifier.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122782 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 08c1ea4..c62225e 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -1709,6 +1709,10 @@
QualType T = Importer.Import(Base1->getType());
if (T.isNull())
return true;
+
+ SourceLocation EllipsisLoc;
+ if (Base1->isPackExpansion())
+ EllipsisLoc = Importer.Import(Base1->getEllipsisLoc());
Bases.push_back(
new (Importer.getToContext())
@@ -1716,7 +1720,8 @@
Base1->isVirtual(),
Base1->isBaseOfClass(),
Base1->getAccessSpecifierAsWritten(),
- Importer.Import(Base1->getTypeSourceInfo())));
+ Importer.Import(Base1->getTypeSourceInfo()),
+ EllipsisLoc));
}
if (!Bases.empty())
ToCXX->setBases(Bases.data(), Bases.size());
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 35c8997..3304ad9 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -196,7 +196,8 @@
data().getVBases()[I] =
CXXBaseSpecifier(VBaseClassDecl->getSourceRange(), true,
VBaseClassDecl->getTagKind() == TTK_Class,
- VBases[I]->getAccessSpecifier(), VBaseTypeInfo);
+ VBases[I]->getAccessSpecifier(), VBaseTypeInfo,
+ SourceLocation());
}
}
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp
index 0aa9f40..834ef4e 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -2137,8 +2137,9 @@
// ::= I <template-arg>* E # argument pack
// ::= sp <expression> # pack expansion of (C++0x)
switch (A.getKind()) {
- default:
- assert(0 && "Unknown template argument kind!");
+ case TemplateArgument::Null:
+ llvm_unreachable("Cannot mangle NULL template argument");
+
case TemplateArgument::Type:
mangleType(A.getAsType());
break;
@@ -2187,6 +2188,16 @@
break;
}
+
+ case TemplateArgument::Pack: {
+ // Note: proposal by Mike Herrick on 12/20/10
+ Out << 'J';
+ for (TemplateArgument::pack_iterator PA = A.pack_begin(),
+ PAEnd = A.pack_end();
+ PA != PAEnd; ++PA)
+ mangleTemplateArg(P, *PA);
+ Out << 'E';
+ }
}
}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index fe2390f..adbecdc 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1196,13 +1196,20 @@
if (BaseType.isInvalid())
return true;
+ // Parse the optional ellipsis (for a pack expansion). The ellipsis is
+ // actually part of the base-specifier-list grammar productions, but we
+ // parse it here for convenience.
+ SourceLocation EllipsisLoc;
+ if (Tok.is(tok::ellipsis))
+ EllipsisLoc = ConsumeToken();
+
// Find the complete source range for the base-specifier.
SourceRange Range(StartLoc, EndLocation);
// Notify semantic analysis that we have parsed a complete
// base-specifier.
return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
- BaseType.get(), BaseLoc);
+ BaseType.get(), BaseLoc, EllipsisLoc);
}
/// getAccessSpecifierIfPresent - Determine whether the next token is
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 0021c79..10d04fa 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -464,7 +464,8 @@
Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- TypeSourceInfo *TInfo) {
+ TypeSourceInfo *TInfo,
+ SourceLocation EllipsisLoc) {
QualType BaseType = TInfo->getType();
// C++ [class.union]p1:
@@ -475,10 +476,17 @@
return 0;
}
+ if (EllipsisLoc.isValid() &&
+ !TInfo->getType()->containsUnexpandedParameterPack()) {
+ Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs)
+ << TInfo->getTypeLoc().getSourceRange();
+ EllipsisLoc = SourceLocation();
+ }
+
if (BaseType->isDependentType())
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
- Access, TInfo);
+ Access, TInfo, EllipsisLoc);
SourceLocation BaseLoc = TInfo->getTypeLoc().getBeginLoc();
@@ -527,7 +535,7 @@
// Create the base specifier.
return new (Context) CXXBaseSpecifier(SpecifierRange, Virtual,
Class->getTagKind() == TTK_Class,
- Access, TInfo);
+ Access, TInfo, EllipsisLoc);
}
/// ActOnBaseSpecifier - Parsed a base specifier. A base specifier is
@@ -538,7 +546,8 @@
BaseResult
Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
- ParsedType basetype, SourceLocation BaseLoc) {
+ ParsedType basetype, SourceLocation BaseLoc,
+ SourceLocation EllipsisLoc) {
if (!classdecl)
return true;
@@ -550,12 +559,14 @@
TypeSourceInfo *TInfo = 0;
GetTypeFromParser(basetype, &TInfo);
- if (DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
+ if (EllipsisLoc.isInvalid() &&
+ DiagnoseUnexpandedParameterPack(SpecifierRange.getBegin(), TInfo,
UPPC_BaseType))
return true;
-
+
if (CXXBaseSpecifier *BaseSpec = CheckBaseSpecifier(Class, SpecifierRange,
- Virtual, Access, TInfo))
+ Virtual, Access, TInfo,
+ EllipsisLoc))
return BaseSpec;
return true;
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 8c9681f..77d3e64 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1155,6 +1155,58 @@
continue;
}
+ SourceLocation EllipsisLoc;
+ if (Base->isPackExpansion()) {
+ // This is a pack expansion. See whether we should expand it now, or
+ // wait until later.
+ llvm::SmallVector<UnexpandedParameterPack, 2> Unexpanded;
+ collectUnexpandedParameterPacks(Base->getTypeSourceInfo()->getTypeLoc(),
+ Unexpanded);
+ bool ShouldExpand = false;
+ unsigned NumExpansions = 0;
+ if (CheckParameterPacksForExpansion(Base->getEllipsisLoc(),
+ Base->getSourceRange(),
+ Unexpanded.data(), Unexpanded.size(),
+ TemplateArgs, ShouldExpand,
+ NumExpansions)) {
+ continue;
+ Invalid = true;
+ }
+
+ // If we should expand this pack expansion now, do so.
+ if (ShouldExpand) {
+ for (unsigned I = 0; I != NumExpansions; ++I) {
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, I);
+
+ TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
+ TemplateArgs,
+ Base->getSourceRange().getBegin(),
+ DeclarationName());
+ if (!BaseTypeLoc) {
+ Invalid = true;
+ continue;
+ }
+
+ if (CXXBaseSpecifier *InstantiatedBase
+ = CheckBaseSpecifier(Instantiation,
+ Base->getSourceRange(),
+ Base->isVirtual(),
+ Base->getAccessSpecifierAsWritten(),
+ BaseTypeLoc,
+ SourceLocation()))
+ InstantiatedBases.push_back(InstantiatedBase);
+ else
+ Invalid = true;
+ }
+
+ continue;
+ }
+
+ // The resulting base specifier will (still) be a pack expansion.
+ EllipsisLoc = Base->getEllipsisLoc();
+ }
+
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(*this, -1);
TypeSourceInfo *BaseTypeLoc = SubstType(Base->getTypeSourceInfo(),
TemplateArgs,
Base->getSourceRange().getBegin(),
@@ -1169,7 +1221,8 @@
Base->getSourceRange(),
Base->isVirtual(),
Base->getAccessSpecifierAsWritten(),
- BaseTypeLoc))
+ BaseTypeLoc,
+ EllipsisLoc))
InstantiatedBases.push_back(InstantiatedBase);
else
Invalid = true;
diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp
index a3e308f..92df1fd 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -294,6 +294,11 @@
CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseType(T);
}
+void Sema::collectUnexpandedParameterPacks(TypeLoc TL,
+ llvm::SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) {
+ CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL);
+}
+
ParsedTemplateArgument
Sema::ActOnPackExpansion(const ParsedTemplateArgument &Arg,
SourceLocation EllipsisLoc) {
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 084778d..dd8807f 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -4292,7 +4292,9 @@
AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]);
TypeSourceInfo *TInfo = GetTypeSourceInfo(F, Record, Idx);
SourceRange Range = ReadSourceRange(F, Record, Idx);
- return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, TInfo);
+ SourceLocation EllipsisLoc = ReadSourceLocation(F, Record, Idx);
+ return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, TInfo,
+ EllipsisLoc);
}
std::pair<CXXBaseOrMemberInitializer **, unsigned>
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 8c0fb42..cbf5ac7 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -3231,6 +3231,9 @@
Record.push_back(Base.getAccessSpecifierAsWritten());
AddTypeSourceInfo(Base.getTypeSourceInfo(), Record);
AddSourceRange(Base.getSourceRange(), Record);
+ AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
+ : SourceLocation(),
+ Record);
}
void ASTWriter::FlushCXXBaseSpecifiers() {