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 | |
Douglas Gregor | eff1dbe | 2011-03-06 20:12:45 +0000 | [diff] [blame] | 3 | namespace PR8965 { |
| 4 | template<typename T> |
| 5 | struct X { |
| 6 | typedef int type; |
| 7 | |
| 8 | T field; // expected-note{{in instantiation of member class}} |
| 9 | }; |
| 10 | |
| 11 | template<typename T> |
| 12 | struct Y { |
| 13 | struct Inner; |
| 14 | |
| 15 | typedef typename X<Inner>::type // expected-note{{in instantiation of template class}} |
| 16 | type; // expected-note{{not-yet-instantiated member is declared here}} |
| 17 | |
| 18 | struct Inner { |
| 19 | typedef type field; // expected-error{{no member 'type' in 'PR8965::Y<int>'; it has not yet been instantiated}} |
| 20 | }; |
| 21 | }; |
| 22 | |
| 23 | Y<int> y; // expected-note{{in instantiation of template class}} |
| 24 | } |
| 25 | |
Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 26 | template<typename T> |
| 27 | class X { |
| 28 | public: |
| 29 | struct C { T &foo(); }; |
| 30 | |
| 31 | struct D { |
Douglas Gregor | d048bb7 | 2009-03-25 21:23:52 +0000 | [diff] [blame] | 32 | struct E { T &bar(); }; // expected-error{{cannot form a reference to 'void'}} |
Douglas Gregor | d475b8d | 2009-03-25 21:17:03 +0000 | [diff] [blame] | 33 | struct F; // expected-note{{member is declared here}} |
| 34 | }; |
| 35 | }; |
| 36 | |
| 37 | X<int>::C *c1; |
| 38 | X<float>::C *c2; |
| 39 | |
Douglas Gregor | 0efc2c1 | 2010-01-13 17:31:36 +0000 | [diff] [blame] | 40 | X<int>::X *xi; // expected-error{{qualified reference to 'X' is a constructor name rather than a type wherever a constructor can be declared}} |
| 41 | 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] | 42 | |
| 43 | void test_naming() { |
Douglas Gregor | d4eea83 | 2010-04-09 00:35:39 +0000 | [diff] [blame] | 44 | c1 = c2; // expected-error{{assigning to 'X<int>::C *' from incompatible type 'X<float>::C *'}} |
| 45 | 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] | 46 | // FIXME: error above doesn't print the type X<int>::X cleanly! |
| 47 | } |
| 48 | |
| 49 | void test_instantiation(X<double>::C *x, |
| 50 | X<float>::D::E *e, |
| 51 | X<float>::D::F *f) { |
| 52 | double &dr = x->foo(); |
| 53 | float &fr = e->bar(); |
John McCall | 7c2342d | 2010-03-10 11:27:22 +0000 | [diff] [blame] | 54 | 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] | 55 | |
| 56 | } |
Douglas Gregor | d048bb7 | 2009-03-25 21:23:52 +0000 | [diff] [blame] | 57 | |
| 58 | |
| 59 | X<void>::C *c3; // okay |
| 60 | X<void>::D::E *e1; // okay |
John McCall | 7c2342d | 2010-03-10 11:27:22 +0000 | [diff] [blame] | 61 | 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] | 62 | |
| 63 | // Redeclarations. |
| 64 | namespace test1 { |
| 65 | template <typename T> struct Registry { |
John McCall | 7002f4c | 2010-04-09 19:03:51 +0000 | [diff] [blame] | 66 | struct node; |
John McCall | 6c1c1b8 | 2009-12-15 22:29:06 +0000 | [diff] [blame] | 67 | static node *Head; |
John McCall | 7002f4c | 2010-04-09 19:03:51 +0000 | [diff] [blame] | 68 | struct node { |
John McCall | 6c1c1b8 | 2009-12-15 22:29:06 +0000 | [diff] [blame] | 69 | node(int v) { Head = this; } |
| 70 | }; |
| 71 | }; |
| 72 | void test() { |
| 73 | Registry<int>::node node(0); |
| 74 | } |
| 75 | } |
John McCall | 2243288 | 2010-03-26 21:56:38 +0000 | [diff] [blame] | 76 | |
| 77 | // Redeclarations during explicit instantiations. |
| 78 | namespace test2 { |
| 79 | template <typename T> class A { |
| 80 | class Foo; |
| 81 | class Foo { |
| 82 | int foo(); |
| 83 | }; |
| 84 | }; |
| 85 | template class A<int>; |
| 86 | |
| 87 | template <typename T> class B { |
| 88 | class Foo; |
| 89 | class Foo { |
John McCall | 7002f4c | 2010-04-09 19:03:51 +0000 | [diff] [blame] | 90 | public: |
John McCall | 2243288 | 2010-03-26 21:56:38 +0000 | [diff] [blame] | 91 | typedef int X; |
| 92 | }; |
| 93 | typename Foo::X x; |
John McCall | 2243288 | 2010-03-26 21:56:38 +0000 | [diff] [blame] | 94 | }; |
| 95 | template class B<int>; |
| 96 | |
| 97 | template <typename T> class C { |
| 98 | class Foo; |
John McCall | 2243288 | 2010-03-26 21:56:38 +0000 | [diff] [blame] | 99 | }; |
| 100 | template <typename T> class C<T>::Foo { |
| 101 | int x; |
| 102 | }; |
| 103 | template class C<int>; |
| 104 | } |
Richard Smith | c89edf5 | 2011-07-01 19:46:12 +0000 | [diff] [blame] | 105 | |
| 106 | namespace AliasTagDef { |
| 107 | template<typename T> |
| 108 | struct F { |
Douglas Gregor | b3df138 | 2011-10-12 19:26:40 +0000 | [diff] [blame] | 109 | using S = struct U { // expected-warning {{C++11}} |
Richard Smith | c89edf5 | 2011-07-01 19:46:12 +0000 | [diff] [blame] | 110 | T g() { |
| 111 | return T(); |
| 112 | } |
| 113 | }; |
| 114 | }; |
| 115 | |
| 116 | int m = F<int>::S().g(); |
| 117 | int n = F<int>::U().g(); |
| 118 | } |
Douglas Gregor | efaa93a | 2011-11-07 17:33:42 +0000 | [diff] [blame] | 119 | |
| 120 | namespace rdar10397846 { |
| 121 | template<int I> struct A |
| 122 | { |
| 123 | struct B |
| 124 | { |
David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame] | 125 | struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \ |
| 126 | expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}} |
Douglas Gregor | efaa93a | 2011-11-07 17:33:42 +0000 | [diff] [blame] | 127 | }; |
| 128 | }; |
| 129 | |
| 130 | template<int N> void foo() |
| 131 | { |
David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame] | 132 | class A<N>::B::C X; // expected-note 2 {{in instantiation of member function}} |
Douglas Gregor | efaa93a | 2011-11-07 17:33:42 +0000 | [diff] [blame] | 133 | int A<N+1>::B::C::*member = 0; |
| 134 | } |
| 135 | |
| 136 | void bar() |
| 137 | { |
David Blaikie | 50800fc | 2012-08-08 17:33:31 +0000 | [diff] [blame] | 138 | foo<0>(); // expected-note{{in instantiation of function template}} |
Douglas Gregor | efaa93a | 2011-11-07 17:33:42 +0000 | [diff] [blame] | 139 | foo<1>(); // expected-note{{in instantiation of function template}} |
| 140 | } |
| 141 | } |