Commit 3008f0ff by Ian Lance Taylor

compiler: lower expression types in lowering pass

    
    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
parent 9734500e
17325c96ccbee4ad6bed1cd3d9517f7dfbdf3ea7 65eaa9003db4effc9c5ffe9c955e9534ba5d7d15
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -2847,8 +2847,16 @@ Const_expression::do_type() ...@@ -2847,8 +2847,16 @@ Const_expression::do_type()
if (this->seen_ || nc->lowering()) 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(); this->type_ = Type::make_error_type();
nc->set_type(this->type_);
return this->type_; return this->type_;
} }
...@@ -2868,6 +2876,9 @@ Const_expression::do_type() ...@@ -2868,6 +2876,9 @@ Const_expression::do_type()
this->seen_ = false; this->seen_ = false;
if (ret->is_error_type())
nc->set_type(ret);
return ret; return ret;
} }
......
...@@ -2751,6 +2751,14 @@ Lower_parse_tree::expression(Expression** pexpr) ...@@ -2751,6 +2751,14 @@ Lower_parse_tree::expression(Expression** pexpr)
return TRAVERSE_EXIT; return TRAVERSE_EXIT;
*pexpr = enew; *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; return TRAVERSE_SKIP_COMPONENTS;
} }
...@@ -6855,6 +6863,16 @@ Result_variable::get_backend_variable(Gogo* gogo, Named_object* function, ...@@ -6855,6 +6863,16 @@ Result_variable::get_backend_variable(Gogo* gogo, Named_object* function,
// Class Named_constant. // 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. // Traverse the initializer expression.
int int
......
...@@ -2147,6 +2147,9 @@ class Named_constant ...@@ -2147,6 +2147,9 @@ class Named_constant
type() const type() const
{ return this->type_; } { return this->type_; }
void
set_type(Type* t);
Expression* Expression*
expr() const expr() const
{ return this->expr_; } { return this->expr_; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment