diff mbox series

Go patch committed: Avoid follow-on errors for bad types

Message ID CAOyqgcVtxKTcW+F03_qoi8ma-DhHp9uEnCsxBwekf8BO9q-6JQ@mail.gmail.com
State New
Headers show
Series Go patch committed: Avoid follow-on errors for bad types | expand

Commit Message

Ian Lance Taylor Nov. 28, 2020, 3:02 p.m. UTC
This patch to the Go frontend marks bad types are erroneous, to avoid
generating further errors.  This required some code using array types
to check for errors.  This is for https://golang.org/issue/19880.
This requires updating one of the tests in the testsuite.
Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
b1adbc27c4a85ded4db81ed65b1cefce4cee8d15
diff mbox series

Patch

diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 59648326fcc..46959070e85 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@ 
-66669bb6cae475eda6666a94f6ff4f616ffa77d7
+16ab9b001c214cf831bc52a7bca5a2d18e9e4f3c
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 448888b0ad7..dc7399ebb3a 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -15303,9 +15303,22 @@  Array_construction_expression::do_is_static_initializer() const
 void
 Array_construction_expression::do_determine_type(const Type_context*)
 {
+  if (this->is_error_expression())
+    {
+      go_assert(saw_errors());
+      return;
+    }
+
   if (this->vals() == NULL)
     return;
-  Type_context subcontext(this->type_->array_type()->element_type(), false);
+  Array_type* at = this->type_->array_type();
+  if (at == NULL || at->is_error() || at->element_type()->is_error())
+    {
+      go_assert(saw_errors());
+      this->set_is_error();
+      return;
+    }
+  Type_context subcontext(at->element_type(), false);
   for (Expression_list::const_iterator pv = this->vals()->begin();
        pv != this->vals()->end();
        ++pv)
@@ -15320,10 +15333,22 @@  Array_construction_expression::do_determine_type(const Type_context*)
 void
 Array_construction_expression::do_check_types(Gogo*)
 {
+  if (this->is_error_expression())
+    {
+      go_assert(saw_errors());
+      return;
+    }
+
   if (this->vals() == NULL)
     return;
 
   Array_type* at = this->type_->array_type();
+  if (at == NULL || at->is_error() || at->element_type()->is_error())
+    {
+      go_assert(saw_errors());
+      this->set_is_error();
+      return;
+    }
   int i = 0;
   Type* element_type = at->element_type();
   for (Expression_list::const_iterator pv = this->vals()->begin();
@@ -15348,6 +15373,12 @@  Expression*
 Array_construction_expression::do_flatten(Gogo*, Named_object*,
 					   Statement_inserter* inserter)
 {
+  if (this->is_error_expression())
+    {
+      go_assert(saw_errors());
+      return this;
+    }
+
   if (this->vals() == NULL)
     return this;
 
@@ -15384,6 +15415,12 @@  Array_construction_expression::do_flatten(Gogo*, Named_object*,
 void
 Array_construction_expression::do_add_conversions()
 {
+  if (this->is_error_expression())
+    {
+      go_assert(saw_errors());
+      return;
+    }
+
   if (this->vals() == NULL)
     return;
 
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index c4570b41a71..286ecc16366 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -261,6 +261,15 @@  Type::is_error_type() const
     }
 }
 
+// Note that this type is an error.  This is called by children when
+// they discover an error during the verify_types pass.
+
+void
+Type::set_is_error()
+{
+  this->classification_ = TYPE_ERROR;
+}
+
 // If this is a pointer type, return the type to which it points.
 // Otherwise, return NULL.
 
@@ -5871,6 +5880,7 @@  Struct_type::do_verify()
 	    {
 	      go_error_at(p->location(), "embedded type may not be a pointer");
 	      p->set_type(Type::make_error_type());
+	      this->set_is_error();
 	    }
 	  else if (t->points_to() != NULL
 		   && t->points_to()->interface_type() != NULL)
@@ -5878,6 +5888,7 @@  Struct_type::do_verify()
 	      go_error_at(p->location(),
 		       "embedded type may not be pointer to interface");
 	      p->set_type(Type::make_error_type());
+	      this->set_is_error();
 	    }
 	}
     }
@@ -7236,6 +7247,13 @@  Array_type::verify_length()
   Type_context context(Type::lookup_integer_type("int"), false);
   this->length_->determine_type(&context);
 
+  if (this->length_->is_error_expression()
+      || this->length_->type()->is_error())
+    {
+      go_assert(saw_errors());
+      return false;
+    }
+
   if (!this->length_->is_constant())
     {
       go_error_at(this->length_->location(), "array bound is not constant");
@@ -7310,7 +7328,10 @@  Array_type::do_verify()
   if (this->element_type()->is_error_type())
     return false;
   if (!this->verify_length())
-    this->length_ = Expression::make_error(this->length_->location());
+    {
+      this->length_ = Expression::make_error(this->length_->location());
+      this->set_is_error();
+    }
   return true;
 }
 
@@ -8125,11 +8146,20 @@  Map_type::do_verify()
 {
   // The runtime support uses "map[void]void".
   if (!this->key_type_->is_comparable() && !this->key_type_->is_void_type())
-    go_error_at(this->location_, "invalid map key type");
+    {
+      go_error_at(this->location_, "invalid map key type");
+      this->set_is_error();
+    }
   if (!this->key_type_->in_heap())
-    go_error_at(this->location_, "go:notinheap map key not allowed");
+    {
+      go_error_at(this->location_, "go:notinheap map key not allowed");
+      this->set_is_error();
+    }
   if (!this->val_type_->in_heap())
-    go_error_at(this->location_, "go:notinheap map value not allowed");
+    {
+      go_error_at(this->location_, "go:notinheap map value not allowed");
+      this->set_is_error();
+    }
   return true;
 }
 
@@ -8660,8 +8690,11 @@  Channel_type::do_verify()
   // We have no location for this error, but this is not something the
   // ordinary user will see.
   if (!this->element_type_->in_heap())
-    go_error_at(Linemap::unknown_location(),
-		"chan of go:notinheap type not allowed");
+    {
+      go_error_at(Linemap::unknown_location(),
+		  "chan of go:notinheap type not allowed");
+      this->set_is_error();
+    }
   return true;
 }
 
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 5965d5a3fde..d0970295d75 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -1141,6 +1141,10 @@  class Type
   virtual void
   do_export(Export*) const;
 
