Commit b02520e9 by Ian Lance Taylor

compiler: Flatten erroneous subtrees into errors.

    
    Between the lowering and flattening passes of the compiler, there are
    several passes that modify the lowered Go parse tree and as errors are
    discovered, several nodes transform into error nodes.  However, for a
    higher level node such as a construction expression, the erroneous
    nodes in the subtrees might not propagate their error.  The flatten
    phase for a node now looks for errors in the subtree and flattens the
    node into an error node if any are found.
    
    Fixes golang/go#11559, golang/go#11536, golang/go#11558.
    
    Reviewed-on: https://go-review.googlesource.com/13097

From-SVN: r226845
parent 2f4fdc09
5fc38e74d132cd6f4e7b56e6bcf9fe57031ab203 fc9da313b4f5c13b4ac3bdddd98e699fd1c89613
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.
...@@ -1958,6 +1958,11 @@ class Call_expression : public Expression ...@@ -1958,6 +1958,11 @@ class Call_expression : public Expression
bool bool
issue_error(); issue_error();
// Whether or not this call contains errors, either in the call or the
// arguments to the call.
bool
is_erroneous_call();
// Whether this call returns multiple results that are used as an // Whether this call returns multiple results that are used as an
// multi-valued argument. // multi-valued argument.
bool bool
......
...@@ -253,6 +253,14 @@ Statement* ...@@ -253,6 +253,14 @@ Statement*
Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function, Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function,
Block*, Statement_inserter* inserter) Block*, Statement_inserter* inserter)
{ {
Variable* var = this->var_->var_value();
if (var->type()->is_error_type()
|| (var->init() != NULL
&& var->init()->is_error_expression()))
{
go_assert(saw_errors());
return Statement::make_error_statement(this->location());
}
this->var_->var_value()->flatten_init_expression(gogo, function, inserter); this->var_->var_value()->flatten_init_expression(gogo, function, inserter);
return this; return this;
} }
...@@ -437,6 +445,14 @@ Statement* ...@@ -437,6 +445,14 @@ Statement*
Temporary_statement::do_flatten(Gogo*, Named_object*, Block*, Temporary_statement::do_flatten(Gogo*, Named_object*, Block*,
Statement_inserter* inserter) Statement_inserter* inserter)
{ {
if (this->type()->is_error_type()
|| (this->init_ != NULL
&& this->init_->is_error_expression()))
{
go_assert(saw_errors());
return Statement::make_error_statement(this->location());
}
if (this->type_ != NULL if (this->type_ != NULL
&& this->init_ != NULL && this->init_ != NULL
&& !Type::are_identical(this->type_, this->init_->type(), false, NULL) && !Type::are_identical(this->type_, this->init_->type(), false, NULL)
...@@ -610,6 +626,15 @@ Statement* ...@@ -610,6 +626,15 @@ Statement*
Assignment_statement::do_flatten(Gogo*, Named_object*, Block*, Assignment_statement::do_flatten(Gogo*, Named_object*, Block*,
Statement_inserter* inserter) Statement_inserter* inserter)
{ {
if (this->lhs_->is_error_expression()
|| this->lhs_->type()->is_error_type()
|| this->rhs_->is_error_expression()
|| this->rhs_->type()->is_error_type())
{
go_assert(saw_errors());
return Statement::make_error_statement(this->location());
}
if (!this->lhs_->is_sink_expression() if (!this->lhs_->is_sink_expression()
&& !Type::are_identical(this->lhs_->type(), this->rhs_->type(), && !Type::are_identical(this->lhs_->type(), this->rhs_->type(),
false, NULL) false, NULL)
...@@ -4397,6 +4422,13 @@ Statement* ...@@ -4397,6 +4422,13 @@ Statement*
Send_statement::do_flatten(Gogo*, Named_object*, Block*, Send_statement::do_flatten(Gogo*, Named_object*, Block*,
Statement_inserter* inserter) Statement_inserter* inserter)
{ {
if (this->channel_->is_error_expression()
|| this->channel_->type()->is_error_type())
{
go_assert(saw_errors());
return Statement::make_error_statement(this->location());
}
Type* element_type = this->channel_->type()->channel_type()->element_type(); Type* element_type = this->channel_->type()->channel_type()->element_type();
if (!Type::are_identical(element_type, this->val_->type(), false, NULL) if (!Type::are_identical(element_type, this->val_->type(), false, NULL)
&& this->val_->type()->interface_type() != NULL && this->val_->type()->interface_type() != NULL
......
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