compiler: lower expression types in lowering pass
authorIan Lance Taylor <ian@gcc.gnu.org>
Wed, 31 Jan 2018 18:35:58 +0000 (18:35 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 31 Jan 2018 18:35:58 +0000 (18:35 +0000)
    Ensure that array types with complicated length expressions are
    handled correctly by lowering expression types in the lowering pass.

    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.

    Fixes golang/go#23545

    Reviewed-on: https://go-review.googlesource.com/91035

From-SVN: r257250

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h

index bcc8136745dec3f90a63c93478c6143f85f4c780..c115b2e4f96cbb70d836731cee20c7ba98d4dd53 100644 (file)
@@ -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 534b61fc6f036e2eb38729ae9895034602cbac30..c90ef8de79578ae683fead9cd643ca76e7060cab 100644 (file)
@@ -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 f89099e7e7f437486ef578459baf18a3d040b730..3f784dd80dc82a697cbbdf262c27d78950a5b2ea 100644 (file)
@@ -2751,6 +2751,14 @@ Lower_parse_tree::expression(Expression** pexpr)
        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(Gogo* gogo, Named_object* function,
 
 // 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 5135042763d7c73d47f7ab0ed15ea865e291bd48..dfff5c170c974cabe0defa5caf47f6292a472875 100644 (file)
@@ -2147,6 +2147,9 @@ class Named_constant
   type() const
   { return this->type_; }
 
+  void
+  set_type(Type* t);
+
   Expression*
   expr() const
   { return this->expr_; }