1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
3 struct X0 {
4   X0();
5   X0(int);
6   X0 f1();
7   X0 f2();
8   typedef int A;
9   typedef X0 B;
10 };
11 
12 template<typename T>
13 struct X1 : X0 {
14   X1();
15   X1<T>(int);
16   (X1<T>)(float);
17   X1 f2();
18   X1 f2(int);
19   X1 f2(float);
20   X1 f2(double);
21   X1 f2(short);
22   X1 f2(long);
23 };
24 
25 // Error recovery: out-of-line constructors whose names have template arguments.
26 template<typename T> X1<T>::X1<T>(int) { } // expected-error{{out-of-line constructor for 'X1' cannot have template arguments}}
27 template<typename T> (X1<T>::X1<T>)(float) { } // expected-error{{out-of-line constructor for 'X1' cannot have template arguments}}
28 
29 // Error recovery: out-of-line constructor names intended to be types
30 X0::X0 X0::f1() { return X0(); } // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}}
31 
32 struct X0::X0 X0::f2() { return X0(); }
33 
34 template<typename T> X1<T>::X1<T> X1<T>::f2() { } // expected-error{{missing 'typename'}}
35 template<typename T> X1<T>::X1<T> (X1<T>::f2)(int) { } // expected-error{{missing 'typename'}}
36 template<typename T> struct X1<T>::X1<T> (X1<T>::f2)(float) { }
37 template<typename T> struct X1<T>::X1 (X1<T>::f2)(double) { }
38 template<typename T> typename X1<T>::template X1<T> X1<T>::f2(short) { } // expected-warning {{qualified reference to 'X1' is a constructor name rather than a template name in this context}}
39 template<typename T> typename X1<T>::template X1<T> (X1<T>::f2)(long) { } // expected-warning {{qualified reference to 'X1' is a constructor name rather than a template name in this context}}
40 
41 void x1test(X1<int> x1i) {
42   x1i.f2();
43   x1i.f2(0);
44   x1i.f2(0.f);
45   x1i.f2(0.);
46 }
47 
48 void other_contexts() {
49   X0::X0 x0; // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}}
50   X1<int>::X1 x1a; // expected-error{{qualified reference to 'X1' is a constructor name rather than a type in this context}}
51   X1<int>::X1<float> x1b; // expected-error{{qualified reference to 'X1' is a constructor name rather than a template name in this context}}
52 
53   X0::B ok1;
54   X0::X0::A ok2;
55   X0::X0::X0 x0b; // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}}
56   X1<int>::X0 ok3;
57   X1<int>::X0::X0 x0c; // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}}
58   X1<int>::X1<float>::X0 ok4;
59 
60   {
61     typename X0::X0 tn1; // expected-warning{{qualified reference to 'X0' is a constructor name rather than a type in this context}} expected-warning 0-1{{typename}}
62     typename X1<int>::X1<float> tn2; // expected-warning{{qualified reference to 'X1' is a constructor name rather than a template name in this context}} expected-warning 0-1{{typename}}
63     typename X0::B ok1; // expected-warning 0-1{{typename}}
64     typename X1<int>::X0 ok2; // expected-warning 0-1{{typename}}
65   }
66 
67   {
68     struct X0::X0 tag1;
69     struct X1<int>::X1 tag2;
70     struct X1<int>::X1<int> tag3;
71   }
72 
73   int a;
74   {
75     X0::X0(a); // expected-error{{qualified reference to 'X0' is a constructor name rather than a type in this context}}
76   }
77 }
78 
79 template<typename T> void in_instantiation_x0() {
80   typename T::X0 x0; // expected-warning{{qualified reference to 'X0' is a constructor name rather than a type in this context}}
81   typename T::A a;
82   typename T::B b;
83 }
84 template void in_instantiation_x0<X0>(); // expected-note {{instantiation of}}
85 
86 template<typename T> void in_instantiation_x1() {
87   typename T::X1 x1; // expected-warning{{qualified reference to 'X1' is a constructor name rather than a type in this context}}
88   typename T::template X1<int> x1i; // expected-warning{{qualified reference to 'X1' is a constructor name rather than a template name in this context}}
89   typename T::X0 x0;
90 }
91 template void in_instantiation_x1<X1<int> >(); // expected-note {{instantiation of}}
92 
93 namespace sfinae {
94   template<typename T> void f(typename T::X0 *) = delete; // expected-warning 0-1{{extension}}
95   template<typename T> void f(...);
96   void g() { f<X0>(0); }
97 }
98 
99 namespace versus_injected_class_name {
100   template <typename T> struct A : T::B {
101     struct T::B *p;
102     typename T::B::type a;
103     A() : T::B() {}
104 
105     typename T::B b; // expected-warning {{qualified reference to 'B' is a constructor name rather than a type in this context}}
106   };
107   struct B {
108     typedef int type;
109   };
110   template struct A<B>; // expected-note {{in instantiation of}}
111 }
112 
113 // We have a special case for lookup within using-declarations that are
114 // member-declarations: foo::bar::baz::baz always names baz's constructor
115 // in such a context, even if looking up 'baz' within foo::bar::baz would
116 // not find the injected-class-name. Likewise foo::bar::baz<T>::baz also
117 // names the constructor.
118 namespace InhCtor {
119   struct A {
120     A(int);
121   protected:
122     int T();
123   };
124   typedef A T;
125   struct B : A {
126     // This is a using-declaration for 'int A::T()' in C++98, but is an
127     // inheriting constructor declaration in C++11.
128     using InhCtor::T::T;
129   };
130 #if __cplusplus < 201103L
131   B b(123);      // expected-error {{no matching constructor}}
132                  // expected-note@-7 2{{candidate constructor}}
133   int n = b.T(); // ok, accessible
134 #else
135   B b(123);      // ok, inheriting constructor
136   int n = b.T(); // expected-error {{'T' is a protected member of 'InhCtor::A'}}
137                  // expected-note@-15 {{declared protected here}}
138 
139   // FIXME: EDG and GCC reject this too, but it's not clear why it would be
140   // ill-formed.
141   template<typename T>
142   struct S : T {
143     struct U : S { // expected-note 6{{candidate}}
144       using S::S;
145     };
146     using T::T;
147   };
148   S<A>::U ua(0); // expected-error {{no match}}
149   S<B>::U ub(0); // expected-error {{no match}}
150 
151   template<typename T>
152   struct X : T {
153     using T::Z::U::U;
154   };
155   template<typename T>
156   struct X2 : T {
157     using T::Z::template V<int>::V;
158   };
159   struct Y {
160     struct Z {
161       typedef Y U;
162       template<typename T> using V = Y;
163     };
164     Y(int);
165   };
166   X<Y> xy(0);
167 
168   namespace Repeat {
169     struct A {
170       struct T {
171         T(int);
172       };
173     };
174     struct Z : A {
175       using A::A::A;
176     };
177     template<typename T>
178     struct ZT : T::T {
179       using T::T::T;
180     };
181   }
182 
183   namespace NS {
184     struct NS {};
185   }
186   struct DerivedFromNS : NS::NS {
187     // No special case unless the NNS names a class.
188     using InhCtor::NS::NS; // expected-error {{using declaration in class refers into 'InhCtor::NS::', which is not a class}}
189 
190   };
191 
192   // FIXME: Consider reusing the same diagnostic between dependent and non-dependent contexts
193   typedef int I;
194   struct UsingInt {
195     using I::I; // expected-error {{'InhCtor::I' (aka 'int') is not a class, namespace, or enumeration}}
196   };
197   template<typename T> struct UsingIntTemplate {
198     using T::T; // expected-error {{type 'int' cannot be used prior to '::' because it has no members}}
199   };
200   UsingIntTemplate<int> uit; // expected-note {{here}}
201 #endif
202 }
203