Daniel Dunbar | a572887 | 2009-12-15 20:14:24 +0000 | [diff] [blame] | 1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 2 | |
| 3 | template<typename T> |
| 4 | class X { |
| 5 | public: |
| 6 | struct C { T &foo(); }; |
| 7 | |
| 8 | struct D { |
Douglas Gregor | d048bb7 | 2009-03-25 21:23:52 +0000 | [diff] [blame] | 9 | struct E { T &bar(); }; // expected-error{{cannot form a reference to 'void'}} |
Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 10 | struct F; // expected-note{{member is declared here}} |
| 11 | }; |
| 12 | }; |
| 13 | |
| 14 | X<int>::C *c1; |
| 15 | X<float>::C *c2; |
| 16 | |
Douglas Gregor | 0efc2c1 | 2010-01-13 17:31:36 +0000 | [diff] [blame] | 17 | X<int>::X *xi; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}} |
| 18 | X<float>::X *xf; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}} |
Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 19 | |
| 20 | void test_naming() { |
Douglas Gregor | d4eea83 | 2010-04-09 00:35:39 +0000 | [diff] [blame] | 21 | c1 = c2; // expected-error{{assigning to 'X<int>::C *' from incompatible type 'X<float>::C *'}} |
| 22 | xi = xf; // expected-error{{assigning to 'X<int>::X<int> *' from incompatible type 'X<float>::X<float> *'}} |
Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 23 | // FIXME: error above doesn't print the type X<int>::X cleanly! |
| 24 | } |
| 25 | |
| 26 | void test_instantiation(X<double>::C *x, |
| 27 | X<float>::D::E *e, |
| 28 | X<float>::D::F *f) { |
| 29 | double &dr = x->foo(); |
| 30 | float &fr = e->bar(); |
John McCall | 7c2342d | 2010-03-10 11:27:22 +0000 | [diff] [blame] | 31 | f->foo(); // expected-error{{implicit instantiation of undefined member 'X<float>::D::F'}} |
Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 32 | |
| 33 | } |
Douglas Gregor | d048bb7 | 2009-03-25 21:23:52 +0000 | [diff] [blame] | 34 | |
| 35 | |
| 36 | X<void>::C *c3; // okay |
| 37 | X<void>::D::E *e1; // okay |
John McCall | 7c2342d | 2010-03-10 11:27:22 +0000 | [diff] [blame] | 38 | X<void>::D::E e2; // expected-note{{in instantiation of member class 'X<void>::D::E' requested here}} |
John McCall | 6c1c1b8 | 2009-12-15 22:29:06 +0000 | [diff] [blame] | 39 | |
| 40 | // Redeclarations. |
| 41 | namespace test1 { |
| 42 | template <typename T> struct Registry { |
John McCall | 7002f4c | 2010-04-09 19:03:51 +0000 | [diff] [blame] | 43 | struct node; |
John McCall | 6c1c1b8 | 2009-12-15 22:29:06 +0000 | [diff] [blame] | 44 | static node *Head; |
John McCall | 7002f4c | 2010-04-09 19:03:51 +0000 | [diff] [blame] | 45 | struct node { |
John McCall | 6c1c1b8 | 2009-12-15 22:29:06 +0000 | [diff] [blame] | 46 | node(int v) { Head = this; } |
| 47 | }; |
| 48 | }; |
| 49 | void test() { |
| 50 | Registry<int>::node node(0); |
| 51 | } |
| 52 | } |
John McCall | 2243288 | 2010-03-26 21:56:38 +0000 | [diff] [blame] | 53 | |
| 54 | // Redeclarations during explicit instantiations. |
| 55 | namespace test2 { |
| 56 | template <typename T> class A { |
| 57 | class Foo; |
| 58 | class Foo { |
| 59 | int foo(); |
| 60 | }; |
| 61 | }; |
| 62 | template class A<int>; |
| 63 | |
| 64 | template <typename T> class B { |
| 65 | class Foo; |
| 66 | class Foo { |
John McCall | 7002f4c | 2010-04-09 19:03:51 +0000 | [diff] [blame] | 67 | public: |
John McCall | 2243288 | 2010-03-26 21:56:38 +0000 | [diff] [blame] | 68 | typedef int X; |
| 69 | }; |
| 70 | typename Foo::X x; |
| 71 | class Foo; |
| 72 | }; |
| 73 | template class B<int>; |
| 74 | |
| 75 | template <typename T> class C { |
| 76 | class Foo; |
| 77 | class Foo; |
| 78 | }; |
| 79 | template <typename T> class C<T>::Foo { |
| 80 | int x; |
| 81 | }; |
| 82 | template class C<int>; |
| 83 | } |