[clang] [clang-tools-extra] [clang] Add formal linkage to textual AST dump (PR #194600)
Vlad Serebrennikov via cfe-commits
cfe-commits at lists.llvm.org
Fri May 1 02:36:24 PDT 2026
================
@@ -0,0 +1,271 @@
+// RUN: %clang_cc1 -ast-dump %s | FileCheck --match-full-lines %s
+
+namespace std {
+template <typename T>
+struct initializer_list {
+ const T* begin;
+ const T* end;
+};
+} // namespace std
+
+typedef int TypedefInt;
+// CHECK: |-TypedefDecl {{.*}} TypedefInt 'int'
+
+using UsingInt = int;
+// CHECK: |-TypeAliasDecl {{.*}} UsingInt 'int'
+
+template <typename T>
+using TemplateUsingInt = T;
+// CHECK: |-TypeAliasTemplateDecl {{.*}} TemplateUsingInt external-linkage
+// CHECK: | `-TypeAliasDecl {{.*}} TemplateUsingInt 'T'
+
+typedef struct {} TypedefUnnamedStruct;
+// CHECK: |-TypedefDecl {{.*}} TypedefUnnamedStruct 'struct TypedefUnnamedStruct' external-linkage
+// CHECK: | `-RecordType {{.*}} 'struct TypedefUnnamedStruct' owns_tag struct
+
+using UsingUnnamedStruct = struct {};
+// CHECK: |-TypeAliasDecl {{.*}} UsingUnnamedStruct 'struct UsingUnnamedStruct' external-linkage
+// CHECK: | `-RecordType {{.*}} 'struct UsingUnnamedStruct' owns_tag struct
+
+typedef struct TypedefNamedStruct {} TypedefNameForNamedStruct;
+// CHECK: |-CXXRecordDecl {{.*}} struct TypedefNamedStruct definition external-linkage
+// CHECK: | `-CXXRecordDecl {{.*}} implicit struct TypedefNamedStruct
+// CHECK: |-TypedefDecl {{.*}} TypedefNameForNamedStruct 'struct TypedefNamedStruct'
+// CHECK: | `-RecordType {{.*}} 'struct TypedefNamedStruct' owns_tag struct
+// CHECK: | `-CXXRecord {{.*}} 'TypedefNamedStruct'
+
+using AliasForNamedStruct = struct UsingNamedStruct {};
+// CHECK: |-CXXRecordDecl {{.*}} struct UsingNamedStruct definition external-linkage
+// CHECK: | `-CXXRecordDecl {{.*}} implicit struct UsingNamedStruct
+// CHECK: |-TypeAliasDecl {{.*}} AliasForNamedStruct 'struct UsingNamedStruct'
+// CHECK: | `-RecordType {{.*}} 'struct UsingNamedStruct' owns_tag struct
+// CHECK: | `-CXXRecord {{.*}} 'UsingNamedStruct'
+
+typedef enum {} TypedefUnnamedEnum;
+// CHECK: |-TypedefDecl {{.*}} TypedefUnnamedEnum 'enum TypedefUnnamedEnum' external-linkage
+// CHECK: | `-EnumType {{.*}} 'enum TypedefUnnamedEnum' owns_tag enum
+
+using UsingUnnamedEnum = enum {};
+// CHECK: |-TypeAliasDecl {{.*}} UsingUnnamedEnum 'enum UsingUnnamedEnum' external-linkage
+// CHECK: | `-EnumType {{.*}} 'enum UsingUnnamedEnum' owns_tag enum
+
+enum Enum {};
+// CHECK: |-EnumDecl {{.*}} Enum external-linkage
+
+enum { Enumerator };
+// CHECK: |-EnumDecl {{.*}} no-linkage
+// CHECK: | `-EnumConstantDecl {{.*}} referenced Enumerator '(unnamed enum at {{.*}})'
+// FIXME: This enum has enumerator as its name for linkage purposes, and has external linkage.
+
+decltype(Enumerator) f();
+// CHECK: |-FunctionDecl {{.*}} f 'decltype(Enumerator) ()' external-linkage
+
+auto [Binding1, Binding2] = {3, 4};
+// CHECK: |-BindingDecl {{.*}} Binding1 'const int *'
+// CHECK: |-BindingDecl {{.*}} Binding2 'const int *'
+// CHECK: |-DecompositionDecl {{.*}} used 'std::initializer_list<int>' cinit external-linkage
+// CHECK: | |-BindingDecl {{.*}} Binding1 'const int *'
+// CHECK: | `-BindingDecl {{.*}} Binding2 'const int *'
+
+int Int = 0;
+// CHECK: |-VarDecl {{.*}} Int 'int' cinit external-linkage
+
+const int ConstInt = 0;
+// CHECK: |-VarDecl {{.*}} ConstInt 'const int' cinit internal-linkage
+
+template <typename T>
+T TemplatedVar = T{};
+// CHECK: |-VarTemplateDecl {{.*}} TemplatedVar external-linkage
+// CHECK: | |-VarDecl {{.*}} TemplatedVar 'T' cinit instantiated_from 0x{{[0-9a-f]*}} external-linkage
+// CHECK: | `-VarTemplateSpecializationDecl {{.*}} used TemplatedVar 'int' implicit_instantiation cinit instantiated_from 0x{{[0-9a-f]*}} external-linkage
+
+int TemplatedVarSpec = TemplatedVar<int>;
+// CHECK: |-VarDecl {{.*}} TemplatedVarSpec 'int' cinit external-linkage
+// CHECK: |-VarTemplateSpecializationDecl {{.*}} used TemplatedVar 'int' implicit_instantiation cinit instantiated_from 0x{{[0-9a-f]*}} external-linkage
+
+void FuncDecl();
+// CHECK: |-FunctionDecl {{.*}} FuncDecl 'void ()' external-linkage
+
+template <typename>
+void TemplatedFuncDecl();
+// CHECK: |-FunctionTemplateDecl {{.*}} TemplatedFuncDecl external-linkage
+// CHECK: | `-FunctionDecl {{.*}} TemplatedFuncDecl 'void ()' external-linkage
+
+void FuncDef() {
+// CHECK: |-FunctionDecl {{.*}} FuncDef 'void ()' external-linkage
+
+ extern int Int;
+// CHECK: | | `-VarDecl {{.*}} Int 'int' extern external-linkage
+ extern const int ConstInt;
+// CHECK: | | `-VarDecl {{.*}} ConstInt 'const int' extern internal-linkage
+ void FuncDecl();
+// CHECK: | | `-FunctionDecl {{.*}} FuncDecl 'void ()' external-linkage
+ extern void FuncDecl();
+// CHECK: | | `-FunctionDecl {{.*}} FuncDecl 'void ()' extern external-linkage
+ {
+ int Int;
+// CHECK: | | `-VarDecl {{.*}} Int 'int' no-linkage
+ {
+ extern int Int;
+// CHECK: | | `-VarDecl {{.*}} Int 'int' extern external-linkage
+ extern const int ConstInt;
+// CHECK: | `-VarDecl {{.*}} ConstInt 'const int' extern internal-linkage
+ }
+ }
+}
+
+template <typename>
+void TemplatedFuncDef() {}
+// CHECK: |-FunctionTemplateDecl {{.*}} TemplatedFuncDef external-linkage
+// CHECK: | `-FunctionDecl {{.*}} TemplatedFuncDef 'void ()' external-linkage
+
+
+struct KnownFriendStruct;
+// CHECK: |-CXXRecordDecl {{.*}} struct KnownFriendStruct external-linkage
+
+template <typename>
+struct KnownFriendStructTemplate;
+// CHECK: |-ClassTemplateDecl {{.*}} KnownFriendStructTemplate external-linkage
+// CHECK: | `-CXXRecordDecl {{.*}} struct KnownFriendStructTemplate external-linkage
+
+namespace N {
+// CHECK: |-NamespaceDecl {{.*}} N external-linkage
+
+struct Struct {
+// CHECK: | `-CXXRecordDecl {{.*}} struct Struct definition external-linkage
+// CHECK: | |-CXXRecordDecl {{.*}} implicit struct Struct
+
+ friend struct UnknownFriendStruct;
+// CHECK: | |-FriendDecl {{.*}} 'struct UnknownFriendStruct'
+// CHECK: | | `-CXXRecordDecl {{.*}} friend_undeclared struct UnknownFriendStruct
+
+ friend struct ::KnownFriendStruct;
+// CHECK: | |-FriendDecl {{.*}} 'struct ::KnownFriendStruct'
+
+ template <typename>
+ friend struct ::KnownFriendStructTemplate;
+// CHECK: | |-FriendDecl {{.*}} col:{{[0-9]*$}}
+// CHECK: | | `-ClassTemplateDecl {{.*}} friend KnownFriendStructTemplate
+// CHECK: | | `-CXXRecordDecl {{.*}} struct KnownFriendStructTemplate
+
+ friend void UnknownFuncDecl();
+// CHECK: | |-FriendDecl {{.*}} col:{{[0-9]*$}}
+// CHECK: | | `-FunctionDecl {{.*}} friend_undeclared UnknownFuncDecl 'void ()'
+
+ friend void ::FuncDecl();
+// CHECK: | |-FriendDecl {{.*}} col:{{[0-9]*$}}
+// CHECK: | | `-FunctionDecl {{.*}} friend FuncDecl 'void ()'
+
+ template <typename>
+ friend void ::TemplatedFuncDecl();
+// CHECK: | |-FriendDecl {{.*}} col:{{[0-9]*$}}
+// CHECK: | | `-FunctionTemplateDecl {{.*}} friend TemplatedFuncDecl
+// CHECK: | | `-FunctionDecl {{.*}} friend TemplatedFuncDecl 'void ()'
+
+ int NonStaticDataMember;
+// CHECK: | |-FieldDecl {{.*}} NonStaticDataMember 'int'
+
+ static int StaticDataMember;
+// CHECK: | |-VarDecl {{.*}} StaticDataMember 'int' static external-linkage
+
+ void NonStaticMemberFunction();
+// CHECK: | |-CXXMethodDecl {{.*}} NonStaticMemberFunction 'void ()' external-linkage
+
+ template <typename>
+ void NonStaticMemberFunctionTemplate();
+// CHECK: | |-FunctionTemplateDecl {{.*}} NonStaticMemberFunctionTemplate external-linkage
+// CHECK: | | `-CXXMethodDecl {{.*}} NonStaticMemberFunctionTemplate 'void ()' external-linkage
+
+ static void StaticMemberFunction();
+// CHECK: | |-CXXMethodDecl {{.*}} StaticMemberFunction 'void ()' static external-linkage
+
+ template <typename>
+ static void StaticMemberFunctionTemplate();
+// CHECK: | |-FunctionTemplateDecl {{.*}} StaticMemberFunctionTemplate external-linkage
+// CHECK: | | `-CXXMethodDecl {{.*}} StaticMemberFunctionTemplate 'void ()' static external-linkage
+
+ struct NestedStruct {};
+// CHECK: | |-CXXRecordDecl {{.*}} struct NestedStruct definition external-linkage
+// CHECK: | | `-CXXRecordDecl {{.*}} implicit struct NestedStruct
+
+ template <typename>
+ struct NestedStructTemplate {};
+// CHECK: | `-ClassTemplateDecl {{.*}} NestedStructTemplate external-linkage
+// CHECK: | `-CXXRecordDecl {{.*}} struct NestedStructTemplate definition external-linkage
+// CHECK: | `-CXXRecordDecl {{.*}} implicit struct NestedStructTemplate
+};
+
+} // namespace N
+
+namespace M {
+template <typename>
+struct StructTemplate {
+// CHECK: | `-ClassTemplateDecl {{.*}} StructTemplate external-linkage
+// CHECK: | `-CXXRecordDecl {{.*}} struct StructTemplate definition external-linkage
+// CHECK: | |-CXXRecordDecl {{.*}} implicit struct StructTemplate
+
+ friend struct UnknownFriendStruct;
+// CHECK: | |-FriendDecl {{.*}} 'struct UnknownFriendStruct'
+// CHECK: | | `-CXXRecordDecl {{.*}} friend_undeclared struct UnknownFriendStruct
+
+ friend struct ::KnownFriendStruct;
+// CHECK: | |-FriendDecl {{.*}} 'struct ::KnownFriendStruct'
----------------
Endilll wrote:
FIXME added
https://github.com/llvm/llvm-project/pull/194600
More information about the cfe-commits
mailing list