aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-06-11 15:50:34 +0200
committerJakub Jelinek <jakub@redhat.com>2021-06-11 15:52:23 +0200
commit117c64266405e244da4dae3ae7b60905af63b955 (patch)
tree54db8563f16d0bb55f7d4b90929984386071d3ef /gcc/cp/decl.c
parent9d20ec97475b1102d6ca005ad165056d34615a3d (diff)
downloadgcc-117c64266405e244da4dae3ae7b60905af63b955.zip
gcc-117c64266405e244da4dae3ae7b60905af63b955.tar.gz
gcc-117c64266405e244da4dae3ae7b60905af63b955.tar.bz2
c++: Add C++23 consteval if support - P1938R3 [PR100974]
The following patch implements consteval if support. There is a new IF_STMT_CONSTEVAL_P flag on IF_STMT and IF_COND is boolean_false_node to match the non-manifestly constant evaluation behavior, while constexpr evaluation special-cases it. Perhaps cleaner would be to set the condition to __builtin_is_constant_evaluated () call but we need the IF_STMT_CONSTEVAL_P flag anyway and the IL would be larger. And I'm not changing the libstdc++ side, where perhaps we could change std::is_constant_evaluated definition for #ifdef __cpp_if_consteval case to if consteval { return true; } else { return false; } but we need to keep it defined to __builtin_is_constant_evaluated () for C++20 or older. 2021-06-11 Jakub Jelinek <jakub@redhat.com> PR c++/100974 gcc/c-family/ * c-cppbuiltin.c (c_cpp_builtins): Predefine __cpp_if_consteval for -std=c++2b for P1938R3 consteval if support. gcc/cp/ * cp-tree.h (struct saved_scope): Add consteval_if_p member. Formatting fix for the discarded_stmt comment. (in_consteval_if_p, IF_STMT_CONSTEVAL_P): Define. * parser.c (cp_parser_lambda_expression): Temporarily disable in_consteval_if_p when parsing lambda body. (cp_parser_selection_statement): Parse consteval if. * decl.c (struct named_label_entry): Add in_consteval_if member. (level_for_consteval_if): New function. (poplevel_named_label_1, check_previous_goto_1, check_goto): Handle consteval if. * constexpr.c (cxx_eval_builtin_function_call): Clarify in comment why CP_BUILT_IN_IS_CONSTANT_EVALUATED needs to *non_constant_p for !ctx->manifestly_const_eval. (cxx_eval_conditional_expression): For IF_STMT_CONSTEVAL_P evaluate condition as if it was __builtin_is_constant_evaluated call. (potential_constant_expression_1): For IF_STMT_CONSTEVAL_P always recurse on both branches. * cp-gimplify.c (genericize_if_stmt): Genericize IF_STMT_CONSTEVAL_P as the else branch. * pt.c (tsubst_expr) <case IF_STMT>: Copy IF_STMT_CONSTEVAL_P. Temporarily set in_consteval_if_p when recursing on IF_STMT_CONSTEVAL_P then branch. (tsubst_lambda_expr): Temporarily disable in_consteval_if_p when instantiating lambda body. * call.c (immediate_invocation_p): Return false when in_consteval_if_p. gcc/testsuite/ * g++.dg/cpp23/consteval-if1.C: New test. * g++.dg/cpp23/consteval-if2.C: New test. * g++.dg/cpp23/consteval-if3.C: New test. * g++.dg/cpp23/consteval-if4.C: New test. * g++.dg/cpp23/consteval-if5.C: New test. * g++.dg/cpp23/consteval-if6.C: New test. * g++.dg/cpp23/consteval-if7.C: New test. * g++.dg/cpp23/consteval-if8.C: New test. * g++.dg/cpp23/consteval-if9.C: New test. * g++.dg/cpp23/consteval-if10.C: New test. * g++.dg/cpp23/feat-cxx2b.C: Add __cpp_if_consteval tests.
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r--gcc/cp/decl.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index cbf647d..da254d8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -222,6 +222,7 @@ struct GTY((for_user)) named_label_entry {
bool in_omp_scope;
bool in_transaction_scope;
bool in_constexpr_if;
+ bool in_consteval_if;
};
#define named_labels cp_function_chain->x_named_labels
@@ -491,6 +492,16 @@ level_for_constexpr_if (cp_binding_level *b)
&& IF_STMT_CONSTEXPR_P (b->this_entity));
}
+/* True if B is the level for the condition of a consteval if. */
+
+static bool
+level_for_consteval_if (cp_binding_level *b)
+{
+ return (b->kind == sk_cond && b->this_entity
+ && TREE_CODE (b->this_entity) == IF_STMT
+ && IF_STMT_CONSTEVAL_P (b->this_entity));
+}
+
/* Update data for defined and undefined labels when leaving a scope. */
int
@@ -530,6 +541,8 @@ poplevel_named_label_1 (named_label_entry **slot, cp_binding_level *bl)
case sk_block:
if (level_for_constexpr_if (bl->level_chain))
ent->in_constexpr_if = true;
+ else if (level_for_consteval_if (bl->level_chain))
+ ent->in_consteval_if = true;
break;
default:
break;
@@ -3391,6 +3404,7 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
bool complained = false;
int identified = 0;
bool saw_eh = false, saw_omp = false, saw_tm = false, saw_cxif = false;
+ bool saw_ceif = false;
if (exited_omp)
{
@@ -3470,6 +3484,12 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
loc = EXPR_LOCATION (b->level_chain->this_entity);
saw_cxif = true;
}
+ else if (!saw_ceif && level_for_consteval_if (b->level_chain))
+ {
+ inf = G_(" enters %<consteval if%> statement");
+ loc = EXPR_LOCATION (b->level_chain->this_entity);
+ saw_ceif = true;
+ }
break;
default:
@@ -3551,12 +3571,13 @@ check_goto (tree decl)
unsigned ix;
if (ent->in_try_scope || ent->in_catch_scope || ent->in_transaction_scope
- || ent->in_constexpr_if
+ || ent->in_constexpr_if || ent->in_consteval_if
|| ent->in_omp_scope || !vec_safe_is_empty (ent->bad_decls))
{
diagnostic_t diag_kind = DK_PERMERROR;
if (ent->in_try_scope || ent->in_catch_scope || ent->in_constexpr_if
- || ent->in_transaction_scope || ent->in_omp_scope)
+ || ent->in_consteval_if || ent->in_transaction_scope
+ || ent->in_omp_scope)
diag_kind = DK_ERROR;
complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl),
&input_location, diag_kind);
@@ -3602,6 +3623,8 @@ check_goto (tree decl)
inform (input_location, " enters synchronized or atomic statement");
else if (ent->in_constexpr_if)
inform (input_location, " enters %<constexpr if%> statement");
+ else if (ent->in_consteval_if)
+ inform (input_location, " enters %<consteval if%> statement");
}
if (ent->in_omp_scope)