diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3d8cf750c12c1..29d668e4fd8d7 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,23 +2752,48 @@ 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( - ArrayRef TemplateParams, + const TemplateParameterList *TemplateParamsList, ArrayRef DeducedArgs) { struct TemplateParamsReferencedFinder : public RecursiveASTVisitor { - llvm::DenseSet TemplateParams; - llvm::DenseSet ReferencedTemplateParams; + const TemplateParameterList *TemplateParamList; + llvm::BitVector ReferencedTemplateParams; - TemplateParamsReferencedFinder(ArrayRef TemplateParams) - : TemplateParams(TemplateParams.begin(), TemplateParams.end()) {} + TemplateParamsReferencedFinder( + const TemplateParameterList *TemplateParamList) + : TemplateParamList(TemplateParamList), + ReferencedTemplateParams(TemplateParamList->size()) {} bool VisitTemplateTypeParmType(TemplateTypeParmType *TTP) { - MarkAppeared(TTP->getDecl()); + // We use the index and depth to retrieve the corresponding template + // parameter from the parameter list, which is more robost. + Mark(TTP->getDepth(), TTP->getIndex()); return true; } + bool VisitDeclRefExpr(DeclRefExpr *DRE) { MarkAppeared(DRE->getFoundDecl()); return true; @@ -2780,16 +2806,22 @@ 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(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[Index]) Results.push_back(Index); } return Results; @@ -2808,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, @@ -3149,7 +3171,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..a088c0a7b0272 100644 --- a/clang/test/AST/ast-dump-ctad-alias.cpp +++ b/clang/test/AST/ast-dump-ctad-alias.cpp @@ -99,3 +99,58 @@ 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 { +// Case 1: type template parameter +template +struct List1 { + List1(int); +}; + +template +struct TemplatedClass1 { + TemplatedClass1(T1); +}; + +template +TemplatedClass1(T1) -> TemplatedClass1>; + +template +using ATemplatedClass1 = TemplatedClass1>; + +ATemplatedClass1 test1(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 + +// 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