Hi!

As mentioned in PR71479, for __builtin_*_overflow we right now require
the last argument to be pointer to INTEGER_TYPE, not INTEGRAL_TYPE_P,
but for __builtin_*_overflow_p we were using INTEGRAL_TYPE_P.

For _Bool/bool, I'd think we could make it well defined if we wanted
(check if the infinite precision result is 0 or 1), but it is hardly useful
and as can be seen, right now we don't implement that (for bool we actually
check if the result fits into unsigned 8 bit integer, plus _Complex bool
is kind of weird), but for enums I think the definition on what is an enum
overflow is quite fuzzy, would it for C++ e.g. work differently between
-fstrict-enums and -fno-strict-enums, would it test overflows only on the
underlying type, or exact precision of the enum, something else?

So, I think it is better to continue what we've been doing already for
__builtin_*_overflow before.  We likely need to adjust the documentation
and possibly the diagnostics.  Maybe have one wording for !INTEGRAL_TYPE_P
and another wording for the != INTEGER_TYPE case (where it would complain
that the type is {pointer to,} {enum,bool,_Bool}?  Any preferences?

The patch below just uses the preexisting wording (where integral stood
for integer types including bool/enums, and integer for non-bool/enum
integer types), I'd just like to see it in soon so that people don't start
to rely on something that doesn't really work and is hard to define.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2016-06-10  Jakub Jelinek  <ja...@redhat.com>

        * c-common.c (check_builtin_function_arguments): Require last
        argument of BUILT_IN_*_OVERFLOW_P to have INTEGER_TYPE type.

        * c-c++-common/builtin-arith-overflow-1.c (f3): Adjust expected
        diagnostics.
        * g++.dg/ext/builtin-arith-overflow-1.C: Pass 0 instead of C
        as last argument to __builtin_add_overflow_p.

--- gcc/c-family/c-common.c.jj  2016-06-10 20:23:57.433135328 +0200
+++ gcc/c-family/c-common.c     2016-06-10 20:44:51.104848132 +0200
@@ -9999,13 +9999,19 @@ check_builtin_function_arguments (locati
       if (builtin_function_validate_nargs (loc, fndecl, nargs, 3))
        {
          unsigned i;
-         for (i = 0; i < 3; i++)
+         for (i = 0; i < 2; i++)
            if (!INTEGRAL_TYPE_P (TREE_TYPE (args[i])))
              {
                error_at (ARG_LOCATION (i), "argument %u in call to function "
                          "%qE does not have integral type", i + 1, fndecl);
                return false;
              }
+         if (TREE_CODE (TREE_TYPE (args[i])) != INTEGER_TYPE)
+           {
+             error_at (ARG_LOCATION (i), "argument %u in call to function "
+                       "%qE does not have integer type", i + 1, fndecl);
+             return false;
+           }
          return true;
        }
       return false;
--- gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c.jj    2016-06-10 
20:24:01.000000000 +0200
+++ gcc/testsuite/c-c++-common/builtin-arith-overflow-1.c       2016-06-10 
20:56:04.461095680 +0200
@@ -236,11 +236,11 @@ f3 (float fa, int a, _Complex long int c
   x += __builtin_sub_overflow_p (ca, b, eb);   /* { dg-error "argument 1 in 
call to function\[^\n\r]*does not have integral type" } */
   x += __builtin_mul_overflow_p (a, fb, bb);   /* { dg-error "argument 2 in 
call to function\[^\n\r]*does not have integral type" } */
   x += __builtin_add_overflow_p (a, pb, a);    /* { dg-error "argument 2 in 
call to function\[^\n\r]*does not have integral type" } */
-  x += __builtin_sub_overflow_p (a, eb, eb);
-  x += __builtin_mul_overflow_p (a, bb, bb);
-  x += __builtin_add_overflow_p (a, b, fa);    /* { dg-error "argument 3 in 
call to function\[^\n\r]*does not have integral type" } */
-  x += __builtin_sub_overflow_p (a, b, ca);    /* { dg-error "argument 3 in 
call to function\[^\n\r]*does not have integral type" } */
-  x += __builtin_mul_overflow_p (a, b, c);     /* { dg-error "argument 3 in 
call to function\[^\n\r]*does not have integral type" } */
+  x += __builtin_sub_overflow_p (a, eb, eb);   /* { dg-error "argument 3 in 
call to function\[^\n\r]*does not have integer type" } */
+  x += __builtin_mul_overflow_p (a, bb, bb);   /* { dg-error "argument 3 in 
call to function\[^\n\r]*does not have integer type" } */
+  x += __builtin_add_overflow_p (a, b, fa);    /* { dg-error "argument 3 in 
call to function\[^\n\r]*does not have integer type" } */
+  x += __builtin_sub_overflow_p (a, b, ca);    /* { dg-error "argument 3 in 
call to function\[^\n\r]*does not have integer type" } */
+  x += __builtin_mul_overflow_p (a, b, c);     /* { dg-error "argument 3 in 
call to function\[^\n\r]*does not have integer type" } */
   return x;
 }
 
--- gcc/testsuite/g++.dg/ext/builtin-arith-overflow-1.C.jj      2016-06-08 
21:01:25.000000000 +0200
+++ gcc/testsuite/g++.dg/ext/builtin-arith-overflow-1.C 2016-06-10 
20:55:04.836870794 +0200
@@ -1,11 +1,11 @@
 // { dg-do compile }
 
-enum A { B = 1, C = 2, D = __builtin_add_overflow_p (B, C, C) };
-int e[__builtin_add_overflow_p (B, C, C) + 1];
+enum A { B = 1, C = 2, D = __builtin_add_overflow_p (B, C, 0) };
+int e[__builtin_add_overflow_p (B, C, 0) + 1];
 template <int N> int foo (int);
 
 void
 bar ()
 {
-  foo <__builtin_add_overflow_p (B, C, C) + 1> (0);
+  foo <__builtin_add_overflow_p (B, C, 0) + 1> (0);
 }

        Jakub

Reply via email to