/* Fold a constant sub-tree into a single node for C-compiler
- Copyright (C) 1987-2018 Free Software Foundation, Inc.
+ Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GCC.
return fold_convert_loc (loc, type, tem);
}
-/* Like fold_negate_expr, but return a NEGATE_EXPR tree, if T can not be
+/* Like fold_negate_expr, but return a NEGATE_EXPR tree, if T cannot be
negated in a simpler way. Also allow for T to be NULL_TREE, in which case
return NULL_TREE. */
/* And some specific cases even faster than that. */
if (code == PLUS_EXPR)
{
- if (integer_zerop (arg0) && !TREE_OVERFLOW (arg0))
+ if (integer_zerop (arg0)
+ && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg0)))
return arg1;
- if (integer_zerop (arg1) && !TREE_OVERFLOW (arg1))
+ if (integer_zerop (arg1)
+ && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg1)))
return arg0;
}
else if (code == MINUS_EXPR)
{
- if (integer_zerop (arg1) && !TREE_OVERFLOW (arg1))
+ if (integer_zerop (arg1)
+ && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg1)))
return arg0;
}
else if (code == MULT_EXPR)
{
- if (integer_onep (arg0) && !TREE_OVERFLOW (arg0))
+ if (integer_onep (arg0)
+ && !TREE_OVERFLOW (tree_strip_any_location_wrapper (arg0)))
return arg1;
}
int
operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags)
{
+ STRIP_ANY_LOCATION_WRAPPER (arg0);
+ STRIP_ANY_LOCATION_WRAPPER (arg1);
+
/* When checking, verify at the outermost operand_equal_p call that
if operand_equal_p returns non-zero then ARG0 and ARG1 has the same
hash value. */
There are problems with FP fields since the type_for_size call
below can fail for, e.g., XFmode. */
if (! INTEGRAL_TYPE_P (TREE_TYPE (exp)))
- return 0;
+ return NULL_TREE;
/* We are interested in the bare arrangement of bits, so strip everything
that doesn't affect the machine mode. However, record the type of the
exp = TREE_OPERAND (exp, 0);
STRIP_NOPS (exp); STRIP_NOPS (and_mask);
if (TREE_CODE (and_mask) != INTEGER_CST)
- return 0;
+ return NULL_TREE;
}
poly_int64 poly_bitsize, poly_bitpos;
|| (! AGGREGATE_TYPE_P (TREE_TYPE (inner))
&& compare_tree_int (TYPE_SIZE (TREE_TYPE (inner)),
*pbitpos + *pbitsize) < 0))
- return 0;
+ return NULL_TREE;
+
+ unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
+ if (unsigned_type == NULL_TREE)
+ return NULL_TREE;
*exp_ = exp;
*punsignedp = TYPE_UNSIGNED (outer_type);
/* Compute the mask to access the bitfield. */
- unsigned_type = lang_hooks.types.type_for_size (*pbitsize, 1);
precision = TYPE_PRECISION (unsigned_type);
mask = build_int_cst_type (unsigned_type, -1);
/* Disable this optimization for function pointer expressions
on targets that require function pointer canonicalization. */
if (targetm.have_canonicalize_funcptr_for_compare ()
- && TREE_CODE (etype) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (etype)) == FUNCTION_TYPE)
+ && POINTER_TYPE_P (etype)
+ && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (etype)))
return NULL_TREE;
if (! in_p)
/* On machines where the branch cost is expensive, if this is a
short-circuited branch and the underlying object on both sides
is the same, make a non-short-circuit operation. */
- else if (LOGICAL_OP_NON_SHORT_CIRCUIT
- && !flag_sanitize_coverage
- && lhs != 0 && rhs != 0
- && (code == TRUTH_ANDIF_EXPR
- || code == TRUTH_ORIF_EXPR)
- && operand_equal_p (lhs, rhs, 0))
+ bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
+ if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
+ logical_op_non_short_circuit
+ = PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
+ if (logical_op_non_short_circuit
+ && !flag_sanitize_coverage
+ && lhs != 0 && rhs != 0
+ && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR)
+ && operand_equal_p (lhs, rhs, 0))
{
/* If simple enough, just rewrite. Otherwise, make a SAVE_EXPR
unless we are at top level or LHS contains a PLACEHOLDER_EXPR, in
}
/* If the right sides are not constant, do the same for it. Also,
- disallow this optimization if a size or signedness mismatch occurs
- between the left and right sides. */
+ disallow this optimization if a size, signedness or storage order
+ mismatch occurs between the left and right sides. */
if (l_const == 0)
{
if (ll_bitsize != lr_bitsize || rl_bitsize != rr_bitsize
|| ll_unsignedp != lr_unsignedp || rl_unsignedp != rr_unsignedp
+ || ll_reversep != lr_reversep
/* Make sure the two fields on the right
correspond to the left without being swapped. */
|| ll_bitpos - rl_bitpos != lr_bitpos - rr_bitpos)
if (!same)
return NULL_TREE;
- if (! INTEGRAL_TYPE_P (type)
+ if (! ANY_INTEGRAL_TYPE_P (type)
|| TYPE_OVERFLOW_WRAPS (type)
/* We are neither factoring zero nor minus one. */
|| TREE_CODE (same) == INTEGER_CST)
if ((tem = fold_truth_andor_1 (loc, code, type, arg0, arg1)) != 0)
return tem;
- if (LOGICAL_OP_NON_SHORT_CIRCUIT
+ bool logical_op_non_short_circuit = LOGICAL_OP_NON_SHORT_CIRCUIT;
+ if (PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT) != -1)
+ logical_op_non_short_circuit
+ = PARAM_VALUE (PARAM_LOGICAL_OP_NON_SHORT_CIRCUIT);
+ if (logical_op_non_short_circuit
&& !flag_sanitize_coverage
&& (code == TRUTH_AND_EXPR
|| code == TRUTH_ANDIF_EXPR
/* Return whether BASE + OFFSET + BITPOS may wrap around the address
space. This is used to avoid issuing overflow warnings for
- expressions like &p->x which can not wrap. */
+ expressions like &p->x which cannot wrap. */
static bool
pointer_may_wrap_p (tree base, tree offset, poly_int64 bitpos)
expr_not_equal_to (tree t, const wide_int &w)
{
wide_int min, max, nz;
- value_range_type rtype;
+ value_range_kind rtype;
switch (TREE_CODE (t))
{
case INTEGER_CST:
strlen(ptr) != 0 => *ptr != 0
Other cases should reduce to one of these two (or a constant)
due to the return value of strlen being unsigned. */
- if (TREE_CODE (arg0) == CALL_EXPR
- && integer_zerop (arg1))
+ if (TREE_CODE (arg0) == CALL_EXPR && integer_zerop (arg1))
{
tree fndecl = get_callee_fndecl (arg0);
if (fndecl
&& fndecl_built_in_p (fndecl, BUILT_IN_STRLEN)
&& call_expr_nargs (arg0) == 1
- && TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0))) == POINTER_TYPE)
+ && (TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (arg0, 0)))
+ == POINTER_TYPE))
{
- tree iref = build_fold_indirect_ref_loc (loc,
- CALL_EXPR_ARG (arg0, 0));
+ tree ptrtype
+ = build_pointer_type (build_qualified_type (char_type_node,
+ TYPE_QUAL_CONST));
+ tree ptr = fold_convert_loc (loc, ptrtype,
+ CALL_EXPR_ARG (arg0, 0));
+ tree iref = build_fold_indirect_ref_loc (loc, ptr);
return fold_build2_loc (loc, code, type, iref,
- build_int_cst (TREE_TYPE (iref), 0));
+ build_int_cst (TREE_TYPE (iref), 0));
}
}
{
const tree_node **slot;
enum tree_code code;
- union tree_node buf;
+ union tree_node *buf;
int i, len;
recursive_label:
&& HAS_DECL_ASSEMBLER_NAME_P (expr))
{
/* Allow DECL_ASSEMBLER_NAME and symtab_node to be modified. */
- memcpy ((char *) &buf, expr, tree_size (expr));
- SET_DECL_ASSEMBLER_NAME ((tree)&buf, NULL);
- buf.decl_with_vis.symtab_node = NULL;
- expr = (tree) &buf;
+ size_t sz = tree_size (expr);
+ buf = XALLOCAVAR (union tree_node, sz);
+ memcpy ((char *) buf, expr, sz);
+ SET_DECL_ASSEMBLER_NAME ((tree) buf, NULL);
+ buf->decl_with_vis.symtab_node = NULL;
+ buf->base.nowarning_flag = 0;
+ expr = (tree) buf;
}
else if (TREE_CODE_CLASS (code) == tcc_type
&& (TYPE_POINTER_TO (expr)
{
/* Allow these fields to be modified. */
tree tmp;
- memcpy ((char *) &buf, expr, tree_size (expr));
- expr = tmp = (tree) &buf;
+ size_t sz = tree_size (expr);
+ buf = XALLOCAVAR (union tree_node, sz);
+ memcpy ((char *) buf, expr, sz);
+ expr = tmp = (tree) buf;
TYPE_CONTAINS_PLACEHOLDER_INTERNAL (tmp) = 0;
TYPE_POINTER_TO (tmp) = NULL;
TYPE_REFERENCE_TO (tmp) = NULL;
TYPE_CACHED_VALUES (tmp) = NULL;
}
}
+ else if (TREE_NO_WARNING (expr) && (DECL_P (expr) || EXPR_P (expr)))
+ {
+ /* Allow TREE_NO_WARNING to be set. Perhaps we shouldn't allow that
+ and change builtins.c etc. instead - see PR89543. */
+ size_t sz = tree_size (expr);
+ buf = XALLOCAVAR (union tree_node, sz);
+ memcpy ((char *) buf, expr, sz);
+ buf->base.nowarning_flag = 0;
+ expr = (tree) buf;
+ }
md5_process_bytes (expr, tree_size (expr), ctx);
if (CODE_CONTAINS_STRUCT (code, TS_TYPED))
fold_checksum_tree (TREE_TYPE (expr), ctx, ht);
if (t == error_mark_node)
return false;
+ STRIP_ANY_LOCATION_WRAPPER (t);
+
tree_code code = TREE_CODE (t);
switch (TREE_CODE_CLASS (code))
{
/* Return a pointer P to a NUL-terminated string representing the sequence
of constant characters referred to by SRC (or a subsequence of such
characters within it if SRC is a reference to a string plus some
- constant offset). If STRLEN is non-null, store stgrlen(P) in *STRLEN.
- If STRSIZE is non-null, store in *STRSIZE the size of the array
- the string is stored in; in that case, even though P points to a NUL
- terminated string, SRC need not refer to one. This can happen when
- SRC refers to a constant character array initialized to all non-NUL
- values, as in the C declaration: char a[4] = "1234"; */
+ constant offset). If STRLEN is non-null, store the number of bytes
+ in the string constant including the terminating NUL char. *STRLEN is
+ typically strlen(P) + 1 in the absence of embedded NUL characters. */
const char *
-c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */,
- unsigned HOST_WIDE_INT *strsize /* = NULL */)
+c_getstr (tree src, unsigned HOST_WIDE_INT *strlen /* = NULL */)
{
tree offset_node;
+ tree mem_size;
if (strlen)
*strlen = 0;
- src = string_constant (src, &offset_node, NULL, NULL);
+ src = string_constant (src, &offset_node, &mem_size, NULL);
if (src == 0)
return NULL;
offset = tree_to_uhwi (offset_node);
}
+ if (!tree_fits_uhwi_p (mem_size))
+ return NULL;
+
/* STRING_LENGTH is the size of the string literal, including any
embedded NULs. STRING_SIZE is the size of the array the string
literal is stored in. */
unsigned HOST_WIDE_INT string_length = TREE_STRING_LENGTH (src);
- unsigned HOST_WIDE_INT string_size = string_length;
- tree type = TREE_TYPE (src);
- if (tree size = TYPE_SIZE_UNIT (type))
- if (tree_fits_shwi_p (size))
- string_size = tree_to_uhwi (size);
+ unsigned HOST_WIDE_INT string_size = tree_to_uhwi (mem_size);
- if (strlen)
- {
- /* Compute and store the length of the substring at OFFSET.
- All offsets past the initial length refer to null strings. */
- if (offset <= string_length)
- *strlen = string_length - offset;
- else
- *strlen = 0;
- }
+ /* Ideally this would turn into a gcc_checking_assert over time. */
+ if (string_length > string_size)
+ string_length = string_size;
const char *string = TREE_STRING_POINTER (src);
+ /* Ideally this would turn into a gcc_checking_assert over time. */
+ if (string_length > string_size)
+ string_length = string_size;
+
if (string_length == 0
|| offset >= string_size)
return NULL;
- if (strsize)
+ if (strlen)
{
- /* Support even constant character arrays that aren't proper
- NUL-terminated strings. */
- *strsize = string_size;
+ /* Compute and store the length of the substring at OFFSET.
+ All offsets past the initial length refer to null strings. */
+ if (offset < string_length)
+ *strlen = string_length - offset;
+ else
+ *strlen = 1;
}
- else if (string[string_length - 1] != '\0')
+ else
{
- /* Support only properly NUL-terminated strings but handle
- consecutive strings within the same array, such as the six
- substrings in "1\0002\0003". */
- return NULL;
+ tree eltype = TREE_TYPE (TREE_TYPE (src));
+ /* Support only properly NUL-terminated single byte strings. */
+ if (tree_to_uhwi (TYPE_SIZE_UNIT (eltype)) != 1)
+ return NULL;
+ if (string[string_length - 1] != '\0')
+ return NULL;
}
- return offset <= string_length ? string + offset : "";
+ return offset < string_length ? string + offset : "";
}
/* Given a tree T, compute which bits in T may be nonzero. */