[clang] ae9d89d - [Clang][C++23] update constexpr diagnostics for missing return statements per P2448 (#94123)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 10 02:59:00 PDT 2024
Author: Oleksandr T
Date: 2024-06-10T11:58:56+02:00
New Revision: ae9d89d53e64bad514171c99f16d553febfbac12
URL: https://github.com/llvm/llvm-project/commit/ae9d89d53e64bad514171c99f16d553febfbac12
DIFF: https://github.com/llvm/llvm-project/commit/ae9d89d53e64bad514171c99f16d553febfbac12.diff
LOG: [Clang][C++23] update constexpr diagnostics for missing return statements per P2448 (#94123)
Fixes #92583
Added:
clang/test/SemaCXX/constexpr-return-non-void-cxx2b.cpp
Modified:
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
clang/test/SemaCXX/constant-expression-cxx14.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index e224e79fdb8ea..37f0df2a6a27d 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1806,6 +1806,7 @@ static unsigned getRecordDiagFromTagKind(TagTypeKind Tag) {
static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
Stmt *Body,
Sema::CheckConstexprKind Kind);
+static bool CheckConstexprMissingReturn(Sema &SemaRef, const FunctionDecl *Dcl);
// Check whether a function declaration satisfies the requirements of a
// constexpr function definition or a constexpr constructor definition. If so,
@@ -2411,20 +2412,9 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
}
} else {
if (ReturnStmts.empty()) {
- // C++1y doesn't require constexpr functions to contain a 'return'
- // statement. We still do, unless the return type might be void, because
- // otherwise if there's no return statement, the function cannot
- // be used in a core constant expression.
- bool OK = SemaRef.getLangOpts().CPlusPlus14 &&
- (Dcl->getReturnType()->isVoidType() ||
- Dcl->getReturnType()->isDependentType());
switch (Kind) {
case Sema::CheckConstexprKind::Diagnose:
- SemaRef.Diag(Dcl->getLocation(),
- OK ? diag::warn_cxx11_compat_constexpr_body_no_return
- : diag::err_constexpr_body_no_return)
- << Dcl->isConsteval();
- if (!OK)
+ if (!CheckConstexprMissingReturn(SemaRef, Dcl))
return false;
break;
@@ -2494,6 +2484,28 @@ static bool CheckConstexprFunctionBody(Sema &SemaRef, const FunctionDecl *Dcl,
return true;
}
+static bool CheckConstexprMissingReturn(Sema &SemaRef,
+ const FunctionDecl *Dcl) {
+ bool IsVoidOrDependentType = Dcl->getReturnType()->isVoidType() ||
+ Dcl->getReturnType()->isDependentType();
+ // Skip emitting a missing return error diagnostic for non-void functions
+ // since C++23 no longer mandates constexpr functions to yield constant
+ // expressions.
+ if (SemaRef.getLangOpts().CPlusPlus23 && !IsVoidOrDependentType)
+ return true;
+
+ // C++14 doesn't require constexpr functions to contain a 'return'
+ // statement. We still do, unless the return type might be void, because
+ // otherwise if there's no return statement, the function cannot
+ // be used in a core constant expression.
+ bool OK = SemaRef.getLangOpts().CPlusPlus14 && IsVoidOrDependentType;
+ SemaRef.Diag(Dcl->getLocation(),
+ OK ? diag::warn_cxx11_compat_constexpr_body_no_return
+ : diag::err_constexpr_body_no_return)
+ << Dcl->isConsteval();
+ return OK;
+}
+
bool Sema::CheckImmediateEscalatingFunctionDefinition(
FunctionDecl *FD, const sema::FunctionScopeInfo *FSI) {
if (!getLangOpts().CPlusPlus20 || !FD->isImmediateEscalating())
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
index 4416c82522649..51990ee4341d2 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp
@@ -212,7 +212,7 @@ constexpr int ClassDecl3() {
return 0;
}
-constexpr int NoReturn() {} // expected-error {{no return statement in constexpr function}}
+constexpr int NoReturn() {} // beforecxx23-error {{no return statement in constexpr function}}
constexpr int MultiReturn() {
return 0; // beforecxx14-note {{return statement}}
return 0; // beforecxx14-warning {{multiple return statements in constexpr function}}
diff --git a/clang/test/SemaCXX/constant-expression-cxx14.cpp b/clang/test/SemaCXX/constant-expression-cxx14.cpp
index 80a7a2dd31531..70ab5dcd357c1 100644
--- a/clang/test/SemaCXX/constant-expression-cxx14.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx14.cpp
@@ -82,7 +82,7 @@ constexpr void k() {
// If the return type is not 'void', no return statements => never a constant
// expression, so still diagnose that case.
-[[noreturn]] constexpr int fn() { // expected-error {{no return statement in constexpr function}}
+[[noreturn]] constexpr int fn() { // cxx14_20-error {{no return statement in constexpr function}}
fn();
}
diff --git a/clang/test/SemaCXX/constexpr-return-non-void-cxx2b.cpp b/clang/test/SemaCXX/constexpr-return-non-void-cxx2b.cpp
new file mode 100644
index 0000000000000..25d1f8df7f716
--- /dev/null
+++ b/clang/test/SemaCXX/constexpr-return-non-void-cxx2b.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
+
+constexpr int f() { } // expected-warning {{non-void function does not return a value}}
+static_assert(__is_same(decltype([] constexpr -> int { }( )), int)); // expected-warning {{non-void lambda does not return a value}}
+
+consteval int g() { } // expected-warning {{non-void function does not return a value}}
+static_assert(__is_same(decltype([] consteval -> int { }( )), int)); // expected-warning {{non-void lambda does not return a value}}
More information about the cfe-commits
mailing list