1*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers -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*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers -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*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers -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*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers -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*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers -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*532dc62bSNikita Popov // RUN: %clang_cc1 -no-opaque-pointers -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
7520a37f5SRichard Smith
8520a37f5SRichard Smith // Check that we behave sensibly when importing a header containing strong and
9520a37f5SRichard Smith // weak, ordered and unordered global initializers.
10520a37f5SRichard Smith //
11520a37f5SRichard Smith // Our behavior is as follows:
12520a37f5SRichard Smith //
13520a37f5SRichard Smith // -- for variables with one or more specific points of initialization
14520a37f5SRichard Smith // (non-template variables, whether or not they are inline or thread_local),
15520a37f5SRichard Smith // emit them if (and only if) a header containing a point of initialization
16520a37f5SRichard Smith // is transitively #included / imported.
17520a37f5SRichard Smith //
18520a37f5SRichard Smith // -- for variables with unordered initialization (any kind of templated
19520a37f5SRichard Smith // variable -- excluding explicit specializations), emit them if any part
20520a37f5SRichard Smith // of any module that triggers an instantiation is imported.
21520a37f5SRichard Smith //
22520a37f5SRichard Smith // The intent is to:
23520a37f5SRichard Smith //
24520a37f5SRichard Smith // 1) preserve order of initialization guarantees
25520a37f5SRichard Smith // 2) preserve the behavior of globals with ctors in headers, and specifically
26520a37f5SRichard Smith // of std::ios_base::Init (do not run the iostreams initializer nor force
27520a37f5SRichard Smith // linking in the iostreams portion of the static library unless <iostream>
28520a37f5SRichard Smith // is included)
29520a37f5SRichard Smith // 3) behave conservatively-correctly with regard to unordered initializers: we
30520a37f5SRichard Smith // might run them in cases where a traditional compilation would not, but
31520a37f5SRichard Smith // will never fail to run them in cases where a traditional compilation
32520a37f5SRichard Smith // would do so
33520a37f5SRichard Smith //
34520a37f5SRichard Smith // Perfect handling of unordered initializers would require tracking all
35520a37f5SRichard Smith // submodules containing points of instantiation, which is very hard when those
36520a37f5SRichard Smith // points of instantiation are within definitions that we skip because we
37520a37f5SRichard Smith // already have a (non-visible) definition for the entity:
38520a37f5SRichard Smith //
39520a37f5SRichard Smith // // a.h
40520a37f5SRichard Smith // template<typename> int v = f();
41520a37f5SRichard Smith // inline int get() { return v<int>; }
42520a37f5SRichard Smith //
43520a37f5SRichard Smith // // b.h
44520a37f5SRichard Smith // template<typename> int v = f();
45520a37f5SRichard Smith // inline int get() { return v<int>; }
46520a37f5SRichard Smith //
47520a37f5SRichard Smith // If a.h and b.h are built as a module, we will only have a point of
48520a37f5SRichard Smith // instantiation for v<int> in one of the two headers, because we will only
49520a37f5SRichard Smith // parse one of the two get() functions.
50520a37f5SRichard Smith
51520a37f5SRichard Smith #pragma clang module build m
52520a37f5SRichard Smith module m {
53520a37f5SRichard Smith module a {
54520a37f5SRichard Smith header "foo.h" { size 123 mtime 456789 }
55520a37f5SRichard Smith }
56520a37f5SRichard Smith module b {}
57520a37f5SRichard Smith }
58520a37f5SRichard Smith
59520a37f5SRichard Smith #pragma clang module contents
60520a37f5SRichard Smith #pragma clang module begin m.a
61520a37f5SRichard Smith inline int non_trivial() { return 3; }
62520a37f5SRichard Smith
63520a37f5SRichard Smith #ifdef NS
64520a37f5SRichard Smith namespace ns {
65520a37f5SRichard Smith #endif
66520a37f5SRichard Smith
67520a37f5SRichard Smith int a = non_trivial();
68520a37f5SRichard Smith inline int b = non_trivial();
69520a37f5SRichard Smith thread_local int c = non_trivial();
70520a37f5SRichard Smith inline thread_local int d = non_trivial();
71520a37f5SRichard Smith
72520a37f5SRichard Smith template<typename U> int e = non_trivial();
73520a37f5SRichard Smith template<typename U> inline int f = non_trivial();
74520a37f5SRichard Smith template<typename U> thread_local int g = non_trivial();
75520a37f5SRichard Smith template<typename U> inline thread_local int h = non_trivial();
76520a37f5SRichard Smith
77520a37f5SRichard Smith inline int unused = 123; // should not be emitted
78520a37f5SRichard Smith
79520a37f5SRichard Smith template<typename T> struct X {
80520a37f5SRichard Smith static int a;
81520a37f5SRichard Smith static inline int b = non_trivial();
82520a37f5SRichard Smith static thread_local int c;
83520a37f5SRichard Smith static inline thread_local int d = non_trivial();
84520a37f5SRichard Smith
85520a37f5SRichard Smith template<typename U> static int e;
86520a37f5SRichard Smith template<typename U> static inline int f = non_trivial();
87520a37f5SRichard Smith template<typename U> static thread_local int g;
88520a37f5SRichard Smith template<typename U> static inline thread_local int h = non_trivial();
89520a37f5SRichard Smith
90520a37f5SRichard Smith static inline int unused = 123; // should not be emitted
91520a37f5SRichard Smith };
92520a37f5SRichard Smith
93520a37f5SRichard Smith template<typename T> int X<T>::a = non_trivial();
94520a37f5SRichard Smith template<typename T> thread_local int X<T>::c = non_trivial();
95520a37f5SRichard Smith template<typename T> template<typename U> int X<T>::e = non_trivial();
96520a37f5SRichard Smith template<typename T> template<typename U> thread_local int X<T>::g = non_trivial();
97520a37f5SRichard Smith
use(bool b,...)98520a37f5SRichard Smith inline void use(bool b, ...) {
99520a37f5SRichard Smith if (b) return;
100520a37f5SRichard Smith use(true, e<int>, f<int>, g<int>, h<int>,
101520a37f5SRichard Smith X<int>::a, X<int>::b, X<int>::c, X<int>::d,
102520a37f5SRichard Smith X<int>::e<int>, X<int>::f<int>, X<int>::g<int>, X<int>::h<int>);
103520a37f5SRichard Smith }
104520a37f5SRichard Smith
105520a37f5SRichard Smith #ifdef NS
106520a37f5SRichard Smith }
107520a37f5SRichard Smith #endif
108520a37f5SRichard Smith
109520a37f5SRichard Smith #pragma clang module end
110520a37f5SRichard Smith #pragma clang module endbuild
111520a37f5SRichard Smith
112520a37f5SRichard Smith #if IMPORT == 1
113520a37f5SRichard Smith // Import the module and the m.a submodule; runs the ordered initializers and
114520a37f5SRichard Smith // the unordered initializers.
115520a37f5SRichard Smith #pragma clang module import m.a
116520a37f5SRichard Smith #elif IMPORT == 2
117520a37f5SRichard Smith // Import the module but not the m.a submodule; runs only the unordered
118520a37f5SRichard Smith // initializers.
119520a37f5SRichard Smith #pragma clang module import m.b
120520a37f5SRichard Smith #else
121520a37f5SRichard Smith // Load the module but do not import any submodules; runs only the unordered
122520a37f5SRichard Smith // initializers. FIXME: Should this skip all of them?
123520a37f5SRichard Smith #pragma clang module load m
124520a37f5SRichard Smith #endif
125520a37f5SRichard Smith
126fd739804SFangrui Song // CHECK-IMPORT-NO-NS-DAG: @[[A:a]] ={{.*}} global i32 0, align 4
127dbc96b51SFangrui Song // CHECK-IMPORT-NO-NS-DAG: @[[B:b]] = linkonce_odr global i32 0, comdat, align 4
128fd739804SFangrui Song // CHECK-IMPORT-NO-NS-DAG: @[[C:c]] ={{.*}} thread_local global i32 0, align 4
129520a37f5SRichard Smith // CHECK-IMPORT-NO-NS-DAG: @[[D:d]] = linkonce_odr thread_local global i32 0, comdat, align 4
130520a37f5SRichard Smith // CHECK-NO-NS-DAG: @[[E:_Z1eIiE]] = linkonce_odr global i32 0, comdat, align 4
131520a37f5SRichard Smith // CHECK-NO-NS-DAG: @[[F:_Z1fIiE]] = linkonce_odr global i32 0, comdat, align 4
132520a37f5SRichard Smith // CHECK-NO-NS-DAG: @[[G:_Z1gIiE]] = linkonce_odr thread_local global i32 0, comdat, align 4
133520a37f5SRichard Smith // CHECK-NO-NS-DAG: @[[H:_Z1hIiE]] = linkonce_odr thread_local global i32 0, comdat, align 4
134520a37f5SRichard Smith
135fd739804SFangrui Song // CHECK-IMPORT-NS-DAG: @[[A:_ZN2ns1aE]] ={{.*}} global i32 0, align 4
136520a37f5SRichard Smith // CHECK-IMPORT-NS-DAG: @[[B:_ZN2ns1bE]] = linkonce_odr global i32 0, comdat, align 4
137520a37f5SRichard Smith // CHECK-IMPORT-NS-DAG: @[[BG:_ZGVN2ns1bE]] = linkonce_odr global i64 0, comdat($[[B]]), align 8
138fd739804SFangrui Song // CHECK-IMPORT-NS-DAG: @[[C:_ZN2ns1cE]] ={{.*}} thread_local global i32 0, align 4
139520a37f5SRichard Smith // CHECK-IMPORT-NS-DAG: @[[D:_ZN2ns1dE]] = linkonce_odr thread_local global i32 0, comdat, align 4
140520a37f5SRichard Smith // CHECK-IMPORT-NS-DAG: @[[DG:_ZGVN2ns1dE]] = linkonce_odr thread_local global i64 0, comdat($[[D]]), align 8
141520a37f5SRichard Smith // CHECK-NS-DAG: @[[E:_ZN2ns1eIiEE]] = linkonce_odr global i32 0, comdat, align 4
142520a37f5SRichard Smith // CHECK-NS-DAG: @[[F:_ZN2ns1fIiEE]] = linkonce_odr global i32 0, comdat, align 4
143520a37f5SRichard Smith // CHECK-NS-DAG: @[[G:_ZN2ns1gIiEE]] = linkonce_odr thread_local global i32 0, comdat, align 4
144520a37f5SRichard Smith // CHECK-NS-DAG: @[[H:_ZN2ns1hIiEE]] = linkonce_odr thread_local global i32 0, comdat, align 4
145520a37f5SRichard Smith
146520a37f5SRichard Smith // CHECK-DAG: @[[XA:_ZN(2ns)?1XIiE1aE]] = linkonce_odr global i32 0, comdat, align 4
147520a37f5SRichard Smith // CHECK-DAG: @[[XB:_ZN(2ns)?1XIiE1bE]] = linkonce_odr global i32 0, comdat, align 4
148520a37f5SRichard Smith // CHECK-DAG: @[[XC:_ZN(2ns)?1XIiE1cE]] = linkonce_odr thread_local global i32 0, comdat, align 4
149520a37f5SRichard Smith // CHECK-DAG: @[[XD:_ZN(2ns)?1XIiE1dE]] = linkonce_odr thread_local global i32 0, comdat, align 4
150520a37f5SRichard Smith // CHECK-DAG: @[[XE:_ZN(2ns)?1XIiE1eIiEE]] = linkonce_odr global i32 0, comdat, align 4
151520a37f5SRichard Smith // CHECK-DAG: @[[XF:_ZN(2ns)?1XIiE1fIiEE]] = linkonce_odr global i32 0, comdat, align 4
152520a37f5SRichard Smith // CHECK-DAG: @[[XG:_ZN(2ns)?1XIiE1gIiEE]] = linkonce_odr thread_local global i32 0, comdat, align 4
153520a37f5SRichard Smith // CHECK-DAG: @[[XH:_ZN(2ns)?1XIiE1hIiEE]] = linkonce_odr thread_local global i32 0, comdat, align 4
154520a37f5SRichard Smith
155520a37f5SRichard Smith // It's OK if the order of the first 6 of these changes.
156520a37f5SRichard Smith // CHECK: @llvm.global_ctors = appending global
157520a37f5SRichard Smith // CHECK-SAME: @[[E_INIT:[^,]*]], {{[^@]*}} @[[E]]
158520a37f5SRichard Smith // CHECK-SAME: @[[F_INIT:[^,]*]], {{[^@]*}} @[[F]]
159520a37f5SRichard Smith // CHECK-SAME: @[[XA_INIT:[^,]*]], {{[^@]*}} @[[XA]]
160520a37f5SRichard Smith // CHECK-SAME: @[[XE_INIT:[^,]*]], {{[^@]*}} @[[XE]]
161520a37f5SRichard Smith // CHECK-SAME: @[[XF_INIT:[^,]*]], {{[^@]*}} @[[XF]]
162520a37f5SRichard Smith // CHECK-SAME: @[[XB_INIT:[^,]*]], {{[^@]*}} @[[XB]]
163520a37f5SRichard Smith // CHECK-IMPORT-SAME: @[[TU_INIT:[^,]*]], i8* null }]
164520a37f5SRichard Smith
165520a37f5SRichard Smith // FIXME: Should this use __cxa_guard_acquire?
166520a37f5SRichard Smith // CHECK: define {{.*}} @[[E_INIT]]()
167520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
168520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[E]],
169520a37f5SRichard Smith
170520a37f5SRichard Smith // FIXME: Should this use __cxa_guard_acquire?
171520a37f5SRichard Smith // CHECK: define {{.*}} @[[F_INIT]]()
172520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
173520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[F]],
174520a37f5SRichard Smith
175520a37f5SRichard Smith // CHECK: define {{.*}} @[[G_INIT:__cxx_global.*]]()
176520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
177520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[G]],
178520a37f5SRichard Smith
179520a37f5SRichard Smith // CHECK: define {{.*}} @[[H_INIT:__cxx_global.*]]()
180520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
181520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[H]],
182520a37f5SRichard Smith
183520a37f5SRichard Smith // FIXME: Should this use __cxa_guard_acquire?
184520a37f5SRichard Smith // CHECK: define {{.*}} @[[XA_INIT]]()
185520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
186520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[XA]],
187520a37f5SRichard Smith
188520a37f5SRichard Smith // CHECK: define {{.*}} @[[XC_INIT:__cxx_global.*]]()
189520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
190520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[XC]],
191520a37f5SRichard Smith
192520a37f5SRichard Smith // FIXME: Should this use __cxa_guard_acquire?
193520a37f5SRichard Smith // CHECK: define {{.*}} @[[XE_INIT]]()
194520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
195520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[XE]],
196520a37f5SRichard Smith
197520a37f5SRichard Smith // CHECK: define {{.*}} @[[XG_INIT:__cxx_global.*]]()
198520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
199520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[XG]],
200520a37f5SRichard Smith
201520a37f5SRichard Smith // CHECK: define {{.*}} @[[XH_INIT:__cxx_global.*]]()
202520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
203520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[XH]],
204520a37f5SRichard Smith
205520a37f5SRichard Smith // FIXME: Should this use __cxa_guard_acquire?
206520a37f5SRichard Smith // CHECK: define {{.*}} @[[XF_INIT]]()
207520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
208520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[XF]],
209520a37f5SRichard Smith
210520a37f5SRichard Smith // CHECK: define {{.*}} @[[XD_INIT:__cxx_global.*]]()
211520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
212520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[XD]],
213520a37f5SRichard Smith
214520a37f5SRichard Smith // FIXME: Should this use __cxa_guard_acquire?
215520a37f5SRichard Smith // CHECK: define {{.*}} @[[XB_INIT]]()
216520a37f5SRichard Smith // CHECK: load {{.*}} (i64* @_ZGV
217520a37f5SRichard Smith // CHECK: store {{.*}}, i32* @[[XB]],
218520a37f5SRichard Smith
219520a37f5SRichard Smith // CHECK-IMPORT: define {{.*}} @[[A_INIT:__cxx_global.*]]()
2201b1c8d83Shyeongyu kim // CHECK-IMPORT: call noundef i32 @_Z11non_trivialv(
221520a37f5SRichard Smith // CHECK-IMPORT: store {{.*}}, i32* @[[A]],
222520a37f5SRichard Smith
223520a37f5SRichard Smith // CHECK-IMPORT: define {{.*}} @[[B_INIT:__cxx_global.*]]()
224520a37f5SRichard Smith // CHECK-IMPORT: call i32 @__cxa_guard_acquire(i64* @_ZGV
225520a37f5SRichard Smith // CHECK-IMPORT: store {{.*}}, i32* @[[B]],
226520a37f5SRichard Smith
227520a37f5SRichard Smith // CHECK-IMPORT: define {{.*}} @[[C_INIT:__cxx_global.*]]()
2281b1c8d83Shyeongyu kim // CHECK-IMPORT: call noundef i32 @_Z11non_trivialv(
229520a37f5SRichard Smith // CHECK-IMPORT: store {{.*}}, i32* @[[C]],
230520a37f5SRichard Smith
231520a37f5SRichard Smith // CHECK-IMPORT: define {{.*}} @[[D_INIT:__cxx_global.*]]()
232520a37f5SRichard Smith // CHECK-IMPORT: load {{.*}} (i64* @_ZGV
233520a37f5SRichard Smith // CHECK-IMPORT: store {{.*}}, i32* @[[D]],
234520a37f5SRichard Smith
235520a37f5SRichard Smith
236520a37f5SRichard Smith // CHECK-IMPORT: define {{.*}} @[[TU_INIT]]()
237520a37f5SRichard Smith // CHECK-IMPORT: call void @[[A_INIT]]()
238520a37f5SRichard Smith
239520a37f5SRichard Smith // CHECK-IMPORT: define {{.*}} @__tls_init()
240520a37f5SRichard Smith // CHECK-IMPORT: call void @[[C_INIT]]()
241520a37f5SRichard Smith // CHECK-IMPORT: call void @[[D_INIT]]()
242