[clang] [clang][AST] Qualify DeclRefExpr printing (PR #206041)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 26 05:23:38 PDT 2026
https://github.com/mygitljf updated https://github.com/llvm/llvm-project/pull/206041
>From f34d7896cebb2a33c7f68397ba8dd6c38a5b492c Mon Sep 17 00:00:00 2001
From: mygitljf <2410316423 at qq.com>
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>
More information about the cfe-commits
mailing list