wide-int.h has /* For fixed-precision integers like offset_int and widest_int, handle the case where the shift value is constant and the result is a single nonnegative HWI (meaning that we don't need to worry about val[1]). This is particularly common for converting a byte count to a bit count.
For variable-precision integers like wide_int, handle HWI and sub-HWI integers inline. */ if (__builtin_constant_p (xi.precision > HOST_BITS_PER_WIDE_INT) ? (__builtin_constant_p (shift < HOST_BITS_PER_WIDE_INT - 1) && xi.len == 1 && xi.val[0] <= (HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) HOST_WIDE_INT_MAX >> shift)) : precision <= HOST_BITS_PER_WIDE_INT) { val[0] = xi.ulow () << shift; result.set_len (1); } __builtin_constant_p is miscompiled due to PR c++/65656, which leads to PR 69399. Backport the PR c++/65656 fix to gcc-5-branch fixes PR 69399. OK for gcc-5-branch if there is no regression on x86-64? Thanks. H.J. -- We have two desires for interaction of __builtin_constant_p with constexpr: 1) it should be a constant-expression even if its operands are not, and 2) we shouldn't fold it to false prematurely when parsing a constexpr function (c++/54021). We were having trouble with both of these, and this patch fixes #1 without breaking #2. gcc/cp/ Backport from mainline 2015-04-28 Jason Merrill <ja...@redhat.com> PR c++/65656 * constexpr.c (cxx_eval_builtin_function_call): Fix __builtin_constant_p. gcc/testsuite/ Backport from mainline 2015-04-28 Jason Merrill <ja...@redhat.com> PR c++/65656 * g++.dg/cpp0x/constexpr-builtin3.C: New test. --- gcc/cp/constexpr.c | 32 +++++++++++++++++-------- gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C | 6 +++++ 2 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 4ca99e8..3c9362e 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1024,7 +1024,7 @@ lookup_parameter_binding (const constexpr_call *call, tree t) represented by _CST nodes. */ static tree -cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, +cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun, bool lval, bool *non_constant_p, bool *overflow_p) { @@ -1032,18 +1032,30 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree *args = (tree *) alloca (nargs * sizeof (tree)); tree new_call; int i; - for (i = 0; i < nargs; ++i) + + /* Don't fold __builtin_constant_p within a constexpr function. */ + if (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P + && current_function_decl + && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) { - args[i] = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, i), - lval, - non_constant_p, overflow_p); - if (ctx->quiet && *non_constant_p) - return t; + *non_constant_p = true; + return t; } - if (*non_constant_p) - return t; + + /* Be permissive for arguments to built-ins; __builtin_constant_p should + return constant false for a non-constant argument. */ + constexpr_ctx new_ctx = *ctx; + new_ctx.quiet = true; + bool dummy1 = false, dummy2 = false; + for (i = 0; i < nargs; ++i) + args[i] = cxx_eval_constant_expression (&new_ctx, CALL_EXPR_ARG (t, i), + lval, &dummy1, &dummy2); + + bool save_ffbcp = force_folding_builtin_constant_p; + force_folding_builtin_constant_p = true; new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t), CALL_EXPR_FN (t), nargs, args); + force_folding_builtin_constant_p = save_ffbcp; VERIFY_CONSTANT (new_call); return new_call; } @@ -1226,7 +1238,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, return void_node; if (is_builtin_fn (fun)) - return cxx_eval_builtin_function_call (ctx, t, + return cxx_eval_builtin_function_call (ctx, t, fun, lval, non_constant_p, overflow_p); if (!DECL_DECLARED_CONSTEXPR_P (fun)) { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C new file mode 100644 index 0000000..3582525 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C @@ -0,0 +1,6 @@ +// PR c++/65656 +// { dg-options "-std=c++11 -O" } + +int main(int argc, char *argv[]) { + constexpr bool x = __builtin_constant_p(argc); +} -- 2.5.0