diff options
author | David Majnemer <david.majnemer@gmail.com> | 2014-12-13 08:12:56 +0000 |
---|---|---|
committer | David Majnemer <david.majnemer@gmail.com> | 2014-12-13 08:12:56 +0000 |
commit | 7fad38e6551160d87715ad126690292ce19ce5ae (patch) | |
tree | 3784c5bc1c9fd1e9accbe0b1dda13b317bdb5181 /lib/Sema/SemaStmt.cpp | |
parent | 73b2922fda06a728375de48a43e3292baad0daa6 (diff) |
Sema: Constexpr functions must have return statements which have an expr
clang lets programmers be pretty cavalier when it comes to void return
statements in functions which have non-void return types. However, we
cannot be so forgiving in constexpr functions: evaluation will go off
the rails very quickly.
Instead, keep the return statement in the AST but mark the function as
invalid. Doing so gives us nice diagnostics while making constexpr
evaluation halt.
This fixes PR21859.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@224189 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaStmt.cpp')
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 78e33c3bf8..8f6c5c6fe3 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/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); |