Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2473,6 +2473,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< Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -8856,7 +8856,10 @@ /// Memoization means we are _not_ instantiating a template because /// it is already instantiated (but we entered a context where we /// would have had to if it was not already instantiated). - Memoization + Memoization, + + /// We are deducing a function return type from its return statement. + ReturnTypeDeduction, } Kind; /// Was the enclosing context a non-instantiation SFINAE context? Index: clang/lib/Frontend/FrontendActions.cpp =================================================================== --- clang/lib/Frontend/FrontendActions.cpp +++ clang/lib/Frontend/FrontendActions.cpp @@ -465,6 +465,8 @@ return "InitializingStructuredBinding"; case CodeSynthesisContext::MarkingClassDllexported: return "MarkingClassDllexported"; + case CodeSynthesisContext::ReturnTypeDeduction: + return "ReturnTypeDeduction"; } return ""; } Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -3757,6 +3757,24 @@ .getReturnLoc(); } +namespace { +struct DeducingReturnType { + Sema &S; + explicit DeducingReturnType(Sema& S, TypeLoc OrigResultType, FunctionDecl *FD) + : S(S) { + Sema::CodeSynthesisContext Ctx; + Ctx.Kind = Sema::CodeSynthesisContext::ReturnTypeDeduction; + Ctx.PointOfInstantiation = OrigResultType.getBeginLoc(); + Ctx.Entity = FD; + Ctx.InstantiationRange = OrigResultType.getSourceRange(); + S.pushCodeSynthesisContext(Ctx); + } + ~DeducingReturnType() { + S.popCodeSynthesisContext(); + } +}; +} // namespace + /// Deduce the return type for a function from a returned expression, per /// C++1y [dcl.spec.auto]p6. bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, @@ -3770,6 +3788,7 @@ return false; TypeLoc OrigResultType = getReturnTypeLoc(FD); + DeducingReturnType DRT(*this, OrigResultType, FD); QualType Deduced; if (RetExpr && isa(RetExpr)) { Index: clang/lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiate.cpp +++ clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -213,6 +213,7 @@ case RewritingOperatorAsSpaceship: case InitializingStructuredBinding: case MarkingClassDllexported: + case ReturnTypeDeduction: return false; // This function should never be called when Kind's value is Memoization. @@ -773,6 +774,17 @@ case CodeSynthesisContext::Memoization: break; + case CodeSynthesisContext::ReturnTypeDeduction: + // PointOfInstantiation and InstantiationRange both point at the AutoType + // in the function declaration. If this is a lambda with an implied 'auto', + // there is no source location for that AutoType, so we shouldn't emit + // the note. + if (Active->PointOfInstantiation.isValid()) + Diags.Report(Active->PointOfInstantiation, + diag::note_deducing_return_type_for) + << cast(Active->Entity) << Active->InstantiationRange; + break; + case CodeSynthesisContext::ConstraintsCheck: { unsigned DiagID = 0; if (!Active->Entity) { @@ -847,6 +859,7 @@ case CodeSynthesisContext::ParameterMappingSubstitution: case CodeSynthesisContext::ConstraintNormalization: case CodeSynthesisContext::NestedRequirementConstraintsCheck: + case CodeSynthesisContext::ReturnTypeDeduction: // This is a template instantiation, so there is no SFINAE. return None; Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2-1z.cpp =================================================================== --- clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2-1z.cpp +++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2-1z.cpp @@ -26,6 +26,7 @@ return 7.6; else return 5; // expected-error {{deduced as 'int' here but deduced as 'const char *' in earlier}} + // expected-note@-9 {{deducing return type for 'c'}} } template auto d() { Index: clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp =================================================================== --- clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp +++ clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp @@ -97,4 +97,6 @@ using Int = decltype(f5da(0)); auto init_list_1() { return { 1, 2, 3 }; } // expected-error {{cannot deduce return type from initializer list}} + // expected-note@-1 {{deducing return type for 'init_list_1'}} decltype(auto) init_list_2() { return { 1, 2, 3 }; } // expected-error {{cannot deduce return type from initializer list}} + // expected-note@-1 {{deducing return type for 'init_list_2'}} Index: clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp =================================================================== --- clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp +++ clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp @@ -20,6 +20,7 @@ } Large auto test1() { // expected-error{{deduced type 'char' does not satisfy 'Large'}} + // expected-note@-1{{deducing return type for 'test1'}} Large auto i = 'a'; // expected-error@-1{{deduced type 'char' does not satisfy 'Large'}} Large auto j = 10; @@ -36,6 +37,7 @@ ::Large auto test2() { return 10; } LargerThan<4> auto test3() { return 10; } // expected-error@-1{{deduced type 'int' does not satisfy 'LargerThan<4>'}} +// expected-note@-2{{deducing return type for 'test3'}} ::LargerThan<2> auto test4() { return 10; } Large auto test5() -> void; Index: clang/test/SemaCUDA/autoret-global.cu =================================================================== --- clang/test/SemaCUDA/autoret-global.cu +++ clang/test/SemaCUDA/autoret-global.cu @@ -19,6 +19,7 @@ __global__ auto f2(int x) { return x + 1; // expected-error@-2 {{kernel function type 'auto (int)' must have void return type}} + // expected-note@-3 {{deducing return type for 'f2'}} } template struct enable_if { typedef T type; }; Index: clang/test/SemaCXX/cxx2b-consteval-if.cpp =================================================================== --- clang/test/SemaCXX/cxx2b-consteval-if.cpp +++ 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() { @@ -24,6 +26,7 @@ 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'}} } } Index: clang/test/SemaCXX/deduced-return-type-cxx14.cpp =================================================================== --- clang/test/SemaCXX/deduced-return-type-cxx14.cpp +++ 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() { @@ -90,6 +91,7 @@ auto init_list() { return { 1, 2, 3 }; // expected-error {{cannot deduce return type from initializer list}} + // expected-note@-2 {{deducing return type for 'init_list'}} } auto fwd_decl(); // expected-note 2{{here}} @@ -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 { Index: clang/test/SemaCXX/deduced-return-void.cpp =================================================================== --- clang/test/SemaCXX/deduced-return-void.cpp +++ 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(); }; Index: clang/test/SemaCXX/typo-correction-crash.cpp =================================================================== --- clang/test/SemaCXX/typo-correction-crash.cpp +++ clang/test/SemaCXX/typo-correction-crash.cpp @@ -9,6 +9,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; }; Index: clang/test/SemaTemplate/concepts.cpp =================================================================== --- clang/test/SemaTemplate/concepts.cpp +++ 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,26 +175,34 @@ template concept C = false; // expected-note 6 {{because 'false' evaluated to false}} C auto f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f1'}} return void(); } C auto f2() { // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f2'}} return; } C auto f3() { // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f3'}} } C decltype(auto) f4() { // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f4'}} return void(); } C decltype(auto) f5() { // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f5'}} return; } C decltype(auto) f6() { // expected-error {{deduced type 'void' does not satisfy 'C'}} + // expected-note@-1 {{deducing return type for 'f6'}} } C auto& f7() { // expected-error {{cannot form a reference to 'void'}} + // expected-note@-1 {{deducing return type for 'f7'}} return void(); } C auto& f8() { return; // expected-error {{cannot deduce return type 'C auto &' from omitted return expression}} + // expected-note@-2 {{deducing return type for 'f8'}} } C auto& f9() { // expected-error {{cannot deduce return type 'C auto &' for function with no return statements}} }