Patchwork Go patch committed: Division by constant integer 0 is a compile error

login
register
mail settings
Submitter Ian Taylor
Date June 26, 2013, 10:42 p.m.
Message ID <mcrip10lcid.fsf@iant-glaptop.roam.corp.google.com>
Download mbox | patch
Permalink /patch/254911/
State New
Headers show

Comments

Ian Taylor - June 26, 2013, 10:42 p.m.
In Go 1 division by an integer constant 0 was changed from a runtime
error to a compile time error.  This patch from Rémy Oudompheng
implements that in gccgo.  This required updating a couple of tests to
new copies from the master sources.  Bootstrapped and ran Go testsuite
on x86_64-unknown-linux-gnu.  Committed to mainline and 4.8 branch.

Ian

Patch

Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 200398)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -5848,6 +5848,20 @@  Binary_expression::do_check_types(Gogo*)
 	  this->set_is_error();
 	  return;
 	}
+      if (this->op_ == OPERATOR_DIV || this->op_ == OPERATOR_MOD)
+	{
+	  // Division by a zero integer constant is an error.
+	  Numeric_constant rconst;
+	  unsigned long rval;
+	  if (left_type->integer_type() != NULL
+	      && this->right_->numeric_constant_value(&rconst)
+	      && rconst.to_unsigned_long(&rval) == Numeric_constant::NC_UL_VALID
+	      && rval == 0)
+	    {
+	      this->report_error(_("integer division by zero"));
+	      return;
+	    }
+	}
     }
   else
     {
Index: gcc/testsuite/go.test/test/fixedbugs/bug410.go
===================================================================
--- gcc/testsuite/go.test/test/fixedbugs/bug410.go	(revision 200210)
+++ gcc/testsuite/go.test/test/fixedbugs/bug410.go	(working copy)
@@ -18,7 +18,7 @@  func zzz () {
     for s := range arr {
         x := make([]byte, 10)
         for i := 0; i < 100 ; i++ {
-            x[i] ^= k[i-arr[s].num%0]
+            x[i] ^= k[i-arr[s].num%3]
         }
     }
 }
Index: gcc/testsuite/go.test/test/64bit.go
===================================================================
--- gcc/testsuite/go.test/test/64bit.go	(revision 200210)
+++ gcc/testsuite/go.test/test/64bit.go	(working copy)
@@ -594,6 +594,19 @@  const binaryConstR = "func test%vBinaryR
 	"}\n" +
 	"\n"
 
+const binaryConstR0 = "func test%vBinaryR%v(a, add, sub, mul, div, mod, and, or, xor, andnot %v, dodiv bool) {\n" +
+	"	const b %v = %v;\n" +
+	"	const typ = `%s`;\n" +
+	"	if n, op, want := a + b, `+`, add; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a - b, `-`, sub; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a * b, `*`, mul; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a & b, `&`, and; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a | b, `|`, or; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a ^ b, `^`, xor; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"	if n, op, want := a &^ b, `&^`, andnot; n != want { ok=false; println(typ, `var`, a, op, `const`, b, `=`, n, `should be`, want); }\n" +
+	"}\n" +
+	"\n"
+
 const shiftConstL = "func test%vShiftL%v(b uint64, left, right %v) {\n" +
 	"	const a %v = %v;\n" +
 	"	const typ = `%s`;\n" +
@@ -621,12 +634,20 @@  const shiftConstR = "func test%vShiftR%v
 func constTests() {
 	for i, a := range int64Values {
 		fmt.Fprintf(bout, binaryConstL, "Int64", i, "int64", "int64", a, "int64")
-		fmt.Fprintf(bout, binaryConstR, "Int64", i, "int64", "int64", a, "int64")
+		if a.hi == 0 && a.lo == 0 {
+			fmt.Fprintf(bout, binaryConstR0, "Int64", i, "int64", "int64", a, "int64")
+		} else {
+			fmt.Fprintf(bout, binaryConstR, "Int64", i, "int64", "int64", a, "int64")
+		}
 		fmt.Fprintf(bout, shiftConstL, "Int64", i, "int64", "int64", a, "int64")
 	}
 	for i, a := range uint64Values {
 		fmt.Fprintf(bout, binaryConstL, "Uint64", i, "uint64", "uint64", a, "uint64")
-		fmt.Fprintf(bout, binaryConstR, "Uint64", i, "uint64", "uint64", a, "uint64")
+		if a.hi == 0 && a.lo == 0 {
+			fmt.Fprintf(bout, binaryConstR0, "Uint64", i, "uint64", "uint64", a, "uint64")
+		} else {
+			fmt.Fprintf(bout, binaryConstR, "Uint64", i, "uint64", "uint64", a, "uint64")
+		}
 		fmt.Fprintf(bout, shiftConstL, "Uint64", i, "uint64", "uint64", a, "uint64")
 	}
 	for i, a := range shiftValues {