Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -4098,7 +4098,9 @@ } else if (!RetValExp && !HasDependentReturnType) { FunctionDecl *FD = getCurFunctionDecl(); - if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { + if ((FD && FD->isInvalidDecl()) || FnRetType->containsErrors()) { + // The intended return type might have been "void", so don't warn. + } else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { // C++11 [stmt.return]p2 Diag(ReturnLoc, diag::err_constexpr_return_missing_expr) << FD << FD->isConsteval(); Index: clang/test/SemaCXX/deduced-return-void.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/deduced-return-void.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s +// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s + +// Check that we don't get any extra warning for "return" without an +// expression, in a function that might have been intended to return +// void all along. +auto f1() { + return 1; + return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}} +} + +decltype(auto) f2() { + return 1; + return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}} +} + +auto *g() { + return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}} +} + +decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}} + return; +}