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 = global i32 4, align 4, !dbg [[A:![0-9]+]]
7 // CHECK: @_ZN1C1bE = global i32 2, align 4, !dbg [[B:![0-9]+]]
8 // CHECK: @_ZN1C1cE = global i32 1, align 4, !dbg [[C:![0-9]+]]
9 
10 enum X {
11   Y
12 };
13 class C
14 {
15   static int a;
16   const static bool const_a = true;
17 protected:
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
24 public:
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]] = distinct !DIGlobalVariable(name: "a", {{.*}} declaration: ![[DECL_A:[0-9]+]])
36 //
37 // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}}, identifier: "_ZTS1X")
38 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct"
39 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var"
40 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "static_decl_templ<int>"
41 // CHECK-NOT:              DIFlagFwdDecl
42 // CHECK-SAME:             ){{$}}
43 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var"
44 
45 int C::a = 4;
46 // CHECK: [[B]] = distinct !DIGlobalVariable(name: "b", {{.*}} declaration: ![[DECL_B:[0-9]+]])
47 // CHECK: ![[DECL_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b"
48 // CHECK-NOT:                                 size:
49 // CHECK-NOT:                                 align:
50 // CHECK-NOT:                                 offset:
51 // CHECK-SAME:                                flags: DIFlagProtected | DIFlagStaticMember)
52 //
53 // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C")
54 //
55 // CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a"
56 // CHECK-NOT:                                 size:
57 // CHECK-NOT:                                 align:
58 // CHECK-NOT:                                 offset:
59 // CHECK-SAME:                                flags: DIFlagStaticMember)
60 //
61 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a"
62 // CHECK-NOT:            size:
63 // CHECK-NOT:            align:
64 // CHECK-NOT:            offset:
65 // CHECK-SAME:           flags: DIFlagStaticMember,
66 // CHECK-SAME:           extraData: i1 true)
67 
68 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b"
69 // CHECK-NOT:            size:
70 // CHECK-NOT:            align:
71 // CHECK-NOT:            offset:
72 // CHECK-SAME:           flags: DIFlagProtected | DIFlagStaticMember,
73 // CHECK-SAME:           extraData: float 0x{{.*}})
74 
75 // CHECK: ![[DECL_C:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "c"
76 // CHECK-NOT:                                 size:
77 // CHECK-NOT:                                 align:
78 // CHECK-NOT:                                 offset:
79 // CHECK-SAME:                                flags: DIFlagPublic | DIFlagStaticMember)
80 //
81 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_c"
82 // CHECK-NOT:            size:
83 // CHECK-NOT:            align:
84 // CHECK-NOT:            offset:
85 // CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember,
86 // CHECK-SAME:           extraData: i32 18)
87 //
88 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a"
89 // CHECK-SAME:           flags: DIFlagPublic | DIFlagStaticMember)
90 
91 int C::b = 2;
92 // CHECK: [[C]] = distinct !DIGlobalVariable(name: "c", {{.*}} declaration: ![[DECL_C]])
93 int C::c = 1;
94 
95 int main()
96 {
97         C instance_C;
98         instance_C.d = 8;
99         return C::c;
100 }
101 
102 // CHECK-NOT: !DIGlobalVariable(name: "anon_static_decl_var"
103 
104 // Test this in an anonymous namespace to ensure the type is retained even when
105 // it doesn't get automatically retained by the string type reference machinery.
106 namespace {
107 struct anon_static_decl_struct {
108   static const int anon_static_decl_var = 117;
109 };
110 }
111 
112 
113 int ref() {
114   return anon_static_decl_struct::anon_static_decl_var;
115 }
116 
117 template<typename T>
118 struct static_decl_templ {
119   static const int static_decl_templ_var = 7;
120 };
121 
122 template<typename T>
123 const int static_decl_templ<T>::static_decl_templ_var;
124 
125 int static_decl_templ_ref() {
126   return static_decl_templ<int>::static_decl_templ_var;
127 }
128 
129 // Verify that even when a static member declaration is created lazily when
130 // creating the definition, the declaration line is that of the canonical
131 // declaration, not the definition. Also, since we look at the canonical
132 // definition, we should also correctly emit the constant value (42) into the
133 // debug info.
134 struct V {
135   virtual ~V(); // cause the definition of 'V' to be omitted by no-standalone-debug optimization
136   static const int const_va = 42;
137 };
138 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_va",
139 // CHECK-SAME:           line: [[@LINE-3]]
140 // CHECK-SAME:           extraData: i32 42
141 const int V::const_va;
142 
143 namespace x {
144 struct y {
145 // CHECK: !DIGlobalVariable(name: "z",
146 // CHECK-SAME:              scope: [[NS_X:![0-9]+]]
147 // CHECK: [[NS_X]] = !DINamespace(name: "x"
148   static int z;
149 };
150 int y::z;
151 }
152