diff --git a/go/expressions.cc b/go/expressions.cc index 3aabbaba4..9f757a2aa 100644 --- a/go/expressions.cc +++ b/go/expressions.cc @@ -3101,6 +3101,12 @@ Expression* Type_conversion_expression::do_flatten(Gogo*, Named_object*, Statement_inserter* inserter) { + if (this->type()->is_error_type() || this->expr_->is_error_expression()) + { + go_assert(saw_errors()); + return Expression::make_error(this->location()); + } + if (((this->type()->is_string_type() && this->expr_->type()->is_slice_type()) || this->expr_->type()->interface_type() != NULL) @@ -3585,8 +3591,13 @@ Expression* Unary_expression::do_flatten(Gogo* gogo, Named_object*, Statement_inserter* inserter) { - if (this->is_error_expression() || this->expr_->is_error_expression()) - return Expression::make_error(this->location()); + if (this->is_error_expression() + || this->expr_->is_error_expression() + || this->expr_->type()->is_error_type()) + { + go_assert(saw_errors()); + return Expression::make_error(this->location()); + } Location location = this->location(); if (this->op_ == OPERATOR_MULT @@ -5062,10 +5073,16 @@ Expression* Binary_expression::do_flatten(Gogo* gogo, Named_object*, Statement_inserter* inserter) { - if (this->classification() == EXPRESSION_ERROR) - return this; - Location loc = this->location(); + if (this->left_->type()->is_error_type() + || this->right_->type()->is_error_type() + || this->left_->is_error_expression() + || this->right_->is_error_expression()) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } + Temporary_statement* temp; if (this->left_->type()->is_string_type() && this->op_ == OPERATOR_PLUS) @@ -6806,6 +6823,11 @@ Builtin_call_expression::do_flatten(Gogo*, Named_object*, Statement_inserter* inserter) { Location loc = this->location(); + if (this->is_erroneous_call()) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } switch (this->code_) { @@ -8733,8 +8755,11 @@ Expression* Call_expression::do_flatten(Gogo* gogo, Named_object*, Statement_inserter* inserter) { - if (this->classification() == EXPRESSION_ERROR) - return this; + if (this->is_erroneous_call()) + { + go_assert(saw_errors()); + return Expression::make_error(this->location()); + } if (this->is_flattened_) return this; @@ -8902,6 +8927,27 @@ Call_expression::issue_error() } } +// Whether or not this call contains errors, either in the call or the +// arguments to the call. + +bool +Call_expression::is_erroneous_call() +{ + if (this->is_error_expression() || this->fn()->is_error_expression()) + return true; + + if (this->args() == NULL) + return false; + for (Expression_list::iterator pa = this->args()->begin(); + pa != this->args()->end(); + ++pa) + { + if ((*pa)->type()->is_error_type() || (*pa)->is_error_expression()) + return true; + } + return false; +} + // Get the type. Type* @@ -9848,30 +9894,47 @@ Array_index_expression::do_flatten(Gogo*, Named_object*, Statement_inserter* inserter) { Location loc = this->location(); + Expression* array = this->array_; + Expression* start = this->start_; + Expression* end = this->end_; + Expression* cap = this->cap_; + if (array->is_error_expression() + || array->type()->is_error_type() + || start->is_error_expression() + || start->type()->is_error_type() + || (end != NULL + && (end->is_error_expression() || end->type()->is_error_type())) + || (cap != NULL + && (cap->is_error_expression() || cap->type()->is_error_type()))) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } + Temporary_statement* temp; - if (this->array_->type()->is_slice_type() && !this->array_->is_variable()) + if (array->type()->is_slice_type() && !array->is_variable()) { - temp = Statement::make_temporary(NULL, this->array_, loc); + temp = Statement::make_temporary(NULL, array, loc); inserter->insert(temp); this->array_ = Expression::make_temporary_reference(temp, loc); } - if (!this->start_->is_variable()) + if (!start->is_variable()) { - temp = Statement::make_temporary(NULL, this->start_, loc); + temp = Statement::make_temporary(NULL, start, loc); inserter->insert(temp); this->start_ = Expression::make_temporary_reference(temp, loc); } - if (this->end_ != NULL - && !this->end_->is_nil_expression() - && !this->end_->is_variable()) + if (end != NULL + && !end->is_nil_expression() + && !end->is_variable()) { - temp = Statement::make_temporary(NULL, this->end_, loc); + temp = Statement::make_temporary(NULL, end, loc); inserter->insert(temp); this->end_ = Expression::make_temporary_reference(temp, loc); } - if (this->cap_ != NULL && !this->cap_->is_variable()) + if (cap!= NULL && !cap->is_variable()) { - temp = Statement::make_temporary(NULL, this->cap_, loc); + temp = Statement::make_temporary(NULL, cap, loc); inserter->insert(temp); this->cap_ = Expression::make_temporary_reference(temp, loc); } @@ -10179,8 +10242,22 @@ Expression* String_index_expression::do_flatten(Gogo*, Named_object*, Statement_inserter* inserter) { - Temporary_statement* temp; Location loc = this->location(); + Expression* string = this->string_; + Expression* start = this->start_; + Expression* end = this->end_; + if (string->is_error_expression() + || string->type()->is_error_type() + || start->is_error_expression() + || start->type()->is_error_type() + || (end != NULL + && (end->is_error_expression() || end->type()->is_error_type()))) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } + + Temporary_statement* temp; if (!this->string_->is_variable()) { temp = Statement::make_temporary(NULL, this->string_, loc); @@ -10419,6 +10496,14 @@ Map_index_expression::do_flatten(Gogo* gogo, Named_object*, { Location loc = this->location(); Map_type* mt = this->get_map_type(); + if (this->index()->is_error_expression() + || this->index()->type()->is_error_type() + || mt->is_error_type()) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } + if (!Type::are_identical(mt->key_type(), this->index_->type(), false, NULL)) { if (this->index_->type()->interface_type() != NULL @@ -10443,6 +10528,9 @@ Map_index_expression::do_flatten(Gogo* gogo, Named_object*, if (this->value_pointer_ == NULL) this->get_value_pointer(this->is_lvalue_); + if (this->value_pointer_->is_error_expression() + || this->value_pointer_->type()->is_error_type()) + return Expression::make_error(loc); if (!this->value_pointer_->is_variable()) { Temporary_statement* temp = @@ -10819,6 +10907,13 @@ Expression* Interface_field_reference_expression::do_flatten(Gogo*, Named_object*, Statement_inserter* inserter) { + if (this->expr_->is_error_expression() + || this->expr_->type()->is_error_type()) + { + go_assert(saw_errors()); + return Expression::make_error(this->location()); + } + if (!this->expr_->is_variable()) { Temporary_statement* temp = @@ -11598,6 +11693,11 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*, { if (*pv != NULL) { + if ((*pv)->is_error_expression() || (*pv)->type()->is_error_type()) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } if (!(*pv)->is_variable()) { Temporary_statement* temp = @@ -11809,6 +11909,11 @@ Array_construction_expression::do_flatten(Gogo*, Named_object*, { if (*pv != NULL) { + if ((*pv)->is_error_expression() || (*pv)->type()->is_error_type()) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } if (!(*pv)->is_variable()) { Temporary_statement* temp = @@ -12124,6 +12229,11 @@ Map_construction_expression::do_flatten(Gogo* gogo, Named_object*, { Expression_list* key_value_pair = new Expression_list(); Expression* key = *pv; + if (key->is_error_expression() || key->type()->is_error_type()) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } if (key->type()->interface_type() != NULL && !key->is_variable()) { Temporary_statement* temp = @@ -12135,6 +12245,11 @@ Map_construction_expression::do_flatten(Gogo* gogo, Named_object*, ++pv; Expression* val = *pv; + if (val->is_error_expression() || val->type()->is_error_type()) + { + go_assert(saw_errors()); + return Expression::make_error(loc); + } if (val->type()->interface_type() != NULL && !val->is_variable()) { Temporary_statement* temp = @@ -13103,6 +13218,13 @@ Expression* Type_guard_expression::do_flatten(Gogo*, Named_object*, Statement_inserter* inserter) { + if (this->expr_->is_error_expression() + || this->expr_->type()->is_error_type()) + { + go_assert(saw_errors()); + return Expression::make_error(this->location()); + } + if (!this->expr_->is_variable()) { Temporary_statement* temp = Statement::make_temporary(NULL, this->expr_, @@ -13297,6 +13419,11 @@ Receive_expression::do_flatten(Gogo*, Named_object*, go_assert(saw_errors()); return this; } + else if (this->channel_->is_error_expression()) + { + go_assert(saw_errors()); + return Expression::make_error(this->location()); + } Type* element_type = channel_type->element_type(); if (this->temp_receiver_ == NULL) diff --git a/go/expressions.h b/go/expressions.h index 6d0f6a4c0..5358b0213 100644 --- a/go/expressions.h +++ b/go/expressions.h @@ -1958,6 +1958,11 @@ class Call_expression : public Expression bool 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 // multi-valued argument. bool diff --git a/go/statements.cc b/go/statements.cc index 40b437382..72b41cb09 100644 --- a/go/statements.cc +++ b/go/statements.cc @@ -253,6 +253,14 @@ Statement* Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function, 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); return this; } @@ -437,6 +445,14 @@ Statement* Temporary_statement::do_flatten(Gogo*, Named_object*, Block*, 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 && this->init_ != NULL && !Type::are_identical(this->type_, this->init_->type(), false, NULL) @@ -610,6 +626,15 @@ Statement* Assignment_statement::do_flatten(Gogo*, Named_object*, Block*, 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() && !Type::are_identical(this->lhs_->type(), this->rhs_->type(), false, NULL) @@ -4397,6 +4422,13 @@ Statement* Send_statement::do_flatten(Gogo*, Named_object*, Block*, 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(); if (!Type::are_identical(element_type, this->val_->type(), false, NULL) && this->val_->type()->interface_type() != NULL