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 // RUN: %clang_cc1 -triple x86_64-windows-msvc -gcodeview -debug-info-kind=limited %s -emit-llvm -o - | FileCheck --check-prefix MSVC %s 5 // PR14471 6 7 // CHECK: @_ZN1C1aE = dso_local global i32 4, align 4, !dbg [[A:![0-9]+]] 8 // CHECK: @_ZN1C1bE = dso_local global i32 2, align 4, !dbg [[B:![0-9]+]] 9 // CHECK: @_ZN1C1cE = 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 // MSVC: distinct !DIGlobalVariable(name: "a" 40 // 41 // CHECK: !DICompositeType(tag: DW_TAG_enumeration_type, name: "X"{{.*}}, identifier: "_ZTS1X") 42 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "anon_static_decl_struct" 43 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "anon_static_decl_var" 44 // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "static_decl_templ<int>" 45 // CHECK-NOT: DIFlagFwdDecl 46 // CHECK-SAME: ){{$}} 47 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "static_decl_templ_var" 48 49 int C::a = 4; 50 // CHECK: [[B]] = !DIGlobalVariableExpression(var: [[BV:.*]], expr: !DIExpression()) 51 // CHECK: [[BV]] = distinct !DIGlobalVariable(name: "b", 52 // CHECK-SAME: declaration: ![[DECL_B:[0-9]+]]) 53 // MSVC: distinct !DIGlobalVariable(name: "b" 54 // CHECK: ![[DECL_B]] = !DIDerivedType(tag: DW_TAG_member, name: "b" 55 // CHECK-NOT: size: 56 // CHECK-NOT: align: 57 // CHECK-NOT: offset: 58 // CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember) 59 // 60 // CHECK: !DICompositeType(tag: DW_TAG_class_type, name: "C"{{.*}}, identifier: "_ZTS1C") 61 // 62 // CHECK: ![[DECL_A]] = !DIDerivedType(tag: DW_TAG_member, name: "a" 63 // CHECK-NOT: size: 64 // CHECK-NOT: align: 65 // CHECK-NOT: offset: 66 // CHECK-SAME: flags: DIFlagStaticMember) 67 // 68 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_a" 69 // CHECK-NOT: size: 70 // CHECK-NOT: align: 71 // CHECK-NOT: offset: 72 // CHECK-SAME: flags: DIFlagStaticMember, 73 // CHECK-SAME: extraData: i1 true) 74 75 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_b" 76 // CHECK-NOT: size: 77 // CHECK-NOT: align: 78 // CHECK-NOT: offset: 79 // CHECK-SAME: flags: DIFlagProtected | DIFlagStaticMember, 80 // CHECK-SAME: extraData: float 0x{{.*}}) 81 82 // CHECK: ![[DECL_C:[0-9]+]] = !DIDerivedType(tag: DW_TAG_member, name: "c" 83 // CHECK-NOT: size: 84 // CHECK-NOT: align: 85 // CHECK-NOT: offset: 86 // CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember) 87 // 88 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_c" 89 // CHECK-NOT: size: 90 // CHECK-NOT: align: 91 // CHECK-NOT: offset: 92 // CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember, 93 // CHECK-SAME: extraData: i32 18) 94 // 95 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "x_a" 96 // CHECK-SAME: flags: DIFlagPublic | DIFlagStaticMember) 97 98 int C::b = 2; 99 // CHECK: [[C]] = !DIGlobalVariableExpression(var: [[CV:.*]], expr: !DIExpression()) 100 // CHECK: [[CV]] = distinct !DIGlobalVariable(name: "c", {{.*}} declaration: ![[DECL_C]]) 101 // MSVC: distinct !DIGlobalVariable(name: "c" 102 int C::c = 1; 103 104 int main() 105 { 106 C instance_C; 107 instance_C.d = 8; 108 return C::c; 109 } 110 111 // CHECK-NOT: !DIGlobalVariable(name: "anon_static_decl_var" 112 113 // Test this in an anonymous namespace to ensure the type is retained even when 114 // it doesn't get automatically retained by the string type reference machinery. 115 namespace { 116 struct anon_static_decl_struct { 117 static const int anon_static_decl_var = 117; 118 }; 119 } 120 121 int ref() { 122 return anon_static_decl_struct::anon_static_decl_var; 123 } 124 125 // In MSVC, static data members should be emitted as global variables when used. 126 // MSVC: !DIGlobalVariableExpression(var: [[ANON_STATIC_DECL:![0-9]+]], 127 // MSVC-SAME: !DIExpression(DW_OP_constu, 117, DW_OP_stack_value) 128 // MSVC: [[ANON_STATIC_DECL]] = distinct !DIGlobalVariable(name: "anon_static_decl_var" 129 // MSVC: !DIGlobalVariableExpression(var: [[STATIC_DECL_TEMPL:![0-9]+]] 130 // MSVC-SAME: !DIExpression(DW_OP_constu, 7, DW_OP_stack_value) 131 // MSVC: [[STATIC_DECL_TEMPL]] = distinct !DIGlobalVariable(name: "static_decl_templ_var" 132 133 template<typename T> 134 struct static_decl_templ { 135 static const int static_decl_templ_var = 7; 136 }; 137 138 template<typename T> 139 const int static_decl_templ<T>::static_decl_templ_var; 140 141 int static_decl_templ_ref() { 142 return static_decl_templ<int>::static_decl_templ_var; 143 } 144 145 // Verify that even when a static member declaration is created lazily when 146 // creating the definition, the declaration line is that of the canonical 147 // declaration, not the definition. Also, since we look at the canonical 148 // definition, we should also correctly emit the constant value (42) into the 149 // debug info. 150 struct V { 151 virtual ~V(); // cause the definition of 'V' to be omitted by no-standalone-debug optimization 152 static const int const_va = 42; 153 }; 154 // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "const_va", 155 // CHECK-SAME: line: [[@LINE-3]] 156 // CHECK-SAME: extraData: i32 42 157 const int V::const_va; 158 159 namespace x { 160 struct y { 161 // CHECK: !DIGlobalVariable(name: "z", 162 // CHECK-SAME: scope: [[NS_X:![0-9]+]] 163 // CHECK: [[NS_X]] = !DINamespace(name: "x" 164 static int z; 165 }; 166 int y::z; 167 } 168