1 // RUN: %clang_cc1 -Wno-unused-local-typedef -fsyntax-only -verify %s
2 
3 // Test that extern instantiation declarations cause members marked with
4 // the exclude_from_explicit_instantiation attribute to be instantiated in
5 // the current TU.
6 
7 #define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation))
8 
9 template <class T>
10 struct Foo {
11   EXCLUDE_FROM_EXPLICIT_INSTANTIATION inline void non_static_member_function1();
12 
13   EXCLUDE_FROM_EXPLICIT_INSTANTIATION void non_static_member_function2();
14 
15   EXCLUDE_FROM_EXPLICIT_INSTANTIATION static inline void static_member_function1();
16 
17   EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function2();
18 
19   EXCLUDE_FROM_EXPLICIT_INSTANTIATION static int static_data_member;
20 
21   struct EXCLUDE_FROM_EXPLICIT_INSTANTIATION member_class1 {
static_member_functionFoo::member_class122     static void static_member_function() {
23       using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
24     }
25   };
26 
27   struct member_class2 {
static_member_functionFoo::member_class228     EXCLUDE_FROM_EXPLICIT_INSTANTIATION static void static_member_function() {
29       using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
30     }
31   };
32 };
33 
34 template <class T>
non_static_member_function1()35 inline void Foo<T>::non_static_member_function1() {
36   using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
37 }
38 
39 template <class T>
non_static_member_function2()40 void Foo<T>::non_static_member_function2() {
41   using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
42 }
43 
44 template <class T>
static_member_function1()45 inline void Foo<T>::static_member_function1() {
46   using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
47 }
48 
49 template <class T>
static_member_function2()50 void Foo<T>::static_member_function2() {
51   using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}}
52 }
53 
54 template <class T>
55 int Foo<T>::static_data_member = T::invalid; // expected-error{{no member named 'invalid' in 'Empty'}}
56 
57 struct Empty { };
58 extern template struct Foo<Empty>;
59 
main()60 int main() {
61   Foo<Empty> foo;
62   foo.non_static_member_function1();                   // expected-note{{in instantiation of}}
63   foo.non_static_member_function2();                   // expected-note{{in instantiation of}}
64   Foo<Empty>::static_member_function1();               // expected-note{{in instantiation of}}
65   Foo<Empty>::static_member_function2();               // expected-note{{in instantiation of}}
66   (void)foo.static_data_member;                        // expected-note{{in instantiation of}}
67   Foo<Empty>::member_class1::static_member_function(); // expected-note{{in instantiation of}}
68   Foo<Empty>::member_class2::static_member_function(); // expected-note{{in instantiation of}}
69 }
70