https://github.com/mygitljf created 
https://github.com/llvm/llvm-project/pull/206041

I updated DeclRefExpr printing so fully-qualified printing consistently uses 
declaration ownership rather than only the written qualifier. This also 
preserves existing behavior for local names and cleaned parameter names.
The added tests cover both the direct expression printer behavior and the 
original type-printing scenario that exposed the missing qualification.
Fixes #205925 

>From f34d7896cebb2a33c7f68397ba8dd6c38a5b492c Mon Sep 17 00:00:00 2001
From: mygitljf <[email protected]>
Date: Fri, 26 Jun 2026 19:42:36 +0000
Subject: [PATCH] [clang][AST] Qualify DeclRefExpr printing

---
 clang/lib/AST/StmtPrinter.cpp           | 73 ++++++++++++++-----------
 clang/unittests/AST/StmtPrinterTest.cpp | 43 +++++++++++++++
 clang/unittests/AST/TypePrinterTest.cpp | 24 ++++++++
 3 files changed, 107 insertions(+), 33 deletions(-)

diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 6c3294573e9d4..e4dc41cf2c043 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1330,42 +1330,49 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
     TPOD->printAsExpr(OS, Policy);
     return;
   }
-  Node->getQualifier().print(OS, Policy);
-  if (Node->hasTemplateKeyword())
-    OS << "template ";
-
   bool ForceAnonymous =
       Policy.PrintAsCanonical && VD->getKind() == Decl::NonTypeTemplateParm;
