Message ID | 20160610190835.GF7387@tucnak.redhat.com |
---|---|
State | New |
Headers | show |
On 06/10/2016 01:08 PM, Jakub Jelinek wrote: > 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 I agree that computing the bool result isn't terribly useful when the type is known, but allowing it could be handy in generic code (macros, C _Generic, and C++ templates). Rejecting it, OTOH, means that users will have to work a little harder to avoid an error in generic contexts. Unless there is some potential problem that I'm not thinking of I would suggest to accept bool. IMO, the right semantics for bool are to match what the standards specify (i.e., no overflow, and the result is a logical OR of the operands). Continuing to reject enumerated and complex integer types makes sense to me. Martin
On Fri, Jun 10, 2016 at 01:28:55PM -0600, Martin Sebor wrote: > IMO, the right semantics for bool are to match what the standards > specify (i.e., no overflow, and the result is a logical OR of the > operands). ??? It is far from that. The documentation says that say for __builtin_add_overflow (x, y, &z), you compute infinite precision signed result of x + y, cast the result to __typeof (z), extend again to infinite precision signed result and compare to the value before casting. So, if z is bool/_Bool, then this means signed_intNNN_t t = (signed_intNNN_t) x + (signed_intNNN_t) y; z = (__typeof (z)) t; ovf = (signed_intNNN_t) z != t; But, unlike normal signed or unsigned integral types or char, cast to bool/_Bool is special, it is actually a comparison != 0. So, I'd say if we want to support arith overflow to bool/_Bool, it should be above with: signed_intNNN_t t = (signed_intNNN_t) x + (signed_intNNN_t) y; z = t != 0; ovf = (signed_intNNN_t) z != t; so in the end, if we'd use movb x, r addb y, r seto ovf to compute whether the result overflowed 8-bits, we'd need to or in (r & 254) != 0 into the ovf and then or in ovf into r. That means changes everywhere where we handle the overflow builtins. :( Jakub
On Tue, 14 Jun 2016, Jakub Jelinek wrote: > But, unlike normal signed or unsigned integral types or char, cast to > bool/_Bool is special, it is actually a comparison != 0. > So, I'd say if we want to support arith overflow to bool/_Bool, it should be > above with: > signed_intNNN_t t = (signed_intNNN_t) x + (signed_intNNN_t) y; > z = t != 0; > ovf = (signed_intNNN_t) z != t; And, I really don't see this as useful. Rejecting boolean types there makes more sense to me.
On Tue, Jun 14, 2016 at 02:05:12PM +0000, Joseph Myers wrote: > On Tue, 14 Jun 2016, Jakub Jelinek wrote: > > > But, unlike normal signed or unsigned integral types or char, cast to > > bool/_Bool is special, it is actually a comparison != 0. > > So, I'd say if we want to support arith overflow to bool/_Bool, it should be > > above with: > > signed_intNNN_t t = (signed_intNNN_t) x + (signed_intNNN_t) y; > > z = t != 0; > > ovf = (signed_intNNN_t) z != t; > > And, I really don't see this as useful. Rejecting boolean types there > makes more sense to me. I also don't think supporting booleans is worth all the hassle. Marek
--- 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); }