diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 5 | ||||
-rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 36 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 79 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 74 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 14 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 193 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateVariadic.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 143 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTCommon.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 12 |
13 files changed, 375 insertions, 228 deletions
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 8deef3343db..6111abab646 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -651,11 +651,13 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case Typedef: case TypeAlias: case TypeAliasTemplate: - case UnresolvedUsingTypename: case TemplateTypeParm: case ObjCTypeParam: return IDNS_Ordinary | IDNS_Type; + case UnresolvedUsingTypename: + return IDNS_Ordinary | IDNS_Type | IDNS_Using; + case UsingShadow: return 0; // we'll actually overwrite this later @@ -663,6 +665,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { return IDNS_Ordinary | IDNS_Using; case Using: + case UsingPack: return IDNS_Using; case ObjCProtocol: diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 8563416a480..1860b948d60 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2250,15 +2250,37 @@ SourceRange UsingDecl::getSourceRange() const { return SourceRange(Begin, getNameInfo().getEndLoc()); } +void UsingPackDecl::anchor() { } + +UsingPackDecl *UsingPackDecl::Create(ASTContext &C, DeclContext *DC, + NamedDecl *InstantiatedFrom, + ArrayRef<NamedDecl *> UsingDecls) { + size_t Extra = additionalSizeToAlloc<NamedDecl *>(UsingDecls.size()); + return new (C, DC, Extra) UsingPackDecl(DC, InstantiatedFrom, UsingDecls); +} + +UsingPackDecl *UsingPackDecl::CreateDeserialized(ASTContext &C, unsigned ID, + unsigned NumExpansions) { + size_t Extra = additionalSizeToAlloc<NamedDecl *>(NumExpansions); + auto *Result = new (C, ID, Extra) UsingPackDecl(nullptr, nullptr, None); + Result->NumExpansions = NumExpansions; + auto *Trail = Result->getTrailingObjects<NamedDecl *>(); + for (unsigned I = 0; I != NumExpansions; ++I) + new (Trail + I) NamedDecl*(nullptr); + return Result; +} + void UnresolvedUsingValueDecl::anchor() { } UnresolvedUsingValueDecl * UnresolvedUsingValueDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo) { + const DeclarationNameInfo &NameInfo, + SourceLocation EllipsisLoc) { return new (C, DC) UnresolvedUsingValueDecl(DC, C.DependentTy, UsingLoc, - QualifierLoc, NameInfo); + QualifierLoc, NameInfo, + EllipsisLoc); } UnresolvedUsingValueDecl * @@ -2266,7 +2288,8 @@ UnresolvedUsingValueDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) UnresolvedUsingValueDecl(nullptr, QualType(), SourceLocation(), NestedNameSpecifierLoc(), - DeclarationNameInfo()); + DeclarationNameInfo(), + SourceLocation()); } SourceRange UnresolvedUsingValueDecl::getSourceRange() const { @@ -2283,17 +2306,18 @@ UnresolvedUsingTypenameDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, - DeclarationName TargetName) { + DeclarationName TargetName, + SourceLocation EllipsisLoc) { return new (C, DC) UnresolvedUsingTypenameDecl( DC, UsingLoc, TypenameLoc, QualifierLoc, TargetNameLoc, - TargetName.getAsIdentifierInfo()); + TargetName.getAsIdentifierInfo(), EllipsisLoc); } UnresolvedUsingTypenameDecl * UnresolvedUsingTypenameDecl::CreateDeserialized(ASTContext &C, unsigned ID) { return new (C, ID) UnresolvedUsingTypenameDecl( nullptr, SourceLocation(), SourceLocation(), NestedNameSpecifierLoc(), - SourceLocation(), nullptr); + SourceLocation(), nullptr, SourceLocation()); } void StaticAssertDecl::anchor() { } diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 46573477580..d7613638016 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -113,6 +113,10 @@ void CodeGenFunction::EmitDecl(const Decl &D) { if (CGDebugInfo *DI = getDebugInfo()) DI->EmitUsingDecl(cast<UsingDecl>(D)); return; + case Decl::UsingPack: + for (auto *Using : cast<UsingPackDecl>(D).expansions()) + EmitDecl(*Using); + return; case Decl::UsingDirective: // using namespace X; [C++] if (CGDebugInfo *DI = getDebugInfo()) DI->EmitUsingDirective(cast<UsingDirectiveDecl>(D)); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d31d1142374..4002b09d2bc 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -560,7 +560,9 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) { // nested-name-specifier, the name is [...] considered to name the // constructor. if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext && - Tok.is(tok::identifier) && NextToken().is(tok::semi) && + Tok.is(tok::identifier) && + (NextToken().is(tok::semi) || NextToken().is(tok::comma) || + NextToken().is(tok::ellipsis)) && D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && !D.SS.getScopeRep()->getAsNamespace() && !D.SS.getScopeRep()->getAsNamespaceAlias()) { @@ -578,7 +580,10 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) { return true; } - // FIXME: Parse optional ellipsis + if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc)) + Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ? + diag::warn_cxx1z_compat_using_declaration_pack : + diag::ext_using_declaration_pack); return false; } @@ -678,9 +683,9 @@ Parser::ParseUsingDeclaration(unsigned Context, D.TypenameLoc = SourceLocation(); } - Decl *UD = - Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc, D.SS, - D.Name, Attrs.getList(), D.TypenameLoc); + Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc, + D.TypenameLoc, D.SS, D.Name, + D.EllipsisLoc, Attrs.getList()); if (UD) DeclsInGroup.push_back(UD); } @@ -708,62 +713,6 @@ Parser::ParseUsingDeclaration(unsigned Context, return Actions.BuildDeclaratorGroup(DeclsInGroup, /*MayContainAuto*/false); } -Decl *Parser::ParseAliasTemplate(const ParsedTemplateInfo &TemplateInfo, - SourceLocation &DeclEnd, AccessSpecifier AS, - ParsedAttributesWithRange &MisplacedAttrs1) { - assert(Tok.is(tok::kw_using) && "Not using token"); - ObjCDeclContextSwitch ObjCDC(*this); - - // Eat 'using'. - SourceLocation UsingLoc = ConsumeToken(); - if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteUsing(getCurScope()); - cutOffParsing(); - return nullptr; - } - - // 'using namespace' means this is a using-directive. - if (Tok.is(tok::kw_namespace)) { - SourceRange R = TemplateInfo.getSourceRange(); - Diag(UsingLoc, diag::err_templated_using_directive_declaration) - << 0 /* directive */ << R; - SkipUntil(tok::semi); - return nullptr; - } - - // Check for misplaced attributes before the identifier. - ParsedAttributesWithRange MisplacedAttrs2(AttrFactory); - MaybeParseCXX11Attributes(MisplacedAttrs2); - - // FIXME: Just parse an identifier here? - UsingDeclarator D; - if (ParseUsingDeclarator(Declarator::FileContext, D)) { - SkipUntil(tok::semi); - return nullptr; - } - - ParsedAttributesWithRange Attrs(AttrFactory); - - // If we had any misplaced attributes from earlier, this is where they - // should have been written. - for (auto *MisplacedAttrs : {&MisplacedAttrs1, &MisplacedAttrs2}) { - if (MisplacedAttrs->Range.isValid()) { - Diag(MisplacedAttrs->Range.getBegin(), diag::err_attributes_not_allowed) - << FixItHint::CreateInsertionFromRange( - Tok.getLocation(), - CharSourceRange::getTokenRange(MisplacedAttrs->Range)) - << FixItHint::CreateRemoval(MisplacedAttrs->Range); - Attrs.takeAllFrom(*MisplacedAttrs); - } - } - - MaybeParseGNUAttributes(Attrs); - MaybeParseCXX11Attributes(Attrs); - - return ParseAliasDeclarationAfterDeclarator(TemplateInfo, UsingLoc, D, - DeclEnd, AS, Attrs); -} - Decl *Parser::ParseAliasDeclarationAfterDeclarator( const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS, @@ -813,6 +762,9 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( else if (D.SS.isNotEmpty()) Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) << FixItHint::CreateRemoval(D.SS.getRange()); + if (D.EllipsisLoc.isValid()) + Diag(D.EllipsisLoc, diag::err_alias_declaration_pack_expansion) + << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc)); Decl *DeclFromDeclSpec = nullptr; TypeResult TypeAlias = @@ -2487,8 +2439,9 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( - getCurScope(), AS, /*UsingLoc*/SourceLocation(), SS, Name, - /*AttrList*/nullptr, /*TypenameLoc*/SourceLocation()))); + getCurScope(), AS, /*UsingLoc*/ SourceLocation(), + /*TypenameLoc*/ SourceLocation(), SS, Name, + /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr))); } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index ac643af1490..21bdd945f06 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8533,12 +8533,18 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, - AttributeList *AttrList, - SourceLocation TypenameLoc) { + SourceLocation EllipsisLoc, + AttributeList *AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); + if (SS.isEmpty()) { + Diag(Name.getLocStart(), diag::err_using_requires_qualname); + return nullptr; + } + switch (Name.getKind()) { case UnqualifiedId::IK_ImplicitSelfParam: case UnqualifiedId::IK_Identifier: @@ -8584,14 +8590,23 @@ Decl *Sema::ActOnUsingDeclaration(Scope *S, << FixItHint::CreateInsertion(SS.getRange().getBegin(), "using "); } - if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || - DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) - return nullptr; + if (EllipsisLoc.isInvalid()) { + if (DiagnoseUnexpandedParameterPack(SS, UPPC_UsingDeclaration) || + DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC_UsingDeclaration)) + return nullptr; + } else { + if (!SS.getScopeRep()->containsUnexpandedParameterPack() && + !TargetNameInfo.containsUnexpandedParameterPack()) { + Diag(EllipsisLoc, diag::err_pack_expansion_without_parameter_packs) + << SourceRange(SS.getBeginLoc(), TargetNameInfo.getEndLoc()); + EllipsisLoc = SourceLocation(); + } + } - NamedDecl *UD = BuildUsingDeclaration(S, AS, UsingLoc, SS, - TargetNameInfo, AttrList, - /* IsInstantiation */ false, - TypenameLoc.isValid(), TypenameLoc); + NamedDecl *UD = + BuildUsingDeclaration(S, AS, UsingLoc, TypenameLoc.isValid(), TypenameLoc, + SS, TargetNameInfo, EllipsisLoc, AttrList, + /*IsInstantiation*/false); if (UD) PushOnScopeChains(UD, S, /*AddToContext*/ false); @@ -8654,6 +8669,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, diag::err_using_decl_nested_name_specifier_is_current_class) << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); + Using->setInvalidDecl(); return true; } @@ -8663,6 +8679,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, << cast<CXXRecordDecl>(CurContext) << Using->getQualifierLoc().getSourceRange(); Diag(Orig->getLocation(), diag::note_using_decl_target); + Using->setInvalidDecl(); return true; } } @@ -8686,7 +8703,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, // We can have UsingDecls in our Previous results because we use the same // LookupResult for checking whether the UsingDecl itself is a valid // redeclaration. - if (isa<UsingDecl>(D)) + if (isa<UsingDecl>(D) || isa<UsingPackDecl>(D)) continue; if (IsEquivalentForUsingDecl(Context, D, Target)) { @@ -8732,6 +8749,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Target->getLocation(), diag::note_using_decl_target); Diag(OldDecl->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8744,6 +8762,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(Tag->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8753,6 +8772,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, Diag(Using->getLocation(), diag::err_using_decl_conflict); Diag(Target->getLocation(), diag::note_using_decl_target); Diag(NonTag->getLocation(), diag::note_using_decl_conflict); + Using->setInvalidDecl(); return true; } @@ -8960,23 +8980,19 @@ private: /// the lookup differently for these declarations. NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, + SourceLocation TypenameLoc, CXXScopeSpec &SS, DeclarationNameInfo NameInfo, + SourceLocation EllipsisLoc, AttributeList *AttrList, - bool IsInstantiation, - bool HasTypenameKeyword, - SourceLocation TypenameLoc) { + bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); // FIXME: We ignore attributes for now. - if (SS.isEmpty()) { - Diag(IdentLoc, diag::err_using_requires_qualname); - return nullptr; - } - // For an inheriting constructor declaration, the name of the using // declaration is the name of a constructor in this class, not in the // base class. @@ -9042,16 +9058,17 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, DeclContext *LookupContext = computeDeclContext(SS); NamedDecl *D; NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); - if (!LookupContext) { + if (!LookupContext || EllipsisLoc.isValid()) { if (HasTypenameKeyword) { // FIXME: not all declaration name kinds are legal here D = UnresolvedUsingTypenameDecl::Create(Context, CurContext, UsingLoc, TypenameLoc, QualifierLoc, - IdentLoc, NameInfo.getName()); + IdentLoc, NameInfo.getName(), + EllipsisLoc); } else { D = UnresolvedUsingValueDecl::Create(Context, CurContext, UsingLoc, - QualifierLoc, NameInfo); + QualifierLoc, NameInfo, EllipsisLoc); } D->setAccess(AS); CurContext->addDecl(D); @@ -9211,6 +9228,19 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, return UD; } +NamedDecl *Sema::BuildUsingPackDecl(NamedDecl *InstantiatedFrom, + ArrayRef<NamedDecl *> Expansions) { + assert(isa<UnresolvedUsingValueDecl>(InstantiatedFrom) || + isa<UnresolvedUsingTypenameDecl>(InstantiatedFrom) || + isa<UsingPackDecl>(InstantiatedFrom)); + + auto *UPD = + UsingPackDecl::Create(Context, CurContext, InstantiatedFrom, Expansions); + UPD->setAccess(InstantiatedFrom->getAccess()); + CurContext->addDecl(UPD); + return UPD; +} + /// Additional checks for a using declaration referring to a constructor name. bool Sema::CheckInheritingConstructorUsingDecl(UsingDecl *UD) { assert(!UD->hasTypename() && "expecting a constructor name"); @@ -9264,7 +9294,7 @@ bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc, // scope? if (Qual->isDependent() && !HasTypenameKeyword) { for (auto *D : Prev) { - if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D)) { + if (!isa<TypeDecl>(D) && !isa<UsingDecl>(D) && !isa<UsingPackDecl>(D)) { bool OldCouldBeEnumerator = isa<UnresolvedUsingValueDecl>(D) || isa<EnumConstantDecl>(D); Diag(NameLoc, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 74beeac7244..5c3900adbde 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -7462,17 +7462,11 @@ Sema::CheckMicrosoftIfExistsSymbol(Scope *S, SourceLocation KeywordLoc, UnqualifiedId &Name) { DeclarationNameInfo TargetNameInfo = GetNameFromUnqualifiedId(Name); - // Check for unexpanded parameter packs. - SmallVector<UnexpandedParameterPack, 4> Unexpanded; - collectUnexpandedParameterPacks(SS, Unexpanded); - collectUnexpandedParameterPacks(TargetNameInfo, Unexpanded); - if (!Unexpanded.empty()) { - DiagnoseUnexpandedParameterPacks(KeywordLoc, - IsIfExists? UPPC_IfExists - : UPPC_IfNotExists, - Unexpanded); + // Check for an unexpanded parameter pack. + auto UPPC = IsIfExists ? UPPC_IfExists : UPPC_IfNotExists; + if (DiagnoseUnexpandedParameterPack(SS, UPPC) || + DiagnoseUnexpandedParameterPack(TargetNameInfo, UPPC)) return IER_Error; - } return CheckMicrosoftIfExistsSymbol(S, SS, TargetNameInfo); } diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d49142b8d85..2129729dab9 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -981,7 +981,7 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, Match = *I; return Ovl_Match; } - } else if (isa<UsingDecl>(OldD)) { + } else if (isa<UsingDecl>(OldD) || isa<UsingPackDecl>(OldD)) { // We can overload with these, which can show up when doing // redeclaration checks for UsingDecls. assert(Old.getLookupKind() == LookupUsingDeclName); @@ -11420,6 +11420,12 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn, assert(!R.empty() && "lookup results empty despite recovery"); + // If recovery created an ambiguity, just bail out. + if (R.isAmbiguous()) { + R.suppressDiagnostics(); + return ExprError(); + } + // Build an implicit member call if appropriate. Just drop the // casts and such from the call, we don't really care. ExprResult NewFn = ExprError(); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 0956a1cc502..dbc322ebfdc 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2495,35 +2495,76 @@ Decl *TemplateDeclInstantiator::VisitConstructorUsingShadowDecl( return nullptr; } -Decl * TemplateDeclInstantiator - ::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { - NestedNameSpecifierLoc QualifierLoc - = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), - TemplateArgs); - if (!QualifierLoc) - return nullptr; +template <typename T> +Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( + T *D, bool InstantiatingPackElement) { + // If this is a pack expansion, expand it now. + if (D->isPackExpansion() && !InstantiatingPackElement) { + SmallVector<UnexpandedParameterPack, 2> Unexpanded; + SemaRef.collectUnexpandedParameterPacks(D->getQualifierLoc(), Unexpanded); + SemaRef.collectUnexpandedParameterPacks(D->getNameInfo(), Unexpanded); - CXXScopeSpec SS; - SS.Adopt(QualifierLoc); + // Determine whether the set of unexpanded parameter packs can and should + // be expanded. + bool Expand = true; + bool RetainExpansion = false; + Optional<unsigned> NumExpansions; + if (SemaRef.CheckParameterPacksForExpansion( + D->getEllipsisLoc(), D->getSourceRange(), Unexpanded, TemplateArgs, + Expand, RetainExpansion, NumExpansions)) + return nullptr; - // Since NameInfo refers to a typename, it cannot be a C++ special name. - // Hence, no transformation is required for it. - DeclarationNameInfo NameInfo(D->getDeclName(), D->getLocation()); - NamedDecl *UD = - SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(), - D->getUsingLoc(), SS, NameInfo, nullptr, - /*instantiation*/ true, - /*typename*/ true, D->getTypenameLoc()); - if (UD) - SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); + // This declaration cannot appear within a function template signature, + // so we can't have a partial argument list for a parameter pack. + assert(!RetainExpansion && + "should never need to retain an expansion for UsingPackDecl"); - return UD; -} + if (!Expand) { + // We cannot fully expand the pack expansion now, so substitute into the + // pattern and create a new pack expansion. + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, -1); + return instantiateUnresolvedUsingDecl(D, true); + } + + // Within a function, we don't have any normal way to check for conflicts + // between shadow declarations from different using declarations in the + // same pack expansion, but this is always ill-formed because all expansions + // must produce (conflicting) enumerators. + // + // Sadly we can't just reject this in the template definition because it + // could be valid if the pack is empty or has exactly one expansion. + if (D->getDeclContext()->isFunctionOrMethod() && *NumExpansions > 1) { + SemaRef.Diag(D->getEllipsisLoc(), + diag::err_using_decl_redeclaration_expansion); + return nullptr; + } + + // Instantiate the slices of this pack and build a UsingPackDecl. + SmallVector<NamedDecl*, 8> Expansions; + for (unsigned I = 0; I != *NumExpansions; ++I) { + Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, I); + Decl *Slice = instantiateUnresolvedUsingDecl(D, true); + if (!Slice) + return nullptr; + // Note that we can still get unresolved using declarations here, if we + // had arguments for all packs but the pattern also contained other + // template arguments (this only happens during partial substitution, eg + // into the body of a generic lambda in a function template). + Expansions.push_back(cast<NamedDecl>(Slice)); + } + + auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions); + if (isDeclWithinFunction(D)) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD); + return NewD; + } + + UnresolvedUsingTypenameDecl *TD = dyn_cast<UnresolvedUsingTypenameDecl>(D); + SourceLocation TypenameLoc = TD ? TD->getTypenameLoc() : SourceLocation(); -Decl * TemplateDeclInstantiator - ::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { NestedNameSpecifierLoc QualifierLoc - = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), TemplateArgs); + = SemaRef.SubstNestedNameSpecifierLoc(D->getQualifierLoc(), + TemplateArgs); if (!QualifierLoc) return nullptr; @@ -2533,17 +2574,48 @@ Decl * TemplateDeclInstantiator DeclarationNameInfo NameInfo = SemaRef.SubstDeclarationNameInfo(D->getNameInfo(), TemplateArgs); - NamedDecl *UD = - SemaRef.BuildUsingDeclaration(/*Scope*/ nullptr, D->getAccess(), - D->getUsingLoc(), SS, NameInfo, nullptr, - /*instantiation*/ true, - /*typename*/ false, SourceLocation()); + // Produce a pack expansion only if we're not instantiating a particular + // slice of a pack expansion. + bool InstantiatingSlice = D->getEllipsisLoc().isValid() && + SemaRef.ArgumentPackSubstitutionIndex != -1; + SourceLocation EllipsisLoc = + InstantiatingSlice ? SourceLocation() : D->getEllipsisLoc(); + + NamedDecl *UD = SemaRef.BuildUsingDeclaration( + /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), + /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr, + /*IsInstantiation*/ true); if (UD) SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); return UD; } +Decl *TemplateDeclInstantiator::VisitUnresolvedUsingTypenameDecl( + UnresolvedUsingTypenameDecl *D) { + return instantiateUnresolvedUsingDecl(D); +} + +Decl *TemplateDeclInstantiator::VisitUnresolvedUsingValueDecl( + UnresolvedUsingValueDecl *D) { + return instantiateUnresolvedUsingDecl(D); +} + +Decl *TemplateDeclInstantiator::VisitUsingPackDecl(UsingPackDecl *D) { + SmallVector<NamedDecl*, 8> Expansions; + for (auto *UD : D->expansions()) { + if (auto *NewUD = + SemaRef.FindInstantiatedDecl(D->getLocation(), UD, TemplateArgs)) + Expansions.push_back(cast<NamedDecl>(NewUD)); + else + return nullptr; + } + + auto *NewD = SemaRef.BuildUsingPackDecl(D, Expansions); + if (isDeclWithinFunction(D)) + SemaRef.CurrentInstantiationScope->InstantiatedLocal(D, NewD); + return NewD; +} Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( ClassScopeFunctionSpecializationDecl *Decl) { @@ -4513,22 +4585,36 @@ static bool isInstantiationOf(UsingShadowDecl *Pattern, Pattern); } -static bool isInstantiationOf(UsingDecl *Pattern, - UsingDecl *Instance, - ASTContext &C) { - return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern); -} - -static bool isInstantiationOf(UnresolvedUsingValueDecl *Pattern, - NamedDecl *Instance, +static bool isInstantiationOf(UsingDecl *Pattern, UsingDecl *Instance, ASTContext &C) { return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern); } -static bool isInstantiationOf(UnresolvedUsingTypenameDecl *Pattern, - NamedDecl *Instance, - ASTContext &C) { - return declaresSameEntity(C.getInstantiatedFromUsingDecl(Instance), Pattern); +template<typename T> +static bool isInstantiationOfUnresolvedUsingDecl(T *Pattern, Decl *Other, + ASTContext &Ctx) { + // An unresolved using declaration can instantiate to an unresolved using + // declaration, or to a using declaration or a using declaration pack. + // + // Multiple declarations can claim to be instantiated from an unresolved + // using declaration if it's a pack expansion. We want the UsingPackDecl + // in that case, not the individual UsingDecls within the pack. + bool OtherIsPackExpansion; + NamedDecl *OtherFrom; + if (auto *OtherUUD = dyn_cast<T>(Other)) { + OtherIsPackExpansion = OtherUUD->isPackExpansion(); + OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUUD); + } else if (auto *OtherUPD = dyn_cast<UsingPackDecl>(Other)) { + OtherIsPackExpansion = true; + OtherFrom = OtherUPD->getInstantiatedFromUsingDecl(); + } else if (auto *OtherUD = dyn_cast<UsingDecl>(Other)) { + OtherIsPackExpansion = false; + OtherFrom = Ctx.getInstantiatedFromUsingDecl(OtherUD); + } else { + return false; + } + return Pattern->isPackExpansion() == OtherIsPackExpansion && + declaresSameEntity(OtherFrom, Pattern); } static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, @@ -4549,21 +4635,14 @@ static bool isInstantiationOfStaticDataMember(VarDecl *Pattern, // Other is the prospective instantiation // D is the prospective pattern static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { - if (D->getKind() != Other->getKind()) { - if (auto *UUD = dyn_cast<UnresolvedUsingTypenameDecl>(D)) { - if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { - return isInstantiationOf(UUD, UD, Ctx); - } - } + if (auto *UUD = dyn_cast<UnresolvedUsingTypenameDecl>(D)) + return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx); - if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(D)) { - if (UsingDecl *UD = dyn_cast<UsingDecl>(Other)) { - return isInstantiationOf(UUD, UD, Ctx); - } - } + if (auto *UUD = dyn_cast<UnresolvedUsingValueDecl>(D)) + return isInstantiationOfUnresolvedUsingDecl(UUD, Other, Ctx); + if (D->getKind() != Other->getKind()) return false; - } if (auto *Record = dyn_cast<CXXRecordDecl>(Other)) return isInstantiationOf(cast<CXXRecordDecl>(D), Record); @@ -4600,12 +4679,6 @@ static bool isInstantiationOf(ASTContext &Ctx, NamedDecl *D, Decl *Other) { if (auto *Using = dyn_cast<UsingDecl>(Other)) return isInstantiationOf(cast<UsingDecl>(D), Using, Ctx); - if (auto *Using = dyn_cast<UnresolvedUsingValueDecl>(Other)) - return isInstantiationOf(cast<UnresolvedUsingValueDecl>(D), Using, Ctx); - - if (auto *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Other)) - return isInstantiationOf(cast<UnresolvedUsingTypenameDecl>(D), Using, Ctx); - if (auto *Shadow = dyn_cast<UsingShadowDecl>(Other)) return isInstantiationOf(cast<UsingShadowDecl>(D), Shadow, Ctx); @@ -4846,6 +4919,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, } NamedDecl *Result = nullptr; + // FIXME: If the name is a dependent name, this lookup won't necessarily + // find it. Does that ever matter? if (D->getDeclName()) { DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName()); Result = findInstantiationOf(Context, D, Found.begin(), Found.end()); diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp b/clang/lib/Sema/SemaTemplateVariadic.cpp index c8bc2c38809..54556b505ee 100644 --- a/clang/lib/Sema/SemaTemplateVariadic.cpp +++ b/clang/lib/Sema/SemaTemplateVariadic.cpp @@ -390,21 +390,18 @@ void Sema::collectUnexpandedParameterPacks(QualType T, void Sema::collectUnexpandedParameterPacks(TypeLoc TL, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded).TraverseTypeLoc(TL); -} +} -void Sema::collectUnexpandedParameterPacks(CXXScopeSpec &SS, - SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { - NestedNameSpecifier *Qualifier = SS.getScopeRep(); - if (!Qualifier) - return; - - NestedNameSpecifierLoc QualifierLoc(Qualifier, SS.location_data()); +void Sema::collectUnexpandedParameterPacks( + NestedNameSpecifierLoc NNS, + SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded) - .TraverseNestedNameSpecifierLoc(QualifierLoc); + .TraverseNestedNameSpecifierLoc(NNS); } -void Sema::collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo, - SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { +void Sema::collectUnexpandedParameterPacks( + const DeclarationNameInfo &NameInfo, + SmallVectorImpl<UnexpandedParameterPack> &Unexpanded) { CollectUnexpandedParameterPacksVisitor(Unexpanded) .TraverseDeclarationNameInfo(NameInfo); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index a76a078fd00..9671b9b35d8 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -457,6 +457,10 @@ public: return cast_or_null<NamedDecl>(getDerived().TransformDecl(Loc, D)); } + /// Transform the set of declarations in an OverloadExpr. + bool TransformOverloadExprDecls(OverloadExpr *Old, bool RequiresADL, + LookupResult &R); + /// \brief Transform the given nested-name-specifier with source-location /// information. /// @@ -821,7 +825,7 @@ public: /// \brief Rebuild an unresolved typename type, given the decl that /// the UnresolvedUsingTypenameDecl was transformed to. - QualType RebuildUnresolvedUsingType(Decl *D); + QualType RebuildUnresolvedUsingType(SourceLocation NameLoc, Decl *D); /// \brief Build a new typedef type. QualType RebuildTypedefType(TypedefNameDecl *Typedef) { @@ -5161,7 +5165,7 @@ TreeTransform<Derived>::TransformUnresolvedUsingType(TypeLocBuilder &TLB, QualType Result = TL.getType(); if (getDerived().AlwaysRebuild() || D != T->getDecl()) { - Result = getDerived().RebuildUnresolvedUsingType(D); + Result = getDerived().RebuildUnresolvedUsingType(TL.getNameLoc(), D); if (Result.isNull()) return QualType(); } @@ -9794,44 +9798,72 @@ TreeTransform<Derived>::TransformCXXPseudoDestructorExpr( Destroyed); } -template<typename Derived> -ExprResult -TreeTransform<Derived>::TransformUnresolvedLookupExpr( - UnresolvedLookupExpr *Old) { - LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), - Sema::LookupOrdinaryName); - +template <typename Derived> +bool TreeTransform<Derived>::TransformOverloadExprDecls(OverloadExpr *Old, + bool RequiresADL, + LookupResult &R) { // Transform all the decls. - for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(), - E = Old->decls_end(); I != E; ++I) { - NamedDecl *InstD = static_cast<NamedDecl*>( - getDerived().TransformDecl(Old->getNameLoc(), - *I)); + bool AllEmptyPacks = true; + for (auto *OldD : Old->decls()) { + Decl *InstD = getDerived().TransformDecl(Old->getNameLoc(), OldD); if (!InstD) { // Silently ignore these if a UsingShadowDecl instantiated to nothing. // This can happen because of dependent hiding. - if (isa<UsingShadowDecl>(*I)) + if (isa<UsingShadowDecl>(OldD)) continue; else { R.clear(); - return ExprError(); + return true; } } + // Expand using pack declarations. + NamedDecl *SingleDecl = cast<NamedDecl>(InstD); + ArrayRef<NamedDecl*> Decls = SingleDecl; + if (auto *UPD = dyn_cast<UsingPackDecl>(InstD)) + Decls = UPD->expansions(); + // Expand using declarations. - if (isa<UsingDecl>(InstD)) { - UsingDecl *UD = cast<UsingDecl>(InstD); - for (auto *I : UD->shadows()) - R.addDecl(I); - continue; + for (auto *D : Decls) { + if (auto *UD = dyn_cast<UsingDecl>(D)) { + for (auto *SD : UD->shadows()) + R.addDecl(SD); + } else { + R.addDecl(D); + } } - R.addDecl(InstD); + AllEmptyPacks &= Decls.empty(); + }; + + // C++ [temp.res]/8.4.2: + // The program is ill-formed, no diagnostic required, if [...] lookup for + // a name in the template definition found a using-declaration, but the + // lookup in the corresponding scope in the instantiation odoes not find + // any declarations because the using-declaration was a pack expansion and + // the corresponding pack is empty + if (AllEmptyPacks && !RequiresADL) { + getSema().Diag(Old->getNameLoc(), diag::err_using_pack_expansion_empty) + << isa<UnresolvedMemberExpr>(Old) << Old->getNameInfo().getName(); + return true; } // Resolve a kind, but don't do any further analysis. If it's // ambiguous, the callee needs to deal with it. R.resolveKind(); + return false; +} + +template<typename Derived> +ExprResult +TreeTransform<Derived>::TransformUnresolvedLookupExpr( + UnresolvedLookupExpr *Old) { + LookupResult R(SemaRef, Old->getName(), Old->getNameLoc(), + Sema::LookupOrdinaryName); + + // Transform the declaration set. + if (TransformOverloadExprDecls(Old, Old->requiresADL(), R)) + return ExprError(); // Rebuild the nested-name qualifier, if present. CXXScopeSpec SS; @@ -10699,35 +10731,9 @@ TreeTransform<Derived>::TransformUnresolvedMemberExpr(UnresolvedMemberExpr *Old) LookupResult R(SemaRef, Old->getMemberNameInfo(), Sema::LookupOrdinaryName); - // Transform all the decls. - for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(), - E = Old->decls_end(); I != E; ++I) { - NamedDecl *InstD = static_cast<NamedDecl*>( - getDerived().TransformDecl(Old->getMemberLoc(), - *I)); - if (!InstD) { - // Silently ignore these if a UsingShadowDecl instantiated to nothing. - // This can happen because of dependent hiding. - if (isa<UsingShadowDecl>(*I)) - continue; - else { - R.clear(); - return ExprError(); - } - } - - // Expand using declarations. - if (isa<UsingDecl>(InstD)) { - UsingDecl *UD = cast<UsingDecl>(InstD); - for (auto *I : UD->shadows()) - R.addDecl(I); - continue; - } - - R.addDecl(InstD); - } - - R.resolveKind(); + // Transform the declaration set. + if (TransformOverloadExprDecls(Old, /*RequiresADL*/false, R)) + return ExprError(); // Determine the naming class. if (Old->getNamingClass()) { @@ -11842,21 +11848,48 @@ QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) { } template<typename Derived> -QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(Decl *D) { +QualType TreeTransform<Derived>::RebuildUnresolvedUsingType(SourceLocation Loc, + Decl *D) { assert(D && "no decl found"); if (D->isInvalidDecl()) return QualType(); // FIXME: Doesn't account for ObjCInterfaceDecl! TypeDecl *Ty; - if (isa<UsingDecl>(D)) { - UsingDecl *Using = cast<UsingDecl>(D); + if (auto *UPD = dyn_cast<UsingPackDecl>(D)) { + // A valid resolved using typename pack expansion decl can have multiple + // UsingDecls, but they must each have exactly one type, and it must be + // the same type in every case. But we must have at least one expansion! + if (UPD->expansions().empty()) { + getSema().Diag(Loc, diag::err_using_pack_expansion_empty) + << UPD->isCXXClassMember() << UPD; + return QualType(); + } + + // We might still have some unresolved types. Try to pick a resolved type + // if we can. The final instantiation will check that the remaining + // unresolved types instantiate to the type we pick. + QualType FallbackT; + QualType T; + for (auto *E : UPD->expansions()) { + QualType ThisT = RebuildUnresolvedUsingType(Loc, E); + if (ThisT.isNull()) + continue; + else if (ThisT->getAs<UnresolvedUsingType>()) + FallbackT = ThisT; + else if (T.isNull()) + T = ThisT; + else + assert(getSema().Context.hasSameType(ThisT, T) && + "mismatched resolved types in using pack expansion"); + } + return T.isNull() ? FallbackT : T; + } else if (auto *Using = dyn_cast<UsingDecl>(D)) { assert(Using->hasTypename() && "UnresolvedUsingTypenameDecl transformed to non-typename using"); // A valid resolved using typename decl points to exactly one type decl. assert(++Using->shadow_begin() == Using->shadow_end()); Ty = cast<TypeDecl>((*Using->shadow_begin())->getTargetDecl()); - } else { assert(isa<UnresolvedUsingTypenameDecl>(D) && "UnresolvedUsingTypenameDecl transformed to non-using decl"); diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp index 79ccffc5abb..ecd249cc502 100644 --- a/clang/lib/Serialization/ASTCommon.cpp +++ b/clang/lib/Serialization/ASTCommon.cpp @@ -285,6 +285,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) { case Decl::NonTypeTemplateParm: case Decl::TemplateTemplateParm: case Decl::Using: + case Decl::UsingPack: case Decl::ObjCMethod: case Decl::ObjCCategory: case Decl::ObjCCategoryImpl: diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 913a1419b3f..dc29a61c0a9 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -322,6 +322,7 @@ namespace clang { void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); void VisitUsingDecl(UsingDecl *D); + void VisitUsingPackDecl(UsingPackDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); @@ -1419,6 +1420,15 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { mergeMergeable(D); } +void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) { + VisitNamedDecl(D); + D->InstantiatedFrom = ReadDeclAs<NamedDecl>(); + NamedDecl **Expansions = D->getTrailingObjects<NamedDecl*>(); + for (unsigned I = 0; I != D->NumExpansions; ++I) + Expansions[I] = ReadDeclAs<NamedDecl>(); + mergeMergeable(D); +} + void ASTDeclReader::VisitUsingShadowDecl(UsingShadowDecl *D) { RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); @@ -1452,6 +1462,7 @@ void ASTDeclReader::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { D->setUsingLoc(ReadSourceLocation()); D->QualifierLoc = Record.ReadNestedNameSpecifierLoc(Idx); ReadDeclarationNameLoc(D->DNLoc, D->getDeclName()); + D->EllipsisLoc = ReadSourceLocation(); mergeMergeable(D); } @@ -1460,6 +1471,7 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( VisitTypeDecl(D); D->TypenameLocation = ReadSourceLocation(); D->QualifierLoc = Record.ReadNestedNameSpecifierLoc(Idx); + D->EllipsisLoc = ReadSourceLocation(); mergeMergeable(D); } @@ -3297,6 +3309,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_USING: D = UsingDecl::CreateDeserialized(Context, ID); break; + case DECL_USING_PACK: + D = UsingPackDecl::CreateDeserialized(Context, ID, Record[Idx++]); + break; case DECL_USING_SHADOW: D = UsingShadowDecl::CreateDeserialized(Context, ID); break; diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 21468619dba..ee220f00a81 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -107,6 +107,7 @@ namespace clang { void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); void VisitUsingDecl(UsingDecl *D); + void VisitUsingPackDecl(UsingPackDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); @@ -1142,6 +1143,15 @@ void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { Code = serialization::DECL_USING; } +void ASTDeclWriter::VisitUsingPackDecl(UsingPackDecl *D) { + Record.push_back(D->NumExpansions); + VisitNamedDecl(D); + Record.AddDeclRef(D->getInstantiatedFromUsingDecl()); + for (auto *E : D->expansions()) + Record.AddDeclRef(E); + Code = serialization::DECL_USING_PACK; +} + void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { VisitRedeclarable(D); VisitNamedDecl(D); @@ -1175,6 +1185,7 @@ void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { Record.AddSourceLocation(D->getUsingLoc()); Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); + Record.AddSourceLocation(D->getEllipsisLoc()); Code = serialization::DECL_UNRESOLVED_USING_VALUE; } @@ -1183,6 +1194,7 @@ void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( VisitTypeDecl(D); Record.AddSourceLocation(D->getTypenameLoc()); Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); + Record.AddSourceLocation(D->getEllipsisLoc()); Code = serialization::DECL_UNRESOLVED_USING_TYPENAME; } |