Skip to content

Commit ae9d89d

Browse files
authored
[Clang][C++23] update constexpr diagnostics for missing return statements per P2448 (#94123)
Fixes #92583
1 parent a6129a5 commit ae9d89d

File tree

4 files changed

+33
-14
lines changed

4 files changed

+33
-14
lines changed

clang/lib/Sema/SemaDeclCXX.cpp

+24-12
Original file line numberDiff line numberDiff line change
@@ -1806,6 +1806,7 @@ static unsigned getRecordDiagFromTagKind(TagTypeKind Tag) {
18061806
static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
18071807
Stmt *Body,
18081808
Sema::CheckConstexprKind Kind);
1809+
static bool CheckConstexprMissingReturn(Sema &SemaRef, const FunctionDecl *Dcl);
18091810

18101811
// Check whether a function declaration satisfies the requirements of a
18111812
// constexpr function definition or a constexpr constructor definition. If so,
@@ -2411,20 +2412,9 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
24112412
}
24122413
} else {
24132414
if (ReturnStmts.empty()) {
2414-
// C++1y doesn't require constexpr functions to contain a 'return'
2415-
// statement. We still do, unless the return type might be void, because
2416-
// otherwise if there's no return statement, the function cannot
2417-
// be used in a core constant expression.
2418-
bool OK = SemaRef.getLangOpts().CPlusPlus14 &&
2419-
(Dcl->getReturnType()->isVoidType() ||
2420-
Dcl->getReturnType()->isDependentType());
24212415
switch (Kind) {
24222416
case Sema::CheckConstexprKind::Diagnose:
2423-
SemaRef.Diag(Dcl->getLocation(),
2424-
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
2425-
: diag::err_constexpr_body_no_return)
2426-
<< Dcl->isConsteval();
2427-
if (!OK)
2417+
if (!CheckConstexprMissingReturn(SemaRef, Dcl))
24282418
return false;
24292419
break;
24302420

@@ -2494,6 +2484,28 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
24942484
return true;
24952485
}
24962486

2487+
static bool CheckConstexprMissingReturn(Sema &SemaRef,
2488+
const FunctionDecl *Dcl) {
2489+
bool IsVoidOrDependentType = Dcl->getReturnType()->isVoidType() ||
2490+
Dcl->getReturnType()->isDependentType();
2491+
// Skip emitting a missing return error diagnostic for non-void functions
2492+
// since C++23 no longer mandates constexpr functions to yield constant
2493+
// expressions.
2494+
if (SemaRef.getLangOpts().CPlusPlus23 && !IsVoidOrDependentType)
2495+
return true;
2496+
2497+
// C++14 doesn't require constexpr functions to contain a 'return'
2498+
// statement. We still do, unless the return type might be void, because
2499+
// otherwise if there's no return statement, the function cannot
2500+
// be used in a core constant expression.
2501+
bool OK = SemaRef.getLangOpts().CPlusPlus14 && IsVoidOrDependentType;
2502+
SemaRef.Diag(Dcl->getLocation(),
2503+
OK ? diag::warn_cxx11_compat_constexpr_body_no_return
2504+
: diag::err_constexpr_body_no_return)
2505+
<< Dcl->isConsteval();
2506+
return OK;
2507+
}
2508+
24972509
bool Sema::CheckImmediateEscalatingFunctionDefinition(
24982510
FunctionDecl *FD, const sema::FunctionScopeInfo *FSI) {
24992511
if (!getLangOpts().CPlusPlus20 || !FD->isImmediateEscalating())

clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ constexpr int ClassDecl3() {
212212
return 0;
213213
}
214214

215-
constexpr int NoReturn() {} // expected-error {{no return statement in constexpr function}}
215+
constexpr int NoReturn() {} // beforecxx23-error {{no return statement in constexpr function}}
216216
constexpr int MultiReturn() {
217217
return 0; // beforecxx14-note {{return statement}}
218218
return 0; // beforecxx14-warning {{multiple return statements in constexpr function}}

clang/test/SemaCXX/constant-expression-cxx14.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ constexpr void k() {
8282

8383
// If the return type is not 'void', no return statements => never a constant
8484
// expression, so still diagnose that case.
85-
[[noreturn]] constexpr int fn() { // expected-error {{no return statement in constexpr function}}
85+
[[noreturn]] constexpr int fn() { // cxx14_20-error {{no return statement in constexpr function}}
8686
fn();
8787
}
8888

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
2+
3+
constexpr int f() { } // expected-warning {{non-void function does not return a value}}
4+
static_assert(__is_same(decltype([] constexpr -> int { }( )), int)); // expected-warning {{non-void lambda does not return a value}}
5+
6+
consteval int g() { } // expected-warning {{non-void function does not return a value}}
7+
static_assert(__is_same(decltype([] consteval -> int { }( )), int)); // expected-warning {{non-void lambda does not return a value}}

0 commit comments

Comments
 (0)