xref: /llvm-project/clang/test/SemaCXX/deduced-return-type-cxx14.cpp (revision eb08c0f1659d12524f58a01bf174177b8acedf2e)
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