xref: /aosp_15_r20/external/clang/test/CodeGenCXX/explicit-instantiation.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-OPT
2*67e74705SXin Li // RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT
3*67e74705SXin Li // RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK-MS
4*67e74705SXin Li 
5*67e74705SXin Li // This check logically is attached to 'template int S<int>::i;' below.
6*67e74705SXin Li // CHECK: @_ZN1SIiE1iE = weak_odr global i32
7*67e74705SXin Li 
8*67e74705SXin Li template<typename T, typename U, typename Result>
9*67e74705SXin Li struct plus {
10*67e74705SXin Li   Result operator()(const T& t, const U& u) const;
11*67e74705SXin Li };
12*67e74705SXin Li 
13*67e74705SXin Li template<typename T, typename U, typename Result>
operator ()(const T & t,const U & u) const14*67e74705SXin Li Result plus<T, U, Result>::operator()(const T& t, const U& u) const {
15*67e74705SXin Li   return t + u;
16*67e74705SXin Li }
17*67e74705SXin Li 
18*67e74705SXin Li // CHECK-LABEL: define weak_odr i32 @_ZNK4plusIillEclERKiRKl
19*67e74705SXin Li template struct plus<int, long, long>;
20*67e74705SXin Li 
21*67e74705SXin Li namespace EarlyInstantiation {
22*67e74705SXin Li   // Check that we emit definitions if we instantiate a function definition before
23*67e74705SXin Li   // it gets explicitly instantiatied.
24*67e74705SXin Li   template<typename T> struct S {
constexpr_functionEarlyInstantiation::S25*67e74705SXin Li     constexpr int constexpr_function() { return 0; }
deduced_return_typeEarlyInstantiation::S26*67e74705SXin Li     auto deduced_return_type() { return 0; }
27*67e74705SXin Li   };
28*67e74705SXin Li 
29*67e74705SXin Li   // From an implicit instantiation.
30*67e74705SXin Li   constexpr int a = S<char>().constexpr_function();
31*67e74705SXin Li   int b = S<char>().deduced_return_type();
32*67e74705SXin Li 
33*67e74705SXin Li   // From an explicit instantiation declaration.
34*67e74705SXin Li   extern template struct S<int>;
35*67e74705SXin Li   constexpr int c = S<int>().constexpr_function();
36*67e74705SXin Li   int d = S<int>().deduced_return_type();
37*67e74705SXin Li 
38*67e74705SXin Li   // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIcE18constexpr_functionEv(
39*67e74705SXin Li   // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIcE19deduced_return_typeEv(
40*67e74705SXin Li   // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIiE18constexpr_functionEv(
41*67e74705SXin Li   // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIiE19deduced_return_typeEv(
42*67e74705SXin Li   template struct S<char>;
43*67e74705SXin Li   template struct S<int>;
44*67e74705SXin Li 
constexpr_function()45*67e74705SXin Li   template<typename T> constexpr int constexpr_function() { return 0; }
deduced_return_type()46*67e74705SXin Li   template<typename T> auto deduced_return_type() { return 0; }
47*67e74705SXin Li 
48*67e74705SXin Li   // From an implicit instantiation.
49*67e74705SXin Li   constexpr int e = constexpr_function<char>();
50*67e74705SXin Li   int f = deduced_return_type<char>();
51*67e74705SXin Li 
52*67e74705SXin Li   // From an explicit instantiation declaration.
53*67e74705SXin Li   extern template int constexpr_function<int>();
54*67e74705SXin Li   extern template auto deduced_return_type<int>();
55*67e74705SXin Li   constexpr int g = constexpr_function<int>();
56*67e74705SXin Li   int h = deduced_return_type<int>();
57*67e74705SXin Li 
58*67e74705SXin Li   // The FIXMEs below are for PR19551.
59*67e74705SXin Li   // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation18constexpr_functionIcEEiv(
60*67e74705SXin Li   // FIXME: define weak_odr i32 @_ZN18EarlyInstantiation19deduced_return_typeIcEEiv(
61*67e74705SXin Li   // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation18constexpr_functionIiEEiv(
62*67e74705SXin Li   // FIXME: define weak_odr i32 @_ZN18EarlyInstantiation19deduced_return_typeIiEEiv(
63*67e74705SXin Li   template int constexpr_function<char>();
64*67e74705SXin Li   // FIXME template auto deduced_return_type<char>();
65*67e74705SXin Li   template int constexpr_function<int>();
66*67e74705SXin Li   // FIXME template auto deduced_return_type<int>();
67*67e74705SXin Li }
68*67e74705SXin Li 
69*67e74705SXin Li namespace LateInstantiation {
70*67e74705SXin Li   // Check that we downgrade the linkage to available_externally if we see an
71*67e74705SXin Li   // explicit instantiation declaration after the function template is
72*67e74705SXin Li   // instantiated.
fLateInstantiation::S73*67e74705SXin Li   template<typename T> struct S { constexpr int f() { return 0; } };
f()74*67e74705SXin Li   template<typename T> constexpr int f() { return 0; }
75*67e74705SXin Li 
76*67e74705SXin Li   // Trigger eager instantiation of the function definitions.
77*67e74705SXin Li   int a, b = S<char>().f() + f<char>() + a;
78*67e74705SXin Li   int c, d = S<int>().f() + f<int>() + a;
79*67e74705SXin Li 
80*67e74705SXin Li   // Don't allow some of those definitions to be emitted.
81*67e74705SXin Li   extern template struct S<int>;
82*67e74705SXin Li   extern template int f<int>();
83*67e74705SXin Li 
84*67e74705SXin Li   // Check that we declare, define, or provide an available-externally
85*67e74705SXin Li   // definition as appropriate.
86*67e74705SXin Li   // CHECK: define linkonce_odr i32 @_ZN17LateInstantiation1SIcE1fEv(
87*67e74705SXin Li   // CHECK: define linkonce_odr i32 @_ZN17LateInstantiation1fIcEEiv(
88*67e74705SXin Li   // CHECK-NO-OPT: declare i32 @_ZN17LateInstantiation1SIiE1fEv(
89*67e74705SXin Li   // CHECK-NO-OPT: declare i32 @_ZN17LateInstantiation1fIiEEiv(
90*67e74705SXin Li   // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1SIiE1fEv(
91*67e74705SXin Li   // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1fIiEEiv(
92*67e74705SXin Li }
93*67e74705SXin Li 
94*67e74705SXin Li namespace PR21718 {
95*67e74705SXin Li // The linkage of a used constexpr member function can change from linkonce_odr
96*67e74705SXin Li // to weak_odr after explicit instantiation without errors about defining the
97*67e74705SXin Li // same function twice.
98*67e74705SXin Li template <typename T>
99*67e74705SXin Li struct S {
100*67e74705SXin Li // CHECK-LABEL: define weak_odr i32 @_ZN7PR217181SIiE1fEv
fPR21718::S101*67e74705SXin Li   __attribute__((used)) constexpr int f() { return 0; }
102*67e74705SXin Li };
g()103*67e74705SXin Li int g() { return S<int>().f(); }
104*67e74705SXin Li template struct S<int>;
105*67e74705SXin Li }
106*67e74705SXin Li 
107*67e74705SXin Li namespace NestedClasses {
108*67e74705SXin Li   // Check how explicit instantiation of an outer class affects the inner class.
109*67e74705SXin Li   template <typename T> struct Outer {
110*67e74705SXin Li     struct Inner {
fNestedClasses::Outer::Inner111*67e74705SXin Li       void f() {}
112*67e74705SXin Li     };
113*67e74705SXin Li   };
114*67e74705SXin Li 
115*67e74705SXin Li   // Explicit instantiation definition of Outer causes explicit instantiation
116*67e74705SXin Li   // definition of Inner.
117*67e74705SXin Li   template struct Outer<int>;
118*67e74705SXin Li   // CHECK: define weak_odr void @_ZN13NestedClasses5OuterIiE5Inner1fEv
119*67e74705SXin Li   // CHECK-MS: define weak_odr x86_thiscallcc void @"\01?f@Inner@?$Outer@H@NestedClasses@@QAEXXZ"
120*67e74705SXin Li 
121*67e74705SXin Li   // Explicit instantiation declaration of Outer causes explicit instantiation
122*67e74705SXin Li   // declaration of Inner, but not in MSVC mode.
123*67e74705SXin Li   extern template struct Outer<char>;
124*67e74705SXin Li   auto use = &Outer<char>::Inner::f;
125*67e74705SXin Li   // CHECK: {{declare|define available_externally}} void @_ZN13NestedClasses5OuterIcE5Inner1fEv
126*67e74705SXin Li   // CHECK-MS: define linkonce_odr x86_thiscallcc void @"\01?f@Inner@?$Outer@D@NestedClasses@@QAEXXZ"
127*67e74705SXin Li }
128*67e74705SXin Li 
129*67e74705SXin Li // Check that we emit definitions from explicit instantiations even when they
130*67e74705SXin Li // occur prior to the definition itself.
131*67e74705SXin Li template <typename T> struct S {
132*67e74705SXin Li   void f();
133*67e74705SXin Li   static void g();
134*67e74705SXin Li   static int i;
135*67e74705SXin Li   struct S2 {
136*67e74705SXin Li     void h();
137*67e74705SXin Li   };
138*67e74705SXin Li };
139*67e74705SXin Li 
140*67e74705SXin Li // CHECK-LABEL: define weak_odr void @_ZN1SIiE1fEv
141*67e74705SXin Li template void S<int>::f();
142*67e74705SXin Li 
143*67e74705SXin Li // CHECK-LABEL: define weak_odr void @_ZN1SIiE1gEv
144*67e74705SXin Li template void S<int>::g();
145*67e74705SXin Li 
146*67e74705SXin Li // See the check line at the top of the file.
147*67e74705SXin Li template int S<int>::i;
148*67e74705SXin Li 
149*67e74705SXin Li // CHECK-LABEL: define weak_odr void @_ZN1SIiE2S21hEv
150*67e74705SXin Li template void S<int>::S2::h();
151*67e74705SXin Li 
f()152*67e74705SXin Li template <typename T> void S<T>::f() {}
g()153*67e74705SXin Li template <typename T> void S<T>::g() {}
154*67e74705SXin Li template <typename T> int S<T>::i;
h()155*67e74705SXin Li template <typename T> void S<T>::S2::h() {}
156