re PR c++/65656 (__builtin_constant_p should always be constexpr)
authorJason Merrill <jason@redhat.com>
Tue, 28 Apr 2015 14:43:59 +0000 (10:43 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 28 Apr 2015 14:43:59 +0000 (10:43 -0400)
PR c++/65656
* constexpr.c (cxx_eval_builtin_function_call): Fix
__builtin_constant_p.

From-SVN: r222531

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp0x/constexpr-builtin3.C [new file with mode: 0644]

index 73d55b9..acf4d49 100644 (file)
@@ -1,5 +1,9 @@
 2015-04-28  Jason Merrill  <jason@redhat.com>
 
+       PR c++/65656
+       * constexpr.c (cxx_eval_builtin_function_call): Fix
+       __builtin_constant_p.
+
        PR c++/50800
        * tree.c (strip_typedefs): Add remove_attributes parm.
        (strip_typedefs_expr): Likewise.
index 6465677..403c7cf 100644 (file)
@@ -1014,7 +1014,7 @@ get_nth_callarg (tree t, int n)
    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)
 {
@@ -1022,18 +1022,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;
 }
@@ -1200,7 +1212,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 (file)
index 0000000..3582525
--- /dev/null
@@ -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);
+}