1 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23 %s
2 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify=expected,since-cxx20,since-cxx14,cxx20_23,cxx23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
3
4 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s
5 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify=expected,cxx20,since-cxx20,since-cxx14,cxx14_20,cxx20_23 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
6
7 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14 %s
8 // RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify=expected,since-cxx14,cxx14_20,cxx14 %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
9
10 auto f(); // expected-note {{previous}}
11 int f(); // expected-error {{differ only in their return type}}
12
13 auto &g();
14 auto g() -> auto &;
15
16 auto h() -> auto *;
17 auto *h();
18
19 struct Conv1 {
20 operator auto(); // expected-note {{declared here}}
21 } conv1;
22 int conv1a = conv1; // expected-error {{function 'operator auto' with deduced return type cannot be used before it is defined}}
23 // expected-error@-1 {{no viable conversion}}
operator auto()24 Conv1::operator auto() { return 123; }
25 int conv1b = conv1;
26 int conv1c = conv1.operator auto();
27 int conv1d = conv1.operator int(); // expected-error {{no member named 'operator int'}}
28
29 struct Conv2 {
operator autoConv230 operator auto() { return 0; } // expected-note {{previous}}
operator autoConv231 operator auto() { return 0.; } // expected-error {{cannot be redeclared}}
32 };
33
34 struct Conv3 {
operator autoConv335 operator auto() { int *p = nullptr; return p; } // expected-note {{candidate}}
operator auto*Conv336 operator auto*() { int *p = nullptr; return p; } // expected-note {{candidate}}
37 } conv3;
38 int *conv3a = conv3; // expected-error {{ambiguous}}
39 int *conv3b = conv3.operator auto();
40 int *conv3c = conv3.operator auto*();
41
42 template<typename T>
43 struct Conv4 {
operator autoConv444 operator auto() { return T(); }
45 };
46 Conv4<int> conv4int;
47 int conv4a = conv4int;
48 int conv4b = conv4int.operator auto();
49
50 auto a();
a()51 auto a() { return 0; }
52 using T = decltype(a());
53 using T = int;
54 auto a(); // expected-note {{previous}}
55 using T = decltype(a());
56 auto *a(); // expected-error {{differ only in their return type}}
57
b(bool k)58 auto b(bool k) {
59 if (k)
60 return "hello";
61 return "goodbye";
62 }
63
64 // Allow 'operator auto' to call only the explicit operator auto.
65 struct BothOps {
66 template <typename T> operator T();
67 template <typename T> operator T *();
operator autoBothOps68 operator auto() { return 0; }
operator auto*BothOps69 operator auto *() { return this; }
70 };
71 struct JustTemplateOp {
72 template <typename T> operator T();
73 template <typename T> operator T *();
74 };
75
c()76 auto c() {
77 BothOps().operator auto(); // ok
78 BothOps().operator auto *(); // ok
79 JustTemplateOp().operator auto(); // expected-error {{no member named 'operator auto' in 'JustTemplateOp'}}
80 JustTemplateOp().operator auto *(); // expected-error {{no member named 'operator auto *' in 'JustTemplateOp'}}
81 }
82
ptr_1()83 auto *ptr_1() {
84 return 100; // expected-error {{cannot deduce return type 'auto *' from returned value of type 'int'}}
85 }
86
ref_1()87 const auto &ref_1() {
88 return 0; // expected-warning {{returning reference to local temporary}}
89 }
90
init_list()91 auto init_list() {
92 return { 1, 2, 3 }; // expected-error {{cannot deduce return type from initializer list}}
93 }
94
95 auto fwd_decl(); // expected-note 2{{here}}
96
97 int n = fwd_decl(); // expected-error {{function 'fwd_decl' with deduced return type cannot be used before it is defined}}
98 int k = sizeof(fwd_decl()); // expected-error {{used before it is defined}}
99
fac(int n)100 auto fac(int n) {
101 if (n <= 2)
102 return n;
103 return n * fac(n-1); // ok
104 }
105
fac_2(int n)106 auto fac_2(int n) { // expected-note {{declared here}}
107 if (n > 2)
108 return n * fac_2(n-1); // expected-error {{cannot be used before it is defined}}
109 return n;
110 }
111
void_ret()112 auto void_ret() {}
113 using Void = void;
114 using Void = decltype(void_ret());
115
void_ret_2()116 auto &void_ret_2() {} // expected-error {{cannot deduce return type 'auto &' for function with no return statements}}
void_ret_3()117 const auto void_ret_3() {} // ok, return type 'const void' is adjusted to 'void'
118
void_ret_4()119 const auto void_ret_4() {
120 if (false)
121 return void();
122 if (false)
123 return;
124 return 0; // expected-error {{'auto' in return type deduced as 'int' here but deduced as 'void' in earlier return statement}}
125 }
126
127 namespace Templates {
f1()128 template<typename T> auto f1() {
129 return T() + 1;
130 }
f2(T && v)131 template<typename T> auto &f2(T &&v) { return v; }
132 // cxx23-error@-1 {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
133 // cxx23-error@-2 {{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}}
134 // cxx23-note@-3 {{candidate template ignored: substitution failure [with T = double]}}
135 int a = f1<int>();
136 const int &b = f2(0); // cxx23-note {{in instantiation of function template specialization 'Templates::f2<int>' requested here}}
137 double d;
138 float &c = f2(0.0); // expected-error {{non-const lvalue reference to type 'float' cannot bind to a value of unrelated type 'double'}}
139 // cxx23-note@-1 {{in instantiation of function template specialization 'Templates::f2<double>' requested here}}
140
141 template<typename T> auto fwd_decl(); // expected-note {{declared here}}
142 int e = fwd_decl<int>(); // expected-error {{cannot be used before it is defined}}
fwd_decl()143 template<typename T> auto fwd_decl() { return 0; }
144 int f = fwd_decl<int>();
145 template <typename T>
146 auto fwd_decl(); // expected-note {{candidate template ignored: could not match 'auto ()' against 'int ()'}}
147 int g = fwd_decl<char>();
148
149 auto (*p)() = f1; // expected-error {{variable 'p' with type 'auto (*)()' has incompatible initializer of type '<overloaded function type>'}}
150 auto (*q)() = f1<int>; // ok
151
152 typedef decltype(f2(1.2)) dbl; // cxx14_20-note {{previous}}
153 // cxx23-error@-1 {{no matching function for call to 'f2'}}
154 typedef float dbl; // cxx14_20-error {{typedef redefinition with different types ('float' vs 'decltype(f2(1.2))' (aka 'double &'))}}
155
156 extern template auto fwd_decl<double>();
157 int k1 = fwd_decl<double>();
158 extern template int fwd_decl<char>(); // expected-error {{does not refer to a function template}}
159 int k2 = fwd_decl<char>();
160
instantiate()161 template <typename T> auto instantiate() { T::error; } // expected-error {{has no members}} \
162 // expected-note {{candidate template ignored: could not match 'auto ()' against 'void ()'}}
163 extern template auto instantiate<int>(); // ok
164 int k = instantiate<int>(); // expected-note {{in instantiation of}}
instantiate()165 template<> auto instantiate<char>() {} // ok
instantiate()166 template<> void instantiate<double>() {} // expected-error {{no function template matches}}
167
arg_single()168 template<typename T> auto arg_single() { return 0; }
arg_multi()169 template<typename T> auto arg_multi() { return 0l; }
arg_multi(int)170 template<typename T> auto arg_multi(int) { return "bad"; }
171 template<typename T> struct Outer {
arg_singleTemplates::Outer172 static auto arg_single() { return 0.f; }
arg_multiTemplates::Outer173 static auto arg_multi() { return 0.; }
arg_multiTemplates::Outer174 static auto arg_multi(int) { return "bad"; }
175 };
176 template<typename T> T &take_fn(T (*p)());
177
178 int &check1 = take_fn(arg_single); // expected-error {{no matching}} expected-note@-2 {{couldn't infer}}
179 int &check2 = take_fn(arg_single<int>);
180 int &check3 = take_fn<int>(arg_single); // expected-error {{no matching}} expected-note@-4{{no overload of 'arg_single'}}
181 int &check4 = take_fn<int>(arg_single<int>);
182 long &check5 = take_fn(arg_multi); // expected-error {{no matching}} expected-note@-6 {{couldn't infer}}
183 long &check6 = take_fn(arg_multi<int>);
184 long &check7 = take_fn<long>(arg_multi); // expected-error {{no matching}} expected-note@-8{{no overload of 'arg_multi'}}
185 long &check8 = take_fn<long>(arg_multi<int>);
186
187 float &mem_check1 = take_fn(Outer<int>::arg_single);
188 float &mem_check2 = take_fn<float>(Outer<char>::arg_single);
189 double &mem_check3 = take_fn(Outer<long>::arg_multi);
190 double &mem_check4 = take_fn<double>(Outer<double>::arg_multi);
191
192 namespace Deduce1 {
f()193 template <typename T> auto f() { return 0; } // expected-note {{couldn't infer template argument 'T'}}
194 template<typename T> void g(T(*)()); // expected-note 2{{candidate}}
h()195 void h() {
196 auto p = f<int>;
197 auto (*q)() = f<int>;
198 int (*r)() = f; // expected-error {{does not match}}
199 g(f<int>);
200 g<int>(f); // expected-error {{no matching function}}
201 g(f); // expected-error {{no matching function}}
202 }
203 }
204
205 namespace Deduce2 {
f(int)206 template <typename T> auto f(int) { return 0; } // expected-note {{couldn't infer template argument 'T'}}
207 template<typename T> void g(T(*)(int)); // expected-note 2{{candidate}}
h()208 void h() {
209 auto p = f<int>;
210 auto (*q)(int) = f<int>;
211 int (*r)(int) = f; // expected-error {{does not match}}
212 g(f<int>);
213 g<int>(f); // expected-error {{no matching function}}
214 g(f); // expected-error {{no matching function}}
215 }
216 }
217
218 namespace Deduce3 {
f(T)219 template<typename T> auto f(T) { return 0; }
220 template<typename T> void g(T(*)(int)); // expected-note {{couldn't infer}}
h()221 void h() {
222 auto p = f<int>;
223 auto (*q)(int) = f<int>;
224 int (*r)(int) = f; // ok
225 g(f<int>);
226 g<int>(f); // ok
227 g(f); // expected-error {{no matching function}}
228 }
229 }
230
231 namespace DeduceInDeducedReturnType {
f()232 template<typename T, typename U> auto f() -> auto (T::*)(U) {
233 int (T::*result)(U) = nullptr;
234 return result;
235 }
236 struct S {};
237 int (S::*(*p)())(double) = f;
238 int (S::*(*q)())(double) = f<S, double>;
239 }
240
241 template<typename T>
242 struct MemberSpecialization {
243 auto f();
244 template<typename U> auto f(U);
245 template<typename U> auto *f(U);
246 };
247
248 template<>
249 auto MemberSpecialization<int>::f();
250
251 template<>
252 template<typename U>
253 auto MemberSpecialization<int>::f(U);
254
255 template<>
256 template<typename U>
257 auto *MemberSpecialization<int>::f(U);
258 }
259
260 auto fwd_decl_using();
261 namespace N { using ::fwd_decl_using; }
fwd_decl_using()262 auto fwd_decl_using() { return 0; }
263 namespace N { int k = N::fwd_decl_using(); }
264
265 namespace OverloadResolutionNonTemplate {
266 auto f();
267 auto f(int); // expected-note {{here}}
268
269 int &g(int (*f)()); // expected-note {{not viable: no overload of 'f' matching 'int (*)()'}}
270 char &g(int (*f)(int)); // expected-note {{not viable: no overload of 'f' matching 'int (*)(int)'}}
271
272 int a = g(f); // expected-error {{no matching function}}
273
f()274 auto f() { return 0; }
275
276 // FIXME: It's not completely clear whether this should be ill-formed.
277 int &b = g(f); // expected-error {{used before it is defined}}
278
f(int)279 auto f(int) { return 0.0; }
280
281 int &c = g(f); // ok
282 }
283
284 namespace OverloadResolutionTemplate {
285 auto f();
286 template<typename T> auto f(T);
287
288 int &g(int (*f)()); // expected-note {{not viable: no overload of 'f' matching 'int (*)()'}} expected-note {{candidate}}
289 char &g(int (*f)(int)); // expected-note {{not viable: no overload of 'f' matching 'int (*)(int)'}} expected-note {{candidate}}
290
291 int a = g(f); // expected-error {{no matching function}}
292
f()293 auto f() { return 0; }
294
295 int &b = g(f); // ok (presumably), due to deduction failure forming type of 'f<int>'
296
f(T)297 template<typename T> auto f(T) { return 0; }
298
299 int &c = g(f); // expected-error {{ambiguous}}
300 }
301
302 namespace DefaultedMethods {
303 struct A {
304 auto operator=(const A&) = default; // expected-error {{must return 'A &'}}
305 A &operator=(A&&); // expected-note {{previous}}
306 };
307 auto A::operator=(A&&) = default; // expected-error {{return type of out-of-line definition of 'DefaultedMethods::A::operator=' differs from that in the declaration}}
308 }
309
310 namespace Constexpr {
f1(int n)311 constexpr auto f1(int n) { return n; }
fConstexpr::X312 template<typename T> struct X { constexpr auto f() {} }; // PR18746
fConstexpr::Y313 template<typename T> struct Y { constexpr T f() {} }; // expected-note {{control reached end of constexpr function}}
f()314 void f() {
315 X<int>().f();
316 Y<void>().f();
317 constexpr int q = Y<int>().f(); // expected-error {{must be initialized by a constant expression}} expected-note {{in call to 'Y<int>().f()'}}
318 }
319 struct NonLiteral { ~NonLiteral(); } nl; // cxx14-note {{user-provided destructor}}
320 // cxx20-note@-1 {{'NonLiteral' is not literal because its destructor is not constexpr}}
f2(int n)321 constexpr auto f2(int n) { return nl; } // cxx14_20-error {{constexpr function's return type 'struct NonLiteral' is not a literal type}}
322 }
323
324 // It's not really clear whether these are valid, but this matches g++.
325 using size_t = decltype(sizeof(0));
326 auto operator new(size_t n, const char*); // expected-error {{must return type 'void *'}}
327 auto operator delete(void *, const char*); // expected-error {{must return type 'void'}}
328
329 namespace Virtual {
330 struct S {
fVirtual::S331 virtual auto f() { return 0; } // expected-error {{function with deduced return type cannot be virtual}} expected-note {{here}}
332 };
333 // Allow 'auto' anyway for error recovery.
334 struct T : S {
335 int f();
336 };
337 struct U : S {
338 auto f(); // expected-error {{different return}}
339 };
340
341 // And here's why...
342 struct V { virtual auto f(); }; // expected-error {{cannot be virtual}}
343 struct W : V { virtual auto f(); }; // expected-error {{cannot be virtual}}
f()344 auto V::f() { return 0; } // in tu1.cpp
f()345 auto W::f() { return 0.0; } // in tu2.cpp
346 W w;
347 int k1 = w.f();
348 int k2 = ((V&)w).f();
349 }
350
351 namespace std_examples {
352
353 namespace NoReturn {
f()354 auto f() {}
355 void (*p)() = &f;
356
357 auto f(); // ok
358
g()359 auto *g() {} // expected-error {{cannot deduce return type 'auto *' for function with no return statements}}
360
361 auto h() = delete; // expected-note {{explicitly deleted}}
362 auto x = h(); // expected-error {{call to deleted}}
363 }
364
365 namespace UseBeforeComplete {
366 auto n = n; // expected-error {{variable 'n' declared with deduced type 'auto' cannot appear in its own initializer}}
367 auto f(); // expected-note {{declared here}}
g()368 void g() { &f; } // expected-error {{function 'f' with deduced return type cannot be used before it is defined}}
sum(int i)369 auto sum(int i) {
370 if (i == 1)
371 return i;
372 else
373 return sum(i - 1) + i;
374 }
375 }
376
377 namespace Redecl {
378 auto f();
f()379 auto f() { return 42; }
380 auto f(); // expected-note 2{{previous}}
381 int f(); // expected-error {{functions that differ only in their return type cannot be overloaded}}
382 decltype(auto) f(); // expected-error {{cannot be overloaded}}
383
g(T t)384 template <typename T> auto g(T t) { return t; } // expected-note {{candidate}} \
385 // expected-note {{candidate function [with T = int]}}
386 template auto g(int);
387 template char g(char); // expected-error {{does not refer to a function}}
388 template<> auto g(double);
389
g(T t)390 template<typename T> T g(T t) { return t; } // expected-note {{candidate}}
391 template char g(char);
392 template auto g(float);
393
h()394 void h() { return g(42); } // expected-error {{ambiguous}}
395 }
396
397 namespace ExplicitInstantiationDecl {
f(T t)398 template<typename T> auto f(T t) { return t; }
399 extern template auto f(int);
400 int (*p)(int) = f;
401 }
402 namespace MemberTemplatesWithDeduction {
403 struct M {
foostd_examples::MemberTemplatesWithDeduction::M404 template<class T> auto foo(T t) { return t; }
operator ()std_examples::MemberTemplatesWithDeduction::M405 template<class T> auto operator()(T t) const { return t; }
static_foostd_examples::MemberTemplatesWithDeduction::M406 template<class T> static __attribute__((unused)) int static_foo(T) {
407 return 5;
408 }
operator Tstd_examples::MemberTemplatesWithDeduction::M409 template<class T> operator T() { return T{}; }
operator autostd_examples::MemberTemplatesWithDeduction::M410 operator auto() { return &static_foo<int>; }
411 };
412 struct N : M {
413 using M::foo;
414 using M::operator();
415 using M::static_foo;
416 using M::operator auto;
417 };
418
test()419 template <class T> int test() {
420 int i = T{}.foo(3);
421 T m = T{}.foo(M{});
422 int j = T{}(3);
423 M m2 = M{}(M{});
424 int k = T{}.static_foo(4);
425 int l = T::static_foo(5);
426 int l2 = T{};
427 struct X { };
428 X x = T{};
429 return 0;
430 }
431 int Minst = test<M>();
432 int Ninst = test<N>();
433
434 }
435 }
436
437 // We resolve a wording bug here: 'decltype(auto)' should not be modeled as a
438 // decltype-specifier, just as a simple-type-specifier. All the extra places
439 // where a decltype-specifier can appear make no sense for 'decltype(auto)'.
440 namespace DecltypeAutoShouldNotBeADecltypeSpecifier {
441 namespace NNS {
442 int n;
443 decltype(auto) i();
444 decltype(n) j();
445 struct X {
446 friend decltype(auto) ::DecltypeAutoShouldNotBeADecltypeSpecifier::NNS::i();
447 friend decltype(n) ::DecltypeAutoShouldNotBeADecltypeSpecifier::NNS::j(); // expected-error {{not a class}}
448 };
449 }
450
451 namespace Dtor {
452 struct A {};
f(A a)453 void f(A a) { a.~decltype(auto)(); } // expected-error {{'decltype(auto)' not allowed here}}
g(int i)454 void g(int i) { i.~decltype(auto)(); } // expected-error {{'decltype(auto)' not allowed here}}
455 }
456
457 namespace BaseClass {
458 struct A : decltype(auto) {}; // expected-error {{'decltype(auto)' not allowed here}}
459 struct B {
BDecltypeAutoShouldNotBeADecltypeSpecifier::BaseClass::B460 B() : decltype(auto)() {} // expected-error {{'decltype(auto)' not allowed here}}
461 };
462 }
463 }
464
465 namespace CurrentInstantiation {
466 // PR16875
467 template<typename T> struct S {
fCurrentInstantiation::S468 auto f() { return T(); }
gCurrentInstantiation::S469 int g() { return f(); }
hCurrentInstantiation::S470 auto h(bool b) {
471 if (b)
472 return T();
473 return h(true);
474 }
475 };
476 int k1 = S<int>().g();
477 int k2 = S<int>().h(false);
478
479 template<typename T> struct U {
480 #ifndef DELAYED_TEMPLATE_PARSING
481 auto f(); // expected-note {{here}}
gCurrentInstantiation::U482 int g() { return f(); } // expected-error {{cannot be used before it is defined}}
483 #else
484 auto f();
485 int g() { return f(); }
486 #endif
487 };
488 #ifndef DELAYED_TEMPLATE_PARSING
489 template int U<int>::g(); // expected-note {{in instantiation of}}
490 #else
491 template int U<int>::g();
492 #endif
f()493 template<typename T> auto U<T>::f() { return T(); }
494 template int U<short>::g(); // ok
495 }
496
497 namespace WithDefaultArgs {
498 template<typename U> struct A {
f(A)499 template<typename T = U> friend auto f(A) { return []{}; }
500 };
501 template<typename T> void f();
502 using T = decltype(f(A<int>()));
503 using T = decltype(f<int>(A<int>()));
504 }
505
506 namespace MultilevelDeduction {
507
F()508 auto F() -> auto* { return (int*)0; }
509
G()510 auto (*G())() -> int* { return F; }
511
512 auto run = G();
513
514 namespace Templated {
515 template<class T>
F(T t)516 auto F(T t) -> auto* { return (T*)0; }
517
518 template<class T>
G(T t)519 auto (*G(T t))(T) -> T* { return &F<T>; }
520
521
522 template<class T>
G2(T t)523 auto (*G2(T t))(T) -> auto* { return &F<T>; }
524
525 auto run_int = G(1);
526 auto run_char = G2('a');
527
528 }
529 }
530
531 namespace rnk {
532 extern "C" int puts(const char *s);
533 template <typename T>
foo(T x)534 auto foo(T x) -> decltype(x) {
535 #ifdef DELAYED_TEMPLATE_PARSING
536 ::rnk::bar();
537 #endif
538 return x;
539 }
bar()540 void bar() { puts("bar"); }
main()541 int main() { return foo(0); }
542
543 }
544
545 namespace OverloadedOperators {
546 template<typename T> struct A {
operator ()OverloadedOperators::A547 auto operator()() { return T{}; }
operator []OverloadedOperators::A548 auto operator[](int) { return T{}; }
operator +OverloadedOperators::A549 auto operator+(int) { return T{}; }
operator +OverloadedOperators::A550 auto operator+() { return T{}; }
operator -(A)551 friend auto operator-(A) { return T{}; }
operator -(A,A)552 friend auto operator-(A, A) { return T{}; }
553 };
f(A<int> a)554 void f(A<int> a) {
555 int b = a();
556 int c = a[0];
557 int d = a + 0;
558 int e = +a;
559 int f = -a;
560 int g = a - a;
561 }
562 }
563
564 namespace TrailingReturnTypeForConversionOperator {
565 struct X {
operator autoTrailingReturnTypeForConversionOperator::X566 operator auto() -> int { return 0; } // expected-error {{cannot specify any part of a return type in the declaration of a conversion function; put the complete type after 'operator'}}
567 } x;
568 int k = x.operator auto();
569
570 struct Y {
operator autoTrailingReturnTypeForConversionOperator::Y571 operator auto() -> int & { // expected-error {{cannot specify}}
572 return 0; // expected-error {{cannot bind to}}
573 }
574 };
575 };
576
577 namespace PR24989 {
__anona85a7f6d0202(auto)578 auto x = [](auto){};
579 using T = decltype(x);
580 void (T::*p)(int) const = &T::operator();
581 }
582
forinit_decltypeauto()583 void forinit_decltypeauto() {
584 for (decltype(auto) forinit_decltypeauto_inner();;) {} // expected-warning {{interpreted as a function}} expected-note {{replace}}
585 }
586
587 namespace PR33222 {
588 auto f1();
589 auto f2();
590
g0(T x)591 template<typename T> decltype(auto) g0(T x) { return x.n; }
592 template<typename T> decltype(auto) g1(T);
593 template<typename T> decltype(auto) g2(T);
594
595 struct X {
596 static auto f1();
597 static auto f2();
598
g0PR33222::X599 template<typename T> static decltype(auto) g0(T x) { return x.n; }
600 template<typename T> static decltype(auto) g1(T);
601 template<typename T> static decltype(auto) g2(T);
602 };
603
604 template<typename U> class A {
605 friend auto f1();
606 friend auto f2();
607
608 friend decltype(auto) g0<>(A);
609 template<typename T> friend decltype(auto) g1(T);
610 template<typename T> friend decltype(auto) g2(T);
611
612 friend auto X::f1();
613 friend auto X::f2();
614
615 // FIXME (PR38882): 'A' names the class template not the injected-class-name here!
616 friend decltype(auto) X::g0<>(A<U>);
617 // FIXME (PR38882): ::T hides the template parameter if both are named T here!
618 template<typename T_> friend decltype(auto) X::g1(T_);
619 template<typename T_> friend decltype(auto) X::g2(T_);
620
621 int n;
622 };
623
f1()624 auto f1() { return A<int>().n; }
g1(T x)625 template<typename T> decltype(auto) g1(T x) { return A<int>().n; }
626
f1()627 auto X::f1() { return A<int>().n; }
g1(T x)628 template<typename T> decltype(auto) X::g1(T x) { return A<int>().n; }
629
630 A<int> ai;
631 int k1 = g0(ai);
632 int k2 = X::g0(ai);
633
634 int k3 = g1(ai);
635 int k4 = X::g1(ai);
636
f2()637 auto f2() { return A<int>().n; }
g2(T x)638 template<typename T> decltype(auto) g2(T x) { return A<int>().n; }
639
f2()640 auto X::f2() { return A<int>().n; }
g2(T x)641 template<typename T> decltype(auto) X::g2(T x) { return A<int>().n; }
642
643 int k5 = g2(ai);
644 int k6 = X::g2(ai);
645
646 template<typename> struct B {
qPR33222::B647 auto *q() { return (float*)0; } // expected-note 2{{previous}}
648 };
q()649 template<> auto *B<char[1]>::q() { return (int*)0; }
q()650 template<> auto B<char[2]>::q() { return (int*)0; } // expected-error {{return type}}
q()651 template<> int B<char[3]>::q() { return 0; } // expected-error {{return type}}
652 }
653
654 namespace PR46637 {
655 using A = auto () -> auto; // expected-error {{'auto' not allowed in type alias}}
656 using B = auto (*)() -> auto; // expected-error {{'auto' not allowed in type alias}}
657 template<auto (*)() -> auto> struct X {}; // cxx14-error {{'auto' not allowed in template parameter until C++17}}
658 template<typename T> struct Y { T x; };
659 Y<auto() -> auto> y; // expected-error {{'auto' not allowed in template argument}}
660 }
661
662 namespace GH71015 {
663
664 // Check that there is no error in case a templated function is recursive and
665 // has a placeholder return type.
666 struct Node {
667 int value;
668 Node* left;
669 Node* right;
670 };
671
672 bool parse(const char*);
673 Node* parsePrimaryExpr();
674
parseMulExpr(auto node)675 auto parseMulExpr(auto node) { // cxx14-error {{'auto' not allowed in function prototype}} \
676 // cxx14-note {{not viable}}
677 if (node == nullptr) node = parsePrimaryExpr();
678 if (!parse("*")) return node;
679 return parseMulExpr(new Node{.left = node, .right = parsePrimaryExpr()});
680 }
681
682 template <typename T>
parseMulExpr2(T node)683 auto parseMulExpr2(T node) {
684 if (node == nullptr) node = parsePrimaryExpr();
685 if (!parse("*")) return node;
686 return parseMulExpr2(new Node{.left = node, .right = parsePrimaryExpr()});
687 }
688
689 template <typename T>
parseMulExpr3(T node)690 auto parseMulExpr3(T node) { // expected-note {{declared here}}
691 if (node == nullptr) node = parsePrimaryExpr();
692 return parseMulExpr3(new Node{.left = node, .right = parsePrimaryExpr()}); // expected-error {{cannot be used before it is defined}}
693 }
694
foo()695 void foo() {
696 parseMulExpr(new Node{}); // cxx14-error {{no matching function}}
697 parseMulExpr2(new Node{});
698 parseMulExpr3(new Node{}); // expected-note {{in instantiation}}
699 }
700
f(auto x)701 auto f(auto x) { // cxx14-error {{'auto' not allowed in function prototype}}
702 if (x == 0) return 0;
703 return f(1) + 1;
704 }
705
706 }
707
708 #if __cplusplus >= 202002L
709 template <typename T>
710 concept C = true;
711 #endif
712
713 struct DeducedTargetTypeOfConversionFunction {
operator autoDeducedTargetTypeOfConversionFunction714 operator auto() const { return char(); }
operator const autoDeducedTargetTypeOfConversionFunction715 operator const auto() const { return float(); }
operator const auto&DeducedTargetTypeOfConversionFunction716 operator const auto&() const { return int(); }
717 // expected-warning@-1 {{returning reference to local temporary object}}
operator decltype(auto)DeducedTargetTypeOfConversionFunction718 operator decltype(auto)() const { return double(); }
719 #if __cplusplus >= 202002L
operator C autoDeducedTargetTypeOfConversionFunction720 operator C auto() const { return unsigned(); }
operator C decltype(auto)DeducedTargetTypeOfConversionFunction721 operator C decltype(auto)() const { return long(); }
722 #endif
723
724 template <typename T>
operator autoDeducedTargetTypeOfConversionFunction725 operator auto() const { return short(); }
726 // since-cxx14-error@-1 {{'auto' not allowed in declaration of conversion function template}}
727 template <typename T>
operator const autoDeducedTargetTypeOfConversionFunction728 operator const auto() const { return int(); }
729 // since-cxx14-error@-1 {{'auto' not allowed in declaration of conversion function template}}
730 template <typename T>
operator const auto&DeducedTargetTypeOfConversionFunction731 operator const auto&() const { return char(); }
732 // since-cxx14-error@-1 {{'auto' not allowed in declaration of conversion function template}}
733 template <typename T>
operator decltype(auto)DeducedTargetTypeOfConversionFunction734 operator decltype(auto)() const { return unsigned(); }
735 // since-cxx14-error@-1 {{'decltype(auto)' not allowed in declaration of conversion function template}}
736 #if __cplusplus >= 202002L
737 template <typename T>
operator C autoDeducedTargetTypeOfConversionFunction738 operator C auto() const { return float(); }
739 // since-cxx20-error@-1 {{'auto' not allowed in declaration of conversion function template}}
740 template <typename T>
operator C decltype(auto)DeducedTargetTypeOfConversionFunction741 operator C decltype(auto)() const { return double(); }
742 // since-cxx20-error@-1 {{'decltype(auto)' not allowed in declaration of conversion function template}}
743 #endif
744 };
745
746 namespace GH79745 {
747 template <typename = int> struct a; // expected-note {{template is declared here}}
f()748 auto f() {
749 a c; // cxx20_23-error {{implicit instantiation of undefined template}} \
750 // cxx14-error {{use of class template 'a' requires template arguments}}
751 return c;
752 }
753 }
754