From 072be6eeb2273616801a2860618671fa227a6e5d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 1 Aug 2024 13:13:57 -0400 Subject: [PATCH 01/35] [WIP] set isMemberSpecialization early --- clang/include/clang/AST/DeclTemplate.h | 30 ++++---------- clang/include/clang/Sema/Sema.h | 7 ++-- clang/lib/AST/DeclTemplate.cpp | 28 ++++++------- clang/lib/Sema/SemaDecl.cpp | 23 +++++------ clang/lib/Sema/SemaDeclCXX.cpp | 3 +- clang/lib/Sema/SemaTemplate.cpp | 48 +++++++++++----------- clang/lib/Sema/SemaTemplateInstantiate.cpp | 18 ++++++++ clang/lib/Serialization/ASTReaderDecl.cpp | 14 +++---- clang/lib/Serialization/ASTWriterDecl.cpp | 9 ++-- clang/test/PCH/cxx-templates.cpp | 6 +-- 10 files changed, 94 insertions(+), 92 deletions(-) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index 687715a22e9fd..3ad31243d5e55 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -809,8 +809,8 @@ class RedeclarableTemplateDecl : public TemplateDecl, }; /// Pointer to the common data shared by all declarations of this - /// template. - mutable CommonBase *Common = nullptr; + /// template, and a flag indicating if the template is a member specialization. + mutable llvm::PointerIntPair Common; /// Retrieves the "common" pointer shared by all (re-)declarations of /// the same template. Calling this routine may implicitly allocate memory @@ -858,14 +858,12 @@ class RedeclarableTemplateDecl : public TemplateDecl, /// struct X::Inner { /* ... */ }; /// \endcode bool isMemberSpecialization() const { - return getCommonPtr()->InstantiatedFromMember.getInt(); + return Common.getInt(); } /// Note that this member template is a specialization. void setMemberSpecialization() { - assert(getCommonPtr()->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - getCommonPtr()->InstantiatedFromMember.setInt(true); + Common.setInt(true); } /// Retrieve the member template from which this template was @@ -2187,17 +2185,12 @@ class ClassTemplatePartialSpecializationDecl /// struct X::Inner { /* ... */ }; /// \endcode bool isMemberSpecialization() const { - const auto *First = - cast(getFirstDecl()); - return First->InstantiatedFromMember.getInt(); + return InstantiatedFromMember.getInt(); } /// Note that this member template is a specialization. void setMemberSpecialization() { - auto *First = cast(getFirstDecl()); - assert(First->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - return First->InstantiatedFromMember.setInt(true); + return InstantiatedFromMember.setInt(true); } /// Retrieves the injected specialization type for this partial @@ -2269,7 +2262,7 @@ class ClassTemplateDecl : public RedeclarableTemplateDecl { } void setCommonPtr(Common *C) { - RedeclarableTemplateDecl::Common = C; + RedeclarableTemplateDecl::Common.setPointer(C); } public: @@ -2949,17 +2942,12 @@ class VarTemplatePartialSpecializationDecl /// U* X::Inner = (T*)(0) + 1; /// \endcode bool isMemberSpecialization() const { - const auto *First = - cast(getFirstDecl()); - return First->InstantiatedFromMember.getInt(); + return InstantiatedFromMember.getInt(); } /// Note that this member template is a specialization. void setMemberSpecialization() { - auto *First = cast(getFirstDecl()); - assert(First->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - return First->InstantiatedFromMember.setInt(true); + return InstantiatedFromMember.setInt(true); } SourceRange getSourceRange() const override LLVM_READONLY; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e1c3a99cfa167..cae01722af23a 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11389,9 +11389,8 @@ class Sema final : public SemaBase { CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, AccessSpecifier AS, SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, - TemplateParameterList **OuterTemplateParamLists, - SkipBodyInfo *SkipBody = nullptr); + SourceLocation FriendLoc, ArrayRef OuterTemplateParamLists, + bool IsMemberSpecialization, SkipBodyInfo *SkipBody = nullptr); /// Translates template arguments as provided by the parser /// into template arguments used by semantic analysis. @@ -11430,7 +11429,7 @@ class Sema final : public SemaBase { DeclResult ActOnVarTemplateSpecialization( Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous, SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, - StorageClass SC, bool IsPartialSpecialization); + StorageClass SC, bool IsPartialSpecialization, bool IsMemberSpecialization); /// Get the specialization of the given variable template corresponding to /// the specified argument list, or a null-but-valid result if the arguments diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index 976b3a3e1eced..58ce956f4b916 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -309,16 +309,16 @@ bool TemplateDecl::isTypeAlias() const { void RedeclarableTemplateDecl::anchor() {} RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() const { - if (Common) - return Common; + if (CommonBase *C = Common.getPointer()) + return C; // Walk the previous-declaration chain until we either find a declaration // with a common pointer or we run out of previous declarations. SmallVector PrevDecls; for (const RedeclarableTemplateDecl *Prev = getPreviousDecl(); Prev; Prev = Prev->getPreviousDecl()) { - if (Prev->Common) { - Common = Prev->Common; + if (CommonBase *C = Prev->Common.getPointer()) { + Common.setPointer(C); break; } @@ -326,18 +326,18 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c } // If we never found a common pointer, allocate one now. - if (!Common) { + if (!Common.getPointer()) { // FIXME: If any of the declarations is from an AST file, we probably // need an update record to add the common data. - Common = newCommon(getASTContext()); + Common.setPointer(newCommon(getASTContext())); } // Update any previous declarations we saw with the common pointer. for (const RedeclarableTemplateDecl *Prev : PrevDecls) - Prev->Common = Common; + Prev->Common.setPointer(Common.getPointer()); - return Common; + return Common.getPointer(); } void RedeclarableTemplateDecl::loadLazySpecializationsImpl() const { @@ -467,15 +467,15 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) { // If we haven't created a common pointer yet, then it can just be created // with the usual method. - if (!Base::Common) + if (!Base::Common.getPointer()) return; - Common *ThisCommon = static_cast(Base::Common); + Common *ThisCommon = static_cast(Base::Common.getPointer()); Common *PrevCommon = nullptr; SmallVector PreviousDecls; for (; Prev; Prev = Prev->getPreviousDecl()) { - if (Prev->Base::Common) { - PrevCommon = static_cast(Prev->Base::Common); + if (CommonBase *C = Prev->Base::Common.getPointer()) { + PrevCommon = static_cast(C); break; } PreviousDecls.push_back(Prev); @@ -485,7 +485,7 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) { // use this common pointer. if (!PrevCommon) { for (auto *D : PreviousDecls) - D->Base::Common = ThisCommon; + D->Base::Common.setPointer(ThisCommon); return; } @@ -493,7 +493,7 @@ void FunctionTemplateDecl::mergePrevDecl(FunctionTemplateDecl *Prev) { assert(ThisCommon->Specializations.size() == 0 && "Can't merge incompatible declarations!"); - Base::Common = PrevCommon; + Base::Common.setPointer(PrevCommon); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 31bf50a32a83c..e269f8b58f5a7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -7655,7 +7655,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( : SourceLocation(); DeclResult Res = ActOnVarTemplateSpecialization( S, D, TInfo, Previous, TemplateKWLoc, TemplateParams, SC, - IsPartialSpecialization); + IsPartialSpecialization, IsMemberSpecialization); if (Res.isInvalid()) return nullptr; NewVD = cast(Res.get()); @@ -7674,6 +7674,10 @@ NamedDecl *Sema::ActOnVariableDeclarator( VarTemplateDecl::Create(Context, DC, D.getIdentifierLoc(), Name, TemplateParams, NewVD); NewVD->setDescribedVarTemplate(NewTemplate); + // If we are providing an explicit specialization of a static variable + // template, make a note of that. + if (IsMemberSpecialization) + NewTemplate->setMemberSpecialization(); } // If this decl has an auto type in need of deduction, make a note of the @@ -8049,12 +8053,6 @@ NamedDecl *Sema::ActOnVariableDeclarator( ? TPC_ClassTemplateMember : TPC_VarTemplate)) NewVD->setInvalidDecl(); - - // If we are providing an explicit specialization of a static variable - // template, make a note of that. - if (PrevVarTemplate && - PrevVarTemplate->getInstantiatedFromMemberTemplate()) - PrevVarTemplate->setMemberSpecialization(); } } @@ -9859,6 +9857,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, NewFD); FunctionTemplate->setLexicalDeclContext(CurContext); NewFD->setDescribedFunctionTemplate(FunctionTemplate); + if (isMemberSpecialization) + FunctionTemplate->setMemberSpecialization(); // For source fidelity, store the other template param lists. if (TemplateParamLists.size() > 1) { @@ -12005,10 +12005,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // If this is an explicit specialization of a member that is a function // template, mark it as a member specialization. - if (IsMemberSpecialization && - NewTemplateDecl->getInstantiatedFromMemberTemplate()) { + if (IsMemberSpecialization) { NewTemplateDecl->setMemberSpecialization(); - assert(OldTemplateDecl->isMemberSpecialization()); + // assert(OldTemplateDecl->isMemberSpecialization()); // Explicit specializations of a member template do not inherit deleted // status from the parent member template that they are specializing. if (OldFD->isDeleted()) { @@ -17067,8 +17066,8 @@ Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, DeclResult Result = CheckClassTemplate( S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams, AS, ModulePrivateLoc, - /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1, - TemplateParameterLists.data(), SkipBody); + /*FriendLoc*/ SourceLocation(), TemplateParameterLists.drop_back(), + isMemberSpecialization, SkipBody); return Result.get(); } else { // The "template<>" header is extraneous. diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index d8cdfcf8c6ec0..8b54c191e94ae 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -17416,8 +17416,7 @@ DeclResult Sema::ActOnTemplatedFriendTag( return CheckClassTemplate(S, TagSpec, TagUseKind::Friend, TagLoc, SS, Name, NameLoc, Attr, TemplateParams, AS_public, /*ModulePrivateLoc=*/SourceLocation(), - FriendLoc, TempParamLists.size() - 1, - TempParamLists.data()) + FriendLoc, TempParamLists.drop_back(), IsMemberSpecialization) .get(); } else { // The "template<>" header is extraneous. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index b052afede2cd6..f7496e82aa18a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1793,8 +1793,8 @@ DeclResult Sema::CheckClassTemplate( CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, AccessSpecifier AS, SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, - TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) { + SourceLocation FriendLoc, ArrayRef OuterTemplateParamLists, + bool IsMemberSpecialization, SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TagUseKind::Reference && @@ -2087,10 +2087,9 @@ DeclResult Sema::CheckClassTemplate( PrevClassTemplate->getTemplatedDecl() : nullptr, /*DelayTypeCreation=*/true); SetNestedNameSpecifier(*this, NewClass, SS); - if (NumOuterTemplateParamLists > 0) + if (!OuterTemplateParamLists.empty()) NewClass->setTemplateParameterListsInfo( - Context, - llvm::ArrayRef(OuterTemplateParamLists, NumOuterTemplateParamLists)); + Context, OuterTemplateParamLists); // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. @@ -2103,7 +2102,10 @@ DeclResult Sema::CheckClassTemplate( = ClassTemplateDecl::Create(Context, SemanticContext, NameLoc, DeclarationName(Name), TemplateParams, NewClass); - + // If we are providing an explicit specialization of a member that is a + // class template, make a note of that. + if (IsMemberSpecialization) + NewTemplate->setMemberSpecialization(); if (ShouldAddRedecl) NewTemplate->setPreviousDecl(PrevClassTemplate); @@ -2118,12 +2120,6 @@ DeclResult Sema::CheckClassTemplate( assert(T->isDependentType() && "Class template type is not dependent?"); (void)T; - // If we are providing an explicit specialization of a member that is a - // class template, make a note of that. - if (PrevClassTemplate && - PrevClassTemplate->getInstantiatedFromMemberTemplate()) - PrevClassTemplate->setMemberSpecialization(); - // Set the access specifier. if (!Invalid && TUK != TagUseKind::Friend && NewTemplate->getDeclContext()->isRecord()) @@ -3974,7 +3970,7 @@ void Sema::CheckDeductionGuideTemplate(FunctionTemplateDecl *TD) { DeclResult Sema::ActOnVarTemplateSpecialization( Scope *S, Declarator &D, TypeSourceInfo *DI, LookupResult &Previous, SourceLocation TemplateKWLoc, TemplateParameterList *TemplateParams, - StorageClass SC, bool IsPartialSpecialization) { + StorageClass SC, bool IsPartialSpecialization, bool IsMemberSpecialization) { // D must be variable template id. assert(D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId && "Variable template specialization is declared with a template id."); @@ -4092,16 +4088,18 @@ DeclResult Sema::ActOnVarTemplateSpecialization( Context, VarTemplate->getDeclContext(), TemplateKWLoc, TemplateNameLoc, TemplateParams, VarTemplate, DI->getType(), DI, SC, CanonicalConverted); + // If we are providing an explicit specialization of a member variable + // template specialization, make a note of that. + if (IsMemberSpecialization) + Partial->setMemberSpecialization(); Partial->setTemplateArgsAsWritten(TemplateArgs); if (!PrevPartial) VarTemplate->AddPartialSpecialization(Partial, InsertPos); Specialization = Partial; - // If we are providing an explicit specialization of a member variable - // template specialization, make a note of that. - if (PrevPartial && PrevPartial->getInstantiatedFromMember()) - PrevPartial->setMemberSpecialization(); + //if (PrevPartial && PrevPartial->getInstantiatedFromMember()) + // PrevPartial->setMemberSpecialization(); CheckTemplatePartialSpecialization(Partial); } else { @@ -8315,8 +8313,8 @@ DeclResult Sema::ActOnClassTemplateSpecialization( TemplateParams, AS_none, /*ModulePrivateLoc=*/SourceLocation(), /*FriendLoc*/SourceLocation(), - TemplateParameterLists.size() - 1, - TemplateParameterLists.data()); + TemplateParameterLists.drop_back(), + isMemberSpecialization); } // Create a new class template partial specialization declaration node. @@ -8326,6 +8324,11 @@ DeclResult Sema::ActOnClassTemplateSpecialization( ClassTemplatePartialSpecializationDecl::Create( Context, Kind, DC, KWLoc, TemplateNameLoc, TemplateParams, ClassTemplate, CanonicalConverted, CanonType, PrevPartial); + + // If we are providing an explicit specialization of a member class + // template specialization, make a note of that. + if (isMemberSpecialization) + Partial->setMemberSpecialization(); Partial->setTemplateArgsAsWritten(TemplateArgs); SetNestedNameSpecifier(*this, Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { @@ -8337,11 +8340,6 @@ DeclResult Sema::ActOnClassTemplateSpecialization( ClassTemplate->AddPartialSpecialization(Partial, InsertPos); Specialization = Partial; - // If we are providing an explicit specialization of a member class - // template specialization, make a note of that. - if (PrevPartial && PrevPartial->getInstantiatedFromMember()) - PrevPartial->setMemberSpecialization(); - CheckTemplatePartialSpecialization(Partial); } else { // Create a new class template specialization declaration node for @@ -11139,7 +11137,7 @@ class ExplicitSpecializationVisibilityChecker { template void checkTemplate(TemplDecl *TD) { - if (TD->isMemberSpecialization()) { + if (TD->getMostRecentDecl()->isMemberSpecialization()) { if (!CheckMemberSpecialization(TD)) diagnose(TD->getMostRecentDecl(), false); } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 55f38743e2768..51f49ef709a58 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -332,12 +332,15 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, MultiLevelTemplateArgumentList &Result) { + #if 0 if (!isa(FTD->getDeclContext())) { Result.addOuterTemplateArguments( const_cast(FTD), const_cast(FTD)->getInjectedTemplateArgs(), /*Final=*/false); + + NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier(); while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) { @@ -381,6 +384,21 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, } return Response::ChangeDecl(FTD->getLexicalDeclContext()); + #else + if (!isa(FTD->getDeclContext())) { + Result.addOuterTemplateArguments( + const_cast(FTD), + const_cast(FTD)->getInjectedTemplateArgs(), + /*Final=*/false); + } + + if (FTD->isMemberSpecialization()) + return Response::Done(); + + if (FTD->getFriendObjectKind()) + return Response::ChangeDecl(FTD->getLexicalDeclContext()); + return Response::UseNextDecl(FTD); + #endif } Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec, diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 9272e23c7da3f..d9556dc4ce731 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2416,11 +2416,13 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { // Make sure we've allocated the Common pointer first. We do this before // VisitTemplateDecl so that getCommonPtr() can be used during initialization. RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl(); - if (!CanonD->Common) { - CanonD->Common = CanonD->newCommon(Reader.getContext()); + if (!CanonD->Common.getPointer()) { + CanonD->Common.setPointer(CanonD->newCommon(Reader.getContext())); Reader.PendingDefinitions.insert(CanonD); } - D->Common = CanonD->Common; + D->Common.setPointer(CanonD->Common.getPointer()); + if (Record.readInt()) + D->setMemberSpecialization(); // If this is the first declaration of the template, fill in the information // for the 'common' pointer. @@ -2429,8 +2431,6 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { assert(RTD->getKind() == D->getKind() && "InstantiatedFromMemberTemplate kind mismatch"); D->setInstantiatedFromMemberTemplate(RTD); - if (Record.readInt()) - D->setMemberSpecialization(); } } @@ -2562,12 +2562,12 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( D->TemplateParams = Params; RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); + D->InstantiatedFromMember.setInt(Record.readInt()); // These are read/set from/to the first declaration. if (ThisDeclID == Redecl.getFirstID()) { D->InstantiatedFromMember.setPointer( readDeclAs()); - D->InstantiatedFromMember.setInt(Record.readInt()); } } @@ -2660,12 +2660,12 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl( D->TemplateParams = Params; RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); + D->InstantiatedFromMember.setInt(Record.readInt()); // These are read/set from/to the first declaration. if (ThisDeclID == Redecl.getFirstID()) { D->InstantiatedFromMember.setPointer( readDeclAs()); - D->InstantiatedFromMember.setInt(Record.readInt()); } } diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 555f6325da646..eb45124f91147 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -1707,13 +1707,14 @@ void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { VisitRedeclarable(D); + // if (D->getInstantiatedFromMemberTemplate()) + Record.push_back(D->isMemberSpecialization()); + // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that // getCommonPtr() can be used while this is still initializing. if (D->isFirstDecl()) { // This declaration owns the 'common' pointer, so serialize that data now. Record.AddDeclRef(D->getInstantiatedFromMemberTemplate()); - if (D->getInstantiatedFromMemberTemplate()) - Record.push_back(D->isMemberSpecialization()); } VisitTemplateDecl(D); @@ -1788,10 +1789,10 @@ void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( VisitClassTemplateSpecializationDecl(D); + Record.push_back(D->isMemberSpecialization()); // These are read/set from/to the first declaration. if (D->getPreviousDecl() == nullptr) { Record.AddDeclRef(D->getInstantiatedFromMember()); - Record.push_back(D->isMemberSpecialization()); } Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; @@ -1856,11 +1857,11 @@ void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl( Record.AddTemplateParameterList(D->getTemplateParameters()); VisitVarTemplateSpecializationDecl(D); + Record.push_back(D->isMemberSpecialization()); // These are read/set from/to the first declaration. if (D->getPreviousDecl() == nullptr) { Record.AddDeclRef(D->getInstantiatedFromMember()); - Record.push_back(D->isMemberSpecialization()); } Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION; diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp index 11ad401de23a8..bbe8c79bec374 100644 --- a/clang/test/PCH/cxx-templates.cpp +++ b/clang/test/PCH/cxx-templates.cpp @@ -34,15 +34,15 @@ struct A { void test(const int (&a6)[17]) { int x = templ_f(3); - + S::templ(); S::partial(); S::explicit_special(); - + Dep::Ty ty; Dep a; a.f(); - + S3 s3; s3.m(); From 6cb3f615c56fa7e24df82b841bf5c6025110620c Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 8 Aug 2024 09:58:22 -0400 Subject: [PATCH 02/35] [WIP] set isMemberSpecialization before comparing template parameter lists of class templates --- clang/lib/Sema/SemaTemplate.cpp | 45 +++++++++++-------- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 11 ++++- clang/lib/Sema/SemaTemplateInstantiate.cpp | 30 ++++++++++--- clang/lib/Serialization/ASTReaderDecl.cpp | 2 +- 4 files changed, 61 insertions(+), 27 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index f7496e82aa18a..0bd5350fd3de2 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1982,6 +1982,7 @@ DeclResult Sema::CheckClassTemplate( } if (PrevClassTemplate) { + #if 0 // Ensure that the template parameter lists are compatible. Skip this check // for a friend in a dependent context: the template parameter list itself // could be dependent. @@ -1994,6 +1995,7 @@ DeclResult Sema::CheckClassTemplate( PrevClassTemplate->getTemplateParameters(), /*Complain=*/true, TPL_TemplateMatch)) return true; + #endif // C++ [temp.class]p4: // In a redeclaration, partial specialization, explicit @@ -2044,23 +2046,6 @@ DeclResult Sema::CheckClassTemplate( return true; } - // Check the template parameter list of this declaration, possibly - // merging in the template parameter list from the previous class - // template declaration. Skip this check for a friend in a dependent - // context, because the template parameter list might be dependent. - if (!(TUK == TagUseKind::Friend && CurContext->isDependentContext()) && - CheckTemplateParameterList( - TemplateParams, - PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate) - : nullptr, - (SS.isSet() && SemanticContext && SemanticContext->isRecord() && - SemanticContext->isDependentContext()) - ? TPC_ClassTemplateMember - : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate - : TPC_ClassTemplate, - SkipBody)) - Invalid = true; - if (SS.isSet()) { // If the name of the template was qualified, we must be defining the // template out-of-line. @@ -2129,6 +2114,30 @@ DeclResult Sema::CheckClassTemplate( NewClass->setLexicalDeclContext(CurContext); NewTemplate->setLexicalDeclContext(CurContext); + + if (ShouldAddRedecl && PrevClassTemplate && !TemplateParameterListsAreEqual( + NewTemplate, TemplateParams, + PrevClassTemplate, PrevClassTemplate->getTemplateParameters(), + /*Complain=*/true, TPL_TemplateMatch)) + return true; + + + // Check the template parameter list of this declaration, possibly + // merging in the template parameter list from the previous class + // template declaration. Skip this check for a friend in a dependent + // context, because the template parameter list might be dependent. + if (ShouldAddRedecl && CheckTemplateParameterList( + TemplateParams, + PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate) + : nullptr, + (SS.isSet() && SemanticContext && SemanticContext->isRecord() && + SemanticContext->isDependentContext()) + ? TPC_ClassTemplateMember + : TUK == TagUseKind::Friend ? TPC_FriendClassTemplate + : TPC_ClassTemplate, + SkipBody)) + Invalid = true; + if (TUK == TagUseKind::Definition && (!SkipBody || !SkipBody->ShouldSkip)) NewClass->startDefinition(); @@ -11138,7 +11147,7 @@ class ExplicitSpecializationVisibilityChecker { template void checkTemplate(TemplDecl *TD) { if (TD->getMostRecentDecl()->isMemberSpecialization()) { - if (!CheckMemberSpecialization(TD)) + if (!CheckMemberSpecialization(TD->getMostRecentDecl())) diagnose(TD->getMostRecentDecl(), false); } } diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index 545da21183c3c..d09b7a807f700 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -802,8 +802,15 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, // A list of template arguments for transforming the require-clause of F. // It must contain the entire set of template argument lists. - MultiLevelTemplateArgumentList ArgsForBuildingRC; + MultiLevelTemplateArgumentList ArgsForBuildingRC = + SemaRef.getTemplateInstantiationArgs( + F, F->getLexicalDeclContext(), + /*Final=*/false, /*Innermost=*/TemplateArgsForBuildingRC, + /*RelativeToPrimary=*/true, + /*Pattern=*/nullptr, + /*ForConstraintInstantiation=*/true);; ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite); + #if 0 ArgsForBuildingRC.addOuterTemplateArguments(TemplateArgsForBuildingRC); // For 2), if the underlying deduction guide F is nested in a class template, // we need the entire template argument list, as the constraint AST in the @@ -846,6 +853,8 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, for (auto It : OuterLevelArgs) ArgsForBuildingRC.addOuterTemplateArguments(It.Args); } + #endif + ExprResult E = SemaRef.SubstExpr(RC, ArgsForBuildingRC); if (E.isInvalid()) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 51f49ef709a58..721a11de14399 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -385,12 +385,10 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, return Response::ChangeDecl(FTD->getLexicalDeclContext()); #else - if (!isa(FTD->getDeclContext())) { - Result.addOuterTemplateArguments( - const_cast(FTD), - const_cast(FTD)->getInjectedTemplateArgs(), - /*Final=*/false); - } + Result.addOuterTemplateArguments( + const_cast(FTD), + const_cast(FTD)->getInjectedTemplateArgs(), + /*Final=*/false); if (FTD->isMemberSpecialization()) return Response::Done(); @@ -401,6 +399,24 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, #endif } +Response HandleClassTemplateDecl(const ClassTemplateDecl *CTD, + MultiLevelTemplateArgumentList &Result) { + #if 0 + Result.addOuterTemplateArguments( + const_cast(CTD), + const_cast(CTD)->getInjectedTemplateArgs(), + /*Final=*/false); + + if (CTD->isMemberSpecialization()) + return Response::Done(); + + if (CTD->getFriendObjectKind()) + return Response::ChangeDecl(CTD->getLexicalDeclContext()); + return Response::UseNextDecl(CTD); + #endif + return Response::ChangeDecl(CTD->getLexicalDeclContext()); +} + Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec, MultiLevelTemplateArgumentList &Result, ASTContext &Context, @@ -539,7 +555,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( } else if (const auto *FTD = dyn_cast(CurDecl)) { R = HandleFunctionTemplateDecl(FTD, Result); } else if (const auto *CTD = dyn_cast(CurDecl)) { - R = Response::ChangeDecl(CTD->getLexicalDeclContext()); + R = HandleClassTemplateDecl(CTD, Result); } else if (!isa(CurDecl)) { R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl); if (const auto *TTP = dyn_cast(CurDecl)) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index d9556dc4ce731..5a893515de9cc 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -2888,7 +2888,7 @@ void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, // If we merged the template with a prior declaration chain, merge the // common pointer. // FIXME: Actually merge here, don't just overwrite. - D->Common = D->getCanonicalDecl()->Common; + D->Common.setPointer(D->getCanonicalDecl()->Common.getPointer()); } /// "Cast" to type T, asserting if we don't have an implicit conversion. From 420b553a8cdca38e036715e7c99c5ea202cf21af Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Thu, 8 Aug 2024 15:00:23 -0400 Subject: [PATCH 03/35] [FOLD] --- clang/lib/Sema/SemaTemplate.cpp | 2 +- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 2 +- clang/lib/Sema/SemaTemplateInstantiate.cpp | 73 +++++++++++++++---- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 ++ 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 0bd5350fd3de2..07b9638b751c8 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2128,7 +2128,7 @@ DeclResult Sema::CheckClassTemplate( // context, because the template parameter list might be dependent. if (ShouldAddRedecl && CheckTemplateParameterList( TemplateParams, - PrevClassTemplate ? GetTemplateParameterList(PrevClassTemplate) + PrevClassTemplate ? PrevClassTemplate->getTemplateParameters() : nullptr, (SS.isSet() && SemanticContext && SemanticContext->isRecord() && SemanticContext->isDependentContext()) diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index d09b7a807f700..ea02e979c4270 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -317,7 +317,7 @@ struct ConvertConstructorToDeductionGuideTransform { } if (NestedPattern) - OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(Template); + OuterInstantiationArgs = SemaRef.getTemplateInstantiationArgs(/*D=*/nullptr, Template->getDeclContext()); } Sema &SemaRef; diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 721a11de14399..aba1767497c56 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -52,7 +52,6 @@ using namespace sema; //===----------------------------------------------------------------------===/ namespace { -namespace TemplateInstArgsHelpers { struct Response { const Decl *NextDecl = nullptr; bool IsDone = false; @@ -84,6 +83,7 @@ struct Response { } }; +namespace TemplateInstArgsHelpers { // Retrieve the primary template for a lambda call operator. It's // unfortunate that we only have the mappings of call operators rather // than lambda classes. @@ -331,7 +331,8 @@ Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, } Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, - MultiLevelTemplateArgumentList &Result) { + MultiLevelTemplateArgumentList &Result, + bool ForConstraintInstantiation) { #if 0 if (!isa(FTD->getDeclContext())) { Result.addOuterTemplateArguments( @@ -385,10 +386,11 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, return Response::ChangeDecl(FTD->getLexicalDeclContext()); #else - Result.addOuterTemplateArguments( - const_cast(FTD), - const_cast(FTD)->getInjectedTemplateArgs(), - /*Final=*/false); + if (ForConstraintInstantiation) + Result.addOuterTemplateArguments( + const_cast(FTD), + const_cast(FTD)->getInjectedTemplateArgs(), + /*Final=*/false); if (FTD->isMemberSpecialization()) return Response::Done(); @@ -400,12 +402,15 @@ Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, } Response HandleClassTemplateDecl(const ClassTemplateDecl *CTD, - MultiLevelTemplateArgumentList &Result) { - #if 0 - Result.addOuterTemplateArguments( - const_cast(CTD), - const_cast(CTD)->getInjectedTemplateArgs(), - /*Final=*/false); + MultiLevelTemplateArgumentList &Result, + bool ForConstraintInstantiation, + bool SkipForSpecialization) { + #if 1 + if (!SkipForSpecialization && ForConstraintInstantiation) + Result.addOuterTemplateArguments( + const_cast(CTD), + const_cast(CTD)->getInjectedTemplateArgs(), + /*Final=*/false); if (CTD->isMemberSpecialization()) return Response::Done(); @@ -496,6 +501,38 @@ Response HandleGenericDeclContext(const Decl *CurDecl) { return Response::UseNextDecl(CurDecl); } } // namespace TemplateInstArgsHelpers + + +struct TemplateInstantiationArgumentCollecter + : DeclVisitor { + MultiLevelTemplateArgumentList &Result; + bool RelativeToPrimary; + bool ForConstraintInstantiation; + bool SkipForSpecialization; + + TemplateInstantiationArgumentCollecter( + MultiLevelTemplateArgumentList &Result, + bool RelativeToPrimary, + bool ForConstraintInstantiation, + bool SkipForSpecialization) : + Result(Result), RelativeToPrimary(RelativeToPrimary), + ForConstraintInstantiation(ForConstraintInstantiation), + SkipForSpecialization(SkipForSpecialization) { } + //using inherited = DeclVisitor; + + + + Decl *VisitDecl(Decl *D) { + if (D->isFileContextDecl()) + return nullptr; + + if (isa(D)) + RelativeToPrimary = false; + + return Decl::castFromDeclContext(D->getDeclContext()); + } +}; + } // namespace MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( @@ -529,6 +566,14 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( CurDecl = Response::UseNextDecl(CurDecl).NextDecl; } + TemplateInstantiationArgumentCollecter Collecter( + Result, RelativeToPrimary, + ForConstraintInstantiation, + SkipForSpecialization); + do { + CurDecl = Collecter.Visit(const_cast(CurDecl)); + } while (CurDecl); + while (!CurDecl->isFileContextDecl()) { Response R; if (const auto *VarTemplSpec = @@ -553,9 +598,9 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( dyn_cast(CurDecl)) { R = HandleImplicitConceptSpecializationDecl(CSD, Result); } else if (const auto *FTD = dyn_cast(CurDecl)) { - R = HandleFunctionTemplateDecl(FTD, Result); + R = HandleFunctionTemplateDecl(FTD, Result, ForConstraintInstantiation); } else if (const auto *CTD = dyn_cast(CurDecl)) { - R = HandleClassTemplateDecl(CTD, Result); + R = HandleClassTemplateDecl(CTD, Result, ForConstraintInstantiation, SkipForSpecialization); } else if (!isa(CurDecl)) { R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl); if (const auto *TTP = dyn_cast(CurDecl)) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index e055c87e78381..69958e494939c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -5186,9 +5186,14 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, RebuildTypeSourceInfoForDefaultSpecialMembers(); SetDeclDefaulted(Function, PatternDecl->getLocation()); } else { + #if 0 MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( Function, Function->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, false, PatternDecl); + #else + MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( + Function, Function->getLexicalDeclContext()); + #endif // Substitute into the qualifier; we can get a substitution failure here // through evil use of alias templates. From bd8156b69aca19021a6ed6598d8d81b8e13801fa Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 12 Aug 2024 08:30:01 -0400 Subject: [PATCH 04/35] [FOLD] pass old and new declarations to TemplateParameterListsAreEqual when comparing variable templates --- clang/lib/Sema/SemaDecl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index e269f8b58f5a7..84b8984971c51 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4506,8 +4506,8 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { // Ensure the template parameters are compatible. if (NewTemplate && - !TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(), - OldTemplate->getTemplateParameters(), + !TemplateParameterListsAreEqual(NewTemplate, NewTemplate->getTemplateParameters(), + OldTemplate, OldTemplate->getTemplateParameters(), /*Complain=*/true, TPL_TemplateMatch)) return New->setInvalidDecl(); From a37d7963ee5bd5d3950dd819b29438dde265d9e1 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 12 Aug 2024 08:30:36 -0400 Subject: [PATCH 05/35] [FOLD] implement TemplateInstantiationArgumentCollecter --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 320 +++++++++++++++++++-- 1 file changed, 299 insertions(+), 21 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index aba1767497c56..f61fd2848ac86 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -82,8 +82,6 @@ struct Response { return R; } }; - -namespace TemplateInstArgsHelpers { // Retrieve the primary template for a lambda call operator. It's // unfortunate that we only have the mappings of call operators rather // than lambda classes. @@ -171,6 +169,23 @@ bool isLambdaEnclosedByTypeAliasDecl( .TraverseType(Underlying); } +namespace TemplateInstArgsHelpers { + +// If we have a template template parameter with translation unit context, +// then we're performing substitution into a default template argument of +// this template template parameter before we've constructed the template +// that will own this template template parameter. In this case, we +// use empty template parameter lists for all of the outer templates +// to avoid performing any substitutions. +Response +HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP, + MultiLevelTemplateArgumentList &Result) { + for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I) + Result.addOuterTemplateArguments(std::nullopt); + return Response::Done(); +} + +#if 0 // Add template arguments from a variable template instantiation. Response HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec, @@ -211,20 +226,6 @@ HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec, return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec); } -// If we have a template template parameter with translation unit context, -// then we're performing substitution into a default template argument of -// this template template parameter before we've constructed the template -// that will own this template template parameter. In this case, we -// use empty template parameter lists for all of the outer templates -// to avoid performing any substitutions. -Response -HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP, - MultiLevelTemplateArgumentList &Result) { - for (unsigned I = 0, N = TTP->getDepth() + 1; I != N; ++I) - Result.addOuterTemplateArguments(std::nullopt); - return Response::Done(); -} - Response HandlePartialClassTemplateSpec( const ClassTemplatePartialSpecializationDecl *PartialClassTemplSpec, MultiLevelTemplateArgumentList &Result, bool SkipForSpecialization) { @@ -500,36 +501,310 @@ Response HandleImplicitConceptSpecializationDecl( Response HandleGenericDeclContext(const Decl *CurDecl) { return Response::UseNextDecl(CurDecl); } +#endif } // namespace TemplateInstArgsHelpers struct TemplateInstantiationArgumentCollecter : DeclVisitor { + Sema &S; MultiLevelTemplateArgumentList &Result; bool RelativeToPrimary; bool ForConstraintInstantiation; bool SkipForSpecialization; TemplateInstantiationArgumentCollecter( + Sema &S, MultiLevelTemplateArgumentList &Result, bool RelativeToPrimary, bool ForConstraintInstantiation, bool SkipForSpecialization) : - Result(Result), RelativeToPrimary(RelativeToPrimary), + S(S), Result(Result), RelativeToPrimary(RelativeToPrimary), ForConstraintInstantiation(ForConstraintInstantiation), SkipForSpecialization(SkipForSpecialization) { } - //using inherited = DeclVisitor; + Decl *Done() { + return nullptr; + } + + Decl *ChangeDecl(const Decl *D) { + RelativeToPrimary = false; + return const_cast(D); + } + + Decl *ChangeDecl(const DeclContext *DC) { + return ChangeDecl(Decl::castFromDeclContext(DC)); + } + + Decl *UseNextDecl(const Decl *D) { + return ChangeDecl(D->getDeclContext()); + } + + Decl *DontClearRelativeToPrimaryNextDecl(const Decl* D) { + return const_cast( + Decl::castFromDeclContext(D->getDeclContext())); + } + + Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) { + for (unsigned I = 0, N = TTPD->getDepth() + 1; I != N; ++I) + Result.addOuterTemplateArguments(std::nullopt); + return Done(); + } + + Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *FTD) { + if (ForConstraintInstantiation) + Result.addOuterTemplateArguments( + FTD, FTD->getInjectedTemplateArgs(), /*Final=*/false); + + if (FTD->isMemberSpecialization()) + return Done(); + + if (FTD->getFriendObjectKind()) + return ChangeDecl(FTD->getLexicalDeclContext()); + return UseNextDecl(FTD); + } + + Decl *VisitVarTemplateDecl(VarTemplateDecl *VTD) { + if (!SkipForSpecialization && ForConstraintInstantiation) + Result.addOuterTemplateArguments( + VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false); + + if (VTD->isMemberSpecialization()) + return Done(); + + return UseNextDecl(VTD); + } + + Decl *VisitClassTemplateDecl(ClassTemplateDecl *CTD) { + if (!SkipForSpecialization && ForConstraintInstantiation) + Result.addOuterTemplateArguments( + CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false); + + if (CTD->isMemberSpecialization()) + return Done(); + + if (CTD->getFriendObjectKind()) + return ChangeDecl(CTD->getLexicalDeclContext()); + return UseNextDecl(CTD); + } + + Decl *VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl *CTPSD) { + if (!SkipForSpecialization) + Result.addOuterRetainedLevels(CTPSD->getTemplateDepth()); + return Done(); + } + + Decl *VisitFunctionDecl(FunctionDecl *FD) { + // Add template arguments from a function template specialization. + if (!RelativeToPrimary && + FD->getTemplateSpecializationKindForInstantiation() == + TSK_ExplicitSpecialization) + return Done(); + + if (!RelativeToPrimary && + FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { + // This is an implicit instantiation of an explicit specialization. We + // don't get any template arguments from this function but might get + // some from an enclosing template. + return UseNextDecl(FD); + } else if (const TemplateArgumentList *TemplateArgs = + FD->getTemplateSpecializationArgs()) { + // Add the template arguments for this specialization. + Result.addOuterTemplateArguments( + FD, TemplateArgs->asArray(), /*Final=*/false); + + if (RelativeToPrimary && + (FD->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization || + (FD->getFriendObjectKind() && + !FD->getPrimaryTemplate()->getFriendObjectKind()))) + return UseNextDecl(FD); + + // If this function was instantiated from a specialized member that is + // a function template, we're done. + assert(FD->getPrimaryTemplate() && "No function template?"); + if (FD->getPrimaryTemplate()->isMemberSpecialization()) + return Done(); + + // If this function is a generic lambda specialization, we are done. + if (!ForConstraintInstantiation && + isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) { + // TypeAliasTemplateDecls should be taken into account, e.g. + // when we're deducing the return type of a lambda. + // + // template int Value = 0; + // template + // using T = decltype([]() { return Value; }()); + // + if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S)) { + if (isLambdaEnclosedByTypeAliasDecl( + /*PrimaryLambdaCallOperator=*/getPrimaryTemplateOfGenericLambda(FD), + /*PrimaryTypeAliasDecl=*/TypeAlias.PrimaryTypeAliasDecl)) + return UseNextDecl(FD); + } + return Done(); + } + + } else if (FD->getDescribedFunctionTemplate()) { + assert( + (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && + "Outer template not instantiated?"); + } + // If this is a friend or local declaration and it declares an entity at + // namespace scope, take arguments from its lexical parent + // instead of its semantic parent, unless of course the pattern we're + // instantiating actually comes from the file's context! + if ((FD->getFriendObjectKind() || FD->isLocalExternDecl()) && + FD->getNonTransparentDeclContext()->isFileContext()) { + return ChangeDecl(FD->getLexicalDeclContext()); + } + + if (ForConstraintInstantiation && FD->getFriendObjectKind()) + return ChangeDecl(FD->getLexicalDeclContext()); + return UseNextDecl(FD); + } + + Decl *VisitCXXRecordDecl(CXXRecordDecl *RD) { + if (ClassTemplateDecl *ClassTemplate = RD->getDescribedClassTemplate()) { + assert( + (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && + "Outer template not instantiated?"); + if (ClassTemplate->isMemberSpecialization()) + return Done(); + if (ForConstraintInstantiation) + Result.addOuterTemplateArguments( + RD, ClassTemplate->getInjectedTemplateArgs(), /*Final=*/false); + } + if (const MemberSpecializationInfo *MSInfo = + RD->getMemberSpecializationInfo()) + if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return Done(); + + bool IsFriend = RD->getFriendObjectKind() || + (RD->getDescribedClassTemplate() && + RD->getDescribedClassTemplate()->getFriendObjectKind()); + if (ForConstraintInstantiation && IsFriend && + RD->getNonTransparentDeclContext()->isFileContext()) { + return ChangeDecl(RD->getLexicalDeclContext()); + } + + // This is to make sure we pick up the VarTemplateSpecializationDecl or the + // TypeAliasTemplateDecl that this lambda is defined inside of. + if (RD->isLambda()) { + if (Decl *LCD = RD->getLambdaContextDecl()) + return ChangeDecl(LCD); + // Retrieve the template arguments for a using alias declaration. + // This is necessary for constraint checking, since we always keep + // constraints relative to the primary template. + if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S)) { + const FunctionDecl *PrimaryLambdaCallOperator = + getPrimaryTemplateOfGenericLambda(RD->getLambdaCallOperator()); + if (isLambdaEnclosedByTypeAliasDecl(PrimaryLambdaCallOperator, + TypeAlias.PrimaryTypeAliasDecl)) { + Result.addOuterTemplateArguments(TypeAlias.Template, + TypeAlias.AssociatedTemplateArguments, + /*Final=*/false); + // Visit the parent of the current type alias declaration rather than + // the lambda thereof. + // E.g., in the following example: + // struct S { + // template using T = decltype([] {} ()); + // }; + // void foo() { + // S::T var; + // } + // The instantiated lambda expression (which we're visiting at 'var') + // has a function DeclContext 'foo' rather than the Record DeclContext + // S. This seems to be an oversight to me that we may want to set a + // Sema Context from the CXXScopeSpec before substituting into T. + return ChangeDecl(TypeAlias.Template->getDeclContext()); + } + } + } + + return UseNextDecl(RD); + } + + Decl *VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) { + if (!CTSD->isClassScopeExplicitSpecialization()) { + // We're done when we hit an explicit specialization. + if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization && + !isa(CTSD)) + return Done(); + + if (!SkipForSpecialization) + Result.addOuterTemplateArguments( + CTSD, CTSD->getTemplateInstantiationArgs().asArray(), /*Final=*/false); + + // If this class template specialization was instantiated from a + // specialized member that is a class template, we're done. + assert(CTSD->getSpecializedTemplate() && "No class template?"); + if (CTSD->getSpecializedTemplate()->isMemberSpecialization()) + return Done(); + + // If this was instantiated from a partial template specialization, we need + // to get the next level of declaration context from the partial + // specialization, as the ClassTemplateSpecializationDecl's + // DeclContext/LexicalDeclContext will be for the primary template. + if (auto *CTPSD = CTSD->getSpecializedTemplateOrPartial() + .dyn_cast()) + return ChangeDecl(CTPSD->getLexicalDeclContext()); + } + return UseNextDecl(CTSD); + } + + Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) { + // For a class-scope explicit specialization, there are no template arguments + // at this level, but there may be enclosing template arguments. + if (VTSD->isClassScopeExplicitSpecialization()) + return DontClearRelativeToPrimaryNextDecl(VTSD); + + // We're done when we hit an explicit specialization. + if (VTSD->getSpecializationKind() == TSK_ExplicitSpecialization && + !isa(VTSD)) + return Done(); + + // If this variable template specialization was instantiated from a + // specialized member that is a variable template, we're done. + assert(VTSD->getSpecializedTemplate() && "No variable template?"); + llvm::PointerUnion + Specialized = VTSD->getSpecializedTemplateOrPartial(); + if (VarTemplatePartialSpecializationDecl *VTPSD = + Specialized.dyn_cast()) { + if (!SkipForSpecialization) + Result.addOuterTemplateArguments( + VTPSD, VTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); + if (VTPSD->isMemberSpecialization()) + return Done(); + } else { + VarTemplateDecl *VTD = Specialized.get(); + if (!SkipForSpecialization) + Result.addOuterTemplateArguments( + VTD, VTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); + if (VTD->isMemberSpecialization()) + return Done(); + } + return DontClearRelativeToPrimaryNextDecl(VTSD); + } + + Decl *VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl *ICSD) { + Result.addOuterTemplateArguments( + ICSD, ICSD->getTemplateArguments(), + /*Final=*/false); + return UseNextDecl(ICSD); + } Decl *VisitDecl(Decl *D) { if (D->isFileContextDecl()) - return nullptr; + return Done(); if (isa(D)) RelativeToPrimary = false; - return Decl::castFromDeclContext(D->getDeclContext()); + return UseNextDecl(D); } }; @@ -567,13 +842,15 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( } TemplateInstantiationArgumentCollecter Collecter( - Result, RelativeToPrimary, + *this, Result, RelativeToPrimary, ForConstraintInstantiation, SkipForSpecialization); do { CurDecl = Collecter.Visit(const_cast(CurDecl)); } while (CurDecl); + return Result; + #if 0 while (!CurDecl->isFileContextDecl()) { Response R; if (const auto *VarTemplSpec = @@ -619,6 +896,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( } return Result; + #endif } bool Sema::CodeSynthesisContext::isInstantiationRecord() const { From 07d100a9d86f6960d965b3c35d6e7c868a5416a7 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 12 Aug 2024 08:52:11 -0400 Subject: [PATCH 06/35] [FOLD] update test --- .../class-template-partial-specializations.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp index 7772eecc69be8..3358869b95e37 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.order/class-template-partial-specializations.cpp @@ -33,11 +33,12 @@ class D{}; // expected-note{{previous definition is here}} template class D{}; // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}} expected-error{{redefinition of 'D'}} -template requires C1 // expected-note{{previous template declaration is here}} -class E{}; +template requires C1 +class E{}; // expected-note{{previous definition is here}} -template // expected-error{{requires clause differs in template redeclaration}} +template class E{}; // expected-error{{class template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}} + // expected-error@-1{{redefinition of 'E'}} template struct F{ enum{ value = 1 }; }; From 37f1461a37c7e8bef103552e2f8f45b524d6cacb Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 12 Aug 2024 12:25:45 -0400 Subject: [PATCH 07/35] [FOLD] further simplify getTemplateInstantiationArgs --- clang/lib/Sema/SemaTemplateDeduction.cpp | 30 +++++ clang/lib/Sema/SemaTemplateInstantiate.cpp | 107 ++++++++++++++++-- clang/test/SemaCXX/friend.cpp | 4 +- .../SemaTemplate/default-expr-arguments.cpp | 26 ++--- 4 files changed, 142 insertions(+), 25 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index cc095ae67ac40..ff9e045289e95 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3138,6 +3138,8 @@ template<> struct IsPartialSpecialization { static constexpr bool value = true; }; + +#if 0 template static bool DeducedArgsNeedReplacement(TemplateDeclT *Template) { return false; @@ -3152,6 +3154,7 @@ bool DeducedArgsNeedReplacement( ClassTemplatePartialSpecializationDecl *Spec) { return !Spec->isClassScopeExplicitSpecialization(); } +#endif template static TemplateDeductionResult @@ -3162,6 +3165,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, llvm::SmallVector AssociatedConstraints; Template->getAssociatedConstraints(AssociatedConstraints); + #if 0 std::optional> Innermost; // If we don't need to replace the deduced template arguments, // we can add them immediately as the inner-most argument list. @@ -3179,6 +3183,32 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, // instead of adding to inner-most. if (!Innermost) MLTAL.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs); + #endif + MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( + Template, Template->getDeclContext(), /*Final=*/false, + /*Innermost=*/CanonicalDeducedArgs, /*RelativeToPrimary=*/true, + /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); + + #if 0 + if (DeducedArgsNeedReplacement(Template)) { + MultiLevelTemplateArgumentList WithReplacement = S.getTemplateInstantiationArgs( + Template, Template->getDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, + /*RelativeToPrimary=*/true, /*Pattern=*/ + nullptr, /*ForConstraintInstantiation=*/true); + + WithReplacement.replaceInnermostTemplateArguments(Template, CanonicalDeducedArgs); + + assert(MLTAL.getNumLevels() == WithReplacement.getNumLevels()); + assert(MLTAL.getNumSubstitutedLevels() == WithReplacement.getNumSubstitutedLevels()); + auto First0 = MLTAL.begin(), Last0 = MLTAL.end(); + auto First1 = WithReplacement.begin(), Last1 = WithReplacement.end(); + + while (First0 != Last0) { + assert(First0->Args.data() == First1->Args.data()); + ++First0, ++First1; + } + } + #endif if (S.CheckConstraintSatisfaction(Template, AssociatedConstraints, MLTAL, Info.getLocation(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index f61fd2848ac86..29f33bd20872f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -546,12 +546,21 @@ struct TemplateInstantiationArgumentCollecter } Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) { + #if 0 for (unsigned I = 0, N = TTPD->getDepth() + 1; I != N; ++I) Result.addOuterTemplateArguments(std::nullopt); return Done(); + #endif + if (ForConstraintInstantiation) + Result.addOuterTemplateArguments(std::nullopt); + + return UseNextDecl(TTPD); } Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *FTD) { + assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && + "outer template not instantiated?"); + if (ForConstraintInstantiation) Result.addOuterTemplateArguments( FTD, FTD->getInjectedTemplateArgs(), /*Final=*/false); @@ -565,6 +574,9 @@ struct TemplateInstantiationArgumentCollecter } Decl *VisitVarTemplateDecl(VarTemplateDecl *VTD) { + assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && + "outer template not instantiated?"); + if (!SkipForSpecialization && ForConstraintInstantiation) Result.addOuterTemplateArguments( VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false); @@ -576,6 +588,9 @@ struct TemplateInstantiationArgumentCollecter } Decl *VisitClassTemplateDecl(ClassTemplateDecl *CTD) { + assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && + "outer template not instantiated?"); + if (!SkipForSpecialization && ForConstraintInstantiation) Result.addOuterTemplateArguments( CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false); @@ -588,13 +603,24 @@ struct TemplateInstantiationArgumentCollecter return UseNextDecl(CTD); } + #if 0 Decl *VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl *CTPSD) { if (!SkipForSpecialization) Result.addOuterRetainedLevels(CTPSD->getTemplateDepth()); return Done(); } + #endif Decl *VisitFunctionDecl(FunctionDecl *FD) { + if (!RelativeToPrimary) { + if (const MemberSpecializationInfo *MSI = FD->getMemberSpecializationInfo(); + MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return Done(); + + if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return UseNextDecl(FD); + } + #if 0 // Add template arguments from a function template specialization. if (!RelativeToPrimary && FD->getTemplateSpecializationKindForInstantiation() == @@ -607,13 +633,15 @@ struct TemplateInstantiationArgumentCollecter // don't get any template arguments from this function but might get // some from an enclosing template. return UseNextDecl(FD); - } else if (const TemplateArgumentList *TemplateArgs = + } else + #endif + if (const TemplateArgumentList *TemplateArgs = FD->getTemplateSpecializationArgs()) { // Add the template arguments for this specialization. Result.addOuterTemplateArguments( FD, TemplateArgs->asArray(), /*Final=*/false); - if (RelativeToPrimary && + if ( // RelativeToPrimary && (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization || (FD->getFriendObjectKind() && @@ -676,10 +704,9 @@ struct TemplateInstantiationArgumentCollecter RD, ClassTemplate->getInjectedTemplateArgs(), /*Final=*/false); } - if (const MemberSpecializationInfo *MSInfo = - RD->getMemberSpecializationInfo()) - if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return Done(); + if (const MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo(); + MSI &&MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return Done(); bool IsFriend = RD->getFriendObjectKind() || (RD->getDescribedClassTemplate() && @@ -727,6 +754,7 @@ struct TemplateInstantiationArgumentCollecter } Decl *VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) { + #if 0 if (!CTSD->isClassScopeExplicitSpecialization()) { // We're done when we hit an explicit specialization. if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization && @@ -752,10 +780,60 @@ struct TemplateInstantiationArgumentCollecter return ChangeDecl(CTPSD->getLexicalDeclContext()); } return UseNextDecl(CTSD); + #else + // For a class-scope explicit specialization, there are no template arguments + // at this level, but there may be enclosing template arguments. + if (CTSD->isClassScopeExplicitSpecialization()) + return DontClearRelativeToPrimaryNextDecl(CTSD); + + // We're done when we hit an explicit specialization. + if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization && + !isa(CTSD)) + return Done(); + + // If this class template specialization was instantiated from a + // specialized member that is a class template, we're done. + assert(CTSD->getSpecializedTemplate() && "No class template?"); + llvm::PointerUnion + Specialized = CTSD->getSpecializedTemplateOrPartial(); + #if 0 + if (auto *CTPSD = Specialized.dyn_cast()) { + if (!SkipForSpecialization) + Result.addOuterTemplateArguments( + CTPSD, CTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); + if (CTPSD->isMemberSpecialization()) + return Done(); + } else { + auto *CTD = Specialized.get(); + if (!SkipForSpecialization) + Result.addOuterTemplateArguments( + CTD, CTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); + if (CTD->isMemberSpecialization()) + return Done(); + } + #else + if (!SkipForSpecialization) + Result.addOuterTemplateArguments( + CTSD, CTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); + if (auto *CTPSD = Specialized.dyn_cast()) { + if (CTPSD->isMemberSpecialization()) + return Done(); + } else { + auto *CTD = Specialized.get(); + if (CTD->isMemberSpecialization()) + return Done(); + } + #endif + + return DontClearRelativeToPrimaryNextDecl(CTSD); + #endif } Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) { - // For a class-scope explicit specialization, there are no template arguments + // For a class-scope explicit specialization, there are no template arguments // at this level, but there may be enclosing template arguments. if (VTSD->isClassScopeExplicitSpecialization()) return DontClearRelativeToPrimaryNextDecl(VTSD); @@ -770,8 +848,7 @@ struct TemplateInstantiationArgumentCollecter assert(VTSD->getSpecializedTemplate() && "No variable template?"); llvm::PointerUnion Specialized = VTSD->getSpecializedTemplateOrPartial(); - if (VarTemplatePartialSpecializationDecl *VTPSD = - Specialized.dyn_cast()) { + if (auto *VTPSD = Specialized.dyn_cast()) { if (!SkipForSpecialization) Result.addOuterTemplateArguments( VTPSD, VTSD->getTemplateInstantiationArgs().asArray(), @@ -779,7 +856,7 @@ struct TemplateInstantiationArgumentCollecter if (VTPSD->isMemberSpecialization()) return Done(); } else { - VarTemplateDecl *VTD = Specialized.get(); + auto *VTD = Specialized.get(); if (!SkipForSpecialization) Result.addOuterTemplateArguments( VTD, VTSD->getTemplateInstantiationArgs().asArray(), @@ -806,6 +883,14 @@ struct TemplateInstantiationArgumentCollecter return UseNextDecl(D); } + + Decl *Visit(Decl *D) { + #if 0 + if (TemplateDecl *TD = D->getDescribedTemplate()) + D = TD; + #endif + return DeclVisitor::Visit(D); + } }; } // namespace @@ -819,6 +904,8 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( // Accumulate the set of template argument lists in this structure. MultiLevelTemplateArgumentList Result; + SkipForSpecialization = false; + using namespace TemplateInstArgsHelpers; const Decl *CurDecl = ND; diff --git a/clang/test/SemaCXX/friend.cpp b/clang/test/SemaCXX/friend.cpp index 53e6bbfcf42a8..0283fa1f7b212 100644 --- a/clang/test/SemaCXX/friend.cpp +++ b/clang/test/SemaCXX/friend.cpp @@ -52,14 +52,14 @@ namespace test3 { namespace test4 { class T4A { friend class T4B; - + public: T4A(class T4B *); protected: T4B *mB; // error here }; - + class T4B {}; } diff --git a/clang/test/SemaTemplate/default-expr-arguments.cpp b/clang/test/SemaTemplate/default-expr-arguments.cpp index 438f5b1aa95f7..7570110caae81 100644 --- a/clang/test/SemaTemplate/default-expr-arguments.cpp +++ b/clang/test/SemaTemplate/default-expr-arguments.cpp @@ -23,10 +23,10 @@ template void f3(T a, T b = T() + T()); // expected-error{{invalid o void g() { f1(10); f1(S()); // expected-note{{in instantiation of default function argument expression for 'f1' required here}} - + f2(10); f2(S()); - + f3(10); f3(S()); // expected-note{{in instantiation of default function argument expression for 'f3' required here}} } @@ -48,7 +48,7 @@ void g2() { void g3(F f, F s) { f.f(); s.f(); // expected-note{{in instantiation of default function argument expression for 'f' required here}} - + F f2; F s2; // expected-note{{in instantiation of default function argument expression for 'F' required here}} } @@ -115,7 +115,7 @@ template struct A { // expected-note 3{{passing argument to parameter here}} }; -struct B : A { +struct B : A { B(); }; B::B() { } // expected-note {{in instantiation of default function argument expression for 'A' required he}} @@ -127,7 +127,7 @@ C::C() { } // expected-note {{in instantiation of default function argument expr struct D { D(); - + A a; }; D::D() { } // expected-note {{in instantiation of default function argument expression for 'A' required he}} @@ -162,12 +162,12 @@ namespace PR5810 { struct allocator { allocator() { int a[sizeof(T) ? -1 : -1]; } // expected-error2 {{array with a negative size}} }; - + template struct vector { vector(const allocator& = allocator()) {} // expected-note2 {{instantiation of}} }; - + struct A { }; struct B { }; @@ -175,7 +175,7 @@ namespace PR5810 { void FilterVTs() { vector Result; } - + void f() { vector Result; } @@ -229,8 +229,8 @@ namespace PR5810b { namespace PR5810c { template - struct X { - X() { + struct X { + X() { T t; double *****p = t; // expected-error{{cannot initialize a variable of type 'double *****' with an lvalue of type 'int'}} } @@ -251,7 +251,7 @@ namespace PR8127 { PointerClass( T * object_p ) : p_( object_p ) { p_->acquire(); } - private: + private: T * p_; }; @@ -285,8 +285,8 @@ namespace rdar8427926 { } namespace PR8401 { - template - struct A { + template + struct A { A() { T* x = 1; } // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} }; From f1e1272862a3d51720ad7c2f5145e13b0117f12c Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 12 Aug 2024 14:17:08 -0400 Subject: [PATCH 08/35] [FOLD] add tests --- .../temp/temp.constr/temp.constr.decl/p4.cpp | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp new file mode 100644 index 0000000000000..f6e0d45334c0f --- /dev/null +++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp @@ -0,0 +1,108 @@ +// RUN: %clang_cc1 -std=c++20 -verify %s + +template +struct A { + template + void f() requires V; + + template<> + void f(); + + template requires V + struct B; + + template requires V + struct B; + + template<> + struct B; + + template requires V + static int x; + + template requires V + static int x; + + template<> + int x; +}; + +template +template +void A::f() requires V { } + +template +template requires V +struct A::B { }; + +template +template requires V +struct A::B { }; + +template +template requires V +struct A::B { }; + +template +template requires V +int A::x = 0; + +template +template requires V +int A::x = 0; + +template +template requires V +int A::x = 0; + +template<> +template +void A::f() requires V; + +template<> +template<> +void A::f(); + +template<> +template<> +void A::f(); + +template<> +template requires V +struct A::B; + +template<> +template<> +struct A::B; + +template<> +template<> +struct A::B; + +template<> +template requires V +struct A::B; + +template<> +template requires V +struct A::B; + +template<> +template requires V +int A::x; + +template<> +template<> +int A::x; + +template<> +template<> +int A::x; + +template<> +template requires V +int A::x; + +template<> +template requires V +int A::x; From 623e4aca11b83d6d45d069ff75f7989535477ede Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 12 Aug 2024 14:59:26 -0400 Subject: [PATCH 09/35] [FOLD] --- clang/lib/Sema/SemaConcept.cpp | 12 ++++++++---- clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 ++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 6a1b32598bb4a..5fd2b998c7fc8 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -585,7 +585,7 @@ static bool CheckConstraintSatisfaction( ArrayRef TemplateArgs = TemplateArgsLists.getNumSubstitutedLevels() > 0 - ? TemplateArgsLists.getOutermost() + ? TemplateArgsLists.getInnermost() : ArrayRef {}; Sema::InstantiatingTemplate Inst(S, TemplateIDRange.getBegin(), Sema::InstantiatingTemplate::ConstraintsCheck{}, @@ -1063,16 +1063,20 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, bool Sema::FriendConstraintsDependOnEnclosingTemplate(const FunctionDecl *FD) { assert(FD->getFriendObjectKind() && "Must be a friend!"); + FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate(); // The logic for non-templates is handled in ASTContext::isSameEntity, so we // don't have to bother checking 'DependsOnEnclosingTemplate' for a // non-function-template. - assert(FD->getDescribedFunctionTemplate() && - "Non-function templates don't need to be checked"); + assert(FTD && "Non-function templates don't need to be checked"); SmallVector ACs; - FD->getDescribedFunctionTemplate()->getAssociatedConstraints(ACs); + FTD->getAssociatedConstraints(ACs); + #if 0 unsigned OldTemplateDepth = CalculateTemplateDepthForConstraints(*this, FD); + #else + unsigned OldTemplateDepth = FTD->getTemplateParameters()->getDepth(); + #endif for (const Expr *Constraint : ACs) if (ConstraintExpressionDependsOnEnclosingTemplate(FD, OldTemplateDepth, Constraint)) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 29f33bd20872f..c3883e0b31d81 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -705,7 +705,7 @@ struct TemplateInstantiationArgumentCollecter } if (const MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo(); - MSI &&MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) return Done(); bool IsFriend = RD->getFriendObjectKind() || @@ -912,6 +912,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( if (!CurDecl) CurDecl = Decl::castFromDeclContext(DC); + #if 1 if (Innermost) { Result.addOuterTemplateArguments(const_cast(ND), *Innermost, Final); @@ -927,6 +928,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( HandleDefaultTempArgIntoTempTempParam(TTP, Result); CurDecl = Response::UseNextDecl(CurDecl).NextDecl; } + #endif TemplateInstantiationArgumentCollecter Collecter( *this, Result, RelativeToPrimary, @@ -935,6 +937,11 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( do { CurDecl = Collecter.Visit(const_cast(CurDecl)); } while (CurDecl); + + #if 0 + if (Innermost) + Result.replaceInnermostTemplateArguments(const_cast(ND), *Innermost); + #endif return Result; #if 0 From 3c78bbfcf1313a2d28d70688012c3c955fa5401c Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 13 Aug 2024 09:27:34 -0400 Subject: [PATCH 10/35] [FOLD] remove SkipForSpecialization and Pattern parameters from getTemplateInstantiationArgs --- clang/include/clang/Sema/Sema.h | 5 +- clang/lib/Sema/SemaConcept.cpp | 15 ++--- clang/lib/Sema/SemaTemplate.cpp | 4 +- clang/lib/Sema/SemaTemplateDeduction.cpp | 2 +- clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 1 - clang/lib/Sema/SemaTemplateInstantiate.cpp | 57 ++++++++----------- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 +- 7 files changed, 32 insertions(+), 54 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index cae01722af23a..ab158d52c6a40 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -13088,10 +13088,7 @@ class Sema final : public SemaBase { MultiLevelTemplateArgumentList getTemplateInstantiationArgs( const NamedDecl *D, const DeclContext *DC = nullptr, bool Final = false, std::optional> Innermost = std::nullopt, - bool RelativeToPrimary = false, const FunctionDecl *Pattern = nullptr, - bool ForConstraintInstantiation = false, - bool SkipForSpecialization = false, - bool ForDefaultArgumentSubstitution = false); + bool RelativeToPrimary = false, bool ForConstraintInstantiation = false); /// RAII object to handle the state changes required to synthesize /// a function body. diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 5fd2b998c7fc8..bff98e21564cd 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -833,7 +833,6 @@ Sema::SetupConstraintCheckingTemplateArgumentsAndScope( getTemplateInstantiationArgs(FD, FD->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); if (SetupConstraintScope(FD, TemplateArgs, MLTAL, Scope)) return std::nullopt; @@ -910,14 +909,12 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, // the purpose of seeing if they differ by constraints. This isn't the same as // getTemplateDepth, because it includes already instantiated parents. static unsigned -CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND, - bool SkipForSpecialization = false) { +CalculateTemplateDepthForConstraints(Sema &S, const NamedDecl *ND) { MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( ND, ND->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/true, SkipForSpecialization); + /*ForConstraintInstantiation=*/true); return MLTAL.getNumLevels(); } @@ -956,8 +953,7 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true, - /*SkipForSpecialization*/ false); + /*ForConstraintInstantiation=*/true); if (MLTAL.getNumSubstitutedLevels() == 0) return ConstrExpr; @@ -1523,7 +1519,6 @@ static bool substituteParameterMappings(Sema &S, NormalizedConstraint &N, CSE->getNamedConcept(), CSE->getNamedConcept()->getLexicalDeclContext(), /*Final=*/false, CSE->getTemplateArguments(), /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); return substituteParameterMappings(S, N, CSE->getNamedConcept(), MLTAL, @@ -1804,8 +1799,8 @@ bool Sema::IsAtLeastAsConstrained(NamedDecl *D1, return false; } - unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1, true); - unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2, true); + unsigned Depth1 = CalculateTemplateDepthForConstraints(*this, D1); + unsigned Depth2 = CalculateTemplateDepthForConstraints(*this, D2); for (size_t I = 0; I != AC1.size() && I != AC2.size(); ++I) { if (Depth2 > Depth1) { diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 07b9638b751c8..4953e522ada4c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5624,9 +5624,7 @@ bool Sema::CheckTemplateArgumentList( MultiLevelTemplateArgumentList MLTAL = getTemplateInstantiationArgs( Template, NewContext, /*Final=*/false, CanonicalConverted, - /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, - /*ForConceptInstantiation=*/true); + /*RelativeToPrimary=*/true, /*ForConceptInstantiation=*/true); if (EnsureTemplateArgumentListConstraints( Template, MLTAL, SourceRange(TemplateLoc, TemplateArgs.getRAngleLoc()))) { diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index ff9e045289e95..cf3db187d85d8 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -3187,7 +3187,7 @@ CheckDeducedArgumentConstraints(Sema &S, TemplateDeclT *Template, MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( Template, Template->getDeclContext(), /*Final=*/false, /*Innermost=*/CanonicalDeducedArgs, /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true); + /*ForConstraintInstantiation=*/true); #if 0 if (DeducedArgsNeedReplacement(Template)) { diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp index ea02e979c4270..e74f9abb3ea41 100644 --- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp +++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp @@ -807,7 +807,6 @@ buildAssociatedConstraints(Sema &SemaRef, FunctionTemplateDecl *F, F, F->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/TemplateArgsForBuildingRC, /*RelativeToPrimary=*/true, - /*Pattern=*/nullptr, /*ForConstraintInstantiation=*/true);; ArgsForBuildingRC.setKind(clang::TemplateSubstitutionKind::Rewrite); #if 0 diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index c3883e0b31d81..a0c17425924de 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -511,17 +511,15 @@ struct TemplateInstantiationArgumentCollecter MultiLevelTemplateArgumentList &Result; bool RelativeToPrimary; bool ForConstraintInstantiation; - bool SkipForSpecialization; TemplateInstantiationArgumentCollecter( Sema &S, MultiLevelTemplateArgumentList &Result, bool RelativeToPrimary, - bool ForConstraintInstantiation, - bool SkipForSpecialization) : + bool ForConstraintInstantiation) : S(S), Result(Result), RelativeToPrimary(RelativeToPrimary), - ForConstraintInstantiation(ForConstraintInstantiation), - SkipForSpecialization(SkipForSpecialization) { } + ForConstraintInstantiation(ForConstraintInstantiation) { + } Decl *Done() { return nullptr; @@ -577,7 +575,7 @@ struct TemplateInstantiationArgumentCollecter assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && "outer template not instantiated?"); - if (!SkipForSpecialization && ForConstraintInstantiation) + if (ForConstraintInstantiation) Result.addOuterTemplateArguments( VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false); @@ -591,7 +589,7 @@ struct TemplateInstantiationArgumentCollecter assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && "outer template not instantiated?"); - if (!SkipForSpecialization && ForConstraintInstantiation) + if (ForConstraintInstantiation) Result.addOuterTemplateArguments( CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false); @@ -798,26 +796,23 @@ struct TemplateInstantiationArgumentCollecter Specialized = CTSD->getSpecializedTemplateOrPartial(); #if 0 if (auto *CTPSD = Specialized.dyn_cast()) { - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - CTPSD, CTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + Result.addOuterTemplateArguments( + CTPSD, CTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); if (CTPSD->isMemberSpecialization()) return Done(); } else { auto *CTD = Specialized.get(); - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - CTD, CTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + Result.addOuterTemplateArguments( + CTD, CTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); if (CTD->isMemberSpecialization()) return Done(); } #else - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - CTSD, CTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + Result.addOuterTemplateArguments( + CTSD, CTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); if (auto *CTPSD = Specialized.dyn_cast()) { if (CTPSD->isMemberSpecialization()) return Done(); @@ -849,18 +844,16 @@ struct TemplateInstantiationArgumentCollecter llvm::PointerUnion Specialized = VTSD->getSpecializedTemplateOrPartial(); if (auto *VTPSD = Specialized.dyn_cast()) { - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - VTPSD, VTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + Result.addOuterTemplateArguments( + VTPSD, VTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); if (VTPSD->isMemberSpecialization()) return Done(); } else { auto *VTD = Specialized.get(); - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - VTD, VTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + Result.addOuterTemplateArguments( + VTD, VTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); if (VTD->isMemberSpecialization()) return Done(); } @@ -897,15 +890,12 @@ struct TemplateInstantiationArgumentCollecter MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( const NamedDecl *ND, const DeclContext *DC, bool Final, - std::optional> Innermost, bool RelativeToPrimary, - const FunctionDecl *Pattern, bool ForConstraintInstantiation, - bool SkipForSpecialization, bool ForDefaultArgumentSubstitution) { + std::optional> Innermost, + bool RelativeToPrimary, bool ForConstraintInstantiation) { assert((ND || DC) && "Can't find arguments for a decl if one isn't provided"); // Accumulate the set of template argument lists in this structure. MultiLevelTemplateArgumentList Result; - SkipForSpecialization = false; - using namespace TemplateInstArgsHelpers; const Decl *CurDecl = ND; @@ -932,8 +922,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( TemplateInstantiationArgumentCollecter Collecter( *this, Result, RelativeToPrimary, - ForConstraintInstantiation, - SkipForSpecialization); + ForConstraintInstantiation); do { CurDecl = Collecter.Visit(const_cast(CurDecl)); } while (CurDecl); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 69958e494939c..8ffdee8375dbb 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4749,7 +4749,7 @@ void Sema::InstantiateExceptionSpec(SourceLocation PointOfInstantiation, MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs(Decl, Decl->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, - /*RelativeToPrimary*/ true); + /*RelativeToPrimary=*/true); // FIXME: We can't use getTemplateInstantiationPattern(false) in general // here, because for a non-defining friend declaration in a class template, From e0bd5230ad594c20a350621aca93f9cf701b7db0 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 14 Aug 2024 07:53:18 -0400 Subject: [PATCH 11/35] [FOLD] using the right next decl after adding innermost template arguments --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 172 +++++++++++++----- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 25 ++- .../temp/temp.constr/temp.constr.decl/p4.cpp | 1 + .../SemaTemplate/default-arguments-cxx0x.cpp | 2 +- 4 files changed, 147 insertions(+), 53 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index a0c17425924de..50f862dae57d2 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -509,15 +509,17 @@ struct TemplateInstantiationArgumentCollecter : DeclVisitor { Sema &S; MultiLevelTemplateArgumentList &Result; + std::optional> Innermost; bool RelativeToPrimary; bool ForConstraintInstantiation; TemplateInstantiationArgumentCollecter( Sema &S, MultiLevelTemplateArgumentList &Result, + std::optional> Innermost, bool RelativeToPrimary, bool ForConstraintInstantiation) : - S(S), Result(Result), RelativeToPrimary(RelativeToPrimary), + S(S), Result(Result), Innermost(Innermost), RelativeToPrimary(RelativeToPrimary), ForConstraintInstantiation(ForConstraintInstantiation) { } @@ -543,14 +545,34 @@ struct TemplateInstantiationArgumentCollecter Decl::castFromDeclContext(D->getDeclContext())); } + void AddInnermostTemplateArguments(const Decl *D) { + assert(Innermost); + Result.addOuterTemplateArguments(const_cast(D), *Innermost, /*Final=*/false); + Innermost.reset(); + } + + void AddOuterTemplateArguments(const Decl *D, ArrayRef Args, bool Final) { + #if 0 + if (Innermost) { + Args = *Innermost; + Innermost.reset(); + } + #endif + Result.addOuterTemplateArguments(const_cast(D), Args, Final); + } + Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) { #if 0 for (unsigned I = 0, N = TTPD->getDepth() + 1; I != N; ++I) Result.addOuterTemplateArguments(std::nullopt); return Done(); #endif + if (Innermost) + AddInnermostTemplateArguments(TTPD); + + // else if (ForConstraintInstantiation) if (ForConstraintInstantiation) - Result.addOuterTemplateArguments(std::nullopt); + AddOuterTemplateArguments(nullptr, std::nullopt, /*Final=*/false); return UseNextDecl(TTPD); } @@ -559,8 +581,10 @@ struct TemplateInstantiationArgumentCollecter assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && "outer template not instantiated?"); - if (ForConstraintInstantiation) - Result.addOuterTemplateArguments( + if (Innermost) + AddInnermostTemplateArguments(FTD); + else if (ForConstraintInstantiation) + AddOuterTemplateArguments( FTD, FTD->getInjectedTemplateArgs(), /*Final=*/false); if (FTD->isMemberSpecialization()) @@ -575,8 +599,10 @@ struct TemplateInstantiationArgumentCollecter assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && "outer template not instantiated?"); - if (ForConstraintInstantiation) - Result.addOuterTemplateArguments( + if (Innermost) + AddInnermostTemplateArguments(VTD); + else if (ForConstraintInstantiation) + AddOuterTemplateArguments( VTD, VTD->getInjectedTemplateArgs(), /*Final=*/false); if (VTD->isMemberSpecialization()) @@ -589,8 +615,10 @@ struct TemplateInstantiationArgumentCollecter assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && "outer template not instantiated?"); - if (ForConstraintInstantiation) - Result.addOuterTemplateArguments( + if (Innermost) + AddInnermostTemplateArguments(CTD); + else if (ForConstraintInstantiation) + AddOuterTemplateArguments( CTD, CTD->getInjectedTemplateArgs(), /*Final=*/false); if (CTD->isMemberSpecialization()) @@ -601,6 +629,27 @@ struct TemplateInstantiationArgumentCollecter return UseNextDecl(CTD); } + Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *TATD) { + assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && + "outer template not instantiated?"); + if (Innermost) + AddInnermostTemplateArguments(TATD); + else if (ForConstraintInstantiation) + AddOuterTemplateArguments( + TATD, TATD->getInjectedTemplateArgs(), /*Final=*/false); + + return UseNextDecl(TATD); + } + + Decl *VisitConceptDecl(ConceptDecl *CD) { + assert((ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && + "outer template not instantiated?"); + if (Innermost) + AddInnermostTemplateArguments(CD); + + return UseNextDecl(CD); + } + #if 0 Decl *VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl *CTPSD) { if (!SkipForSpecialization) @@ -636,8 +685,11 @@ struct TemplateInstantiationArgumentCollecter if (const TemplateArgumentList *TemplateArgs = FD->getTemplateSpecializationArgs()) { // Add the template arguments for this specialization. - Result.addOuterTemplateArguments( - FD, TemplateArgs->asArray(), /*Final=*/false); + if (Innermost) + AddInnermostTemplateArguments(FD); + else + AddOuterTemplateArguments( + FD, TemplateArgs->asArray(), /*Final=*/false); if ( // RelativeToPrimary && (FD->getTemplateSpecializationKind() == @@ -698,7 +750,7 @@ struct TemplateInstantiationArgumentCollecter if (ClassTemplate->isMemberSpecialization()) return Done(); if (ForConstraintInstantiation) - Result.addOuterTemplateArguments( + AddOuterTemplateArguments( RD, ClassTemplate->getInjectedTemplateArgs(), /*Final=*/false); } @@ -727,9 +779,9 @@ struct TemplateInstantiationArgumentCollecter getPrimaryTemplateOfGenericLambda(RD->getLambdaCallOperator()); if (isLambdaEnclosedByTypeAliasDecl(PrimaryLambdaCallOperator, TypeAlias.PrimaryTypeAliasDecl)) { - Result.addOuterTemplateArguments(TypeAlias.Template, - TypeAlias.AssociatedTemplateArguments, - /*Final=*/false); + AddOuterTemplateArguments(TypeAlias.Template, + TypeAlias.AssociatedTemplateArguments, + /*Final=*/false); // Visit the parent of the current type alias declaration rather than // the lambda thereof. // E.g., in the following example: @@ -781,7 +833,8 @@ struct TemplateInstantiationArgumentCollecter #else // For a class-scope explicit specialization, there are no template arguments // at this level, but there may be enclosing template arguments. - if (CTSD->isClassScopeExplicitSpecialization()) + if (CTSD->isClassScopeExplicitSpecialization() && + !isa(CTSD)) return DontClearRelativeToPrimaryNextDecl(CTSD); // We're done when we hit an explicit specialization. @@ -810,9 +863,12 @@ struct TemplateInstantiationArgumentCollecter return Done(); } #else - Result.addOuterTemplateArguments( - CTSD, CTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + if (Innermost) + AddInnermostTemplateArguments(CTSD); + else + AddOuterTemplateArguments( + CTSD, CTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); if (auto *CTPSD = Specialized.dyn_cast()) { if (CTPSD->isMemberSpecialization()) return Done(); @@ -830,7 +886,8 @@ struct TemplateInstantiationArgumentCollecter Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) { // For a class-scope explicit specialization, there are no template arguments // at this level, but there may be enclosing template arguments. - if (VTSD->isClassScopeExplicitSpecialization()) + if (VTSD->isClassScopeExplicitSpecialization() && + !isa(VTSD)) return DontClearRelativeToPrimaryNextDecl(VTSD); // We're done when we hit an explicit specialization. @@ -844,16 +901,22 @@ struct TemplateInstantiationArgumentCollecter llvm::PointerUnion Specialized = VTSD->getSpecializedTemplateOrPartial(); if (auto *VTPSD = Specialized.dyn_cast()) { - Result.addOuterTemplateArguments( - VTPSD, VTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + if (Innermost) + AddInnermostTemplateArguments(VTPSD); + else + AddOuterTemplateArguments( + VTPSD, VTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); if (VTPSD->isMemberSpecialization()) return Done(); } else { auto *VTD = Specialized.get(); - Result.addOuterTemplateArguments( - VTD, VTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); + if (Innermost) + AddInnermostTemplateArguments(VTD); + else + AddOuterTemplateArguments( + VTD, VTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); if (VTD->isMemberSpecialization()) return Done(); } @@ -861,7 +924,7 @@ struct TemplateInstantiationArgumentCollecter } Decl *VisitImplicitConceptSpecializationDecl(ImplicitConceptSpecializationDecl *ICSD) { - Result.addOuterTemplateArguments( + AddOuterTemplateArguments( ICSD, ICSD->getTemplateArguments(), /*Final=*/false); return UseNextDecl(ICSD); @@ -877,13 +940,13 @@ struct TemplateInstantiationArgumentCollecter return UseNextDecl(D); } - Decl *Visit(Decl *D) { #if 0 + Decl *Visit(Decl *D) { if (TemplateDecl *TD = D->getDescribedTemplate()) D = TD; - #endif return DeclVisitor::Visit(D); } + #endif }; } // namespace @@ -902,7 +965,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( if (!CurDecl) CurDecl = Decl::castFromDeclContext(DC); - #if 1 + #if 0 if (Innermost) { Result.addOuterTemplateArguments(const_cast(ND), *Innermost, Final); @@ -921,7 +984,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( #endif TemplateInstantiationArgumentCollecter Collecter( - *this, Result, RelativeToPrimary, + *this, Result, Innermost, RelativeToPrimary, ForConstraintInstantiation); do { CurDecl = Collecter.Visit(const_cast(CurDecl)); @@ -2125,25 +2188,42 @@ namespace { ExprResult RebuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, LambdaScopeInfo *LSI) { + #if 1 CXXMethodDecl *MD = LSI->CallOperator; - for (ParmVarDecl *PVD : MD->parameters()) { - assert(PVD && "null in a parameter list"); - if (!PVD->hasDefaultArg()) - continue; - Expr *UninstExpr = PVD->getUninstantiatedDefaultArg(); - // FIXME: Obtain the source location for the '=' token. - SourceLocation EqualLoc = UninstExpr->getBeginLoc(); - if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) { - // If substitution fails, the default argument is set to a - // RecoveryExpr that wraps the uninstantiated default argument so - // that downstream diagnostics are omitted. - ExprResult ErrorResult = SemaRef.CreateRecoveryExpr( - UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), - { UninstExpr }, UninstExpr->getType()); - if (ErrorResult.isUsable()) - PVD->setDefaultArg(ErrorResult.get()); + if (MD->getParentFunctionOrMethod()) { + #if 0 + NamedDecl *Pattern = MD; + std::optional> Innermost; + if (FunctionTemplateDecl *FTD = MD->getDescribedFunctionTemplate()) { + Pattern = FTD; + Innermost = FTD->getInjectedTemplateArgs(); + } + MultiLevelTemplateArgumentList MLTAL = + SemaRef.getTemplateInstantiationArgs(Pattern, Pattern->getLexicalDeclContext(), + /*Final=*/false, Innermost, + /*RelativeToPrimary=*/true); + #endif +; + for (ParmVarDecl *PVD : MD->parameters()) { + assert(PVD && "null in a parameter list"); + if (!PVD->hasDefaultArg()) + continue; + Expr *UninstExpr = PVD->getUninstantiatedDefaultArg(); + // FIXME: Obtain the source location for the '=' token. + SourceLocation EqualLoc = UninstExpr->getBeginLoc(); + if (SemaRef.SubstDefaultArgument(EqualLoc, PVD, TemplateArgs)) { + // If substitution fails, the default argument is set to a + // RecoveryExpr that wraps the uninstantiated default argument so + // that downstream diagnostics are omitted. + ExprResult ErrorResult = SemaRef.CreateRecoveryExpr( + UninstExpr->getBeginLoc(), UninstExpr->getEndLoc(), + { UninstExpr }, UninstExpr->getType()); + if (ErrorResult.isUsable()) + PVD->setDefaultArg(ErrorResult.get()); + } } } + #endif return inherited::RebuildLambdaExpr(StartLoc, EndLoc, LSI); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 8ffdee8375dbb..b45163de8f7bc 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4686,6 +4686,21 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, ParmVarDecl *Param) { assert(Param->hasUninstantiatedDefaultArg()); + NamedDecl *Pattern = nullptr; + std::optional> Innermost; + #if 1 + if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) { + Pattern = FTD->isCXXClassMember() ? FTD->getFirstDecl() : FTD; + Innermost = FD->getTemplateSpecializationArgs()->asArray(); + } else if (FD->isCXXClassMember()) { + Pattern = FD->getFirstDecl(); + } else { + Pattern = FD; + } + #else + Pattern = FD; + #endif + // Instantiate the expression. // // FIXME: Pass in a correct Pattern argument, otherwise @@ -4703,12 +4718,10 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, // // template // A Foo(int a = A::FooImpl()); - MultiLevelTemplateArgumentList TemplateArgs = getTemplateInstantiationArgs( - FD, FD->getLexicalDeclContext(), - /*Final=*/false, /*Innermost=*/std::nullopt, - /*RelativeToPrimary=*/true, /*Pattern=*/nullptr, - /*ForConstraintInstantiation=*/false, /*SkipForSpecialization=*/false, - /*ForDefaultArgumentSubstitution=*/true); + MultiLevelTemplateArgumentList TemplateArgs = + getTemplateInstantiationArgs(Pattern, Pattern->getLexicalDeclContext(), + /*Final=*/false, Innermost, + /*RelativeToPrimary=*/true); if (SubstDefaultArgument(CallLoc, Param, TemplateArgs, /*ForCallExpr*/ true)) return true; diff --git a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp index f6e0d45334c0f..c39d13c47c8a1 100644 --- a/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp +++ b/clang/test/CXX/temp/temp.constr/temp.constr.decl/p4.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -std=c++20 -verify %s +// expected-no-diagnostics template struct A { diff --git a/clang/test/SemaTemplate/default-arguments-cxx0x.cpp b/clang/test/SemaTemplate/default-arguments-cxx0x.cpp index 4972c57a71922..bd9388eede316 100644 --- a/clang/test/SemaTemplate/default-arguments-cxx0x.cpp +++ b/clang/test/SemaTemplate/default-arguments-cxx0x.cpp @@ -12,7 +12,7 @@ void f0(); void g0() { f0(); // okay! -} +} template int &f1(T); From 658c6c93015a16f89958f256f630f4d2ab013687 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 20 Aug 2024 06:41:24 -0400 Subject: [PATCH 12/35] [FOLD] instantiate lambda default args correctly --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 3 ++- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 50f862dae57d2..8ef35e4a0382a 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2190,7 +2190,8 @@ namespace { LambdaScopeInfo *LSI) { #if 1 CXXMethodDecl *MD = LSI->CallOperator; - if (MD->getParentFunctionOrMethod()) { + // if (MD->getParentFunctionOrMethod()) { + if (true) { #if 0 NamedDecl *Pattern = MD; std::optional> Innermost; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index b45163de8f7bc..4f4a4b9982b9e 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -12,6 +12,7 @@ #include "TreeTransform.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" @@ -4689,6 +4690,7 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, NamedDecl *Pattern = nullptr; std::optional> Innermost; #if 1 + if (FunctionTemplateDecl *FTD = FD->getPrimaryTemplate()) { Pattern = FTD->isCXXClassMember() ? FTD->getFirstDecl() : FTD; Innermost = FD->getTemplateSpecializationArgs()->asArray(); @@ -4701,6 +4703,9 @@ bool Sema::InstantiateDefaultArgument(SourceLocation CallLoc, FunctionDecl *FD, Pattern = FD; #endif + if (isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) + Pattern = FD; + // Instantiate the expression. // // FIXME: Pass in a correct Pattern argument, otherwise From 4832287b21fa7ccd38c7822ea217a895219b66cd Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 23 Aug 2024 11:51:49 -0400 Subject: [PATCH 13/35] [FOLD] handle template template params correctly and switch to described template --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 422 +----------------- .../namespace.udecl/p8-cxx0x.cpp | 4 +- 2 files changed, 20 insertions(+), 406 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 8ef35e4a0382a..b957f2e107bea 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -185,323 +185,6 @@ HandleDefaultTempArgIntoTempTempParam(const TemplateTemplateParmDecl *TTP, return Response::Done(); } -#if 0 -// Add template arguments from a variable template instantiation. -Response -HandleVarTemplateSpec(const VarTemplateSpecializationDecl *VarTemplSpec, - MultiLevelTemplateArgumentList &Result, - bool SkipForSpecialization) { - // For a class-scope explicit specialization, there are no template arguments - // at this level, but there may be enclosing template arguments. - if (VarTemplSpec->isClassScopeExplicitSpecialization()) - return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec); - - // We're done when we hit an explicit specialization. - if (VarTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization && - !isa(VarTemplSpec)) - return Response::Done(); - - // If this variable template specialization was instantiated from a - // specialized member that is a variable template, we're done. - assert(VarTemplSpec->getSpecializedTemplate() && "No variable template?"); - llvm::PointerUnion - Specialized = VarTemplSpec->getSpecializedTemplateOrPartial(); - if (VarTemplatePartialSpecializationDecl *Partial = - Specialized.dyn_cast()) { - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - Partial, VarTemplSpec->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); - if (Partial->isMemberSpecialization()) - return Response::Done(); - } else { - VarTemplateDecl *Tmpl = Specialized.get(); - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - Tmpl, VarTemplSpec->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); - if (Tmpl->isMemberSpecialization()) - return Response::Done(); - } - return Response::DontClearRelativeToPrimaryNextDecl(VarTemplSpec); -} - -Response HandlePartialClassTemplateSpec( - const ClassTemplatePartialSpecializationDecl *PartialClassTemplSpec, - MultiLevelTemplateArgumentList &Result, bool SkipForSpecialization) { - if (!SkipForSpecialization) - Result.addOuterRetainedLevels(PartialClassTemplSpec->getTemplateDepth()); - return Response::Done(); -} - -// Add template arguments from a class template instantiation. -Response -HandleClassTemplateSpec(const ClassTemplateSpecializationDecl *ClassTemplSpec, - MultiLevelTemplateArgumentList &Result, - bool SkipForSpecialization) { - if (!ClassTemplSpec->isClassScopeExplicitSpecialization()) { - // We're done when we hit an explicit specialization. - if (ClassTemplSpec->getSpecializationKind() == TSK_ExplicitSpecialization && - !isa(ClassTemplSpec)) - return Response::Done(); - - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - const_cast(ClassTemplSpec), - ClassTemplSpec->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); - - // If this class template specialization was instantiated from a - // specialized member that is a class template, we're done. - assert(ClassTemplSpec->getSpecializedTemplate() && "No class template?"); - if (ClassTemplSpec->getSpecializedTemplate()->isMemberSpecialization()) - return Response::Done(); - - // If this was instantiated from a partial template specialization, we need - // to get the next level of declaration context from the partial - // specialization, as the ClassTemplateSpecializationDecl's - // DeclContext/LexicalDeclContext will be for the primary template. - if (auto *InstFromPartialTempl = ClassTemplSpec->getSpecializedTemplateOrPartial() - .dyn_cast()) - return Response::ChangeDecl(InstFromPartialTempl->getLexicalDeclContext()); - } - return Response::UseNextDecl(ClassTemplSpec); -} - -Response HandleFunction(Sema &SemaRef, const FunctionDecl *Function, - MultiLevelTemplateArgumentList &Result, - const FunctionDecl *Pattern, bool RelativeToPrimary, - bool ForConstraintInstantiation, - bool ForDefaultArgumentSubstitution) { - // Add template arguments from a function template specialization. - if (!RelativeToPrimary && - Function->getTemplateSpecializationKindForInstantiation() == - TSK_ExplicitSpecialization) - return Response::Done(); - - if (!RelativeToPrimary && - Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { - // This is an implicit instantiation of an explicit specialization. We - // don't get any template arguments from this function but might get - // some from an enclosing template. - return Response::UseNextDecl(Function); - } else if (const TemplateArgumentList *TemplateArgs = - Function->getTemplateSpecializationArgs()) { - // Add the template arguments for this specialization. - Result.addOuterTemplateArguments(const_cast(Function), - TemplateArgs->asArray(), - /*Final=*/false); - - if (RelativeToPrimary && - (Function->getTemplateSpecializationKind() == - TSK_ExplicitSpecialization || - (Function->getFriendObjectKind() && - !Function->getPrimaryTemplate()->getFriendObjectKind()))) - return Response::UseNextDecl(Function); - - // If this function was instantiated from a specialized member that is - // a function template, we're done. - assert(Function->getPrimaryTemplate() && "No function template?"); - if (!ForDefaultArgumentSubstitution && - Function->getPrimaryTemplate()->isMemberSpecialization()) - return Response::Done(); - - // If this function is a generic lambda specialization, we are done. - if (!ForConstraintInstantiation && - isGenericLambdaCallOperatorOrStaticInvokerSpecialization(Function)) - return Response::Done(); - - } else if (Function->getDescribedFunctionTemplate()) { - assert( - (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && - "Outer template not instantiated?"); - } - // If this is a friend or local declaration and it declares an entity at - // namespace scope, take arguments from its lexical parent - // instead of its semantic parent, unless of course the pattern we're - // instantiating actually comes from the file's context! - if ((Function->getFriendObjectKind() || Function->isLocalExternDecl()) && - Function->getNonTransparentDeclContext()->isFileContext() && - (!Pattern || !Pattern->getLexicalDeclContext()->isFileContext())) { - return Response::ChangeDecl(Function->getLexicalDeclContext()); - } - - if (ForConstraintInstantiation && Function->getFriendObjectKind()) - return Response::ChangeDecl(Function->getLexicalDeclContext()); - return Response::UseNextDecl(Function); -} - -Response HandleFunctionTemplateDecl(const FunctionTemplateDecl *FTD, - MultiLevelTemplateArgumentList &Result, - bool ForConstraintInstantiation) { - #if 0 - if (!isa(FTD->getDeclContext())) { - Result.addOuterTemplateArguments( - const_cast(FTD), - const_cast(FTD)->getInjectedTemplateArgs(), - /*Final=*/false); - - - - NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier(); - - while (const Type *Ty = NNS ? NNS->getAsType() : nullptr) { - if (NNS->isInstantiationDependent()) { - if (const auto *TSTy = Ty->getAs()) { - ArrayRef Arguments = TSTy->template_arguments(); - // Prefer template arguments from the injected-class-type if possible. - // For example, - // ```cpp - // template struct S { - // template void foo(); - // }; - // template template - // ^^^^^^^^^^^^^ InjectedTemplateArgs - // They're of kind TemplateArgument::Pack, not of - // TemplateArgument::Type. - // void S::foo() {} - // ^^^^^^^ - // TSTy->template_arguments() (which are of PackExpansionType) - // ``` - // This meets the contract in - // TreeTransform::TryExpandParameterPacks that the template arguments - // for unexpanded parameters should be of a Pack kind. - if (TSTy->isCurrentInstantiation()) { - auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl(); - if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) - Arguments = CTD->getInjectedTemplateArgs(); - else if (auto *Specialization = - dyn_cast(RD)) - Arguments = - Specialization->getTemplateInstantiationArgs().asArray(); - } - Result.addOuterTemplateArguments( - const_cast(FTD), Arguments, - /*Final=*/false); - } - } - - NNS = NNS->getPrefix(); - } - } - - return Response::ChangeDecl(FTD->getLexicalDeclContext()); - #else - if (ForConstraintInstantiation) - Result.addOuterTemplateArguments( - const_cast(FTD), - const_cast(FTD)->getInjectedTemplateArgs(), - /*Final=*/false); - - if (FTD->isMemberSpecialization()) - return Response::Done(); - - if (FTD->getFriendObjectKind()) - return Response::ChangeDecl(FTD->getLexicalDeclContext()); - return Response::UseNextDecl(FTD); - #endif -} - -Response HandleClassTemplateDecl(const ClassTemplateDecl *CTD, - MultiLevelTemplateArgumentList &Result, - bool ForConstraintInstantiation, - bool SkipForSpecialization) { - #if 1 - if (!SkipForSpecialization && ForConstraintInstantiation) - Result.addOuterTemplateArguments( - const_cast(CTD), - const_cast(CTD)->getInjectedTemplateArgs(), - /*Final=*/false); - - if (CTD->isMemberSpecialization()) - return Response::Done(); - - if (CTD->getFriendObjectKind()) - return Response::ChangeDecl(CTD->getLexicalDeclContext()); - return Response::UseNextDecl(CTD); - #endif - return Response::ChangeDecl(CTD->getLexicalDeclContext()); -} - -Response HandleRecordDecl(Sema &SemaRef, const CXXRecordDecl *Rec, - MultiLevelTemplateArgumentList &Result, - ASTContext &Context, - bool ForConstraintInstantiation) { - if (ClassTemplateDecl *ClassTemplate = Rec->getDescribedClassTemplate()) { - assert( - (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && - "Outer template not instantiated?"); - if (ClassTemplate->isMemberSpecialization()) - return Response::Done(); - if (ForConstraintInstantiation) - Result.addOuterTemplateArguments(const_cast(Rec), - ClassTemplate->getInjectedTemplateArgs(), - /*Final=*/false); - } - - if (const MemberSpecializationInfo *MSInfo = - Rec->getMemberSpecializationInfo()) - if (MSInfo->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return Response::Done(); - - bool IsFriend = Rec->getFriendObjectKind() || - (Rec->getDescribedClassTemplate() && - Rec->getDescribedClassTemplate()->getFriendObjectKind()); - if (ForConstraintInstantiation && IsFriend && - Rec->getNonTransparentDeclContext()->isFileContext()) { - return Response::ChangeDecl(Rec->getLexicalDeclContext()); - } - - // This is to make sure we pick up the VarTemplateSpecializationDecl or the - // TypeAliasTemplateDecl that this lambda is defined inside of. - if (Rec->isLambda()) { - if (const Decl *LCD = Rec->getLambdaContextDecl()) - return Response::ChangeDecl(LCD); - // Retrieve the template arguments for a using alias declaration. - // This is necessary for constraint checking, since we always keep - // constraints relative to the primary template. - if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(SemaRef); - ForConstraintInstantiation && TypeAlias) { - if (isLambdaEnclosedByTypeAliasDecl(Rec->getLambdaCallOperator(), - TypeAlias.PrimaryTypeAliasDecl)) { - Result.addOuterTemplateArguments(TypeAlias.Template, - TypeAlias.AssociatedTemplateArguments, - /*Final=*/false); - // Visit the parent of the current type alias declaration rather than - // the lambda thereof. - // E.g., in the following example: - // struct S { - // template using T = decltype([] {} ()); - // }; - // void foo() { - // S::T var; - // } - // The instantiated lambda expression (which we're visiting at 'var') - // has a function DeclContext 'foo' rather than the Record DeclContext - // S. This seems to be an oversight to me that we may want to set a - // Sema Context from the CXXScopeSpec before substituting into T. - return Response::ChangeDecl(TypeAlias.Template->getDeclContext()); - } - } - } - - return Response::UseNextDecl(Rec); -} - -Response HandleImplicitConceptSpecializationDecl( - const ImplicitConceptSpecializationDecl *CSD, - MultiLevelTemplateArgumentList &Result) { - Result.addOuterTemplateArguments( - const_cast(CSD), - CSD->getTemplateArguments(), - /*Final=*/false); - return Response::UseNextDecl(CSD); -} - -Response HandleGenericDeclContext(const Decl *CurDecl) { - return Response::UseNextDecl(CurDecl); -} -#endif } // namespace TemplateInstArgsHelpers @@ -529,6 +212,8 @@ struct TemplateInstantiationArgumentCollecter Decl *ChangeDecl(const Decl *D) { RelativeToPrimary = false; + if (const TemplateDecl *TD = D->getDescribedTemplate()) + D = TD; return const_cast(D); } @@ -541,8 +226,10 @@ struct TemplateInstantiationArgumentCollecter } Decl *DontClearRelativeToPrimaryNextDecl(const Decl* D) { - return const_cast( - Decl::castFromDeclContext(D->getDeclContext())); + D = Decl::castFromDeclContext(D->getDeclContext()); + if (const TemplateDecl *TD = D->getDescribedTemplate()) + D = TD; + return const_cast(D); } void AddInnermostTemplateArguments(const Decl *D) { @@ -562,19 +249,15 @@ struct TemplateInstantiationArgumentCollecter } Decl *VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTPD) { - #if 0 - for (unsigned I = 0, N = TTPD->getDepth() + 1; I != N; ++I) - Result.addOuterTemplateArguments(std::nullopt); - return Done(); - #endif if (Innermost) AddInnermostTemplateArguments(TTPD); + else if (ForConstraintInstantiation) + AddOuterTemplateArguments(nullptr, std::nullopt, /*Final=*/false); - // else if (ForConstraintInstantiation) - if (ForConstraintInstantiation) + for (unsigned Depth = TTPD->getDepth() + 1; Depth--;) AddOuterTemplateArguments(nullptr, std::nullopt, /*Final=*/false); - return UseNextDecl(TTPD); + return Done(); } Decl *VisitFunctionTemplateDecl(FunctionTemplateDecl *FTD) { @@ -706,22 +389,8 @@ struct TemplateInstantiationArgumentCollecter // If this function is a generic lambda specialization, we are done. if (!ForConstraintInstantiation && - isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) { - // TypeAliasTemplateDecls should be taken into account, e.g. - // when we're deducing the return type of a lambda. - // - // template int Value = 0; - // template - // using T = decltype([]() { return Value; }()); - // - if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S)) { - if (isLambdaEnclosedByTypeAliasDecl( - /*PrimaryLambdaCallOperator=*/getPrimaryTemplateOfGenericLambda(FD), - /*PrimaryTypeAliasDecl=*/TypeAlias.PrimaryTypeAliasDecl)) - return UseNextDecl(FD); - } + isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) return Done(); - } } else if (FD->getDescribedFunctionTemplate()) { assert( @@ -747,6 +416,7 @@ struct TemplateInstantiationArgumentCollecter assert( (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && "Outer template not instantiated?"); + // llvm_unreachable("shouldn't get here"); if (ClassTemplate->isMemberSpecialization()) return Done(); if (ForConstraintInstantiation) @@ -774,11 +444,10 @@ struct TemplateInstantiationArgumentCollecter // Retrieve the template arguments for a using alias declaration. // This is necessary for constraint checking, since we always keep // constraints relative to the primary template. - if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S)) { - const FunctionDecl *PrimaryLambdaCallOperator = - getPrimaryTemplateOfGenericLambda(RD->getLambdaCallOperator()); - if (isLambdaEnclosedByTypeAliasDecl(PrimaryLambdaCallOperator, - TypeAlias.PrimaryTypeAliasDecl)) { + if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(S); + ForConstraintInstantiation && TypeAlias) { + if (isLambdaEnclosedByTypeAliasDecl(RD->getLambdaCallOperator(), + TypeAlias.PrimaryTypeAliasDecl)) { AddOuterTemplateArguments(TypeAlias.Template, TypeAlias.AssociatedTemplateArguments, /*Final=*/false); @@ -989,60 +658,7 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( do { CurDecl = Collecter.Visit(const_cast(CurDecl)); } while (CurDecl); - - #if 0 - if (Innermost) - Result.replaceInnermostTemplateArguments(const_cast(ND), *Innermost); - #endif return Result; - - #if 0 - while (!CurDecl->isFileContextDecl()) { - Response R; - if (const auto *VarTemplSpec = - dyn_cast(CurDecl)) { - R = HandleVarTemplateSpec(VarTemplSpec, Result, SkipForSpecialization); - } else if (const auto *PartialClassTemplSpec = - dyn_cast(CurDecl)) { - R = HandlePartialClassTemplateSpec(PartialClassTemplSpec, Result, - SkipForSpecialization); - } else if (const auto *ClassTemplSpec = - dyn_cast(CurDecl)) { - R = HandleClassTemplateSpec(ClassTemplSpec, Result, - SkipForSpecialization); - } else if (const auto *Function = dyn_cast(CurDecl)) { - R = HandleFunction(*this, Function, Result, Pattern, RelativeToPrimary, - ForConstraintInstantiation, - ForDefaultArgumentSubstitution); - } else if (const auto *Rec = dyn_cast(CurDecl)) { - R = HandleRecordDecl(*this, Rec, Result, Context, - ForConstraintInstantiation); - } else if (const auto *CSD = - dyn_cast(CurDecl)) { - R = HandleImplicitConceptSpecializationDecl(CSD, Result); - } else if (const auto *FTD = dyn_cast(CurDecl)) { - R = HandleFunctionTemplateDecl(FTD, Result, ForConstraintInstantiation); - } else if (const auto *CTD = dyn_cast(CurDecl)) { - R = HandleClassTemplateDecl(CTD, Result, ForConstraintInstantiation, SkipForSpecialization); - } else if (!isa(CurDecl)) { - R = Response::DontClearRelativeToPrimaryNextDecl(CurDecl); - if (const auto *TTP = dyn_cast(CurDecl)) { - R = HandleDefaultTempArgIntoTempTempParam(TTP, Result); - } - } else { - R = HandleGenericDeclContext(CurDecl); - } - - if (R.IsDone) - return Result; - if (R.ClearRelativeToPrimary) - RelativeToPrimary = false; - assert(R.NextDecl); - CurDecl = R.NextDecl; - } - - return Result; - #endif } bool Sema::CodeSynthesisContext::isInstantiationRecord() const { @@ -2160,10 +1776,8 @@ namespace { CXXRecordDecl::LambdaDependencyKind ComputeLambdaDependency(LambdaScopeInfo *LSI) { - if (auto TypeAlias = - TemplateInstArgsHelpers::getEnclosingTypeAliasTemplateDecl( - getSema()); - TypeAlias && TemplateInstArgsHelpers::isLambdaEnclosedByTypeAliasDecl( + if (auto TypeAlias = getEnclosingTypeAliasTemplateDecl(getSema()); + TypeAlias && isLambdaEnclosedByTypeAliasDecl( LSI->CallOperator, TypeAlias.PrimaryTypeAliasDecl)) { unsigned TypeAliasDeclDepth = TypeAlias.Template->getTemplateDepth(); if (TypeAliasDeclDepth >= TemplateArgs.getNumSubstitutedLevels()) diff --git a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp index 0ea4eeb1e9b08..8361a35e96ec1 100644 --- a/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp +++ b/clang/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8-cxx0x.cpp @@ -61,14 +61,14 @@ namespace PR21933 { } }; template - struct Y : T { + struct Y : T { static void StaticFun() { using T::member; // expected-error 2{{class member}} expected-note {{use a reference instead}} (void)member; } }; - void f() { + void f() { X::StaticFun(); // expected-note {{instantiation of}} X::StaticFun(); // expected-note {{instantiation of}} X::StaticFun(); From 3c8ce5c429430be77da17bb38af6447e090359eb Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 23 Aug 2024 12:08:33 -0400 Subject: [PATCH 14/35] [FOLD] remove code for handling described templates --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 35 +++++----------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index b957f2e107bea..b46ae24f9f9ac 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -212,8 +212,6 @@ struct TemplateInstantiationArgumentCollecter Decl *ChangeDecl(const Decl *D) { RelativeToPrimary = false; - if (const TemplateDecl *TD = D->getDescribedTemplate()) - D = TD; return const_cast(D); } @@ -226,10 +224,8 @@ struct TemplateInstantiationArgumentCollecter } Decl *DontClearRelativeToPrimaryNextDecl(const Decl* D) { - D = Decl::castFromDeclContext(D->getDeclContext()); - if (const TemplateDecl *TD = D->getDescribedTemplate()) - D = TD; - return const_cast(D); + return const_cast( + Decl::castFromDeclContext(D->getDeclContext())); } void AddInnermostTemplateArguments(const Decl *D) { @@ -239,12 +235,6 @@ struct TemplateInstantiationArgumentCollecter } void AddOuterTemplateArguments(const Decl *D, ArrayRef Args, bool Final) { - #if 0 - if (Innermost) { - Args = *Innermost; - Innermost.reset(); - } - #endif Result.addOuterTemplateArguments(const_cast(D), Args, Final); } @@ -342,6 +332,8 @@ struct TemplateInstantiationArgumentCollecter #endif Decl *VisitFunctionDecl(FunctionDecl *FD) { + assert(!FD->getDescribedFunctionTemplate() && "not for templated declarations"); + if (!RelativeToPrimary) { if (const MemberSpecializationInfo *MSI = FD->getMemberSpecializationInfo(); MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) @@ -392,11 +384,8 @@ struct TemplateInstantiationArgumentCollecter isGenericLambdaCallOperatorOrStaticInvokerSpecialization(FD)) return Done(); - } else if (FD->getDescribedFunctionTemplate()) { - assert( - (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && - "Outer template not instantiated?"); } + // If this is a friend or local declaration and it declares an entity at // namespace scope, take arguments from its lexical parent // instead of its semantic parent, unless of course the pattern we're @@ -412,17 +401,7 @@ struct TemplateInstantiationArgumentCollecter } Decl *VisitCXXRecordDecl(CXXRecordDecl *RD) { - if (ClassTemplateDecl *ClassTemplate = RD->getDescribedClassTemplate()) { - assert( - (ForConstraintInstantiation || Result.getNumSubstitutedLevels() == 0) && - "Outer template not instantiated?"); - // llvm_unreachable("shouldn't get here"); - if (ClassTemplate->isMemberSpecialization()) - return Done(); - if (ForConstraintInstantiation) - AddOuterTemplateArguments( - RD, ClassTemplate->getInjectedTemplateArgs(), /*Final=*/false); - } + assert(!RD->getDescribedClassTemplate() && "not for templated declarations"); if (const MemberSpecializationInfo *MSI = RD->getMemberSpecializationInfo(); MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) @@ -609,7 +588,7 @@ struct TemplateInstantiationArgumentCollecter return UseNextDecl(D); } - #if 0 + #if 1 Decl *Visit(Decl *D) { if (TemplateDecl *TD = D->getDescribedTemplate()) D = TD; From fd186a97bcb5c161e9c5b5b0bd22a0a3a99cdf92 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 23 Aug 2024 12:37:40 -0400 Subject: [PATCH 15/35] [FOLD] handle partial specializations that are member specializations --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 43 +++++++++++++--------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index b46ae24f9f9ac..e79e79f6f2fd5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -490,11 +490,6 @@ struct TemplateInstantiationArgumentCollecter !isa(CTSD)) return Done(); - // If this class template specialization was instantiated from a - // specialized member that is a class template, we're done. - assert(CTSD->getSpecializedTemplate() && "No class template?"); - llvm::PointerUnion - Specialized = CTSD->getSpecializedTemplateOrPartial(); #if 0 if (auto *CTPSD = Specialized.dyn_cast()) { Result.addOuterTemplateArguments( @@ -511,12 +506,25 @@ struct TemplateInstantiationArgumentCollecter return Done(); } #else + if (Innermost) AddInnermostTemplateArguments(CTSD); else AddOuterTemplateArguments( CTSD, CTSD->getTemplateInstantiationArgs().asArray(), /*Final=*/false); + + if (auto *CTPSD = dyn_cast(CTSD)) { + if (CTPSD->isMemberSpecialization()) + return Done(); + } + + // If this class template specialization was instantiated from a + // specialized member that is a class template, we're done. + assert(CTSD->getSpecializedTemplate() && "No class template?"); + llvm::PointerUnion + Specialized = CTSD->getSpecializedTemplateOrPartial(); + if (auto *CTPSD = Specialized.dyn_cast()) { if (CTPSD->isMemberSpecialization()) return Done(); @@ -526,7 +534,6 @@ struct TemplateInstantiationArgumentCollecter return Done(); } #endif - return DontClearRelativeToPrimaryNextDecl(CTSD); #endif } @@ -543,28 +550,28 @@ struct TemplateInstantiationArgumentCollecter !isa(VTSD)) return Done(); + if (Innermost) + AddInnermostTemplateArguments(VTSD); + else + AddOuterTemplateArguments( + VTSD, VTSD->getTemplateInstantiationArgs().asArray(), + /*Final=*/false); + + if (auto *VTPSD = dyn_cast(VTSD)) { + if (VTPSD->isMemberSpecialization()) + return Done(); + } + // If this variable template specialization was instantiated from a // specialized member that is a variable template, we're done. assert(VTSD->getSpecializedTemplate() && "No variable template?"); llvm::PointerUnion Specialized = VTSD->getSpecializedTemplateOrPartial(); if (auto *VTPSD = Specialized.dyn_cast()) { - if (Innermost) - AddInnermostTemplateArguments(VTPSD); - else - AddOuterTemplateArguments( - VTPSD, VTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); if (VTPSD->isMemberSpecialization()) return Done(); } else { auto *VTD = Specialized.get(); - if (Innermost) - AddInnermostTemplateArguments(VTD); - else - AddOuterTemplateArguments( - VTD, VTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); if (VTD->isMemberSpecialization()) return Done(); } From 66b0d8938fa214c0c2e83370a5867d87b7991d2f Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 23 Aug 2024 12:40:51 -0400 Subject: [PATCH 16/35] [FOLD] cleanups --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 92 +--------------------- 1 file changed, 4 insertions(+), 88 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index e79e79f6f2fd5..d16264c2f1d96 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -323,40 +323,22 @@ struct TemplateInstantiationArgumentCollecter return UseNextDecl(CD); } - #if 0 - Decl *VisitClassTemplatePartialSpecializationDecl(ClassTemplatePartialSpecializationDecl *CTPSD) { - if (!SkipForSpecialization) - Result.addOuterRetainedLevels(CTPSD->getTemplateDepth()); - return Done(); - } - #endif - Decl *VisitFunctionDecl(FunctionDecl *FD) { assert(!FD->getDescribedFunctionTemplate() && "not for templated declarations"); if (!RelativeToPrimary) { + // Add template arguments from a function template specialization. if (const MemberSpecializationInfo *MSI = FD->getMemberSpecializationInfo(); MSI && MSI->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) return Done(); + // This is an implicit instantiation of an explicit specialization. We + // don't get any template arguments from this function but might get + // some from an enclosing template. if (FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) return UseNextDecl(FD); } - #if 0 - // Add template arguments from a function template specialization. - if (!RelativeToPrimary && - FD->getTemplateSpecializationKindForInstantiation() == - TSK_ExplicitSpecialization) - return Done(); - if (!RelativeToPrimary && - FD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { - // This is an implicit instantiation of an explicit specialization. We - // don't get any template arguments from this function but might get - // some from an enclosing template. - return UseNextDecl(FD); - } else - #endif if (const TemplateArgumentList *TemplateArgs = FD->getTemplateSpecializationArgs()) { // Add the template arguments for this specialization. @@ -452,33 +434,6 @@ struct TemplateInstantiationArgumentCollecter } Decl *VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) { - #if 0 - if (!CTSD->isClassScopeExplicitSpecialization()) { - // We're done when we hit an explicit specialization. - if (CTSD->getSpecializationKind() == TSK_ExplicitSpecialization && - !isa(CTSD)) - return Done(); - - if (!SkipForSpecialization) - Result.addOuterTemplateArguments( - CTSD, CTSD->getTemplateInstantiationArgs().asArray(), /*Final=*/false); - - // If this class template specialization was instantiated from a - // specialized member that is a class template, we're done. - assert(CTSD->getSpecializedTemplate() && "No class template?"); - if (CTSD->getSpecializedTemplate()->isMemberSpecialization()) - return Done(); - - // If this was instantiated from a partial template specialization, we need - // to get the next level of declaration context from the partial - // specialization, as the ClassTemplateSpecializationDecl's - // DeclContext/LexicalDeclContext will be for the primary template. - if (auto *CTPSD = CTSD->getSpecializedTemplateOrPartial() - .dyn_cast()) - return ChangeDecl(CTPSD->getLexicalDeclContext()); - } - return UseNextDecl(CTSD); - #else // For a class-scope explicit specialization, there are no template arguments // at this level, but there may be enclosing template arguments. if (CTSD->isClassScopeExplicitSpecialization() && @@ -490,23 +445,6 @@ struct TemplateInstantiationArgumentCollecter !isa(CTSD)) return Done(); - #if 0 - if (auto *CTPSD = Specialized.dyn_cast()) { - Result.addOuterTemplateArguments( - CTPSD, CTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); - if (CTPSD->isMemberSpecialization()) - return Done(); - } else { - auto *CTD = Specialized.get(); - Result.addOuterTemplateArguments( - CTD, CTSD->getTemplateInstantiationArgs().asArray(), - /*Final=*/false); - if (CTD->isMemberSpecialization()) - return Done(); - } - #else - if (Innermost) AddInnermostTemplateArguments(CTSD); else @@ -533,9 +471,7 @@ struct TemplateInstantiationArgumentCollecter if (CTD->isMemberSpecialization()) return Done(); } - #endif return DontClearRelativeToPrimaryNextDecl(CTSD); - #endif } Decl *VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) { @@ -595,13 +531,11 @@ struct TemplateInstantiationArgumentCollecter return UseNextDecl(D); } - #if 1 Decl *Visit(Decl *D) { if (TemplateDecl *TD = D->getDescribedTemplate()) D = TD; return DeclVisitor::Visit(D); } - #endif }; } // namespace @@ -620,24 +554,6 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( if (!CurDecl) CurDecl = Decl::castFromDeclContext(DC); - #if 0 - if (Innermost) { - Result.addOuterTemplateArguments(const_cast(ND), *Innermost, - Final); - // Populate placeholder template arguments for TemplateTemplateParmDecls. - // This is essential for the case e.g. - // - // template concept Concept = false; - // template