diff mbox

[gcc-5-branch] Fix C++ __builtin_constant_p

Message ID 20160121202447.GA5618@intel.com
State New
Headers show

Commit Message

H.J. Lu Jan. 21, 2016, 8:24 p.m. UTC
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  <jason@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  <jason@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 mbox

Patch

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);
+}