[clang] [clang] Add visibility to AST dump (PR #218113)

Vlad Serebrennikov via cfe-commits cfe-commits at lists.llvm.org
Sat Aug 22 01:32:10 PDT 2026


https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/218113

>From 59a399602dac4da9e59ce52dba7b1547e25e2790 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 22 Aug 2026 10:59:12 +0300
Subject: [PATCH 1/3] [clang] Add visibility to AST dump

---
 clang/include/clang/AST/TextNodeDumper.h |  2 +-
 clang/lib/AST/TextNodeDumper.cpp         | 48 +++++++++++++++++-------
 2 files changed, 36 insertions(+), 14 deletions(-)

diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index 1cdd8c37c7fc6..2caee7612753f 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -208,7 +208,7 @@ class TextNodeDumper
   void dumpType(QualType T);
   void dumpBareDeclRef(const Decl *D);
   void dumpName(const NamedDecl *ND);
-  void dumpFormalLinkage(const NamedDecl *ND);
+  void dumpLV(const NamedDecl *ND);
   void dumpAccessSpecifier(AccessSpecifier AS);
   void dumpCleanupObject(const ExprWithCleanups::CleanupObject &C);
   void dumpTemplateSpecializationKind(TemplateSpecializationKind TSK);
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index f58cc4f5761b7..4ee3fd06d0aa0 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1456,7 +1456,7 @@ static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
   OS << ')';
 }
 
-void TextNodeDumper::dumpFormalLinkage(const NamedDecl *ND) {
+void TextNodeDumper::dumpLV(const NamedDecl *ND) {
   switch (ND->getFormalLinkage()) {
   case Linkage::None:
     // A lot of declarations have no linkage, so we only dump linkage if there
@@ -1477,6 +1477,28 @@ void TextNodeDumper::dumpFormalLinkage(const NamedDecl *ND) {
   case Linkage::VisibleNone:
     llvm_unreachable("Not a formal linkage!");
   }
+
+  // FIXME: HLSLAttributedResourceType should always have contained type,
+  //        or LinkageComputer::computeTypeLinkageInfo needs to deal with
+  //        the lack of contained type.
+  if (const auto *VD = dyn_cast<VarDecl>(ND)) {
+    if (const auto* Ty = dyn_cast<HLSLAttributedResourceType>(VD->getType()); Ty && Ty->getContainedType().isNull()) {
+      return;
+    }
+  }
+
+  switch (ND->getVisibility()) {
+  case Visibility::DefaultVisibility:
+    // A lot of declarations have default visibility, so we only dump other
+    // kinds of visibility.
+    break;
+  case Visibility::HiddenVisibility:
+    OS << " hidden-visibility";
+    break;
+  case Visibility::ProtectedVisibility:
+    OS << " protected-visibility";
+    break; 
+  }
 }
 
 void TextNodeDumper::VisitLoopControlStmt(const LoopControlStmt *Node) {
@@ -2382,7 +2404,7 @@ void TextNodeDumper::VisitTypedefDecl(const TypedefDecl *D) {
 
   const TagDecl *TD = D->getUnderlyingType()->getAsTagDecl();
   if (TD && TD->getTypedefNameForAnonDecl()) {
-    dumpFormalLinkage(D);
+    dumpLV(D);
   }
 }
 
@@ -2404,7 +2426,7 @@ void TextNodeDumper::VisitEnumDecl(const EnumDecl *D) {
     dumpPointer(Instance);
   }
 
-  dumpFormalLinkage(D);
+  dumpLV(D);
 }
 
 void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) {
@@ -2416,7 +2438,7 @@ void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) {
     OS << " definition";
 
   if (!D->isImplicit() && !D->getDescribedTemplate()) {
-    dumpFormalLinkage(D);
+    dumpLV(D);
   }
 }
 
@@ -2517,7 +2539,7 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) {
   }
 
   if (!isa<CXXDeductionGuideDecl>(D) && !D->getDescribedTemplate()) {
-    dumpFormalLinkage(D);
+    dumpLV(D);
   }
 }
 
