diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2466,6 +2466,8 @@ def warn_cxx11_compat_deduced_return_type : Warning< "return type deduction is incompatible with C++ standards before C++14">, InGroup, DefaultIgnore; +def note_deducing_return_type_for : Note< + "deducing return type for %0">; // C++11 override control def override_keyword_only_allowed_on_virtual_member_functions : Error< diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3801,8 +3801,12 @@ Diag(RetExpr->getExprLoc(), diag::err_auto_fn_deduction_failure) << OrigResultType.getType() << RetExpr->getType(); - if (DAR != DAR_Succeeded) + if (DAR != DAR_Succeeded) { + if (OrigResultType.getBeginLoc().isValid()) + Diag(OrigResultType.getBeginLoc(), diag::note_deducing_return_type_for) + << FD << OrigResultType.getSourceRange(); return true; + } // If a local type is part of the returned type, mark its fields as // referenced. @@ -3815,6 +3819,9 @@ if (!FD->getReturnType()->getAs()) { Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto) << OrigResultType.getType(); + if (OrigResultType.getBeginLoc().isValid()) + Diag(OrigResultType.getBeginLoc(), diag::note_deducing_return_type_for) + << FD << OrigResultType.getSourceRange(); return true; } // In the case of a return with no operand, the initializer is considered @@ -3828,8 +3835,12 @@ Diag(ReturnLoc, diag::err_auto_fn_deduction_failure) << OrigResultType.getType() << Dummy->getType(); - if (DAR != DAR_Succeeded) + if (DAR != DAR_Succeeded) { + if (OrigResultType.getBeginLoc().isValid()) + Diag(OrigResultType.getBeginLoc(), diag::note_deducing_return_type_for) + << FD << OrigResultType.getSourceRange(); return true; + } } // CUDA: Kernel function must have 'void' return type. @@ -3866,6 +3877,9 @@ Diag(ReturnLoc, diag::err_auto_fn_different_deductions) << (AT->isDecltypeAuto() ? 1 : 0) << NewAT->getDeducedType() << DeducedT; + if (OrigResultType.getBeginLoc().isValid()) + Diag(OrigResultType.getBeginLoc(), diag::note_deducing_return_type_for) + << FD << OrigResultType.getSourceRange(); } return true; } diff --git a/clang/test/Sema/invalid-bitwidth-expr.mm b/clang/test/Sema/invalid-bitwidth-expr.mm --- a/clang/test/Sema/invalid-bitwidth-expr.mm +++ b/clang/test/Sema/invalid-bitwidth-expr.mm @@ -13,6 +13,7 @@ auto func() { return undef(); // expected-error {{use of undeclared identifier}} + // expected-note@-2 {{deducing return type for 'func'}} } struct Y { int X : func(); @@ -23,7 +24,7 @@ template struct Base {}; template -auto func() { +auto func() { // expected-note {{deducing return type for 'func'}} // error-bit should be propagated from TemplateArgument to NestNameSpecifier. class Base::type C; // expected-error {{no matching function for call to 'Foo'}} return C; diff --git a/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp b/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp --- a/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp +++ b/clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp @@ -11,6 +11,7 @@ int(&r1)[] = ga; #if __cplusplus < 202002 // expected-error@-2{{cannot bind to a value of unrelated type}} + // expected-note@-4{{deducing return type for 'frob1'}} #endif return r1; @@ -20,6 +21,7 @@ int(&r2)[] = arp; #if __cplusplus < 202002 // expected-error@-2{{cannot bind to a value of unrelated type}} + // expected-note@-4{{deducing return type for 'frob2'}} #endif return r2; diff --git a/clang/test/SemaCXX/cxx2b-consteval-if.cpp b/clang/test/SemaCXX/cxx2b-consteval-if.cpp --- a/clang/test/SemaCXX/cxx2b-consteval-if.cpp +++ b/clang/test/SemaCXX/cxx2b-consteval-if.cpp @@ -4,11 +4,13 @@ constexpr auto f() { if consteval { return 0; } if !consteval { return 0.0; } // expected-error {{'auto' in return type deduced as 'double' here but deduced as 'int' in earlier return statement}} + // expected-note@-3 {{deducing return type for 'f'}} } constexpr auto g() { if !consteval { return 0; } if consteval { return 0.0; } // expected-error {{'auto' in return type deduced as 'double' here but deduced as 'int' in earlier return statement}} + // expected-note@-3 {{deducing return type for 'g'}} } constexpr auto h() { @@ -19,11 +21,12 @@ constexpr auto i() { if consteval { if consteval { // expected-warning {{consteval if is always true in an immediate context}} - return 1; - } - return 2; + return 1; + } + return 2; } else { return 1.0; // expected-error {{'auto' in return type deduced as 'double' here but deduced as 'int' in earlier return statement}} + // expected-note@-8 {{deducing return type for 'i'}} } } diff --git a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp --- a/clang/test/SemaCXX/deduced-return-type-cxx14.cpp +++ b/clang/test/SemaCXX/deduced-return-type-cxx14.cpp @@ -82,6 +82,7 @@ auto *ptr_1() { return 100; // expected-error {{cannot deduce return type 'auto *' from returned value of type 'int'}} + // expected-note@-2 {{deducing return type for 'ptr_1'}} } const auto &ref_1() { @@ -106,6 +107,7 @@ auto fac_2(int n) { // expected-note {{declared here}} if (n > 2) return n * fac_2(n-1); // expected-error {{cannot be used before it is defined}} + // expected-note@-3 {{deducing return type for 'fac_2'}} return n; } @@ -122,6 +124,7 @@ if (false) return; return 0; // expected-error {{'auto' in return type deduced as 'int' here but deduced as 'void' in earlier return statement}} + // expected-note@-6 {{deducing return type for 'void_ret_4'}} } namespace Templates { diff --git a/clang/test/SemaCXX/deduced-return-void.cpp b/clang/test/SemaCXX/deduced-return-void.cpp --- a/clang/test/SemaCXX/deduced-return-void.cpp +++ b/clang/test/SemaCXX/deduced-return-void.cpp @@ -16,10 +16,12 @@ auto f4() { return i; return; // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}} + // expected-note@-3 {{deducing return type for 'f4'}} } auto f5() { return i; return void(); // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}} + // expected-note@-3 {{deducing return type for 'f5'}} } auto l1 = []() { }; @@ -44,10 +46,12 @@ decltype(auto) f4() { return i; return; // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}} + // expected-note@-3 {{deducing return type for 'f4'}} } decltype(auto) f5() { return i; return void(); // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}} + // expected-note@-3 {{deducing return type for 'f5'}} } auto l1 = []() -> decltype(auto) { }; @@ -56,10 +60,12 @@ auto l4 = []() -> decltype(auto) { return i; return; // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}} + // expected-note@-3 {{deducing return type for 'operator()'}} }; auto l5 = []() -> decltype(auto) { return i; return void(); // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}} + // expected-note@-3 {{deducing return type for 'operator()'}} }; } // namespace DecltypeAuto @@ -69,33 +75,41 @@ auto *f1() { } // expected-error {{cannot deduce return type 'auto *' for function with no return statements}} auto *f2() { return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}} + // expected-note@-2 {{deducing return type for 'f2'}} } auto *f3() { return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}} + // expected-note@-2 {{deducing return type for 'f3'}} } auto *f4() { return &i; return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}} + // expected-note@-3 {{deducing return type for 'f4'}} } auto *f5() { return &i; return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}} + // expected-note@-3 {{deducing return type for 'f5'}} } auto l1 = []() -> auto* { }; // expected-error {{cannot deduce return type 'auto *' for function with no return statements}} auto l2 = []() -> auto* { return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}} + // expected-note@-2 {{deducing return type for 'operator()'}} }; auto l3 = []() -> auto* { return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}} + // expected-note@-2 {{deducing return type for 'operator()'}} }; auto l4 = []() -> auto* { return &i; return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}} + // expected-note@-3 {{deducing return type for 'operator()'}} }; auto l5 = []() -> auto* { return &i; return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}} + // expected-note@-3 {{deducing return type for 'operator()'}} }; } // namespace AutoPtr @@ -105,32 +119,39 @@ } auto& f2() { return; // expected-error {{cannot deduce return type 'auto &' from omitted return expression}} + // expected-note@-2 {{deducing return type for 'f2'}} } auto& f3() { return void(); // expected-error@-1 {{cannot form a reference to 'void'}} + // expected-note@-2 {{deducing return type for 'f3'}} } auto& f4() { return i; return; // expected-error {{cannot deduce return type 'auto &' from omitted return expression}} + // expected-note@-3 {{deducing return type for 'f4'}} } auto& f5() { return i; return void(); // expected-error@-2 {{cannot form a reference to 'void'}} + // expected-note@-3 {{deducing return type for 'f5'}} } auto& f6() { return 42; } // expected-error {{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} auto l1 = []() -> auto& { }; // expected-error {{cannot deduce return type 'auto &' for function with no return statements}} auto l2 = []() -> auto& { return; // expected-error {{cannot deduce return type 'auto &' from omitted return expression}} + // expected-note@-2 {{deducing return type for 'operator()'}} }; auto l3 = []() -> auto& { // expected-error {{cannot form a reference to 'void'}} + // expected-note@-1 {{deducing return type for 'operator()'}} return void(); }; -auto l4 = []() -> auto& { +auto l4 = []() -> auto& { // expected-note {{deducing return type for 'operator()'}} return i; return; // expected-error {{cannot deduce return type 'auto &' from omitted return expression}} }; auto l5 = []() -> auto& { // expected-error {{cannot form a reference to 'void'}} + // expected-note@-1 {{deducing return type for 'operator()'}} return i; return void(); }; diff --git a/clang/test/SemaCXX/std-compare-cxx2a.cpp b/clang/test/SemaCXX/std-compare-cxx2a.cpp --- a/clang/test/SemaCXX/std-compare-cxx2a.cpp +++ b/clang/test/SemaCXX/std-compare-cxx2a.cpp @@ -32,6 +32,7 @@ auto compare_incomplete_test() { // expected-error@+1 {{incomplete type 'std::partial_ordering' where a complete type is required}} return (-1.2 <=> 123.0); + // expected-note@-3 {{deducing return type for 'compare_incomplete_test'}} } namespace std { @@ -45,6 +46,7 @@ auto missing_member_test() { // expected-error@+1 {{standard library implementation of 'std::partial_ordering' is not supported; member 'equivalent' is missing}} return (1.0 <=> 1.0); + // expected-note@-3 {{deducing return type for 'missing_member_test'}} } namespace std { @@ -59,6 +61,7 @@ auto test_non_constexpr_var() { // expected-error@+1 {{standard library implementation of 'std::strong_ordering' is not supported; member 'equal' does not have expected form}} return (1 <=> 0); + // expected-note@-3 {{deducing return type for 'test_non_constexpr_var'}} } #else @@ -77,6 +80,7 @@ auto test_non_trivial(int LHS, int RHS) { // expected-error@+1 {{standard library implementation of 'std::strong_ordering' is not supported; the type is not trivially copyable}} return LHS <=> RHS; + // expected-note@-3 {{deducing return type for 'test_non_trivial'}} } #endif diff --git a/clang/test/SemaCXX/typo-correction-crash.cpp b/clang/test/SemaCXX/typo-correction-crash.cpp --- a/clang/test/SemaCXX/typo-correction-crash.cpp +++ b/clang/test/SemaCXX/typo-correction-crash.cpp @@ -2,6 +2,7 @@ auto check1() { return 1; return s; // expected-error {{use of undeclared identifier 's'}} + // expected-note@-3 {{deducing return type for 'check1'}} } int test = 11; // expected-note 2 {{'test' declared here}} @@ -9,6 +10,7 @@ return "s"; return tes; // expected-error {{use of undeclared identifier 'tes'; did you mean 'test'?}} // expected-error@-1 {{deduced as 'int' here but deduced as 'const char *' in earlier}} + // expected-note@-4 {{deducing return type for 'check2'}} } template struct is_same { static constexpr bool value = false; }; diff --git a/clang/test/SemaOpenCLCXX/template-astype.cl b/clang/test/SemaOpenCLCXX/template-astype.cl --- a/clang/test/SemaOpenCLCXX/template-astype.cl +++ b/clang/test/SemaOpenCLCXX/template-astype.cl @@ -11,6 +11,7 @@ auto neg_test_int(int x) { return templated_astype(x); } // expected-note@-1{{in instantiation of function template specialization 'templated_astype' requested here}} +// expected-note@-2{{deducing return type for 'neg_test_int'}} auto test_short4(short4 x) { return templated_astype(x); } diff --git a/clang/test/SemaTemplate/concepts.cpp b/clang/test/SemaTemplate/concepts.cpp --- a/clang/test/SemaTemplate/concepts.cpp +++ b/clang/test/SemaTemplate/concepts.cpp @@ -114,6 +114,7 @@ } template void g5() { ([]() -> C auto{ // expected-error-re {{deduced type {{.*}} does not satisfy}} + // expected-note@-1 {{deducing return type for 'operator()'}} return T(); }(), ...); } @@ -174,11 +175,17 @@ template concept C = false; // expected-note 6 {{because 'false' evaluated to false}} C auto f1() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f1'}} C auto f2() { return; } // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f2'}} C auto f3() {} // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f3'}} C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f4'}} C decltype(auto) f5() { return; } // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f5'}} C decltype(auto) f6() {} // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f6'}} void g() { f1();