From c9297f8abe8d480fdcd3ba6d6598268fef74ddb4 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 8 Jul 2024 13:19:13 +0200 Subject: [PATCH 1/5] [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 TemplateParamsReferencedInTemplateArgumentList( - ArrayRef TemplateParams, + const TemplateParameterList* TemplateParamsList, ArrayRef DeducedArgs) { struct TemplateParamsReferencedFinder : public RecursiveASTVisitor { + const TemplateParameterList* TemplateParamList; llvm::DenseSet TemplateParams; llvm::DenseSet ReferencedTemplateParams; - TemplateParamsReferencedFinder(ArrayRef 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 TemplateParamsReferencedInTemplateArgumentList( ReferencedTemplateParams.insert(ND); } }; - TemplateParamsReferencedFinder Finder(TemplateParams); + TemplateParamsReferencedFinder Finder(TemplateParamsList); Finder.TraverseTemplateArguments(DeducedArgs); SmallVector 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 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 'auto (double, double) -> Foo' implicit_instantiation + +namespace GH90209 { +template +struct List { + List(int); +}; + +template +struct TemplatedClass { + TemplatedClass(T1); +}; + +template +TemplatedClass(T1) -> TemplatedClass>; + +template +using ATemplatedClass = TemplatedClass>; + +ATemplatedClass test(1); +// Verify that we have a correct template parameter list for the deduction guide. +// +// CHECK: FunctionTemplateDecl {{.*}} +// 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 Date: Thu, 11 Jul 2024 11:09:55 +0200 Subject: [PATCH 2/5] 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(TemplateParam)) + return TTP->getDepth(); + if (auto *TTP = dyn_cast(TemplateParam)) + return TTP->getDepth(); + if (auto *NTTP = dyn_cast(TemplateParam)) + return NTTP->getDepth(); + llvm_unreachable("Unhandled template parameter types"); +} + +unsigned getTemplateParameterIndex(NamedDecl *TemplateParam) { + if (auto *TTP = dyn_cast(TemplateParam)) + return TTP->getIndex(); + if (auto *TTP = dyn_cast(TemplateParam)) + return TTP->getIndex(); + if (auto *NTTP = dyn_cast(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 TemplateParamsReferencedInTemplateArgumentList( @@ -2759,26 +2780,17 @@ SmallVector TemplateParamsReferencedInTemplateArgumentList( struct TemplateParamsReferencedFinder : public RecursiveASTVisitor { const TemplateParameterList* TemplateParamList; - llvm::DenseSet TemplateParams; - llvm::DenseSet 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 TemplateParamsReferencedInTemplateArgumentList( } void MarkAppeared(NamedDecl *ND) { - if (TemplateParams.contains(ND)) - ReferencedTemplateParams.insert(ND); + if (llvm::isa(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 TemplateParamsReferencedInTemplateArgumentList( SmallVector 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(TemplateParam)) - return TTP->getDepth(); - if (auto *TTP = dyn_cast(TemplateParam)) - return TTP->getDepth(); - if (auto *NTTP = dyn_cast(TemplateParam)) - return NTTP->getDepth(); - llvm_unreachable("Unhandled template parameter types"); -} - NamedDecl *transformTemplateParameter(Sema &SemaRef, DeclContext *DC, NamedDecl *TemplateParam, MultiLevelTemplateArgumentList &Args, From 71b589bb019c27f4855278d035f602d77738f028 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 11 Jul 2024 11:41:05 +0200 Subject: [PATCH 3/5] clang-format --- clang/lib/Sema/SemaTemplate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 58082cd111a9a..6d52ca23940dc 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2779,7 +2779,7 @@ SmallVector TemplateParamsReferencedInTemplateArgumentList( ArrayRef DeducedArgs) { struct TemplateParamsReferencedFinder : public RecursiveASTVisitor { - const TemplateParameterList* TemplateParamList; + const TemplateParameterList *TemplateParamList; llvm::BitVector ReferencedTemplateParams; TemplateParamsReferencedFinder( From 3f4d58e79748906603737c5b249d7bd82a57ddeb Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 11 Jul 2024 14:24:48 +0200 Subject: [PATCH 4/5] Add testcase for template template parameter --- clang/test/AST/ast-dump-ctad-alias.cpp | 48 +++++++++++++++++++++----- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/clang/test/AST/ast-dump-ctad-alias.cpp b/clang/test/AST/ast-dump-ctad-alias.cpp index adccad97a205b..a088c0a7b0272 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -101,26 +101,56 @@ BFoo b2(1.0, 2.0); // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (double, double) -> Foo' implicit_instantiation namespace GH90209 { +// Case 1: type template parameter template -struct List { - List(int); +struct List1 { + List1(int); }; template -struct TemplatedClass { - TemplatedClass(T1); +struct TemplatedClass1 { + TemplatedClass1(T1); }; template -TemplatedClass(T1) -> TemplatedClass>; +TemplatedClass1(T1) -> TemplatedClass1>; template -using ATemplatedClass = TemplatedClass>; +using ATemplatedClass1 = TemplatedClass1>; -ATemplatedClass test(1); +ATemplatedClass1 test1(1); // Verify that we have a correct template parameter list for the deduction guide. // -// CHECK: FunctionTemplateDecl {{.*}} +// CHECK: FunctionTemplateDecl {{.*}} // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T2 // CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible -} // namespace GH90209 \ No newline at end of file + +// Case 2: template template parameter +template struct Foo{}; + +template typename Ts> +struct List2 { + List2(int); +}; + +template +struct TemplatedClass2 { + TemplatedClass2(T1); +}; + +template typename T1> +TemplatedClass2(T1) -> TemplatedClass2>; + +template typename T2> +using ATemplatedClass2 = TemplatedClass2>; + +List2 list(1); +ATemplatedClass2 test2(list); +// Verify that we have a correct template parameter list for the deduction guide. +// +// CHECK: FunctionTemplateDecl {{.*}} +// CHECK-NEXT: |-TemplateTemplateParmDecl {{.*}} depth 0 index 0 T2 +// CHECK-NEXT: | `-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 +// CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible + +} // namespace GH90209 From e0d228930c690afc033239cc5ac6658d2b7f6b34 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 11 Jul 2024 14:41:40 +0200 Subject: [PATCH 5/5] clang-format --- clang/lib/Sema/SemaTemplate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 6d52ca23940dc..29d668e4fd8d7 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2775,7 +2775,7 @@ unsigned getTemplateParameterIndex(NamedDecl *TemplateParam) { // Find all template parameters that appear in the given DeducedArgs. // Return the indices of the template parameters in the TemplateParams. SmallVector TemplateParamsReferencedInTemplateArgumentList( - const TemplateParameterList* TemplateParamsList, + const TemplateParameterList *TemplateParamsList, ArrayRef DeducedArgs) { struct TemplateParamsReferencedFinder : public RecursiveASTVisitor {