85 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -O0 -o - %s | FileCheck %s2 3// Test that we do not assume that entities marked with the4// exclude_from_explicit_instantiation attribute are instantiated5// in another TU when an extern template instantiation declaration6// is present. We test that by making sure that definitions are7// generated in this TU despite there being an extern template8// instantiation declaration, which is normally not the case.9 10#define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))11 12template <class T>13struct Foo {14 EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1();15 EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2();16 17 EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1();18 EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2();19 20 EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member;21 22 struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 {23 static void static_member_function() { }24 };25 26 struct member_class2 {27 EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() { }28 };29};30 31template <class T> inline void Foo<T>::non_static_member_function1() { }32template <class T> void Foo<T>::non_static_member_function2() { }33 34template <class T> inline void Foo<T>::static_member_function1() { }35template <class T> void Foo<T>::static_member_function2() { }36 37template <class T> int Foo<T>::static_data_member = 0;38 39extern template struct Foo<int>;40 41void use() {42 Foo<int> f;43 44 // An inline non-static member function marked with the attribute is not45 // part of the extern template declaration, so a definition must be emitted46 // in this TU.47 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function1Ev48 f.non_static_member_function1();49 50 // A non-inline non-static member function marked with the attribute is51 // not part of the extern template declaration, so a definition must be52 // emitted in this TU.53 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function2Ev54 f.non_static_member_function2();55 56 // An inline static member function marked with the attribute is not57 // part of the extern template declaration, so a definition must be58 // emitted in this TU.59 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function1Ev60 Foo<int>::static_member_function1();61 62 // A non-inline static member function marked with the attribute is not63 // part of the extern template declaration, so a definition must be64 // emitted in this TU.65 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function2Ev66 Foo<int>::static_member_function2();67 68 // A static data member marked with the attribute is not part of the69 // extern template declaration, so a definition must be emitted in this TU.70 // CHECK-DAG: @_ZN3FooIiE18static_data_memberE = linkonce_odr global71 int& odr_use = Foo<int>::static_data_member;72 73 // A member class marked with the attribute is not part of the extern74 // template declaration (it is not recursively instantiated), so its member75 // functions must be emitted in this TU.76 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class122static_member_functionEv77 Foo<int>::member_class1::static_member_function();78 79 // A member function marked with the attribute in a member class is not80 // part of the extern template declaration of the parent class template, so81 // it must be emitted in this TU.82 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class222static_member_functionEv83 Foo<int>::member_class2::static_member_function();84}85