[clang] 9121283 - [clang][Index][USR] Generate USRs for class-type non-type template arguments (#212356)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 27 16:51:12 PDT 2026


Author: Patryk Stefanski
Date: 2026-07-27T16:51:06-07:00
New Revision: 912128312f026605bce4ff11ef8a37d56a1a03f8

URL: https://github.com/llvm/llvm-project/commit/912128312f026605bce4ff11ef8a37d56a1a03f8
DIFF: https://github.com/llvm/llvm-project/commit/912128312f026605bce4ff11ef8a37d56a1a03f8.diff

LOG: [clang][Index][USR] Generate USRs for class-type non-type template arguments (#212356)

A class-type non-type template parameter is represented in the AST by a
TemplateParamObjectDecl, which has an empty DeclarationName.
USRGenerator had no visitor for it, so it fell through to
VisitNamedDecl, where EmitDeclName fails on the empty name and sets
IgnoreResults. That discarded the USR of the enclosing declaration.

Add a visitor that encodes the parameter object's type and value, so
specializations on distinct values get distinct USRs and equal values
agree.

Fixes #212351

Added: 
    clang/test/Index/USR/class-type-tpl-arg.cpp

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/UnifiedSymbolResolution/USRGeneration.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index cc340ede25c6b..ac2688886c1ee 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -345,6 +345,8 @@ features cannot lower the translation-unit ABI level;
 - Fixed an assertion failure when passing a wide string literal to `__builtin_nan`. (#GH212108)
 - Fixed a constraint comparison bug in partial ordering. (#GH182671)
 - Fixed a rejected-valid case that used an explicit object parameter in an out-of-line definition of a nested class member. (#GH136472)
+- Fixed USR generation for declarations whose signature mentions a class-type
+  non-type template parameter. (#GH212351)
 
 #### Bug Fixes to Compiler Builtins
 

diff  --git a/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp b/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp
index 5f689ad32159b..f167302aca74b 100644
--- a/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp
+++ b/clang/lib/UnifiedSymbolResolution/USRGeneration.cpp
@@ -193,6 +193,7 @@ class USRGenerator : public ConstDeclVisitor<USRGenerator> {
   void VisitTemplateArgument(const TemplateArgument &Arg);
 
   void VisitMSGuidDecl(const MSGuidDecl *D);
+  void VisitTemplateParamObjectDecl(const TemplateParamObjectDecl *D);
 
   /// Emit a Decl's name using NamedDecl::printName() and return true if
   ///  the decl had no name.
@@ -1212,6 +1213,15 @@ void USRGenerator::VisitMSGuidDecl(const MSGuidDecl *D) {
   D->NamedDecl::printName(Out);
 }
 
+void USRGenerator::VisitTemplateParamObjectDecl(
+    const TemplateParamObjectDecl *D) {
+  Out << "@TPO@";
+  VisitType(D->getType());
+  ODRHash Hash{};
+  Hash.AddStructuralValue(D->getValue());
+  Out << Hash.CalculateHash();
+}
+
 //===----------------------------------------------------------------------===//
 // USR generation functions.
 //===----------------------------------------------------------------------===//

diff  --git a/clang/test/Index/USR/class-type-tpl-arg.cpp b/clang/test/Index/USR/class-type-tpl-arg.cpp
new file mode 100644
index 0000000000000..2ef0d02ece14b
--- /dev/null
+++ b/clang/test/Index/USR/class-type-tpl-arg.cpp
@@ -0,0 +1,27 @@
+// RUN: c-index-test core -print-source-symbols -- -std=c++20 %s | FileCheck %s
+
+// Check USRs of template specializations with class-type NTTP values.
+
+struct R {
+  int a;
+};
+
+template <R> struct L {};
+
+// Equal parameter object values must produce equal USRs, and distinct values
+// must produce distinct ones.
+
+// CHECK: | f | c:@F at f#$@S at L>#@TPO at 1$@S at R[[#HASH0:]]#
+void f(L<R{0}>);
+
+// CHECK: | g | c:@F at g#$@S at L>#@TPO at 1$@S at R[[#HASH0]]#
+void g(L<R{0}>);
+
+// CHECK: | h | c:@F at h#$@S at L>#@TPO at 1$@S at R[[#HASH1:]]#
+// CHECK-NOT: | h | c:@F at h#$@S at L>#@TPO at 1$@S at R[[#HASH0]]#
+void h(L<R{1}>);
+
+struct S {
+  // CHECK: | set | c:@S at S@F at set#&&$@S at L>#@TPO at 1$@S at R[[#HASH0]]#
+  void set(L<R{0}> &&);
+};


        


More information about the cfe-commits mailing list