On Sun, May 01, 2016 at 10:39:48AM -0600, Martin Sebor wrote:
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -7878,50 +7878,101 @@ fold_builtin_unordered_cmp (location_t loc, tree
> fndecl, tree arg0, tree arg1,
>
> static tree
> fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
> - tree arg0, tree arg1, tree arg2)
> + tree arg0, tree arg1, tree arg2 = NULL_TREE)
> {
> enum internal_fn ifn = IFN_LAST;
> - tree type = TREE_TYPE (TREE_TYPE (arg2));
> - tree mem_arg2 = build_fold_indirect_ref_loc (loc, arg2);
> + enum tree_code opcode;
> +
> + /* For the "generic" overloads, the first two arguments can have different
> + types and the last argument determines the target type to use to check
> + for overflow. The names of each of the other overloads determines
> + the target type and so the last argument can be omitted. */
> + tree type = NULL_TREE;
> +
> switch (fcode)
> {
> case BUILT_IN_ADD_OVERFLOW:
> + type = type ? type : TREE_TYPE (TREE_TYPE (arg2));
> case BUILT_IN_SADD_OVERFLOW:
> + type = type ? type : integer_type_node;
> case BUILT_IN_SADDL_OVERFLOW:
> + type = type ? type : long_integer_type_node;
> case BUILT_IN_SADDLL_OVERFLOW:
> + type = type ? type : long_long_integer_type_node;
> case BUILT_IN_UADD_OVERFLOW:
> + type = type ? type : unsigned_type_node;
> case BUILT_IN_UADDL_OVERFLOW:
> + type = type ? type : long_unsigned_type_node;
> case BUILT_IN_UADDLL_OVERFLOW:
> + type = type ? type : long_long_unsigned_type_node;
> ifn = IFN_ADD_OVERFLOW;
> + opcode = PLUS_EXPR;
...
I fail to understand this. You set type to NULL_TREE, and then (not in any
kind of loop, nor any label you could goto to) do:
type = type ? type : xxx;
That is necessarily equal to type = xxx;, isn't it?
> break;
> case BUILT_IN_SUB_OVERFLOW:
> + type = type ? type : TREE_TYPE (TREE_TYPE (arg2));
> case BUILT_IN_SSUB_OVERFLOW:
> + type = type ? type : integer_type_node;
> case BUILT_IN_SSUBL_OVERFLOW:
> + type = type ? type : long_integer_type_node;
> case BUILT_IN_SSUBLL_OVERFLOW:
> + type = type ? type : long_long_integer_type_node;
> case BUILT_IN_USUB_OVERFLOW:
> + type = type ? type : unsigned_type_node;
> case BUILT_IN_USUBL_OVERFLOW:
> + type = type ? type : long_unsigned_type_node;
> case BUILT_IN_USUBLL_OVERFLOW:
> + type = type ? type : long_long_unsigned_type_node;
> ifn = IFN_SUB_OVERFLOW;
> + opcode = MINUS_EXPR;
> break;
> case BUILT_IN_MUL_OVERFLOW:
> + type = type ? type : TREE_TYPE (TREE_TYPE (arg2));
> case BUILT_IN_SMUL_OVERFLOW:
> + type = type ? type : integer_type_node;
> case BUILT_IN_SMULL_OVERFLOW:
> + type = type ? type : long_integer_type_node;
> case BUILT_IN_SMULLL_OVERFLOW:
> + type = type ? type : long_long_integer_type_node;
> case BUILT_IN_UMUL_OVERFLOW:
> + type = type ? type : unsigned_type_node;
> case BUILT_IN_UMULL_OVERFLOW:
> + type = type ? type : long_unsigned_type_node;
> case BUILT_IN_UMULLL_OVERFLOW:
> + type = type ? type : long_long_unsigned_type_node;
> ifn = IFN_MUL_OVERFLOW;
> + opcode = MULT_EXPR;
> break;
> default:
> gcc_unreachable ();
> }
> +
> + /* When the last argument is a NULL pointer and the first two arguments
> + are constant, attempt to fold the built-in call into a constant
> + expression indicating whether or not it detected an overflow but
> + without storing the result. */
> + if ((!arg2 || zerop (arg2))
As I said in another mail, IMNSHO you don't want to change the clang
compatibility builtins, therefore arg2 should never be NULL.
As it is a pointer, shouldn't the above be integer_zerop instead?
Regarding the varargs vs. named args only different diagnostics, if you
think it should change, then IMHO you should submit as independent patch
a change to the diagnostics wording, so that the wording is the same, rather
than changing functions from fixed arguments to varargs (/ typegeneric).
Jakub