[clang] [clang][AST] Don't print inherited default template args (PR #161953)

Andrey Ali Khan Bolshakov via cfe-commits cfe-commits at lists.llvm.org
Sat Oct 4 07:15:08 PDT 2025


https://github.com/bolshakov-a updated https://github.com/llvm/llvm-project/pull/161953

>From 66bfe4906f61104468c7299002d32098d67b6e7e Mon Sep 17 00:00:00 2001
From: Bolshakov <bolsh.andrey at yandex.ru>
Date: Sat, 4 Oct 2025 12:09:19 +0300
Subject: [PATCH] [clang][AST] Don't print inherited default template args

Prior to this change, for the code like this:

template <int, int = 0>
class Tpl;
template <int = 0, int>
class Tpl;

pretty-printing produced an uncompilable code:

template <int, int = 0> class Tpl;
template <int = 0, int = 0> class Tpl;
---
 clang/docs/ReleaseNotes.rst            |  3 +++
 clang/lib/AST/DeclPrinter.cpp          |  4 ++--
 clang/test/AST/ast-print-record-decl.c | 13 ++++++++++++-
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 79dc0b2728e98..47fd674ef18ff 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -123,6 +123,9 @@ AST Dumping Potentially Breaking Changes
 
     ``__atomic_test_and_set(p, 0)``
 
+- Pretty-printing of templates with inherited (i.e. specified in a previous
+  redeclaration) default arguments has been fixed.
+
 Clang Frontend Potentially Breaking Changes
 -------------------------------------------
 - Members of anonymous unions/structs are now injected as ``IndirectFieldDecl``
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 196057f7b45a4..7001adeff5397 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -1894,7 +1894,7 @@ void DeclPrinter::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *TTP) {
       Out << TTP->getDeclName();
   }
 
-  if (TTP->hasDefaultArgument()) {
+  if (TTP->hasDefaultArgument() && !TTP->defaultArgumentWasInherited()) {
     Out << " = ";
     TTP->getDefaultArgument().getArgument().print(Policy, Out,
                                                   /*IncludeType=*/false);
@@ -1909,7 +1909,7 @@ void DeclPrinter::VisitNonTypeTemplateParmDecl(
         Policy.CleanUglifiedParameters ? II->deuglifiedName() : II->getName();
   printDeclType(NTTP->getType(), Name, NTTP->isParameterPack());
 
-  if (NTTP->hasDefaultArgument()) {
+  if (NTTP->hasDefaultArgument() && !NTTP->defaultArgumentWasInherited()) {
     Out << " = ";
     NTTP->getDefaultArgument().getArgument().print(Policy, Out,
                                                    /*IncludeType=*/false);
diff --git a/clang/test/AST/ast-print-record-decl.c b/clang/test/AST/ast-print-record-decl.c
index d3717a4feab83..fd815881ebeb0 100644
--- a/clang/test/AST/ast-print-record-decl.c
+++ b/clang/test/AST/ast-print-record-decl.c
@@ -290,9 +290,9 @@ KW DeclGroupInMemberList {
 // A tag decl group in the tag decl's own member list is exercised in
 // defSelfRef above.
 
+#ifdef __cplusplus
 
 // Check out-of-line record definition
-#ifdef __cplusplus
 // PRINT-CXX-NEXT: [[KW]] OutOfLineRecord {
 KW OutOfLineRecord {
   // PRINT-CXX-NEXT: [[KW]] Inner
@@ -304,4 +304,15 @@ KW OutOfLineRecord {
 KW OutOfLineRecord::Inner {
   // PRINT-CXX-NEXT: };
 };
+
+// PRINT-CXX-NEXT: template <typename, typename = int> [[KW]] SmearedTypeDefArgs;
+template <typename, typename = int> KW SmearedTypeDefArgs;
+// PRINT-CXX-NEXT: template <typename = int, typename> [[KW]] SmearedTypeDefArgs;
+template <typename = int, typename> KW SmearedTypeDefArgs;
+
+// PRINT-CXX-NEXT: template <int, int = 0> [[KW]] SmearedNTTPDefArgs;
+template <int, int = 0> KW SmearedNTTPDefArgs;
+// PRINT-CXX-NEXT: template <int = 0, int> [[KW]] SmearedNTTPDefArgs;
+template <int = 0, int> KW SmearedNTTPDefArgs;
+
 #endif



More information about the cfe-commits mailing list