diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 20 | ||||
-rw-r--r-- | clang/test/SemaCXX/constant-expression-cxx11.cpp | 5 |
3 files changed, 23 insertions, 4 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index ec0c3f8f4ff..48fdf6f826e 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1875,6 +1875,8 @@ def err_enable_if_never_constant_expr : Error< "'enable_if' attribute expression never produces a constant expression">; def err_constexpr_body_no_return : Error< "no return statement in constexpr function">; +def err_constexpr_return_missing_expr : Error< + "non-void constexpr function %0 should return a value">; def warn_cxx11_compat_constexpr_body_no_return : Warning< "constexpr function with no return statements is incompatible with C++ " "standards before C++14">, InGroup<CXXPre14Compat>, DefaultIgnore; diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 78e33c3bf8c..8f6c5c6fe34 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -3039,14 +3039,26 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { Result = new (Context) ReturnStmt(ReturnLoc, RetValExp, nullptr); } else if (!RetValExp && !HasDependentReturnType) { - unsigned DiagID = diag::warn_return_missing_expr; // C90 6.6.6.4p4 - // C99 6.8.6.4p1 (ext_ since GCC warns) - if (getLangOpts().C99) DiagID = diag::ext_return_missing_expr; + FunctionDecl *FD = getCurFunctionDecl(); - if (FunctionDecl *FD = getCurFunctionDecl()) + unsigned DiagID; + if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) { + // C++11 [stmt.return]p2 + DiagID = diag::err_constexpr_return_missing_expr; + FD->setInvalidDecl(); + } else if (getLangOpts().C99) { + // C99 6.8.6.4p1 (ext_ since GCC warns) + DiagID = diag::ext_return_missing_expr; + } else { + // C90 6.6.6.4p4 + DiagID = diag::warn_return_missing_expr; + } + + if (FD) Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/; else Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; + Result = new (Context) ReturnStmt(ReturnLoc); } else { assert(RetValExp || HasDependentReturnType); diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp index 5fb6f2c5f81..cf317950c77 100644 --- a/clang/test/SemaCXX/constant-expression-cxx11.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp @@ -1969,3 +1969,8 @@ namespace PR21786 { static_assert(&Bar::x != nullptr, ""); static_assert(&Bar::x != &Bar::y, ""); // expected-error {{constant expression}} } + +namespace PR21859 { + constexpr int Fun() { return; } // expected-error {{non-void constexpr function 'Fun' should return a value}} + constexpr int Var = Fun(); // expected-error {{constexpr variable 'Var' must be initialized by a constant expression}} +} |