Clang Project

clang_source_code/test/CodeGenCXX/debug-info-static-member.cpp
1// RUN: %clangxx -target x86_64-unknown-unknown -g %s -emit-llvm -S -o - | FileCheck %s
2// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++98 %s -emit-llvm -S -o - | FileCheck %s
3// RUN: %clangxx -target x86_64-unknown-unknown -g -std=c++11 %s -emit-llvm -S -o - | FileCheck %s
4// PR14471
5
6// CHECK: @_ZN1C1aE = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]]
7// CHECK: @_ZN1C1bE = dso_local global i32 2, align 4, !dbg [[B:![0-9]+]]
8// CHECK: @_ZN1C1cE = dso_local global i32 1, align 4, !dbg [[C:![0-9]+]]
9
10enum X {
11  Y
12};
13class C
14{
15  static int a;
16  const static bool const_a = true;
17protected:
18  static int b;
19#if __cplusplus >= 201103L
20  constexpr static float const_b = 3.14;
21#else
22  const static float const_b = 3.14;
23#endif
24public:
25  static int c;
26  const static int const_c = 18;
27  int d;
28  static X x_a;
29};
30
31// The definition of C::a drives the emission of class C, which is
32// why the definition of "a" comes before the declarations while
33// "b" and "c" come after.
34
35// CHECK: [[A]] = !DIGlobalVariableExpression(var: [[AV:.*]], expr: !DIExpression())
36// CHECK: [[AV]] = distinct !DIGlobalVariable(name: "a",
37// CHECK-SAME:                                declaration: ![[DECL_A:[0-9]+]])
38//
39// CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}}, identifier: "_ZTS1X")
40// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct"
41// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var"
42// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "static_decl_templ<int>"
43// CHECK-NOT:              DIFlagFwdDecl
44// CHECK-SAME:             ){{$}}
45// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var"
46
47int C::a = 4;
48// CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BV:.*]], expr: !DIExpression())
49// CHECK: [[BV]] = distinct !DIGlobalVariable(name: "b",
50// CHECK-SAME:                                declaration: ![[DECL_B:[0-9]+]])
51// CHECK: ![[DECL_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b"
52// CHECK-NOT:                                 size:
53// CHECK-NOT:                                 align:
54// CHECK-NOT:                                 offset:
55// CHECK-SAME:                                flags: DIFlagProtected | DIFlagStaticMember)
56//
57// CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C")
58//
59// CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a"
60// CHECK-NOT:                                 size:
61// CHECK-NOT:                                 align:
62// CHECK-NOT:                                 offset:
63// CHECK-SAME:                                flags: DIFlagStaticMember)
64//
65// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a"
66// CHECK-NOT:            size:
67// CHECK-NOT:            align:
68// CHECK-NOT:            offset:
69// CHECK-SAME:           flags: DIFlagStaticMember,
70// CHECK-SAME:           extraData: i1 true)
71
72// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b"
73// CHECK-NOT:            size:
74// CHECK-NOT:            align:
75// CHECK-NOT:            offset:
76// CHECK-SAME:           flags: DIFlagProtected | DIFlagStaticMember,
77// CHECK-SAME:           extraData: float 0x{{.*}})
78
79// CHECK: ![[DECL_C:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "c"
80// CHECK-NOT:                                 size:
81// CHECK-NOT:                                 align:
82// CHECK-NOT:                                 offset:
83// CHECK-SAME:                                flags: DIFlagPublic | DIFlagStaticMember)
84//
85// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_c"
86// CHECK-NOT:            size:
87// CHECK-NOT:            align:
88// CHECK-NOT:            offset:
89// CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember,
90// CHECK-SAME:           extraData: i32 18)
91//
92// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a"
93// CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember)
94
95int C::b = 2;
96// CHECK: [[C]] = !DIGlobalVariableExpression(var: [[CV:.*]], expr: !DIExpression())
97// CHECK: [[CV]] = distinct !DIGlobalVariable(name: "c", {{.*}} declaration: ![[DECL_C]])
98int C::c = 1;
99
100int main()
101{
102        C instance_C;
103        instance_C.d = 8;
104        return C::c;
105}
106
107// CHECK-NOT: !DIGlobalVariable(name: "anon_static_decl_var"
108
109// Test this in an anonymous namespace to ensure the type is retained even when
110// it doesn't get automatically retained by the string type reference machinery.
111namespace {
112struct anon_static_decl_struct {
113  static const int anon_static_decl_var = 117;
114};
115}
116
117
118int ref() {
119  return anon_static_decl_struct::anon_static_decl_var;
120}
121
122template<typename T>
123struct static_decl_templ {
124  static const int static_decl_templ_var = 7;
125};
126
127template<typename T>
128const int static_decl_templ<T>::static_decl_templ_var;
129
130int static_decl_templ_ref() {
131  return static_decl_templ<int>::static_decl_templ_var;
132}
133
134// Verify that even when a static member declaration is created lazily when
135// creating the definition, the declaration line is that of the canonical
136// declaration, not the definition. Also, since we look at the canonical
137// definition, we should also correctly emit the constant value (42) into the
138// debug info.
139struct V {
140  virtual ~V(); // cause the definition of 'V' to be omitted by no-standalone-debug optimization
141  static const int const_va = 42;
142};
143// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_va",
144// CHECK-SAME:           line: [[@LINE-3]]
145// CHECK-SAME:           extraData: i32 42
146const int V::const_va;
147
148namespace x {
149struct y {
150// CHECK: !DIGlobalVariable(name: "z",
151// CHECK-SAME:              scope: [[NS_X:![0-9]+]]
152// CHECK: [[NS_X]] = !DINamespace(name: "x"
153  static int z;
154};
155int y::z;
156}
157