+  // For children to call when they detect that they are in error.
+  void
+  set_is_error();
+
   // Return whether a method expects a pointer as the receiver.
   static bool
   method_expects_pointer(const Named_object*);
diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug255.go b/gcc/testsuite/go.test/test/fixedbugs/bug255.go
index acf4f23910d..458fb972b20 100644
--- a/gcc/testsuite/go.test/test/fixedbugs/bug255.go
+++ b/gcc/testsuite/go.test/test/fixedbugs/bug255.go
@@ -1,15 +1,20 @@ 
 // errorcheck
 
-// Copyright 2010 The Go Authors.  All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
 package main
 
-var a [10]int	// ok
-var b [1e1]int	// ok
-var c [1.5]int	// ERROR "truncated"
-var d ["abc"]int	// ERROR "invalid array bound|not numeric"
-var e [nil]int	// ERROR "invalid array bound|not numeric"
-var f [e]int	// ERROR "invalid array bound|not constant"
-var g [1<<65]int	// ERROR "array bound is too large|overflows"
+var a [10]int      // ok
+var b [1e1]int     // ok
+var c [1.5]int     // ERROR "truncated"
+var d ["abc"]int   // ERROR "invalid array bound|not numeric"
+var e [nil]int     // ERROR "use of untyped nil|invalid array bound|not numeric"
+var f [e]int       // ok: error already reported for e
+var g [1 << 65]int // ERROR "array bound is too large|overflows"
+var h [len(a)]int  // ok
+
+func ff() string
+
+var i [len([1]string{ff()})]int // ERROR "non-constant array bound|not constant"