1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -O0 -o - %s | FileCheck %s 2 3 // Test that we do not assume that entities marked with the 4 // exclude_from_explicit_instantiation attribute are instantiated 5 // in another TU when an extern template instantiation declaration 6 // is present. We test that by making sure that definitions are 7 // generated in this TU despite there being an extern template 8 // instantiation declaration, which is normally not the case. 9 10 #define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) 11 12 template <class T> 13 struct 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 { static_member_functionFoo::member_class123 static void static_member_function() { } 24 }; 25 26 struct member_class2 { static_member_functionFoo::member_class227 EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() { } 28 }; 29 }; 30 non_static_member_function1()31template <class T> inline void Foo<T>::non_static_member_function1() { } non_static_member_function2()32template <class T> void Foo<T>::non_static_member_function2() { } 33 static_member_function1()34template <class T> inline void Foo<T>::static_member_function1() { } static_member_function2()35template <class T> void Foo<T>::static_member_function2() { } 36 37 template <class T> int Foo<T>::static_data_member = 0; 38 39 extern template struct Foo<int>; 40 use()41void use() { 42 Foo<int> f; 43 44 // An inline non-static member function marked with the attribute is not 45 // part of the extern template declaration, so a definition must be emitted 46 // in this TU. 47 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function1Ev 48 f.non_static_member_function1(); 49 50 // A non-inline non-static member function marked with the attribute is 51 // not part of the extern template declaration, so a definition must be 52 // emitted in this TU. 53 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE27non_static_member_function2Ev 54 f.non_static_member_function2(); 55 56 // An inline static member function marked with the attribute is not 57 // part of the extern template declaration, so a definition must be 58 // emitted in this TU. 59 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function1Ev 60 Foo<int>::static_member_function1(); 61 62 // A non-inline static member function marked with the attribute is not 63 // part of the extern template declaration, so a definition must be 64 // emitted in this TU. 65 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE23static_member_function2Ev 66 Foo<int>::static_member_function2(); 67 68 // A static data member marked with the attribute is not part of the 69 // extern template declaration, so a definition must be emitted in this TU. 70 // CHECK-DAG: @_ZN3FooIiE18static_data_memberE = linkonce_odr global 71 int& odr_use = Foo<int>::static_data_member; 72 73 // A member class marked with the attribute is not part of the extern 74 // template declaration (it is not recursively instantiated), so its member 75 // functions must be emitted in this TU. 76 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class122static_member_functionEv 77 Foo<int>::member_class1::static_member_function(); 78 79 // A member function marked with the attribute in a member class is not 80 // part of the extern template declaration of the parent class template, so 81 // it must be emitted in this TU. 82 // CHECK-DAG: define linkonce_odr void @_ZN3FooIiE13member_class222static_member_functionEv 83 Foo<int>::member_class2::static_member_function(); 84 } 85