1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | |
3 | // Test that we properly merge the exclude_from_explicit_instantiation |
4 | // attribute on redeclarations. |
5 | |
6 | #define EXCLUDE_FROM_EXPLICIT_INSTANTIATION __attribute__((exclude_from_explicit_instantiation)) |
7 | |
8 | template <class T> |
9 | struct Foo { |
10 | // Declaration without the attribute, definition with the attribute. |
11 | void func1(); |
12 | |
13 | // Declaration with the attribute, definition without the attribute. |
14 | EXCLUDE_FROM_EXPLICIT_INSTANTIATION void func2(); |
15 | |
16 | // Declaration with the attribute, definition with the attribute. |
17 | EXCLUDE_FROM_EXPLICIT_INSTANTIATION void func3(); |
18 | }; |
19 | |
20 | template <class T> |
21 | EXCLUDE_FROM_EXPLICIT_INSTANTIATION void Foo<T>::func1() { |
22 | using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} |
23 | } |
24 | |
25 | template <class T> |
26 | void Foo<T>::func2() { |
27 | using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} |
28 | } |
29 | |
30 | template <class T> |
31 | EXCLUDE_FROM_EXPLICIT_INSTANTIATION void Foo<T>::func3() { |
32 | using Fail = typename T::invalid; // expected-error{{no type named 'invalid' in 'Empty'}} |
33 | } |
34 | |
35 | struct Empty { }; |
36 | extern template struct Foo<Empty>; |
37 | |
38 | int main() { |
39 | Foo<Empty> foo; |
40 | foo.func1(); // expected-note{{in instantiation of}} |
41 | foo.func2(); // expected-note{{in instantiation of}} |
42 | foo.func3(); // expected-note{{in instantiation of}} |
43 | } |
44 | |