constexpr.c (cxx_eval_builtin_function_call): Use cp_fully_fold to fold arguments...
authorJason Merrill <jason@redhat.com>
Tue, 17 Nov 2015 03:58:18 +0000 (22:58 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 17 Nov 2015 03:58:18 +0000 (22:58 -0500)
* constexpr.c (cxx_eval_builtin_function_call): Use cp_fully_fold
to fold arguments to __builtin_constant_p.

From-SVN: r230453

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/cp-gimplify.c
gcc/testsuite/g++.dg/delayedfold/builtin-constant1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/delayedfold/builtin-constant2.C [new file with mode: 0644]

index 7027d937acf6b8a7f3479284c6629348fe86e9ff..05b92528995dca597c9ab96e085f24b5dc3ca3c2 100644 (file)
@@ -1,3 +1,8 @@
+2015-11-16  Jason Merrill  <jason@redhat.com>
+
+       * constexpr.c (cxx_eval_builtin_function_call): Use cp_fully_fold
+       to fold arguments to __builtin_constant_p.
+
 2015-11-16  Kirill Yukhin  <kirill.yukhin@intel.com>
 
        * parser.c (cp_parser_late_parsing_cilk_simd_fn_info): Look for
index aabb980915459ef1b7bd4657ee486361661ed65b..459173dec07113ae74788ec33bf92e9741a10ec8 100644 (file)
@@ -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;
index 5f5cd367f58830ad7b7e5b22306e7d31c0596f0f..8fe9e133407dbd301f2daa51e4d45d2aad18c9e4 100644 (file)
@@ -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 (file)
index 0000000..56bcfc5
--- /dev/null
@@ -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 (file)
index 0000000..05fd286
--- /dev/null
@@ -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();
+}