On Mon, Feb 18, 2019 at 04:04:15PM -1000, Jason Merrill wrote: > > --- gcc/cp/constexpr.c.jj 2019-02-17 17:09:47.113351897 +0100 > > +++ gcc/cp/constexpr.c 2019-02-18 19:34:57.995136395 +0100 > > @@ -1269,6 +1301,49 @@ cxx_eval_builtin_function_call (const co > > return t; > > } > > + if (fndecl_built_in_p (fun, BUILT_IN_NORMAL)) > > + switch (DECL_FUNCTION_CODE (fun)) > > + { > > + case BUILT_IN_ADD_OVERFLOW: > > + case BUILT_IN_SADD_OVERFLOW: > > + case BUILT_IN_SADDL_OVERFLOW: > > + case BUILT_IN_SADDLL_OVERFLOW: > > + case BUILT_IN_UADD_OVERFLOW: > > + case BUILT_IN_UADDL_OVERFLOW: > > + case BUILT_IN_UADDLL_OVERFLOW: > > + case BUILT_IN_SUB_OVERFLOW: > > + case BUILT_IN_SSUB_OVERFLOW: > > + case BUILT_IN_SSUBL_OVERFLOW: > > + case BUILT_IN_SSUBLL_OVERFLOW: > > + case BUILT_IN_USUB_OVERFLOW: > > + case BUILT_IN_USUBL_OVERFLOW: > > + case BUILT_IN_USUBLL_OVERFLOW: > > + case BUILT_IN_MUL_OVERFLOW: > > + case BUILT_IN_SMUL_OVERFLOW: > > + case BUILT_IN_SMULL_OVERFLOW: > > + case BUILT_IN_SMULLL_OVERFLOW: > > + case BUILT_IN_UMUL_OVERFLOW: > > + case BUILT_IN_UMULL_OVERFLOW: > > + case BUILT_IN_UMULLL_OVERFLOW: > > + /* These builtins will fold into > > + (cast) > > + ((something = __real__ SAVE_EXPR <.???_OVERFLOW (cst1, cst2)>), > > + __imag__ SAVE_EXPR <.???_OVERFLOW (cst1, cst2)>) > > + which fails is_constant_expression. */ > > + if (TREE_CODE (args[0]) != INTEGER_CST > > + || TREE_CODE (args[1]) != INTEGER_CST > > + || !potential_constant_expression (args[2])) > > + { > > + if (!*non_constant_p && !ctx->quiet) > > + error ("%q+E is not a constant expression", new_call); > > + *non_constant_p = true; > > + return t; > > + } > > + return cxx_eval_constant_expression (&new_ctx, new_call, lval, > > + non_constant_p, overflow_p); > > + default: > > + break; > > + } > > What is this for? Won't this recursive cxx_eval_constant_expression come > back to this function again? If the expression is constant, shouldn't it > have been folded by fold_builtin_call_array?
This is for the constexpr-arith-overflow.C testcase. The arguments are INTEGER_CST, INTEGER_CST and ADDR_EXPR of a VAR_DECL or PARM_DECL, and fold_builtin_call_array returns new_call: (z = REALPART_EXPR <SAVE_EXPR <.ADD_OVERFLOW (0, 0)>>;, (bool) IMAGPART_EXPR <SAVE_EXPR <.ADD_OVERFLOW (0, 0)>>;); where this doesn't pass is_constant_expression because of the z store. cxx_eval_constant_expression is able to evaluate this, as z = 0; false; in this case. I guess builtins.c folding could be improved and simplify it to (z = 0; (bool) false;); but that still doesn't pass is_constant_expression check. For C++14 it passes potential_constant_expression though, and that is what I've used for these builtins in the first iteration, but the testcase happened to pass even for C++11 and potential_constant_expression is false here. Though, perhaps we are going too far for C++11 here and should reject it, after all, people have the possibility to use __builtin_*_overflow_p now which should be usable even in C++11. The reason why it passed with C++11 is that when parsing we saw a __builtin_add_overflow (0, 0, &z) call and potential_constant_expression said it is ok, then folded it into that (z = REALPART_EXPR <SAVE_EXPR <.ADD_OVERFLOW (0, 0)>>;, (bool) IMAGPART_EXPR <SAVE_EXPR <.ADD_OVERFLOW (0, 0)>>;); which is not potential_constant_expression, but nothing called it again and cxx_eval_constant_expression can handle it. > > @@ -1358,6 +1433,9 @@ cxx_bind_parameters_in_call (const const > > x = ctx->object; > > x = build_address (x); > > } > > + if (TREE_ADDRESSABLE (type) && TYPE_REF_P (TREE_TYPE (x))) > > + /* Undo convert_for_arg_passing work here. */ > > + x = build_fold_indirect_ref_loc (EXPR_LOCATION (x), x); > > Not convert_from_reference? Will change. > > @@ -4036,6 +4113,10 @@ label_matches (const constexpr_ctx *ctx, > > } > > break; > > + case BREAK_STMT: > > + case CONTINUE_STMT: > > + break; > > + > > Let's add a comment that these are handled directly in cxx_eval_loop_expr. Ok, will do. Jakub