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)
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
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)
Statement_inserter* inserter)
{
Location loc = this->location();
+ if (this->is_erroneous_call())
+ {
+ go_assert(saw_errors());
+ return Expression::make_error(loc);
+ }
switch (this->code_)
{
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;
}
}
+// 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*
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);
}
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);
{
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
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 =
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 =
{
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 =
{
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 =
{
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 =
++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 =
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_,
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)
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;
}
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)
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)
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