[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / Modules / initializers.cpp
blobdcd9b08ec6f7a4acfdcdf605ff965b6ff4186969
1 // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -emit-llvm -DIMPORT=1 -fmodules %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IMPORT,CHECK-NO-NS,CHECK-IMPORT-NO-NS --implicit-check-not=unused
2 // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -emit-llvm -DIMPORT=1 -DNS -fmodules %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IMPORT,CHECK-NS,CHECK-IMPORT-NS --implicit-check-not=unused
3 // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -emit-llvm -DIMPORT=2 -fmodules %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NO-NS --implicit-check-not=unused
4 // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -emit-llvm -DIMPORT=2 -DNS -fmodules %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NS --implicit-check-not=unused
5 // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -emit-llvm -fmodules %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NO-NS --implicit-check-not=unused
6 // RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -emit-llvm -DNS -fmodules %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-NS --implicit-check-not=unused
8 // Check that we behave sensibly when importing a header containing strong and
9 // weak, ordered and unordered global initializers.
11 // Our behavior is as follows:
13 // -- for variables with one or more specific points of initialization
14 // (non-template variables, whether or not they are inline or thread_local),
15 // emit them if (and only if) a header containing a point of initialization
16 // is transitively #included / imported.
18 // -- for variables with unordered initialization (any kind of templated
19 // variable -- excluding explicit specializations), emit them if any part
20 // of any module that triggers an instantiation is imported.
22 // The intent is to:
24 // 1) preserve order of initialization guarantees
25 // 2) preserve the behavior of globals with ctors in headers, and specifically
26 // of std::ios_base::Init (do not run the iostreams initializer nor force
27 // linking in the iostreams portion of the static library unless <iostream>
28 // is included)
29 // 3) behave conservatively-correctly with regard to unordered initializers: we
30 // might run them in cases where a traditional compilation would not, but
31 // will never fail to run them in cases where a traditional compilation
32 // would do so
34 // Perfect handling of unordered initializers would require tracking all
35 // submodules containing points of instantiation, which is very hard when those
36 // points of instantiation are within definitions that we skip because we
37 // already have a (non-visible) definition for the entity:
39 // // a.h
40 // template<typename> int v = f();
41 // inline int get() { return v<int>; }
43 // // b.h
44 // template<typename> int v = f();
45 // inline int get() { return v<int>; }
47 // If a.h and b.h are built as a module, we will only have a point of
48 // instantiation for v<int> in one of the two headers, because we will only
49 // parse one of the two get() functions.
51 #pragma clang module build m
52 module m {
53 module a {
54 header "foo.h" { size 123 mtime 456789 }
56 module b {}
59 #pragma clang module contents
60 #pragma clang module begin m.a
61 inline int non_trivial() { return 3; }
63 #ifdef NS
64 namespace ns {
65 #endif
67 int a = non_trivial();
68 inline int b = non_trivial();
69 thread_local int c = non_trivial();
70 inline thread_local int d = non_trivial();
72 template<typename U> int e = non_trivial();
73 template<typename U> inline int f = non_trivial();
74 template<typename U> thread_local int g = non_trivial();
75 template<typename U> inline thread_local int h = non_trivial();
77 inline int unused = 123; // should not be emitted
79 template<typename T> struct X {
80 static int a;
81 static inline int b = non_trivial();
82 static thread_local int c;
83 static inline thread_local int d = non_trivial();
85 template<typename U> static int e;
86 template<typename U> static inline int f = non_trivial();
87 template<typename U> static thread_local int g;
88 template<typename U> static inline thread_local int h = non_trivial();
90 static inline int unused = 123; // should not be emitted
93 template<typename T> int X<T>::a = non_trivial();
94 template<typename T> thread_local int X<T>::c = non_trivial();
95 template<typename T> template<typename U> int X<T>::e = non_trivial();
96 template<typename T> template<typename U> thread_local int X<T>::g = non_trivial();
98 inline void use(bool b, ...) {
99 if (b) return;
100 use(true, e<int>, f<int>, g<int>, h<int>,
101 X<int>::a, X<int>::b, X<int>::c, X<int>::d,
102 X<int>::e<int>, X<int>::f<int>, X<int>::g<int>, X<int>::h<int>);
105 #ifdef NS
107 #endif
109 #pragma clang module end
110 #pragma clang module endbuild
112 #if IMPORT == 1
113 // Import the module and the m.a submodule; runs the ordered initializers and
114 // the unordered initializers.
115 #pragma clang module import m.a
116 #elif IMPORT == 2
117 // Import the module but not the m.a submodule; runs only the unordered
118 // initializers.
119 #pragma clang module import m.b
120 #else
121 // Load the module but do not import any submodules; runs only the unordered
122 // initializers. FIXME: Should this skip all of them?
123 #pragma clang module load m
124 #endif
126 // CHECK-IMPORT-NO-NS-DAG: @[[A:a]] ={{.*}} global i32 0, align 4
127 // CHECK-IMPORT-NO-NS-DAG: @[[B:b]] = linkonce_odr global i32 0, comdat, align 4
128 // CHECK-IMPORT-NO-NS-DAG: @[[C:c]] ={{.*}} thread_local global i32 0, align 4
129 // CHECK-IMPORT-NO-NS-DAG: @[[D:d]] = linkonce_odr thread_local global i32 0, comdat, align 4
130 // CHECK-NO-NS-DAG: @[[E:_Z1eIiE]] = linkonce_odr global i32 0, comdat, align 4
131 // CHECK-NO-NS-DAG: @[[F:_Z1fIiE]] = linkonce_odr global i32 0, comdat, align 4
132 // CHECK-NO-NS-DAG: @[[G:_Z1gIiE]] = linkonce_odr thread_local global i32 0, comdat, align 4
133 // CHECK-NO-NS-DAG: @[[H:_Z1hIiE]] = linkonce_odr thread_local global i32 0, comdat, align 4
135 // CHECK-IMPORT-NS-DAG: @[[A:_ZN2ns1aE]] ={{.*}} global i32 0, align 4
136 // CHECK-IMPORT-NS-DAG: @[[B:_ZN2ns1bE]] = linkonce_odr global i32 0, comdat, align 4
137 // CHECK-IMPORT-NS-DAG: @[[BG:_ZGVN2ns1bE]] = linkonce_odr global i64 0, comdat($[[B]]), align 8
138 // CHECK-IMPORT-NS-DAG: @[[C:_ZN2ns1cE]] ={{.*}} thread_local global i32 0, align 4
139 // CHECK-IMPORT-NS-DAG: @[[D:_ZN2ns1dE]] = linkonce_odr thread_local global i32 0, comdat, align 4
140 // CHECK-IMPORT-NS-DAG: @[[DG:_ZGVN2ns1dE]] = linkonce_odr thread_local global i64 0, comdat($[[D]]), align 8
141 // CHECK-NS-DAG: @[[E:_ZN2ns1eIiEE]] = linkonce_odr global i32 0, comdat, align 4
142 // CHECK-NS-DAG: @[[F:_ZN2ns1fIiEE]] = linkonce_odr global i32 0, comdat, align 4
143 // CHECK-NS-DAG: @[[G:_ZN2ns1gIiEE]] = linkonce_odr thread_local global i32 0, comdat, align 4
144 // CHECK-NS-DAG: @[[H:_ZN2ns1hIiEE]] = linkonce_odr thread_local global i32 0, comdat, align 4
146 // CHECK-DAG: @[[XA:_ZN(2ns)?1XIiE1aE]] = linkonce_odr global i32 0, comdat, align 4
147 // CHECK-DAG: @[[XB:_ZN(2ns)?1XIiE1bE]] = linkonce_odr global i32 0, comdat, align 4
148 // CHECK-DAG: @[[XC:_ZN(2ns)?1XIiE1cE]] = linkonce_odr thread_local global i32 0, comdat, align 4
149 // CHECK-DAG: @[[XD:_ZN(2ns)?1XIiE1dE]] = linkonce_odr thread_local global i32 0, comdat, align 4
150 // CHECK-DAG: @[[XE:_ZN(2ns)?1XIiE1eIiEE]] = linkonce_odr global i32 0, comdat, align 4
151 // CHECK-DAG: @[[XF:_ZN(2ns)?1XIiE1fIiEE]] = linkonce_odr global i32 0, comdat, align 4
152 // CHECK-DAG: @[[XG:_ZN(2ns)?1XIiE1gIiEE]] = linkonce_odr thread_local global i32 0, comdat, align 4
153 // CHECK-DAG: @[[XH:_ZN(2ns)?1XIiE1hIiEE]] = linkonce_odr thread_local global i32 0, comdat, align 4
155 // It's OK if the order of the first 6 of these changes.
156 // CHECK: @llvm.global_ctors = appending global
157 // CHECK-SAME: @[[E_INIT:[^,]*]], {{[^@]*}} @[[E]]
158 // CHECK-SAME: @[[F_INIT:[^,]*]], {{[^@]*}} @[[F]]
159 // CHECK-SAME: @[[XA_INIT:[^,]*]], {{[^@]*}} @[[XA]]
160 // CHECK-SAME: @[[XE_INIT:[^,]*]], {{[^@]*}} @[[XE]]
161 // CHECK-SAME: @[[XF_INIT:[^,]*]], {{[^@]*}} @[[XF]]
162 // CHECK-SAME: @[[XB_INIT:[^,]*]], {{[^@]*}} @[[XB]]
163 // CHECK-IMPORT-SAME: @[[TU_INIT:[^,]*]], ptr null }]
165 // FIXME: Should this use __cxa_guard_acquire?
166 // CHECK: define {{.*}} @[[E_INIT]]()
167 // CHECK: load {{.*}} ptr @_ZGV
168 // CHECK: store {{.*}}, ptr @[[E]],
170 // FIXME: Should this use __cxa_guard_acquire?
171 // CHECK: define {{.*}} @[[F_INIT]]()
172 // CHECK: load {{.*}} ptr @_ZGV
173 // CHECK: store {{.*}}, ptr @[[F]],
175 // CHECK: define {{.*}} @[[G_INIT:__cxx_global.*]]()
176 // CHECK: load {{.*}} ptr @_ZGV
177 // CHECK: [[G_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @[[G]])
178 // CHECK: store {{.*}}, ptr [[G_ADDR]]
180 // CHECK: define {{.*}} @[[H_INIT:__cxx_global.*]]()
181 // CHECK: load {{.*}} ptr @_ZGV
182 // CHECK: [[H_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @[[H]])
183 // CHECK: store {{.*}}, ptr [[H_ADDR]],
185 // FIXME: Should this use __cxa_guard_acquire?
186 // CHECK: define {{.*}} @[[XA_INIT]]()
187 // CHECK: load {{.*}} ptr @_ZGV
188 // CHECK: store {{.*}}, ptr @[[XA]],
190 // CHECK: define {{.*}} @[[XC_INIT:__cxx_global.*]]()
191 // CHECK: load {{.*}} ptr @_ZGV
192 // CHECK: [[XC_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @[[XC]])
193 // CHECK: store {{.*}}, ptr [[XC_ADDR]],
195 // FIXME: Should this use __cxa_guard_acquire?
196 // CHECK: define {{.*}} @[[XE_INIT]]()
197 // CHECK: load {{.*}} ptr @_ZGV
198 // CHECK: store {{.*}}, ptr @[[XE]],
200 // CHECK: define {{.*}} @[[XG_INIT:__cxx_global.*]]()
201 // CHECK: load {{.*}} ptr @_ZGV
202 // CHECK: [[XG_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @[[XG]])
203 // CHECK: store {{.*}}, ptr [[XG_ADDR]],
205 // CHECK: define {{.*}} @[[XH_INIT:__cxx_global.*]]()
206 // CHECK: load {{.*}} ptr @_ZGV
207 // CHECK: [[XH_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @[[XH]])
208 // CHECK: store {{.*}}, ptr [[XH_ADDR]],
210 // FIXME: Should this use __cxa_guard_acquire?
211 // CHECK: define {{.*}} @[[XF_INIT]]()
212 // CHECK: load {{.*}} ptr @_ZGV
213 // CHECK: store {{.*}}, ptr @[[XF]],
215 // CHECK: define {{.*}} @[[XD_INIT:__cxx_global.*]]()
216 // CHECK: load {{.*}} ptr @_ZGV
217 // CHECK: [[XD_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @[[XD]])
218 // CHECK: store {{.*}}, ptr [[XD_ADDR]],
220 // FIXME: Should this use __cxa_guard_acquire?
221 // CHECK: define {{.*}} @[[XB_INIT]]()
222 // CHECK: load {{.*}} ptr @_ZGV
223 // CHECK: store {{.*}}, ptr @[[XB]],
225 // CHECK-IMPORT: define {{.*}} @[[A_INIT:__cxx_global.*]]()
226 // CHECK-IMPORT: call noundef i32 @_Z11non_trivialv(
227 // CHECK-IMPORT: store {{.*}}, ptr @[[A]],
229 // CHECK-IMPORT: define {{.*}} @[[B_INIT:__cxx_global.*]]()
230 // CHECK-IMPORT: call i32 @__cxa_guard_acquire(ptr @_ZGV
231 // CHECK-IMPORT: store {{.*}}, ptr @[[B]],
233 // CHECK-IMPORT: define {{.*}} @[[C_INIT:__cxx_global.*]]()
234 // CHECK-IMPORT: call noundef i32 @_Z11non_trivialv(
235 // CHECK-IMPORT: [[C_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @[[C]])
236 // CHECK-IMPORT: store {{.*}}, ptr [[C_ADDR]],
238 // CHECK-IMPORT: define {{.*}} @[[D_INIT:__cxx_global.*]]()
239 // CHECK-IMPORT: load {{.*}} ptr @_ZGV
240 // CHECK-IMPORT: [[D_ADDR:%.+]] = call align 4 ptr @llvm.threadlocal.address.p0(ptr align 4 @[[D]])
241 // CHECK-IMPORT: store {{.*}}, ptr [[D_ADDR]],
244 // CHECK-IMPORT: define {{.*}} @[[TU_INIT]]()
245 // CHECK-IMPORT: call void @[[A_INIT]]()
247 // CHECK-IMPORT: define {{.*}} @__tls_init()
248 // CHECK-IMPORT: call void @[[C_INIT]]()
249 // CHECK-IMPORT: call void @[[D_INIT]]()