@@ -2621,7 +2643,7 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
   }
 
   if (!D->getDescribedVarTemplate()) {
-    dumpFormalLinkage(D);
+    dumpLV(D);
   }
 }
 
@@ -2740,7 +2762,7 @@ void TextNodeDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
   if (!D->isFirstDecl())
     dumpDeclRef(D->getFirstDecl(), "original");
 
-  dumpFormalLinkage(D);
+  dumpLV(D);
 }
 
 void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
@@ -2759,14 +2781,14 @@ void TextNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
 
   const TagDecl *TD = D->getUnderlyingType()->getAsTagDecl();
   if (TD && TD->getTypedefNameForAnonDecl()) {
-    dumpFormalLinkage(D);
+    dumpLV(D);
   }
 }
 
 void TextNodeDumper::VisitTypeAliasTemplateDecl(
     const TypeAliasTemplateDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLV(D);
 }
 
 void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
@@ -2927,17 +2949,17 @@ void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
 
 void TextNodeDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLV(D);
 }
 
 void TextNodeDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLV(D);
 }
 
 void TextNodeDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLV(D);
 }
 
 void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
@@ -3248,7 +3270,7 @@ void TextNodeDumper::VisitBlockDecl(const BlockDecl *D) {
 
 void TextNodeDumper::VisitConceptDecl(const ConceptDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLV(D);
 }
 
 void TextNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {

>From 0129209d3afcd56cecb9aa2579b9dc10838ba287 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 22 Aug 2026 11:22:04 +0300
Subject: [PATCH 2/3] Add tests

---
 clang/test/AST/ast-dump-visibility.cpp | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 clang/test/AST/ast-dump-visibility.cpp

diff --git a/clang/test/AST/ast-dump-visibility.cpp b/clang/test/AST/ast-dump-visibility.cpp
new file mode 100644
index 0000000000000..63a485b1e83ea
--- /dev/null
+++ b/clang/test/AST/ast-dump-visibility.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -ast-dump -std=c++2c -fms-extensions %s | FileCheck --match-full-lines --check-prefix=CHECK %s
+
+int a1;
+// CHECK: |-VarDecl {{.*}} a1 'int' external-linkage
+
+[[gnu::visibility("default")]] int a2;
+// CHECK: |-VarDecl {{.*}} a2 'int' external-linkage
+
+__declspec(dllexport) int a3;
+// CHECK: |-VarDecl {{.*}} a3 'int' external-linkage
+
+[[gnu::visibility("hidden")]] int b;
+// CHECK: |-VarDecl {{.*}} b 'int' external-linkage hidden-visibility
+
+[[gnu::visibility("protected")]] int c;
+// CHECK: `-VarDecl {{.*}} c 'int' external-linkage protected-visibility

>From d5159f189cc6b2f2078038fcbd3f844c11352c8d Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Sat, 22 Aug 2026 11:31:54 +0300
Subject: [PATCH 3/3] Run clang-format

---
 clang/lib/AST/TextNodeDumper.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 4ee3fd06d0aa0..4a912cbf4dae4 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1482,7 +1482,8 @@ void TextNodeDumper::dumpLV(const NamedDecl *ND) {
   //        or LinkageComputer::computeTypeLinkageInfo needs to deal with
   //        the lack of contained type.
   if (const auto *VD = dyn_cast<VarDecl>(ND)) {
-    if (const auto* Ty = dyn_cast<HLSLAttributedResourceType>(VD->getType()); Ty && Ty->getContainedType().isNull()) {
+    if (const auto *Ty = dyn_cast<HLSLAttributedResourceType>(VD->getType());
+        Ty && Ty->getContainedType().isNull()) {
       return;
     }
   }
@@ -1497,7 +1498,7 @@ void TextNodeDumper::dumpLV(const NamedDecl *ND) {
     break;
   case Visibility::ProtectedVisibility:
     OS << " protected-visibility";
-    break; 
+    break;
   }
 }
 



More information about the cfe-commits mailing list