[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