Commit 56632b27 by Jason Merrill Committed by Jason Merrill

Handle C++14 constexpr flow control.

	* constexpr.c (cxx_eval_loop_expr, cxx_eval_switch_expr): New.
	(cxx_eval_statement_list): New.
	(cxx_eval_constant_expression): Handle LABEL_EXPR,
	CASE_LABEL_EXPR, GOTO_EXPR, LOOP_EXPR, SWITCH_EXPR.  Handle jump
	semantics of RETURN_EXPR.
	(many functions): Add jump_target parameter.
	(returns, breaks, continues, switches, label_matches): New.
	* cp-tree.h (LABEL_DECL_BREAK, LABEL_DECL_CONTINUE): New.
	* cp-gimplify.c (begin_bc_block): Set them.

From-SVN: r217670
parent 27d93d2c
2014-11-17 Jason Merrill <jason@redhat.com> 2014-11-17 Jason Merrill <jason@redhat.com>
Handle C++14 constexpr flow control.
* constexpr.c (cxx_eval_loop_expr, cxx_eval_switch_expr): New.
(cxx_eval_statement_list): New.
(cxx_eval_constant_expression): Handle LABEL_EXPR,
CASE_LABEL_EXPR, GOTO_EXPR, LOOP_EXPR, SWITCH_EXPR. Handle jump
semantics of RETURN_EXPR.
(many functions): Add jump_target parameter.
(returns, breaks, continues, switches, label_matches): New.
* cp-tree.h (LABEL_DECL_BREAK, LABEL_DECL_CONTINUE): New.
* cp-gimplify.c (begin_bc_block): Set them.
* cp-gimplify.c (genericize_cp_loop): Use LOOP_EXPR. * cp-gimplify.c (genericize_cp_loop): Use LOOP_EXPR.
(genericize_for_stmt): Handle null statement-list. (genericize_for_stmt): Handle null statement-list.
......
...@@ -74,6 +74,10 @@ begin_bc_block (enum bc_t bc, location_t location) ...@@ -74,6 +74,10 @@ begin_bc_block (enum bc_t bc, location_t location)
tree label = create_artificial_label (location); tree label = create_artificial_label (location);
DECL_CHAIN (label) = bc_label[bc]; DECL_CHAIN (label) = bc_label[bc];
bc_label[bc] = label; bc_label[bc] = label;
if (bc == bc_break)
LABEL_DECL_BREAK (label) = true;
else
LABEL_DECL_CONTINUE (label) = true;
return label; return label;
} }
......
...@@ -148,12 +148,14 @@ c-common.h, not after. ...@@ -148,12 +148,14 @@ c-common.h, not after.
DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL) DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL)
DECL_MUTABLE_P (in FIELD_DECL) DECL_MUTABLE_P (in FIELD_DECL)
DECL_DEPENDENT_P (in USING_DECL) DECL_DEPENDENT_P (in USING_DECL)
LABEL_DECL_BREAK (in LABEL_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL). 1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL) DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL) DECL_MEMBER_TEMPLATE_P (in TEMPLATE_DECL)
USING_DECL_TYPENAME_P (in USING_DECL) USING_DECL_TYPENAME_P (in USING_DECL)
DECL_VLA_CAPTURE_P (in FIELD_DECL) DECL_VLA_CAPTURE_P (in FIELD_DECL)
DECL_ARRAY_PARAMETER_P (in PARM_DECL) DECL_ARRAY_PARAMETER_P (in PARM_DECL)
LABEL_DECL_CONTINUE (in LABEL_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL). 2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL) DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P. 3: DECL_IN_AGGR_P.
...@@ -3243,6 +3245,14 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -3243,6 +3245,14 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define DECL_LOCAL_FUNCTION_P(NODE) \ #define DECL_LOCAL_FUNCTION_P(NODE) \
DECL_LANG_FLAG_0 (FUNCTION_DECL_CHECK (NODE)) DECL_LANG_FLAG_0 (FUNCTION_DECL_CHECK (NODE))
/* Nonzero if NODE is the target for genericization of 'break' stmts. */
#define LABEL_DECL_BREAK(NODE) \
DECL_LANG_FLAG_0 (LABEL_DECL_CHECK (NODE))
/* Nonzero if NODE is the target for genericization of 'continue' stmts. */
#define LABEL_DECL_CONTINUE(NODE) \
DECL_LANG_FLAG_1 (LABEL_DECL_CHECK (NODE))
/* True if NODE was declared with auto in its return type, but it has /* True if NODE was declared with auto in its return type, but it has
started compilation and so the return type might have been changed by started compilation and so the return type might have been changed by
return type deduction; its declared return type should be found in return type deduction; its declared return type should be found in
......
// { dg-do compile { target c++14 } }
constexpr int f (int i)
{
int j = 0;
for (; i > 0; --i)
++j;
return j;
}
constexpr int i = f(42);
#define SA(X) static_assert((X),#X)
SA(i==42);
// { dg-do compile { target c++14 } }
constexpr int f (int i)
{
return 24;
return 36;
}
constexpr int i = f(42);
#define SA(X) static_assert((X),#X)
SA(i==24);
// { dg-do compile { target c++14 } }
constexpr int f (int i)
{
}
constexpr int i = f(42); // { dg-error "flows off the end" }
// { dg-do compile { target c++14 } }
constexpr int f (int i)
{
switch (i)
{
case 1:
return 42;
default:
return 0;
}
}
constexpr int i = f(1);
#define SA(X) static_assert((X),#X)
SA(i==42);
// { dg-do compile { target c++14 } }
constexpr int f (int i)
{
int j = 0;
switch (i)
{
case 1:
j = 42;
break;
default:
j = 24;
break;
}
return j;
}
constexpr int i = f(1);
#define SA(X) static_assert((X),#X)
SA(i==42);
// { dg-do compile { target c++14 } }
constexpr int f (int i)
{
int j = 0;
switch (i)
{
case 1:
j = 42;
break;
default:
j = 24;
break;
}
return j;
}
constexpr int i = f(2);
#define SA(X) static_assert((X),#X)
SA(i==24);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment