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