diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-01-03 22:36:02 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-01-03 22:36:02 +0000 |
commit | f90b27ad077c3339b62befc892382845339f9490 (patch) | |
tree | 43c0b1485e694007d51d4ddf51c8244aed3e5434 /lib | |
parent | 0fe5397b26695926a835fa99eceb7fc879b307af (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.cpp | 7 | ||||
-rw-r--r-- | lib/AST/DeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 15 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 9 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 55 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 5 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 4 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 3 |
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() { |