aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-01-03 22:36:02 +0000
committerDouglas Gregor <dgregor@apple.com>2011-01-03 22:36:02 +0000
commitf90b27ad077c3339b62befc892382845339f9490 (patch)
tree43c0b1485e694007d51d4ddf51c8244aed3e5434 /lib
parent0fe5397b26695926a835fa99eceb7fc879b307af (diff)
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
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTImporter.cpp7
-rw-r--r--lib/AST/DeclCXX.cpp3
-rw-r--r--lib/CodeGen/Mangle.cpp15
-rw-r--r--lib/Parse/ParseDeclCXX.cpp9
-rw-r--r--lib/Sema/SemaDeclCXX.cpp25
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp55
-rw-r--r--lib/Sema/SemaTemplateVariadic.cpp5
-rw-r--r--lib/Serialization/ASTReader.cpp4
-rw-r--r--lib/Serialization/ASTWriter.cpp3
9 files changed, 112 insertions, 14 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 08c1ea45f7..c62225ef40 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -1709,6 +1709,10 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) {
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 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To) {
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 35c89971ea..3304ad9a29 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -196,7 +196,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
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 0aa9f402f9..834ef4e569 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -2137,8 +2137,9 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
// ::= 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 @@ void CXXNameMangler::mangleTemplateArg(const NamedDecl *P,
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 fe2390f1aa..adbecdc4a9 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1196,13 +1196,20 @@ Parser::BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
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 0021c79823..10d04fa9a3 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -464,7 +464,8 @@ CXXBaseSpecifier *
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 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
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 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
// 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 @@ Sema::CheckBaseSpecifier(CXXRecordDecl *Class,
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 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange,
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 8c9681ffd5..77d3e64a15 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1155,6 +1155,58 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
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 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
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 a3e308fe11..92df1fd863 100644
--- a/lib/Sema/SemaTemplateVariadic.cpp
+++ b/lib/Sema/SemaTemplateVariadic.cpp
@@ -294,6 +294,11 @@ void Sema::collectUnexpandedParameterPacks(QualType T,
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 084778d856..dd8807fb00 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -4292,7 +4292,9 @@ ASTReader::ReadCXXBaseSpecifier(PerFileData &F,
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 8c0fb42f5f..cbf5ac7919 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -3231,6 +3231,9 @@ void ASTWriter::AddCXXBaseSpecifier(const CXXBaseSpecifier &Base,
Record.push_back(Base.getAccessSpecifierAsWritten());
AddTypeSourceInfo(Base.getTypeSourceInfo(), Record);
AddSourceRange(Base.getSourceRange(), Record);
+ AddSourceLocation(Base.isPackExpansion()? Base.getEllipsisLoc()
+ : SourceLocation(),
+ Record);
}
void ASTWriter::FlushCXXBaseSpecifiers() {