xref: /llvm-project/clang/test/CodeGenCXX/module-initializer-guard-elision.cpp (revision c5de4dd1eab00df76c1a68c5f397304ceacb71f2)
1 // RUN: rm -rf %t
2 // RUN: split-file %s %t
3 // RUN: cd %t
4 
5 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.cpp \
6 // RUN:    -emit-module-interface -o O.pcm
7 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 O.pcm -emit-llvm \
8 // RUN:  -o - | FileCheck %s --check-prefix=CHECK-O
9 
10 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 P.cpp \
11 // RUN:    -emit-module-interface -fprebuilt-module-path=%t -o P.pcm
12 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 P.pcm -emit-llvm \
13 // RUN:   -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-P
14 
15 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 Q.cpp \
16 // RUN:    -emit-module-interface -o Q.pcm
17 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 Q.pcm -emit-llvm \
18 // RUN:    -o - | FileCheck %s --check-prefix=CHECK-Q
19 
20 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 R.cpp \
21 // RUN:    -emit-module-interface -fprebuilt-module-path=%t -o R.pcm
22 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 R.pcm -emit-llvm \
23 // RUN:    -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-R
24 
25 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 S.cpp \
26 // RUN:    -emit-module-interface -fprebuilt-module-path=%t -o S.pcm
27 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 S.pcm -emit-llvm \
28 // RUN:    -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-S
29 
30 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 T.cpp \
31 // RUN:    -emit-module-interface -fprebuilt-module-path=%t -o T.pcm
32 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 T.pcm -emit-llvm \
33 // RUN:    -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-T
34 
35 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 U.cpp \
36 // RUN:    -emit-module-interface -fprebuilt-module-path=%t -o U.pcm
37 // RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++20 U.pcm -emit-llvm \
38 // RUN:    -fprebuilt-module-path=%t -o - | FileCheck %s --check-prefix=CHECK-U
39 
40 // Testing cases where we can elide the module initializer guard variable.
41 
42 // This module has no global inits and does not import any other module
43 //--- O.cpp
44 
45 export module O;
46 
47 export int foo ();
48 
49 // CHECK-O: define void @_ZGIW1O
50 // CHECK-O-LABEL: entry
51 // CHECK-O-NEXT: ret void
52 // CHECK-O-NOT: @_ZGIW1O__in_chrg
53 
54 // This has no global inits and all the imported modules don't need inits. So
55 // guard variable is not needed.
56 //--- P.cpp
57 
58 export module P;
59 
60 export import O;
61 export int bar ();
62 
63 // CHECK-P: define void @_ZGIW1P
64 // CHECK-P-LABEL: entry
65 // CHECK-P-NEXT: ret void
66 // CHECK-P-NOT: @_ZGIW1P__in_chrg
67 
68 // This has global inits, so needs a guard.
69 //--- Q.cpp
70 
71 export module Q;
72 
73 export struct Quack {
QuackQuack74   Quack(){};
75 };
76 
77 export Quack Duck;
78 
79 export int baz ();
80 
81 // CHECK-Q: define internal void @__cxx_global_var_init
82 // CHECK-Q: call {{.*}} @_ZNW1Q5QuackC1Ev
83 // CHECK-Q: define void @_ZGIW1Q
84 // CHECK-Q: store i8 1, ptr @_ZGIW1Q__in_chrg
85 // CHECK-Q: call void @__cxx_global_var_init
86 
87 // This doesn't have a global init, but it imports a module which needs global
88 // init, so needs a guard
89 //--- R.cpp
90 
91 export module R;
92 export import Q;
93 
94 // CHECK-R: define void @_ZGIW1R
95 // CHECK-R: store i8 1, ptr @_ZGIW1R__in_chrg
96 // CHECK-R: call{{.*}}@_ZGIW1Q
97 
98 // This doesn't have a global init and the imported module doesn't have variables needs
99 // dynamic initialization.
100 // But the imported module contains modules initialization. So needs a guard.
101 //--- S.cpp
102 
103 export module S;
104 export import R;
105 
106 // CHECK-S: define void @_ZGIW1S
107 // CHECK-S: store i8 1, ptr @_ZGIW1S__in_chrg
108 // CHECK-S: call{{.*}}@_ZGIW1R
109 
110 // The module itself doesn't have a global init and it doesn't import any module.
111 // But the global module fragment imports a module that needs an init. So needs a guard.
112 //--- T.cpp
113 module;
114 import S;
115 export module T;
116 
117 // CHECK-T: define void @_ZGIW1T
118 // CHECK-T: store i8 1, ptr @_ZGIW1T__in_chrg
119 // CHECK-T: call{{.*}}@_ZGIW1S
120 
121 // The module itself doesn't have a global init and it doesn't import any module.
122 // But the private module fragment imports a module that needs an init. So needs a guard.
123 //--- U.cpp
124 export module U;
125 module :private;
126 import T;
127 
128 // CHECK-U: define void @_ZGIW1U
129 // CHECK-U: store i8 1, ptr @_ZGIW1U__in_chrg
130 // CHECK-U: call{{.*}}@_ZGIW1T
131