This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH for division by zero in template arguments
- To: jason at cygnus dot com
- Subject: Re: PATCH for division by zero in template arguments
- From: Mark Mitchell <mark at markmitchell dot com>
- Date: Wed, 17 Jun 1998 11:44:42 -0700
- CC: derrick at tapir dot Caltech dot EDU, egcs-patches at cygnus dot com
- References: <199806162146.OAA16621@smtp.earthlink.net> <u9vhq0cvw2.fsf@yorick.cygnus.com>
- Reply-to: mark at markmitchell dot com
>>>>> "Jason" == Jason Merrill <jason@cygnus.com> writes:
>>>>> Mark Mitchell <mark@markmitchell.com> writes:
>> Here's a fix for your problem. Jason, OK?
Jason> No. The GCC policy is to handle division by zero at
Jason> runtime. This is especially important for reals, where
Jason> division by zero may be deliberate, to generate a NaN.
OK. Still, since programs that divide by a constant 0 are ill-formed,
not merely undefined, I think this should be a pedwarn. I also think
the result of the operation should not be marked TREE_CONSTANT, since
it's not: it's a run-time division.
Here's a patch to that effect.
--
Mark Mitchell mark@markmitchell.com
Mark Mitchell Consulting http://www.markmitchell.com
1998-06-16 Mark Mitchell <mark@markmitchell.com>
* typeck.c (build_binary_op_nodefault): Make dividing by a
constant zero a pedwarn, rather than a warning. And don't
treat such expressions as constants.
Index: testsuite/g++.old-deja/g++.pt/crash10.C
===================================================================
RCS file: crash10.C
diff -N crash10.C
*** /dev/null Mon Dec 31 20:00:00 1979
--- crash10.C Tue Jun 16 14:25:33 1998
***************
*** 0 ****
--- 1,11 ----
+ // Build don't link:
+
+ template<int M, int N>
+ class GCD {
+ public:
+ enum { val = (N == 0) ? M : GCD<N, M % N>::val };
+ };
+
+ main() {
+ GCD< 1, 0 >::val; // ERROR - division
+ }
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.84
diff -c -p -r1.84 typeck.c
*** typeck.c 1998/06/17 02:07:28 1.84
--- typeck.c 1998/06/17 18:40:25
*************** build_binary_op_nodefault (code, orig_op
*** 3225,3230 ****
--- 3225,3234 ----
/* Nonzero means set RESULT_TYPE to the common type of the args. */
int common = 0;
+ /* Nonzero means the result of the expression is not constant,
+ even if all the operands are. */
+ int cannot_be_constant = 0;
+
/* Apply default conversions. */
if (code == TRUTH_AND_EXPR || code == TRUTH_ANDIF_EXPR
|| code == TRUTH_OR_EXPR || code == TRUTH_ORIF_EXPR
*************** build_binary_op_nodefault (code, orig_op
*** 3296,3306 ****
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE))
{
! if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
! cp_warning ("division by zero in `%E / 0'", op0);
! else if (TREE_CODE (op1) == REAL_CST && real_zerop (op1))
! cp_warning ("division by zero in `%E / 0.'", op0);
!
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
--- 3300,3312 ----
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
|| code1 == COMPLEX_TYPE))
{
! if ((TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
! || (TREE_CODE (op1) == REAL_CST && real_zerop (op1)))
! {
! cp_pedwarn ("division by zero in `%E / 0'", op0);
! cannot_be_constant = 1;
! }
!
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
*************** build_binary_op_nodefault (code, orig_op
*** 3353,3363 ****
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
! if (code1 == INTEGER_TYPE && integer_zerop (op1))
! cp_warning ("division by zero in `%E % 0'", op0);
! else if (code1 == REAL_TYPE && real_zerop (op1))
! cp_warning ("division by zero in `%E % 0.'", op0);
!
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
/* Although it would be tempting to shorten always here, that loses
--- 3359,3371 ----
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
! if ((code1 == INTEGER_TYPE && integer_zerop (op1))
! || (code1 == REAL_TYPE && real_zerop (op1)))
! {
! cp_pedwarn ("division by zero in `%E / 0'", op0);
! cannot_be_constant = 1;
! }
!
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
/* Although it would be tempting to shorten always here, that loses
*************** build_binary_op_nodefault (code, orig_op
*** 3951,3958 ****
register tree folded;
folded = fold (result);
! if (folded == result)
! TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
if (final_type != 0)
return cp_convert (final_type, folded);
return folded;
--- 3959,3967 ----
register tree folded;
folded = fold (result);
! if (folded == result)
! TREE_CONSTANT (folded) = (!cannot_be_constant &&
! TREE_CONSTANT (op0) & TREE_CONSTANT (op1));
if (final_type != 0)
return cp_convert (final_type, folded);
return folded;