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