[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
This commit is contained in:
Patryk Stefanski 2026-07-27 16:51:06 -07:00 committed by GitHub
parent e364a21086
commit 912128312f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 39 additions and 0 deletions

View file

@ -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

View file

@ -193,6 +193,7 @@ public:
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.
//===----------------------------------------------------------------------===//

View file

@ -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@f#$@S@L>#@TPO@1$@S@R[[#HASH0:]]#
void f(L<R{0}>);
// CHECK: | g | c:@F@g#$@S@L>#@TPO@1$@S@R[[#HASH0]]#
void g(L<R{0}>);
// CHECK: | h | c:@F@h#$@S@L>#@TPO@1$@S@R[[#HASH1:]]#
// CHECK-NOT: | h | c:@F@h#$@S@L>#@TPO@1$@S@R[[#HASH0]]#
void h(L<R{1}>);
struct S {
// CHECK: | set | c:@S@S@F@set#&&$@S@L>#@TPO@1$@S@R[[#HASH0]]#
void set(L<R{0}> &&);
};