https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/98013
>From c9297f8abe8d480fdcd3ba6d6598268fef74ddb4 Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Mon, 8 Jul 2024 13:19:13 +0200 Subject: [PATCH 1/2] [clang] CTAD: use index and depth to retrieve template parameters in TemplateParamsReferencedInTemplateArgumentList. --- clang/lib/Sema/SemaTemplate.cpp | 31 +++++++++++++++++++------- clang/test/AST/ast-dump-ctad-alias.cpp | 25 +++++++++++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3d8cf750c12c1..196a5cc10ce40 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2754,20 +2754,34 @@ struct ConvertConstructorToDeductionGuideTransform { // Find all template parameters that appear in the given DeducedArgs. // Return the indices of the template parameters in the TemplateParams. SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( - ArrayRef<NamedDecl *> TemplateParams, + const TemplateParameterList* TemplateParamsList, ArrayRef<TemplateArgument> DeducedArgs) { struct TemplateParamsReferencedFinder : public RecursiveASTVisitor<TemplateParamsReferencedFinder> { + const TemplateParameterList* TemplateParamList; llvm::DenseSet<NamedDecl *> TemplateParams; llvm::DenseSet<const NamedDecl *> ReferencedTemplateParams; - TemplateParamsReferencedFinder(ArrayRef<NamedDecl *> TemplateParams) - : TemplateParams(TemplateParams.begin(), TemplateParams.end()) {} + TemplateParamsReferencedFinder( + const TemplateParameterList *TemplateParamList) + : TemplateParamList(TemplateParamList), + TemplateParams(TemplateParamList->begin(), TemplateParamList->end()) { + } bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) { - MarkAppeared(TTP->getDecl()); + // We use the index and depth to retrieve the corresponding template + // parameter from the parameter list. + // Note that Clang may not preserve type sugar during template argument + // deduction. In such cases, the TTP is a canonical TemplateTypeParamType, + // which only retains its index and depth information. + if (TTP->getDepth() == TemplateParamList->getDepth() && + TTP->getIndex() < TemplateParamList->size()) { + ReferencedTemplateParams.insert( + TemplateParamList->getParam(TTP->getIndex())); + } return true; } + bool VisitDeclRefExpr(DeclRefExpr *DRE) { MarkAppeared(DRE->getFoundDecl()); return true; @@ -2784,12 +2798,13 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( ReferencedTemplateParams.insert(ND); } }; - TemplateParamsReferencedFinder Finder(TemplateParams); + TemplateParamsReferencedFinder Finder(TemplateParamsList); Finder.TraverseTemplateArguments(DeducedArgs); SmallVector<unsigned> Results; - for (unsigned Index = 0; Index < TemplateParams.size(); ++Index) { - if (Finder.ReferencedTemplateParams.contains(TemplateParams[Index])) + for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) { + if (Finder.ReferencedTemplateParams.contains( + TemplateParamsList->getParam(Index))) Results.push_back(Index); } return Results; @@ -3149,7 +3164,7 @@ BuildDeductionGuideForTypeAlias(Sema &SemaRef, } auto DeducedAliasTemplateParams = TemplateParamsReferencedInTemplateArgumentList( - AliasTemplate->getTemplateParameters()->asArray(), DeducedArgs); + AliasTemplate->getTemplateParameters(), DeducedArgs); // All template arguments null by default. SmallVector<TemplateArgument> TemplateArgsForBuildingFPrime( F->getTemplateParameters()->size()); diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index 6f07a62e9a069..adccad97a205b 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -99,3 +99,28 @@ BFoo b2(1.0, 2.0); // CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'type-parameter-0-0' // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'type-parameter-0-0' // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used <deduction guide for BFoo> 'auto (double, double) -> Foo<double, double>' implicit_instantiation + +namespace GH90209 { +template <class Ts> +struct List { + List(int); +}; + +template <class T1> +struct TemplatedClass { + TemplatedClass(T1); +}; + +template <class T1> +TemplatedClass(T1) -> TemplatedClass<List<T1>>; + +template <class T2> +using ATemplatedClass = TemplatedClass<List<T2>>; + +ATemplatedClass test(1); +// Verify that we have a correct template parameter list for the deduction guide. +// +// CHECK: FunctionTemplateDecl {{.*}} <deduction guide for ATemplatedClass> +// CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T2 +// CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible +} // namespace GH90209 \ No newline at end of file >From 7626982d97d7f0f088af95be371f65d5a0f02ee9 Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Thu, 11 Jul 2024 11:09:55 +0200 Subject: [PATCH 2/2] Address review comment. --- clang/lib/Sema/SemaTemplate.cpp | 61 ++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 196a5cc10ce40..58082cd111a9a 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -37,6 +37,7 @@ #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Template.h" #include "clang/Sema/TemplateDeduction.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -2751,6 +2752,26 @@ struct ConvertConstructorToDeductionGuideTransform { } }; +unsigned getTemplateParameterDepth(NamedDecl *TemplateParam) { + if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) + return TTP->getDepth(); + if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) + return TTP->getDepth(); + if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) + return NTTP->getDepth(); + llvm_unreachable("Unhandled template parameter types"); +} + +unsigned getTemplateParameterIndex(NamedDecl *TemplateParam) { + if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) + return TTP->getIndex(); + if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) + return TTP->getIndex(); + if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) + return NTTP->getIndex(); + llvm_unreachable("Unhandled template parameter types"); +} + // Find all template parameters that appear in the given DeducedArgs. // Return the indices of the template parameters in the TemplateParams. SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( @@ -2759,26 +2780,17 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( struct TemplateParamsReferencedFinder : public RecursiveASTVisitor<TemplateParamsReferencedFinder> { const TemplateParameterList* TemplateParamList; - llvm::DenseSet<NamedDecl *> TemplateParams; - llvm::DenseSet<const NamedDecl *> ReferencedTemplateParams; + llvm::BitVector ReferencedTemplateParams; TemplateParamsReferencedFinder( const TemplateParameterList *TemplateParamList) : TemplateParamList(TemplateParamList), - TemplateParams(TemplateParamList->begin(), TemplateParamList->end()) { - } + ReferencedTemplateParams(TemplateParamList->size()) {} bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) { // We use the index and depth to retrieve the corresponding template - // parameter from the parameter list. - // Note that Clang may not preserve type sugar during template argument - // deduction. In such cases, the TTP is a canonical TemplateTypeParamType, - // which only retains its index and depth information. - if (TTP->getDepth() == TemplateParamList->getDepth() && - TTP->getIndex() < TemplateParamList->size()) { - ReferencedTemplateParams.insert( - TemplateParamList->getParam(TTP->getIndex())); - } + // parameter from the parameter list, which is more robost. + Mark(TTP->getDepth(), TTP->getIndex()); return true; } @@ -2794,8 +2806,14 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( } void MarkAppeared(NamedDecl *ND) { - if (TemplateParams.contains(ND)) - ReferencedTemplateParams.insert(ND); + if (llvm::isa<NonTypeTemplateParmDecl, TemplateTypeParmDecl, + TemplateTemplateParmDecl>(ND)) + Mark(getTemplateParameterDepth(ND), getTemplateParameterIndex(ND)); + } + void Mark(unsigned Depth, unsigned Index) { + if (Index < TemplateParamList->size() && + TemplateParamList->getParam(Index)->getTemplateDepth() == Depth) + ReferencedTemplateParams.set(Index); } }; TemplateParamsReferencedFinder Finder(TemplateParamsList); @@ -2803,8 +2821,7 @@ SmallVector<unsigned> TemplateParamsReferencedInTemplateArgumentList( SmallVector<unsigned> Results; for (unsigned Index = 0; Index < TemplateParamsList->size(); ++Index) { - if (Finder.ReferencedTemplateParams.contains( - TemplateParamsList->getParam(Index))) + if (Finder.ReferencedTemplateParams[Index]) Results.push_back(Index); } return Results; @@ -2823,16 +2840,6 @@ bool hasDeclaredDeductionGuides(DeclarationName Name, DeclContext *DC) { return false; } -unsigned getTemplateParameterDepth(NamedDecl *TemplateParam) { - if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParam)) - return TTP->getDepth(); - if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TemplateParam)) - return TTP->getDepth(); - if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TemplateParam)) - return NTTP->getDepth(); - llvm_unreachable("Unhandled template parameter types"); -} - NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC, NamedDecl *TemplateParam, MultiLevelTemplateArgumentList &Args, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits