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