192 lines · cpp
1// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-OPT2// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-passes -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT3// RUN: %clang_cc1 -emit-llvm -triple i686-pc-win32 -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK-MS4 5// This check logically is attached to 'template int S<int>::i;' below.6// CHECK: @_ZN1SIiE1iE = weak_odr global i327 8// This check is logically attached to 'template int ExportedStaticLocal::f<int>()' below.9// CHECK-OPT: @_ZZN19ExportedStaticLocal1fIiEEvvE1i = linkonce_odr global10 11template<typename T, typename U, typename Result>12struct plus {13 Result operator()(const T& t, const U& u) const;14};15 16template<typename T, typename U, typename Result>17Result plus<T, U, Result>::operator()(const T& t, const U& u) const {18 return t + u;19}20 21// CHECK-LABEL: define weak_odr noundef i32 @_ZNK4plusIillEclERKiRKl22template struct plus<int, long, long>;23 24namespace EarlyInstantiation {25 // Check that we emit definitions if we instantiate a function definition before26 // it gets explicitly instantiatied.27 template<typename T> struct S {28 constexpr int constexpr_function() { return 0; }29 auto deduced_return_type() { return 0; }30 };31 32 // From an implicit instantiation.33 constexpr int a = S<char>().constexpr_function();34 int b = S<char>().deduced_return_type();35 36 // From an explicit instantiation declaration.37 extern template struct S<int>;38 constexpr int c = S<int>().constexpr_function();39 int d = S<int>().deduced_return_type();40 41 // CHECK: define weak_odr noundef i32 @_ZN18EarlyInstantiation1SIcE18constexpr_functionEv(42 // CHECK: define weak_odr noundef i32 @_ZN18EarlyInstantiation1SIcE19deduced_return_typeEv(43 // CHECK: define weak_odr noundef i32 @_ZN18EarlyInstantiation1SIiE18constexpr_functionEv(44 // CHECK: define weak_odr noundef i32 @_ZN18EarlyInstantiation1SIiE19deduced_return_typeEv(45 template struct S<char>;46 template struct S<int>;47 48 template<typename T> constexpr int constexpr_function() { return 0; }49 template<typename T> auto deduced_return_type() { return 0; }50 51 // From an implicit instantiation.52 constexpr int e = constexpr_function<char>();53 int f = deduced_return_type<char>();54 55 // From an explicit instantiation declaration.56 extern template int constexpr_function<int>();57 extern template auto deduced_return_type<int>();58 constexpr int g = constexpr_function<int>();59 int h = deduced_return_type<int>();60 61 // The FIXMEs below are for PR19551.62 // CHECK: define weak_odr noundef i32 @_ZN18EarlyInstantiation18constexpr_functionIcEEiv(63 // FIXME: define weak_odr noundef i32 @_ZN18EarlyInstantiation19deduced_return_typeIcEEiv(64 // CHECK: define weak_odr noundef i32 @_ZN18EarlyInstantiation18constexpr_functionIiEEiv(65 // FIXME: define weak_odr noundef i32 @_ZN18EarlyInstantiation19deduced_return_typeIiEEiv(66 template int constexpr_function<char>();67 // FIXME template auto deduced_return_type<char>();68 template int constexpr_function<int>();69 // FIXME template auto deduced_return_type<int>();70}71 72namespace LateInstantiation {73 // Check that we downgrade the linkage to available_externally if we see an74 // explicit instantiation declaration after the function template is75 // instantiated.76 template<typename T> struct S { constexpr int f() { return 0; } };77 template<typename T> constexpr int f() { return 0; }78 79 // Trigger eager instantiation of the function definitions.80 int a, b = S<char>().f() + f<char>() + a;81 int c, d = S<int>().f() + f<int>() + a;82 83 // Don't allow some of those definitions to be emitted.84 extern template struct S<int>;85 extern template int f<int>();86 87 // Check that we declare, define, or provide an available-externally88 // definition as appropriate.89 // CHECK: define linkonce_odr noundef i32 @_ZN17LateInstantiation1SIcE1fEv(90 // CHECK: define linkonce_odr noundef i32 @_ZN17LateInstantiation1fIcEEiv(91 // CHECK-NO-OPT: declare noundef i32 @_ZN17LateInstantiation1SIiE1fEv(92 // CHECK-NO-OPT: declare noundef i32 @_ZN17LateInstantiation1fIiEEiv(93 // CHECK-OPT: define available_externally noundef i32 @_ZN17LateInstantiation1SIiE1fEv(94 // CHECK-OPT: define available_externally noundef i32 @_ZN17LateInstantiation1fIiEEiv(95}96 97namespace PR21718 {98// The linkage of a used constexpr member function can change from linkonce_odr99// to weak_odr after explicit instantiation without errors about defining the100// same function twice.101template <typename T>102struct S {103// CHECK-LABEL: define weak_odr noundef i32 @_ZN7PR217181SIiE1fEv104 __attribute__((used)) constexpr int f() { return 0; }105};106int g() { return S<int>().f(); }107template struct S<int>;108}109 110namespace NestedClasses {111 // Check how explicit instantiation of an outer class affects the inner class.112 template <typename T> struct Outer {113 struct Inner {114 void f() {}115 };116 };117 118 // Explicit instantiation definition of Outer causes explicit instantiation119 // definition of Inner.120 template struct Outer<int>;121 // CHECK: define weak_odr void @_ZN13NestedClasses5OuterIiE5Inner1fEv122 // CHECK-MS: define weak_odr dso_local x86_thiscallcc void @"?f@Inner@?$Outer@H@NestedClasses@@QAEXXZ"123 124 // Explicit instantiation declaration of Outer causes explicit instantiation125 // declaration of Inner, but not in MSVC mode.126 extern template struct Outer<char>;127 auto use = &Outer<char>::Inner::f;128 // CHECK: {{declare|define available_externally}} void @_ZN13NestedClasses5OuterIcE5Inner1fEv129 // CHECK-MS: define linkonce_odr dso_local x86_thiscallcc void @"?f@Inner@?$Outer@D@NestedClasses@@QAEXXZ"130}131 132// Check that we emit definitions from explicit instantiations even when they133// occur prior to the definition itself.134template <typename T> struct S {135 void f();136 static void g();137 static int i;138 struct S2 {139 void h();140 };141};142 143// CHECK-LABEL: define weak_odr void @_ZN1SIiE1fEv144template void S<int>::f();145 146// CHECK-LABEL: define weak_odr void @_ZN1SIiE1gEv147template void S<int>::g();148 149// See the check line at the top of the file.150template int S<int>::i;151 152// CHECK-LABEL: define weak_odr void @_ZN1SIiE2S21hEv153template void S<int>::S2::h();154 155template <typename T> void S<T>::f() {}156template <typename T> void S<T>::g() {}157template <typename T> int S<T>::i;158template <typename T> void S<T>::S2::h() {}159 160namespace ExportedStaticLocal {161void sink(int&);162template <typename T>163inline void f() {164 static int i;165 sink(i);166}167// See the check line at the top of the file.168extern template void f<int>();169void use() {170 f<int>();171}172}173 174namespace DefaultedMembers {175 struct B { B(); B(const B&); ~B(); };176 template<typename T> struct A : B {177 A() = default;178 ~A() = default;179 };180 extern template struct A<int>;181 182 // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiEC2Ev183 // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiED2Ev184 A<int> ai;185 186 // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiEC2ERKS1_187 A<int> ai2(ai);188 189 // CHECK-NOT: @_ZN16DefaultedMembers1AIcE190 template struct A<char>;191}192