From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30735 invoked by alias); 13 May 2015 13:41:20 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 30723 invoked by uid 89); 13 May 2015 13:41:19 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL,BAYES_05,SPF_HELO_PASS,SPF_PASS,T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 13 May 2015 13:41:17 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 473EB31CAC8; Wed, 13 May 2015 13:41:16 +0000 (UTC) Received: from redhat.com (ovpn-204-66.brq.redhat.com [10.40.204.66]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t4DDfBFe021583 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO); Wed, 13 May 2015 09:41:14 -0400 Date: Wed, 13 May 2015 13:49:00 -0000 From: Marek Polacek To: GCC Patches , Richard Biener Cc: Joseph Myers Subject: [PATCH] Don't fold away division by zero (PR middle-end/66127) Message-ID: <20150513134111.GA27320@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-SW-Source: 2015-05/txt/msg01221.txt.bz2 As discussed in the PR, match.pd happily folds 0 * whatever into 0. That is undesirable from the C/C++ FE POV, since it can make us accept invalid initializers. So fixed in match.pd -- I'd hope there's a better way to do this, but this seems to work. There was some fallout, but nothing unexpected or surprising. Bootstrapped/regtested on x86_64-linux, ok for trunk? 2015-05-13 Marek Polacek PR middle-end/66127 * match.pd (0 * X): Preserve divisions by zero. * g++.dg/warn/overflow-warn-1.C: Adjust dg-warning and dg-error. * g++.dg/warn/overflow-warn-3.C: Likewise. * g++.dg/warn/overflow-warn-4.C: Likewise. * g++.dg/ubsan/div-by-zero-1.C: Likewise. diff --git gcc/match.pd gcc/match.pd index 51a950a..510e2db 100644 --- gcc/match.pd +++ gcc/match.pd @@ -78,7 +78,19 @@ along with GCC; see the file COPYING3. If not see (simplify (mult @0 integer_zerop@1) - @1) + /* Make sure to preserve divisions by zero. */ + (with { enum tree_code code = TREE_CODE (@0); } + (if ((code != TRUNC_DIV_EXPR + && code != EXACT_DIV_EXPR + && code != ROUND_DIV_EXPR + && code != FLOOR_DIV_EXPR + && code != CEIL_DIV_EXPR + && code != TRUNC_MOD_EXPR + && code != CEIL_MOD_EXPR + && code != FLOOR_MOD_EXPR + && code != ROUND_MOD_EXPR) + || !integer_zerop (TREE_OPERAND (@0, 1))) + @1))) /* Maybe fold x * 0 to 0. The expressions aren't the same when x is NaN, since x * 0 is also NaN. Nor are they the --- gcc/testsuite/g++.dg/warn/overflow-warn-1.C +++ gcc/testsuite/g++.dg/warn/overflow-warn-1.C @@ -17,7 +17,7 @@ enum e { /* But as in DR#031, the 1/0 in an evaluated subexpression means the whole expression violates the constraints. */ E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */ - /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ + /* { dg-error "enumerator value for 'E4' is not an integer constant|not a constant.expression" "enum error" { target *-*-* } 19 } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */ /* Again, overflow in evaluated subexpression. */ @@ -30,8 +30,9 @@ enum e { struct s { int a; int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ + /* { dg-error "not an integer constant|not a constant.expression" "bit-field error" { target *-*-* } 32 } */ int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ - /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 33 } */ + /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 34 } */ }; void @@ -45,7 +46,6 @@ f (void) /* This expression is neither required to be constant. */ static int sc = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } */ - // Test for overflow in null pointer constant. void *n = 0; /* The first two of these involve overflow, so are not null pointer @@ -54,7 +54,7 @@ void *n = 0; void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ /* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 54 } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */ -/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 56 } */ +/* { dg-warning "invalid conversion from 'int' to 'void\\*'" "null" { target *-*-* } 56 } */ void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */ void @@ -63,9 +63,10 @@ g (int i) switch (i) { case 0 * (1/0): /* { dg-warning "division by zero" } */ + /* { dg-error "not a constant.expression" "case error" { target *-*-* } 65 } */ ; case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ - /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 67 } */ + /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 68 } */ ; } } --- gcc/testsuite/g++.dg/warn/overflow-warn-3.C +++ gcc/testsuite/g++.dg/warn/overflow-warn-3.C @@ -17,7 +17,7 @@ enum e { /* But as in DR#031, the 1/0 in an evaluated subexpression means the whole expression violates the constraints. */ E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */ - /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ + /* { dg-error "enumerator value for 'E4' is not an integer constant|not a constant.expression" "enum error" { target *-*-* } 19 } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */ /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */ /* Again, overflow in evaluated subexpression. */ @@ -30,8 +30,9 @@ enum e { struct s { int a; int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ + /* { dg-error "not an integer constant|not a constant.expression" "bit-field error" { target *-*-* } 32 } */ int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ - /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 33 } */ + /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 34 } */ }; void @@ -40,7 +41,6 @@ f (void) /* This expression is not required to be a constant expression, so it should just involve undefined behavior at runtime. */ int c = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } */ - } /* This expression is neither required to be constant. */ @@ -56,7 +56,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } /* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 55 } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */ -/* { dg-warning "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */ +/* { dg-warning "invalid conversion from 'int' to 'void\\*'" "null" { target *-*-* } 58 } */ void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */ void @@ -65,9 +65,10 @@ g (int i) switch (i) { case 0 * (1/0): /* { dg-warning "division by zero" } */ + /* { dg-error "not a constant.expression" "case error" { target *-*-* } 67 } */ ; case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ - /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 69 } */ + /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 70 } */ ; } } --- gcc/testsuite/g++.dg/warn/overflow-warn-4.C +++ gcc/testsuite/g++.dg/warn/overflow-warn-4.C @@ -17,7 +17,7 @@ enum e { /* But as in DR#031, the 1/0 in an evaluated subexpression means the whole expression violates the constraints. */ E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */ - /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */ + /* { dg-error "enumerator value for 'E4' is not an integer constant|not a constant.expression" "enum error" { target *-*-* } 19 } */ E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */ /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */ /* { dg-error "enumerator value for 'E5' is not an integer constant" "enum error" { target *-*-* } 21 } */ @@ -32,9 +32,10 @@ enum e { struct s { int a; int : 0 * (1 / 0); /* { dg-warning "division by zero" } */ + /* { dg-error "not an integer constant|not a constant.expression" "bit-field error" { target *-*-* } 34 } */ int : 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } */ - /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 35 } */ - /* { dg-error "bit-field .* width not an integer constant" "" { target *-*-* } 35 } */ + /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 36 } */ + /* { dg-error "bit-field .* width not an integer constant" "" { target *-*-* } 36 } */ }; void @@ -43,7 +44,6 @@ f (void) /* This expression is not required to be a constant expression, so it should just involve undefined behavior at runtime. */ int c = INT_MAX + 1; /* { dg-warning "integer overflow in expression" } */ - } /* This expression is neither required to be constant. */ @@ -59,7 +59,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" } /* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */ void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */ -/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 61 } */ +/* { dg-error "invalid conversion from 'int' to 'void\\*'" "null" { target *-*-* } 61 } */ void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */ void @@ -68,9 +68,10 @@ g (int i) switch (i) { case 0 * (1/0): /* { dg-warning "division by zero" } */ + /* { dg-error "not a constant.expression" "case error" { target *-*-* } 70 } */ ; case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */ - /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 72 } */ + /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 73 } */ ; } } --- gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C +++ gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C @@ -1,14 +1,10 @@ /* { dg-do compile } */ /* { dg-options "-fsanitize=integer-divide-by-zero" } */ -/* TODO: We expect an error on the invalid case here, because that - must be a constant-expression. This will be fixed when we have - proper delayed folding. */ - void foo (int i) { switch (i) case 0 * (1 / 0): /* { dg-warning "division by zero" } */ - ; /* { dg-error "division by zero" "" { xfail *-*-* } 10 } */ + ; /* { dg-error "not a constant.expression" "" { target *-*-* } 8 } */ } Marek