diff mbox series

Go patch committed: Lower expression types in lowering pass

Message ID CAOyqgcUPKFYey5iG6Y8HCAsrVGDo-jLY6_+t_61p9H_S8VS0Cw@mail.gmail.com
State New
Headers show
Series Go patch committed: Lower expression types in lowering pass | expand

Commit Message

Ian Lance Taylor Jan. 31, 2018, 6:36 p.m. UTC
This patch to the Go frontend, based on one by Cherry Zhang, lowers
expression types in the lowering pass.  This ensures that array types
with complicated length expressions are handled correctly.

This required some adjustment of constant expression types to not
report too many errors for circular constant expressions.  We now
record error types in the Named_constant type.  If we find the
circularity due to lowering the Named_constant, we use that location
for the error message; this retains the error location we used to use.

This fixes https://golang.org/issue/23545 .

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 257249)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-17325c96ccbee4ad6bed1cd3d9517f7dfbdf3ea7
+65eaa9003db4effc9c5ffe9c955e9534ba5d7d15
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 257217)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -2847,8 +2847,16 @@  Const_expression::do_type()
 
   if (this->seen_ || nc->lowering())
     {
-      this->report_error(_("constant refers to itself"));
+      if (nc->type() == NULL || !nc->type()->is_error_type())
+	{
+	  Location loc = this->location();
+	  if (!this->seen_)
+	    loc = nc->location();
+	  go_error_at(loc, "constant refers to itself");
+	}
+      this->set_is_error();
       this->type_ = Type::make_error_type();
+      nc->set_type(this->type_);
       return this->type_;
     }
 
@@ -2868,6 +2876,9 @@  Const_expression::do_type()
 
   this->seen_ = false;
 
+  if (ret->is_error_type())
+    nc->set_type(ret);
+
   return ret;
 }
 
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 257217)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -2751,6 +2751,14 @@  Lower_parse_tree::expression(Expression*
 	return TRAVERSE_EXIT;
       *pexpr = enew;
     }
+
+  // Lower the type of this expression before the parent looks at it,
+  // in case the type contains an array that has expressions in its
+  // length.  Skip an Unknown_expression, as at this point that means
+  // a composite literal key that does not have a type.
+  if ((*pexpr)->unknown_expression() == NULL)
+    Type::traverse((*pexpr)->type(), this);
+
   return TRAVERSE_SKIP_COMPONENTS;
 }
 
@@ -6855,6 +6863,16 @@  Result_variable::get_backend_variable(Go
 
 // Class Named_constant.
 
+// Set the type of a named constant.  This is only used to set the
+// type to an error type.
+
+void
+Named_constant::set_type(Type* t)
+{
+  go_assert(this->type_ == NULL || t->is_error_type());
+  this->type_ = t;
+}
+
 // Traverse the initializer expression.
 
 int
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h	(revision 257217)
+++ gcc/go/gofrontend/gogo.h	(working copy)
@@ -2147,6 +2147,9 @@  class Named_constant
   type() const
   { return this->type_; }
 
+  void
+  set_type(Type* t);
+
   Expression*
   expr() const
   { return this->expr_; }