Author: Vlad Serebrennikov
Date: 2026-08-26T14:18:43+04:00
New Revision: 82507b433507e06e795fa13afb7cb2b20402c1da

URL: 
https://github.com/llvm/llvm-project/commit/82507b433507e06e795fa13afb7cb2b20402c1da
DIFF: 
https://github.com/llvm/llvm-project/commit/82507b433507e06e795fa13afb7cb2b20402c1da.diff

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

Similarly to https://github.com/llvm/llvm-project/pull/194600, this PR
adds visibility information (default/hidden/protected) to AST dump in
exactly the same places where linkage is printed. As with no linkage,
default visibility is assumed and not printed, as it's so common that I
didn't have to update any of the existing tests.

Added: 
    clang/test/AST/ast-dump-visibility.cpp

Modified: 
    clang/include/clang/AST/TextNodeDumper.h
    clang/lib/AST/TextNodeDumper.cpp
    clang/lib/AST/Type.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/TextNodeDumper.h 
b/clang/include/clang/AST/TextNodeDumper.h
index 1cdd8c37c7fc6..7219a0d3f8e50 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 dumpLinkageAndVisibility(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..f10753fe675d8 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::dumpLinkageAndVisibility(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,19 @@ void TextNodeDumper::dumpFormalLinkage(const NamedDecl 
*ND) {
   case Linkage::VisibleNone:
     llvm_unreachable("Not a formal linkage!");
   }
+
+  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 +2395,7 @@ void TextNodeDumper::VisitTypedefDecl(const TypedefDecl 
*D) {
 
   const TagDecl *TD = D->getUnderlyingType()->getAsTagDecl();
   if (TD && TD->getTypedefNameForAnonDecl()) {
-    dumpFormalLinkage(D);
+    dumpLinkageAndVisibility(D);
   }
 }
 
@@ -2404,7 +2417,7 @@ void TextNodeDumper::VisitEnumDecl(const EnumDecl *D) {
     dumpPointer(Instance);
   }
 
-  dumpFormalLinkage(D);
+  dumpLinkageAndVisibility(D);
 }
 
 void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) {
@@ -2416,7 +2429,7 @@ void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) 
{
     OS << " definition";
 
   if (!D->isImplicit() && !D->getDescribedTemplate()) {
-    dumpFormalLinkage(D);
+    dumpLinkageAndVisibility(D);
   }
 }
 
@@ -2517,7 +2530,7 @@ void TextNodeDumper::VisitFunctionDecl(const FunctionDecl 
*D) {
   }
 
   if (!isa<CXXDeductionGuideDecl>(D) && !D->getDescribedTemplate()) {
-    dumpFormalLinkage(D);
+    dumpLinkageAndVisibility(D);
   }
 }
 
@@ -2621,7 +2634,7 @@ void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
   }
 
   if (!D->getDescribedVarTemplate()) {
-    dumpFormalLinkage(D);
+    dumpLinkageAndVisibility(D);
   }
 }
 
@@ -2740,7 +2753,7 @@ void TextNodeDumper::VisitNamespaceDecl(const 
NamespaceDecl *D) {
   if (!D->isFirstDecl())
     dumpDeclRef(D->getFirstDecl(), "original");
 
-  dumpFormalLinkage(D);
+  dumpLinkageAndVisibility(D);
 }
 
 void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
@@ -2759,14 +2772,14 @@ void TextNodeDumper::VisitTypeAliasDecl(const 
TypeAliasDecl *D) {
 
   const TagDecl *TD = D->getUnderlyingType()->getAsTagDecl();
   if (TD && TD->getTypedefNameForAnonDecl()) {
-    dumpFormalLinkage(D);
+    dumpLinkageAndVisibility(D);
   }
 }
 
 void TextNodeDumper::VisitTypeAliasTemplateDecl(
     const TypeAliasTemplateDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLinkageAndVisibility(D);
 }
 
 void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
@@ -2927,17 +2940,17 @@ void TextNodeDumper::VisitCXXRecordDecl(const 
CXXRecordDecl *D) {
 
 void TextNodeDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLinkageAndVisibility(D);
 }
 
 void TextNodeDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLinkageAndVisibility(D);
 }
 
 void TextNodeDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLinkageAndVisibility(D);
 }
 
 void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
@@ -3248,7 +3261,7 @@ void TextNodeDumper::VisitBlockDecl(const BlockDecl *D) {
 
 void TextNodeDumper::VisitConceptDecl(const ConceptDecl *D) {
   dumpName(D);
-  dumpFormalLinkage(D);
+  dumpLinkageAndVisibility(D);
 }
 
 void TextNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {

diff  --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index b92dec99613f7..48da2451dc40f 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -5150,9 +5150,8 @@ LinkageInfo LinkageComputer::computeTypeLinkageInfo(const 
Type *T) {
     return computeTypeLinkageInfo(
         cast<OverflowBehaviorType>(T)->getUnderlyingType());
   case Type::HLSLAttributedResource:
-    return computeTypeLinkageInfo(cast<HLSLAttributedResourceType>(T)
-                                      ->getContainedType()
-                                      ->getCanonicalTypeInternal());
+    return computeTypeLinkageInfo(
+        cast<HLSLAttributedResourceType>(T)->getWrappedType());
   case Type::HLSLInlineSpirv:
     return LinkageInfo::external();
   }

diff  --git a/clang/test/AST/ast-dump-visibility.cpp 
b/clang/test/AST/ast-dump-visibility.cpp
new file mode 100644
index 0000000000000..59ba3c23c4cad
--- /dev/null
+++ b/clang/test/AST/ast-dump-visibility.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -ast-dump -std=c++2c -triple x86_64-unknown-linux-gnu 
-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


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

Reply via email to