The delayed folding merge inadvertently changed the semantics of
__builtin_constant_p so that it would only be true for a C++ constant
expression, which is a more restricted set than expressions that GCC can
fold to a constant. In particular, (non-constant && false) is not a C++
constant expression, which broke PPC bootstrap. I think we want
__builtin_constant_p of that expression to be true, so we need to fold
the operand of __builtin_constant_p more aggressively, and not try to
fold the call itself before we've folded its operands.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit f3386799b9836d61be95d01ec75c289fa6a5202f
Author: Jason Merrill <ja...@redhat.com>
Date: Mon Nov 16 15:35:14 2015 -0500
* constexpr.c (cxx_eval_builtin_function_call): Use cp_fully_fold
to fold arguments to __builtin_constant_p.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index aabb980..459173d 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1014,7 +1014,9 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
int i;
/* Don't fold __builtin_constant_p within a constexpr function. */
- if (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P
+ bool bi_const_p = (DECL_FUNCTION_CODE (fun) == BUILT_IN_CONSTANT_P);
+
+ if (bi_const_p
&& current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
{
@@ -1028,8 +1030,14 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
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);
+ {
+ args[i] = cxx_eval_constant_expression (&new_ctx, CALL_EXPR_ARG (t, i),
+ lval, &dummy1, &dummy2);
+ if (bi_const_p)
+ /* For __built_in_constant_p, fold all expressions with constant values
+ even if they aren't C++ constant-expressions. */
+ args[i] = cp_fully_fold (args[i]);
+ }
bool save_ffbcp = force_folding_builtin_constant_p;
force_folding_builtin_constant_p = true;
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 5f5cd36..8fe9e13 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2107,20 +2107,14 @@ cp_fold (tree x)
int i, m, sv = optimize, nw = sv, changed = 0;
tree callee = get_callee_fndecl (x);
+ /* Some built-in function calls will be evaluated at compile-time in
+ fold (). Set optimize to 1 when folding __builtin_constant_p inside
+ a constexpr function so that fold_builtin_1 doesn't fold it to 0. */
if (callee && DECL_BUILT_IN (callee) && !optimize
&& DECL_IS_BUILTIN_CONSTANT_P (callee)
&& current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
nw = 1;
- optimize = nw;
- r = fold (x);
- optimize = sv;
-
- if (TREE_CODE (r) != CALL_EXPR)
- {
- x = cp_fold (r);
- break;
- }
x = copy_node (x);
@@ -2145,11 +2139,11 @@ cp_fold (tree x)
optimize = nw;
- /* Invoke maybe_constant_value for functions being declared
- constexpr, and are no AGGR_INIT_EXPRs ...
+ /* Invoke maybe_constant_value for functions declared
+ constexpr and not called with AGGR_INIT_EXPRs.
TODO:
- Due issues in maybe_constant_value for CALL_EXPR with
- arguments passed by reference, it is disabled. */
+ Do constexpr expansion of expressions where the call itself is not
+ constant, but the call followed by an INDIRECT_REF is. */
if (callee && DECL_DECLARED_CONSTEXPR_P (callee))
r = maybe_constant_value (x);
optimize = sv;
diff --git a/gcc/testsuite/g++.dg/delayedfold/builtin-constant1.C b/gcc/testsuite/g++.dg/delayedfold/builtin-constant1.C
new file mode 100644
index 0000000..56bcfc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/delayedfold/builtin-constant1.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert ((X),#X)
+
+int i;
+
+SA(__builtin_constant_p (i == 42 && false));
diff --git a/gcc/testsuite/g++.dg/delayedfold/builtin-constant2.C b/gcc/testsuite/g++.dg/delayedfold/builtin-constant2.C
new file mode 100644
index 0000000..05fd286
--- /dev/null
+++ b/gcc/testsuite/g++.dg/delayedfold/builtin-constant2.C
@@ -0,0 +1,13 @@
+// { dg-do run }
+
+int i;
+
+#define CV(X) (__builtin_constant_p (X) ? (X) : -1)
+
+int ar[] = { CV (i == 42 && false) };
+
+int main()
+{
+ if (ar[0] != 0)
+ __builtin_abort();
+}