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