diff options
author | Corentin Jabot <corentinjabot@gmail.com> | 2021-10-05 23:33:31 +0200 |
---|---|---|
committer | Corentin Jabot <corentinjabot@gmail.com> | 2022-03-22 19:51:19 +0100 |
commit | 683e83c56f98df6fe42d506a04dda44309ca758f (patch) | |
tree | 425747d6753617f8a8f10b6df4de06805135143b /clang/lib/AST/ExprConstant.cpp | |
parent | bafbae238aa1948aa511c734a613a95d89a72546 (diff) | |
download | llvm-683e83c56f98df6fe42d506a04dda44309ca758f.zip llvm-683e83c56f98df6fe42d506a04dda44309ca758f.tar.gz llvm-683e83c56f98df6fe42d506a04dda44309ca758f.tar.bz2 |
[Clang][C++2b] P2242R3: Non-literal variables [...] in constexpr
Allow goto, labelled statements as well as `static`, `thread_local`, and
non-literal variables in `constexpr` functions.
As specified. for all of the above (except labelled statements) constant
evaluation of the construct still fails.
For `constexpr` bodies, the proposal is implemented with diagnostics as
a language extension in older language modes. For determination of
whether a lambda body satisfies the requirements for a constexpr
function, the proposal is implemented only in C++2b mode to retain the
semantics of older modes for programs conforming to them.
Reviewed By: aaron.ballman, hubert.reinterpretcast, erichkeane
Differential Revision: https://reviews.llvm.org/D111400
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 99f136a..78f7592 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -5003,6 +5003,18 @@ static EvalStmtResult EvaluateSwitch(StmtResult &Result, EvalInfo &Info, llvm_unreachable("Invalid EvalStmtResult!"); } +static bool CheckLocalVariableDeclaration(EvalInfo &Info, const VarDecl *VD) { + // An expression E is a core constant expression unless the evaluation of E + // would evaluate one of the following: [C++2b] - a control flow that passes + // through a declaration of a variable with static or thread storage duration. + if (VD->isLocalVarDecl() && VD->isStaticLocal()) { + Info.CCEDiag(VD->getLocation(), diag::note_constexpr_static_local) + << (VD->getTSCSpec() == TSCS_unspecified ? 0 : 1) << VD; + return false; + } + return true; +} + // Evaluate a statement. static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const Stmt *S, const SwitchCase *Case) { @@ -5113,6 +5125,8 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, const DeclStmt *DS = cast<DeclStmt>(S); for (const auto *D : DS->decls()) { if (const auto *VD = dyn_cast<VarDecl>(D)) { + if (!CheckLocalVariableDeclaration(Info, VD)) + return ESR_Failed; if (VD->hasLocalStorage() && !VD->getInit()) if (!EvaluateVarDecl(Info, VD)) return ESR_Failed; @@ -5156,6 +5170,9 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info, case Stmt::DeclStmtClass: { const DeclStmt *DS = cast<DeclStmt>(S); for (const auto *D : DS->decls()) { + const VarDecl *VD = dyn_cast_or_null<VarDecl>(D); + if (VD && !CheckLocalVariableDeclaration(Info, VD)) + return ESR_Failed; // Each declaration initialization is its own full-expression. FullExpressionRAII Scope(Info); if (!EvaluateDecl(Info, D) && !Info.noteFailure()) |