aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorCorentin Jabot <corentinjabot@gmail.com>2021-10-05 23:33:31 +0200
committerCorentin Jabot <corentinjabot@gmail.com>2022-03-22 19:51:19 +0100
commit683e83c56f98df6fe42d506a04dda44309ca758f (patch)
tree425747d6753617f8a8f10b6df4de06805135143b /clang/lib/AST/ExprConstant.cpp
parentbafbae238aa1948aa511c734a613a95d89a72546 (diff)
downloadllvm-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.cpp17
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())