diff mbox

C++ PATCH to __builtin_constant_p handling

Message ID 564AA5BF.7040602@redhat.com
State New
Headers show

Commit Message

Jason Merrill Nov. 17, 2015, 3:57 a.m. UTC
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.
diff mbox

Patch

commit f3386799b9836d61be95d01ec75c289fa6a5202f
Author: Jason Merrill <jason@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();
+}