+2017-05-17 Marek Polacek <polacek@redhat.com>
+
+ * c-common.c (c_save_expr): Remove.
+ (c_common_truthvalue_conversion): Remove a call to c_save_expr.
+ * c-common.h (c_save_expr): Remove declaration.
+
2017-05-09 Volker Reichelt <v.reichelt@netcologne.de>
PR c/35441
return expr;
}
-/* Wrap a SAVE_EXPR around EXPR, if appropriate. Like save_expr, but
- for C folds the inside expression and wraps a C_MAYBE_CONST_EXPR
- around the SAVE_EXPR if needed so that c_fully_fold does not need
- to look inside SAVE_EXPRs. */
-
-tree
-c_save_expr (tree expr)
-{
- bool maybe_const = true;
- if (c_dialect_cxx ())
- return save_expr (expr);
- expr = c_fully_fold (expr, false, &maybe_const);
- expr = save_expr (expr);
- if (!maybe_const)
- expr = c_wrap_maybe_const (expr, true);
- return expr;
-}
-
/* Return whether EXPR is a declaration whose address can never be
NULL. */
if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
{
- tree t = (in_late_binary_op ? save_expr (expr) : c_save_expr (expr));
+ tree t = save_expr (expr);
expr = (build_binary_op
(EXPR_LOCATION (expr),
(TREE_SIDE_EFFECTS (expr)
extern bool decl_with_nonnull_addr_p (const_tree);
extern tree c_fully_fold (tree, bool, bool *);
extern tree c_wrap_maybe_const (tree, bool);
-extern tree c_save_expr (tree);
extern tree c_common_truthvalue_conversion (location_t, tree);
extern void c_apply_type_quals_to_decl (int, tree);
extern tree c_sizeof_or_alignof_type (location_t, tree, bool, bool, int);
+2017-05-17 Marek Polacek <polacek@redhat.com>
+
+ * c-convert.c (convert): Replace c_save_expr with save_expr. Don't
+ call c_fully_fold.
+ (convert) <case COMPLEX_TYPE>: Remove special handling of COMPLEX_TYPEs.
+ * c-decl.c (grokdeclarator): Replace c_save_expr with save_expr.
+ * c-fold.c (c_fully_fold_internal): Handle SAVE_EXPR.
+ * c-parser.c (c_parser_declaration_or_fndef): Replace c_save_expr with
+ save_expr.
+ (c_parser_conditional_expression): Likewise.
+ * c-tree.h (SAVE_EXPR_FOLDED_P): Define.
+ * c-typeck.c (build_modify_expr): Replace c_save_expr with save_expr.
+ (process_init_element): Likewise.
+ (build_binary_op): Likewise.
+ (handle_omp_array_sections_1): Likewise.
+
2017-05-12 Thomas Schwinge <thomas@codesourcery.com>
* c-parser.c (c_parser_omp_clause_num_gangs)
&& COMPLETE_TYPE_P (type)
&& do_ubsan_in_current_function ())
{
- if (in_late_binary_op)
- expr = save_expr (expr);
- else
- {
- expr = c_save_expr (expr);
- expr = c_fully_fold (expr, false, NULL);
- }
+ expr = save_expr (expr);
tree check = ubsan_instrument_float_cast (loc, type, expr);
expr = fold_build1 (FIX_TRUNC_EXPR, type, expr);
if (check == NULL_TREE)
goto maybe_fold;
case COMPLEX_TYPE:
- /* If converting from COMPLEX_TYPE to a different COMPLEX_TYPE
- and e is not COMPLEX_EXPR, convert_to_complex uses save_expr,
- but for the C FE c_save_expr needs to be called instead. */
- if (TREE_CODE (TREE_TYPE (e)) == COMPLEX_TYPE)
- {
- if (TREE_CODE (e) != COMPLEX_EXPR)
- {
- tree subtype = TREE_TYPE (type);
- tree elt_type = TREE_TYPE (TREE_TYPE (e));
-
- if (in_late_binary_op)
- e = save_expr (e);
- else
- e = c_save_expr (e);
- ret
- = fold_build2_loc (loc, COMPLEX_EXPR, type,
- convert (subtype,
- fold_build1 (REALPART_EXPR,
- elt_type, e)),
- convert (subtype,
- fold_build1 (IMAGPART_EXPR,
- elt_type, e)));
- goto maybe_fold;
- }
- }
ret = convert_to_complex (type, e);
goto maybe_fold;
&& do_ubsan_in_current_function ())
{
/* Evaluate the array size only once. */
- size = c_save_expr (size);
+ size = save_expr (size);
size = c_fully_fold (size, false, NULL);
size = fold_build2 (COMPOUND_EXPR, TREE_TYPE (size),
ubsan_instrument_vla (loc, size),
bool unused_p;
source_range old_range;
- /* Constants, declarations, statements, errors, SAVE_EXPRs and
- anything else not counted as an expression cannot usefully be
- folded further at this point. */
+ /* Constants, declarations, statements, errors, and anything else not
+ counted as an expression cannot usefully be folded further at this
+ point. */
if (!IS_EXPR_CODE_CLASS (kind)
- || kind == tcc_statement
- || code == SAVE_EXPR)
+ || kind == tcc_statement)
return expr;
if (IS_EXPR_CODE_CLASS (kind))
appropriate in any particular case. */
gcc_unreachable ();
+ case SAVE_EXPR:
+ /* Make sure to fold the contents of a SAVE_EXPR exactly once. */
+ if (!SAVE_EXPR_FOLDED_P (expr))
+ {
+ op0 = TREE_OPERAND (expr, 0);
+ op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
+ maybe_const_itself, for_int_const);
+ /* Don't wrap the folded tree in a SAVE_EXPR if we don't
+ have to. */
+ if (tree_invariant_p (op0))
+ ret = op0;
+ else
+ {
+ TREE_OPERAND (expr, 0) = op0;
+ SAVE_EXPR_FOLDED_P (expr) = true;
+ }
+ }
+ goto out;
+
default:
/* Various codes may appear through folding built-in functions
and their arguments. */
bool vm_type = variably_modified_type_p (init_type,
NULL_TREE);
if (vm_type)
- init.value = c_save_expr (init.value);
+ init.value = save_expr (init.value);
finish_init ();
specs->typespec_kind = ctsk_typeof;
specs->locations[cdw_typedef] = init_loc;
e = TREE_OPERAND (e, 1);
warn_for_omitted_condop (middle_loc, e);
/* Make sure first operand is calculated only once. */
- exp1.value = c_save_expr (default_conversion (cond.value));
+ exp1.value = save_expr (default_conversion (cond.value));
if (eptype)
exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
exp1.original_type = NULL;
subexpression meaning it is not a constant expression. */
#define CONSTRUCTOR_NON_CONST(EXPR) TREE_LANG_FLAG_1 (CONSTRUCTOR_CHECK (EXPR))
+/* For a SAVE_EXPR, nonzero if the operand of the SAVE_EXPR has already
+ been folded. */
+#define SAVE_EXPR_FOLDED_P(EXP) TREE_LANG_FLAG_1 (SAVE_EXPR_CHECK (EXP))
+
/* Record parser information about an expression that is irrelevant
for code generation alongside a tree representing its value. */
struct c_expr
that modify LHS. */
if (TREE_SIDE_EFFECTS (rhs))
{
- newrhs = in_late_binary_op ? save_expr (rhs) : c_save_expr (rhs);
+ newrhs = save_expr (rhs);
rhseval = newrhs;
}
newrhs = build_binary_op (location,
semantic_type = TREE_TYPE (value.value);
value.value = TREE_OPERAND (value.value, 0);
}
- value.value = c_save_expr (value.value);
+ value.value = save_expr (value.value);
if (semantic_type)
value.value = build1 (EXCESS_PRECISION_EXPR, semantic_type,
value.value);
return error_mark_node;
if (first_complex)
{
- op0 = c_save_expr (op0);
+ op0 = save_expr (op0);
real = build_unary_op (EXPR_LOCATION (orig_op0), REALPART_EXPR,
op0, true);
imag = build_unary_op (EXPR_LOCATION (orig_op0), IMAGPART_EXPR,
{
case MULT_EXPR:
case TRUNC_DIV_EXPR:
- op1 = c_save_expr (op1);
+ op1 = save_expr (op1);
imag = build2 (resultcode, real_type, imag, op1);
/* Fall through. */
case PLUS_EXPR:
}
else
{
- op1 = c_save_expr (op1);
+ op1 = save_expr (op1);
real = build_unary_op (EXPR_LOCATION (orig_op1), REALPART_EXPR,
op1, true);
imag = build_unary_op (EXPR_LOCATION (orig_op1), IMAGPART_EXPR,
switch (code)
{
case MULT_EXPR:
- op0 = c_save_expr (op0);
+ op0 = save_expr (op0);
imag = build2 (resultcode, real_type, op0, imag);
/* Fall through. */
case PLUS_EXPR:
&& !require_constant_value)
{
/* OP0 and/or OP1 might have side-effects. */
- op0 = c_save_expr (op0);
- op1 = c_save_expr (op1);
+ op0 = save_expr (op0);
+ op1 = save_expr (op1);
op0 = c_fully_fold (op0, false, NULL);
op1 = c_fully_fold (op1, false, NULL);
if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE
/* For [lb:] we will need to evaluate lb more than once. */
if (length == NULL_TREE && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
{
- tree lb = c_save_expr (low_bound);
+ tree lb = save_expr (low_bound);
if (lb != low_bound)
{
TREE_PURPOSE (t) = lb;
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND)
types.safe_push (TREE_TYPE (ret));
/* We will need to evaluate lb more than once. */
- tree lb = c_save_expr (low_bound);
+ tree lb = save_expr (low_bound);
if (lb != low_bound)
{
TREE_PURPOSE (t) = lb;