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