-  DeclarationNameInfo NameInfo = Node->getNameInfo();
-  if (IdentifierInfo *ID = NameInfo.getName().getAsIdentifierInfo();
-      !ForceAnonymous &&
-      (ID || NameInfo.getName().getNameKind() != DeclarationName::Identifier)) 
{
-    if (Policy.CleanUglifiedParameters &&
-        isa<ParmVarDecl, NonTypeTemplateParmDecl>(VD) && ID)
-      OS << ID->deuglifiedName();
-    else
-      NameInfo.printName(OS, Policy);
+  bool CleanUglifiedParameter = Policy.CleanUglifiedParameters &&
+                                isa<ParmVarDecl, NonTypeTemplateParmDecl>(VD);
+
+  if (Policy.FullyQualifiedName && !ForceAnonymous && !CleanUglifiedParameter) 
{
+    VD->printQualifiedName(OS, Policy);
   } else {
-    switch (VD->getKind()) {
-    case Decl::NonTypeTemplateParm: {
-      auto *TD = cast<NonTypeTemplateParmDecl>(VD);
-      OS << "value-parameter-" << TD->getDepth() << '-' << TD->getIndex() << 
"";
-      break;
-    }
-    case Decl::ParmVar: {
-      auto *PD = cast<ParmVarDecl>(VD);
-      OS << "function-parameter-" << PD->getFunctionScopeDepth() << '-'
-         << PD->getFunctionScopeIndex();
-      break;
-    }
-    case Decl::Decomposition:
-      OS << "decomposition";
-      for (const auto &I : cast<DecompositionDecl>(VD)->bindings())
-        OS << '-' << I->getName();
-      break;
-    default:
-      OS << "unhandled-anonymous-" << VD->getDeclKindName();
-      break;
+    Node->getQualifier().print(OS, Policy);
+    if (Node->hasTemplateKeyword())
+      OS << "template ";
+
+    DeclarationNameInfo NameInfo = Node->getNameInfo();
+    if (IdentifierInfo *ID = NameInfo.getName().getAsIdentifierInfo();
+        !ForceAnonymous && (ID || NameInfo.getName().getNameKind() !=
+                                      DeclarationName::Identifier)) {
+      if (CleanUglifiedParameter && ID)
+        OS << ID->deuglifiedName();
+      else
+        NameInfo.printName(OS, Policy);
+    } else {
+      switch (VD->getKind()) {
+      case Decl::NonTypeTemplateParm: {
+        auto *TD = cast<NonTypeTemplateParmDecl>(VD);
+        OS << "value-parameter-" << TD->getDepth() << '-' << TD->getIndex()
+           << "";
+        break;
+      }
+      case Decl::ParmVar: {
+        auto *PD = cast<ParmVarDecl>(VD);
+        OS << "function-parameter-" << PD->getFunctionScopeDepth() << '-'
+           << PD->getFunctionScopeIndex();
+        break;
+      }
+      case Decl::Decomposition:
+        OS << "decomposition";
+        for (const auto &I : cast<DecompositionDecl>(VD)->bindings())
+          OS << '-' << I->getName();
+        break;
+      default:
+        OS << "unhandled-anonymous-" << VD->getDeclKindName();
+        break;
+      }
     }
   }
   if (Node->hasExplicitTemplateArgs()) {
diff --git a/clang/unittests/AST/StmtPrinterTest.cpp 
b/clang/unittests/AST/StmtPrinterTest.cpp
index 24ad5f30d9480..2b75253fa6698 100644
--- a/clang/unittests/AST/StmtPrinterTest.cpp
+++ b/clang/unittests/AST/StmtPrinterTest.cpp
@@ -297,6 +297,42 @@ TEST(StmtPrinter, TerseOutputWithLambdas) {
       [](PrintingPolicy &PP) { PP.TerseOutput = true; }));
 }
 
+TEST(StmtPrinter, FullyQualifiedDeclRefExpr) {
+  auto FullyQualified = [](PrintingPolicy &Policy) {
+    Policy.FullyQualifiedName = true;
+  };
+
+  ASSERT_TRUE(PrintedStmtCXXMatches(
+      StdVer::CXX17,
+      R"cpp(
+        namespace ns { int value; }
+        using namespace ns;
+        void A() { (void)value; }
+      )cpp",
+      declRefExpr(to(varDecl(hasName("::ns::value")))).bind("id"), "ns::value",
+      FullyQualified));
+
+  ASSERT_TRUE(PrintedStmtCXXMatches(
+      StdVer::CXX17,
+      R"cpp(
+        namespace ns { template <class T> void func(); }
+        using namespace ns;
+        void A() { func<int>(); }
+      )cpp",
+      declRefExpr(to(functionDecl(hasName("::ns::func")))).bind("id"),
+      "ns::func<int>", FullyQualified));
+
+  ASSERT_TRUE(PrintedStmtCXXMatches(
+      StdVer::CXX17, "void A(int param) { (void)param; }",
+      declRefExpr(to(parmVarDecl(hasName("param")))).bind("id"), "param",
+      FullyQualified));
+
+  ASSERT_TRUE(PrintedStmtCXXMatches(
+      StdVer::CXX17, "void A() { int local = 0; (void)local; }",
+      declRefExpr(to(varDecl(hasName("local")))).bind("id"), "local",
+      FullyQualified));
+}
+
 TEST(StmtPrinter, ParamsUglified) {
   llvm::StringLiteral Code = R"cpp(
     template <typename _T, int _I, template <typename> class _C>
@@ -307,6 +343,10 @@ TEST(StmtPrinter, ParamsUglified) {
   auto Clean = [](PrintingPolicy &Policy) {
     Policy.CleanUglifiedParameters = true;
   };
+  auto CleanFullyQualified = [](PrintingPolicy &Policy) {
+    Policy.CleanUglifiedParameters = true;
+    Policy.FullyQualifiedName = true;
+  };
 
   ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX14, Code,
                                     returnStmt().bind("id"),
@@ -314,4 +354,7 @@ TEST(StmtPrinter, ParamsUglified) {
   ASSERT_TRUE(
       PrintedStmtCXXMatches(StdVer::CXX14, Code, returnStmt().bind("id"),
                             "return typename C<T>::_F(I, j);\n", Clean));
+  ASSERT_TRUE(PrintedStmtCXXMatches(
+      StdVer::CXX14, Code, returnStmt().bind("id"),
+      "return typename _C<T>::_F(I, j);\n", CleanFullyQualified));
 }
diff --git a/clang/unittests/AST/TypePrinterTest.cpp 
b/clang/unittests/AST/TypePrinterTest.cpp
index 5023b5e093ec3..79f75909c57b5 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -121,6 +121,30 @@ TEST(TypePrinter, TemplateSpecializationFullyQualified) {
       [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = true; }));
 }
 
+TEST(TypePrinter, TemplateArgumentExpressionFullyQualified) {
+  llvm::StringLiteral Code = R"cpp(
+    namespace ns {
+      template <class T> inline constexpr bool pred_v = sizeof(T) > 0;
+      template <bool, class T> struct ei {};
+      template <class T> struct ei<true, T> { using type = T; };
+      template <bool B, class T> using enable_if_t = typename ei<B, T>::type;
+      struct Ret {};
+      template <class T> enable_if_t<pred_v<T>, Ret> f() { return {}; }
+    }
+    inline auto *ns_f_int = &ns::f<int>;
+  )cpp";
+
+  auto Matcher = functionDecl(hasName("::ns::f"), isTemplateInstantiation(),
+                              returns(qualType().bind("id")));
+  ASSERT_TRUE(PrintedTypeMatches(
+      Code, {"-std=c++17"}, Matcher, "enable_if_t<pred_v<int>, Ret>",
+      [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = false; }));
+  ASSERT_TRUE(PrintedTypeMatches(
+      Code, {"-std=c++17"}, Matcher,
+      "ns::enable_if_t<ns::pred_v<int>, ns::Ret>",
+      [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = true; }));
+}
+
 TEST(TypePrinter, TemplateIdWithNTTP) {
   constexpr char Code[] = R"cpp(
     template <int N>

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to