[clang] [clang] Add formal linkage to textual AST dump (PR #194600)
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 28 06:06:47 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
----------------
AaronBallman wrote:
Might be worth a FIXME -- it's odd that we're printing the `VarTemplateSpecializationDecl` twice (seems like we're re-visiting the node accidentally).
https://github.com/llvm/llvm-project/pull/194600
More information about the cfe-commits
mailing list