void
Unary_expression::do_check_types(Gogo*)
{
+ Type* type = this->expr_->type();
+ if (type->is_error_type())
+ {
+ this->set_is_error();
+ return;
+ }
+
switch (this->op_)
{
case OPERATOR_PLUS:
case OPERATOR_MINUS:
- {
- Type* type = this->expr_->type();
- if (type->integer_type() == NULL
- && type->float_type() == NULL
- && type->complex_type() == NULL
- && !type->is_error_type())
- this->report_error(_("expected numeric type"));
- }
+ if (type->integer_type() == NULL
+ && type->float_type() == NULL
+ && type->complex_type() == NULL)
+ this->report_error(_("expected numeric type"));
break;
case OPERATOR_NOT:
case OPERATOR_XOR:
- {
- Type* type = this->expr_->type();
- if (type->integer_type() == NULL
- && !type->is_boolean_type()
- && !type->is_error_type())
- this->report_error(_("expected integer or boolean type"));
- }
+ if (type->integer_type() == NULL
+ && !type->is_boolean_type())
+ this->report_error(_("expected integer or boolean type"));
break;
case OPERATOR_AND:
case OPERATOR_MULT:
// Indirecting through a pointer.
- {
- Type* type = this->expr_->type();
- if (type->points_to() == NULL
- && !type->is_error_type())
- this->report_error(_("expected pointer"));
- }
+ if (type->points_to() == NULL)
+ this->report_error(_("expected pointer"));
break;
default:
Type* left_type = this->left_->type();
Type* right_type = this->right_->type();
if (left_type->is_error_type() || right_type->is_error_type())
- return;
+ {
+ this->set_is_error();
+ return;
+ }
if (this->op_ == OPERATOR_EQEQ
|| this->op_ == OPERATOR_NOTEQ
gcc_unreachable();
}
- if (left_type->is_string_type())
+ if (left_type->is_string_type() && right_type->is_string_type())
{
- gcc_assert(right_type->is_string_type());
tree string_type = Type::make_string_type()->get_tree(context->gogo());
static tree string_compare_decl;
left_tree = Gogo::call_builtin(&string_compare_decl,
right_tree);
right_tree = build_int_cst_type(integer_type_node, 0);
}
-
- if ((left_type->interface_type() != NULL
- && right_type->interface_type() == NULL
- && !right_type->is_nil_type())
- || (left_type->interface_type() == NULL
- && !left_type->is_nil_type()
- && right_type->interface_type() != NULL))
+ else if ((left_type->interface_type() != NULL
+ && right_type->interface_type() == NULL
+ && !right_type->is_nil_type())
+ || (left_type->interface_type() == NULL
+ && !left_type->is_nil_type()
+ && right_type->interface_type() != NULL))
{
// Comparing an interface value to a non-interface value.
if (left_type->interface_type() == NULL)
}
}
+ if (left_tree == error_mark_node || right_tree == error_mark_node)
+ return error_mark_node;
+
tree ret = fold_build2(code, boolean_type_node, left_tree, right_tree);
if (CAN_HAVE_LOCATION_P(ret))
SET_EXPR_LOCATION(ret, location);
? this->expr_type_
: this->expr_->type());
etype = etype->deref();
- if (!Type::are_identical(rtype, etype, NULL))
+ if (!Type::are_identical(rtype, etype, true, NULL))
this->report_error(_("method type does not match object type"));
}
}
if (arg == NULL)
return false;
Type* arg_type = arg->type();
- if (arg_type->is_error_type())
+ if (arg_type->is_error_type() || arg_type->is_undefined())
return false;
if (arg_type->is_abstract())
return false;
bool ret = false;
Type* itype;
if (args->back()->float_constant_value(i, &itype)
- && Type::are_identical(rtype, itype, NULL))
+ && Type::are_identical(rtype, itype, false, NULL))
{
mpfr_set(real, r, GMP_RNDN);
mpfr_set(imag, i, GMP_RNDN);
break;
}
- if (!Type::are_identical(e1, e2, NULL))
+ if (!Type::are_identical(e1, e2, true, NULL))
this->report_error(_("element types must be the same"));
}
break;
|| args->back()->type()->is_error_type())
this->set_is_error();
else if (!Type::are_identical(args->front()->type(),
- args->back()->type(), NULL))
+ args->back()->type(), true, NULL))
this->report_error(_("cmplx arguments must have identical types"));
else if (args->front()->type()->float_type() == NULL)
this->report_error(_("cmplx arguments must have "
gcc_unreachable();
}
+ if (val_tree == error_mark_node)
+ return error_mark_node;
+
tree type_tree = Type::lookup_integer_type("int")->get_tree(gogo);
if (type_tree == TREE_TYPE(val_tree))
return val_tree;
void_type_node,
TREE_TYPE(arg),
arg);
- append_to_statement_list(call, &stmt_list);
+ if (call != error_mark_node)
+ append_to_statement_list(call, &stmt_list);
}
}
arg1_tree = save_expr(arg1_tree);
tree arg1_val = at->value_pointer_tree(gogo, arg1_tree);
tree arg1_len = at->length_tree(gogo, arg1_tree);
+ if (arg1_val == error_mark_node || arg1_len == error_mark_node)
+ return error_mark_node;
Type* arg2_type = arg2->type();
tree arg2_val;
arg2_val = String_type::bytes_tree(gogo, arg2_tree);
arg2_len = String_type::length_tree(gogo, arg2_tree);
}
+ if (arg2_val == error_mark_node || arg2_len == error_mark_node)
+ return error_mark_node;
arg1_len = save_expr(arg1_len);
arg2_len = save_expr(arg2_len);
Type* element_type = at->element_type();
tree element_type_tree = element_type->get_tree(gogo);
+ if (element_type_tree == error_mark_node)
+ return error_mark_node;
tree element_size = TYPE_SIZE_UNIT(element_type_tree);
tree bytecount = fold_convert_loc(location, TREE_TYPE(element_size),
len);
Array_type* param_at = param_type->array_type();
if (param_at != NULL
&& Type::are_identical(var_at->element_type(),
- param_at->element_type(), NULL))
+ param_at->element_type(), true, NULL))
return true;
error_at(arg->location(), "... mismatch: passing ...T as ...");
*issued_error = true;
ok = false;
}
if (!ok)
- error_at(this->location(),
- "number of results does not match number of values");
+ this->report_error(_("number of results does not match number of values"));
}
// Determine the type. We have nothing to do here, but the 0 result
gcc_assert(array_type != NULL);
tree type_tree = array_type->get_tree(gogo);
+ if (type_tree == error_mark_node)
+ return error_mark_node;
tree array_tree = this->array_->get_tree(context);
if (array_tree == error_mark_node)
if (array_type->length() == NULL && !DECL_P(array_tree))
array_tree = save_expr(array_tree);
tree length_tree = array_type->length_tree(gogo, array_tree);
+ if (length_tree == error_mark_node)
+ return error_mark_node;
length_tree = save_expr(length_tree);
tree length_type = TREE_TYPE(length_tree);
// Open array.
tree values = array_type->value_pointer_tree(gogo, array_tree);
tree element_type_tree = array_type->element_type()->get_tree(gogo);
+ if (element_type_tree == error_mark_node)
+ return error_mark_node;
tree element_size = TYPE_SIZE_UNIT(element_type_tree);
tree offset = fold_build2_loc(loc, MULT_EXPR, sizetype,
start_tree, element_size);
// Array slice.
tree capacity_tree = array_type->capacity_tree(gogo, array_tree);
+ if (capacity_tree == error_mark_node)
+ return error_mark_node;
capacity_tree = fold_convert_loc(loc, length_type, capacity_tree);
tree end_tree;
}
tree element_type_tree = array_type->element_type()->get_tree(gogo);
+ if (element_type_tree == error_mark_node)
+ return error_mark_node;
tree element_size = TYPE_SIZE_UNIT(element_type_tree);
tree offset = fold_build2_loc(loc, MULT_EXPR, sizetype,
element_size);
tree value_pointer = array_type->value_pointer_tree(gogo, array_tree);
+ if (value_pointer == error_mark_node)
+ return error_mark_node;
value_pointer = fold_build2_loc(loc, POINTER_PLUS_EXPR,
TREE_TYPE(value_pointer),
return error_mark_node;
gcc_assert(TREE_CODE(TREE_TYPE(struct_tree)) == RECORD_TYPE);
tree field = TYPE_FIELDS(TREE_TYPE(struct_tree));
- gcc_assert(field != NULL_TREE);
+ if (field == NULL_TREE)
+ {
+ // This can happen for a type which refers to itself indirectly
+ // and then turns out to be erroneous.
+ gcc_assert(saw_errors());
+ return error_mark_node;
+ }
for (unsigned int i = this->field_index_; i > 0; --i)
{
field = DECL_CHAIN(field);
{
Type* element_type = this->type()->array_type()->element_type();
tree element_type_tree = element_type->get_tree(context->gogo());
+ if (element_type_tree == error_mark_node)
+ return error_mark_node;
+
tree values;
tree length_tree;
if (this->vals() == NULL || this->vals()->empty())
// Build a constructor for the open array.
tree type_tree = this->type()->get_tree(context->gogo());
+ if (type_tree == error_mark_node)
+ return error_mark_node;
gcc_assert(TREE_CODE(type_tree) == RECORD_TYPE);
VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
elt->value = fold_convert(TREE_TYPE(field), length_tree);
tree constructor = build_constructor(type_tree, init);
+ if (constructor == error_mark_node)
+ return error_mark_node;
if (!is_in_function && is_constant_initializer)
TREE_CONSTANT(constructor) = 1;
make_array(Type*, Expression_list*);
Expression*
- lower_map(Type*);
+ lower_map(Gogo*, Named_object*, Type*);
// The type of the composite literal.
Type* type_;
// the type.
Expression*
-Composite_literal_expression::do_lower(Gogo*, Named_object*, int)
+Composite_literal_expression::do_lower(Gogo* gogo, Named_object* function, int)
{
Type* type = this->type_;
else if (type->array_type() != NULL)
return this->lower_array(type);
else if (type->map_type() != NULL)
- return this->lower_map(type);
+ return this->lower_map(gogo, function, type);
else
{
error_at(this->location(),
// Lower a map composite literal.
Expression*
-Composite_literal_expression::lower_map(Type* type)
+Composite_literal_expression::lower_map(Gogo* gogo, Named_object* function,
+ Type* type)
{
source_location location = this->location();
if (this->vals_ != NULL)
return Expression::make_error(location);
}
- for (Expression_list::const_iterator p = this->vals_->begin();
+ for (Expression_list::iterator p = this->vals_->begin();
p != this->vals_->end();
p += 2)
{
"map composite literal must have keys for every value");
return Expression::make_error(location);
}
+ // Make sure we have lowered the key; it may not have been
+ // lowered in order to handle keys for struct composite
+ // literals. Lower it now to get the right error message.
+ if ((*p)->unknown_expression() != NULL)
+ {
+ (*p)->unknown_expression()->clear_is_composite_literal_key();
+ gogo->lower_expression(function, &*p);
+ gcc_assert((*p)->is_error_expression());
+ return Expression::make_error(location);
+ }
}
}
this->report_error(_("invalid unsafe.Pointer conversion"));
}
else if (expr_type->interface_type() == NULL)
- this->report_error(_("type assertion only valid for interface types"));
+ {
+ if (!expr_type->is_error_type() && !this->type_->is_error_type())
+ this->report_error(_("type assertion only valid for interface types"));
+ this->set_is_error();
+ }
else if (this->type_->interface_type() == NULL)
{
std::string reason;
if (!expr_type->interface_type()->implements_interface(this->type_,
&reason))
{
- if (reason.empty())
- this->report_error(_("impossible type assertion: "
- "type does not implement interface"));
- else
+ if (!this->type_->is_error_type())
{
- error_at(this->location(),
- ("impossible type assertion: "
- "type does not implement interface (%s)"),
- reason.c_str());
- this->set_is_error();
+ if (reason.empty())
+ this->report_error(_("impossible type assertion: "
+ "type does not implement interface"));
+ else
+ error_at(this->location(),
+ ("impossible type assertion: "
+ "type does not implement interface (%s)"),
+ reason.c_str());
}
+ this->set_is_error();
}
}
}