diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 55 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 5 |
3 files changed, 77 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 0021c798235..10d04fa9a31 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 8c9681ffd5a..77d3e64a157 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/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/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index a3e308fe11f..92df1fd8636 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/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) { |