[clang] [clang] CTAD: use index and depth to retrieve template parameter for TemplateParamsReferencedInTemplateArgumentList (PR #98013)

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 11 02:41:26 PDT 2024


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.wu at gmail.com>
Date: Mon, 8 Jul 2024 13:19:13 +0200
Subject: [PATCH 1/3] [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.wu at gmail.com>
Date: Thu, 11 Jul 2024 11:09:55 +0200
Subject: [PATCH 2/3] 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,

>From 71b589bb019c27f4855278d035f602d77738f028 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Thu, 11 Jul 2024 11:41:05 +0200
Subject: [PATCH 3/3] 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<unsigned> TemplateParamsReferencedInTemplateArgumentList(
     ArrayRef<TemplateArgument> DeducedArgs) {
   struct TemplateParamsReferencedFinder
       : public RecursiveASTVisitor<TemplateParamsReferencedFinder> {
-    const TemplateParameterList* TemplateParamList;
+    const TemplateParameterList *TemplateParamList;
     llvm::BitVector ReferencedTemplateParams;
 
     TemplateParamsReferencedFinder(



More information about the cfe-commits mailing list