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()31 template <class T> inline void Foo<T>::non_static_member_function1() { }
non_static_member_function2()32 template <class T>        void Foo<T>::non_static_member_function2() { }
33 
static_member_function1()34 template <class T> inline void Foo<T>::static_member_function1() { }
static_member_function2()35 template <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()41 void 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