This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gccgo] Give error for invalid copy of value method
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 18 Dec 2009 21:58:58 -0800
- Subject: [gccgo] Give error for invalid copy of value method
gccgo was not giving an error when a method which takes a value was
called with a type which can not be copied. This patch fixes that
case. That in turn forced me to clean up a few cases so that methods
were correctly marked as taking a pointer rather than a value, and so
that the code explicitly uses the address operator when calling a
pointer method. Previously those were being hidden by the fact that
the compiler always takes the address behind the scenes. Patch
committed to gccgo branch.
Ian
Index: types.cc
===================================================================
--- types.cc (revision 155355)
+++ types.cc (working copy)
@@ -4893,6 +4893,8 @@ Named_type::bind_field_or_method(Express
Gogo::unpack_hidden_name(name).c_str());
return Expression::make_error(location);
}
+ if (!m->is_value_method() && expr->type()->points_to() == NULL)
+ expr = Expression::make_unary(OPERATOR_AND, expr, location);
return m->bind_method(expr, location);
}
else
@@ -5107,7 +5109,8 @@ Named_type::add_local_methods_for_type(
bool is_value_method = (is_embedded_pointer
|| !Named_type::method_expects_pointer(no));
Method* m = new Named_method(no, field_indexes, depth, is_value_method,
- needs_stub_method);
+ (needs_stub_method
+ || (depth > 0 && is_value_method)));
if (this->all_methods_->insert(no->name(), m))
ret = true;
else
@@ -5255,7 +5258,9 @@ Named_type::build_stub_methods(Gogo* gog
snprintf(buf, sizeof buf, "%s%d", Named_type::receiver_name, counter);
++counter;
- Type* receiver_type = Type::make_pointer_type(this);
+ Type* receiver_type = this;
+ if (!m->is_value_method())
+ receiver_type = Type::make_pointer_type(receiver_type);
source_location receiver_location = m->receiver_location();
Typed_identifier* receiver = new Typed_identifier(buf, receiver_type,
receiver_location);
Index: expressions.cc
===================================================================
--- expressions.cc (revision 155355)
+++ expressions.cc (working copy)
@@ -6221,8 +6221,32 @@ Call_expression::do_check_types(Gogo*)
{
// We don't support pointers to methods, so the function has to
// be a bound method expression.
- if (this->fn_->bound_method_expression() == NULL)
- this->report_error(_("method call without object"));
+ Bound_method_expression* bme = this->fn_->bound_method_expression();
+ if (bme == NULL)
+ {
+ this->report_error(_("method call without object"));
+ return;
+ }
+ Type* first_arg_type = bme->first_argument()->type();
+ if (first_arg_type->points_to() == NULL)
+ {
+ // When passing a value, we need to check that we are
+ // permitted to copy it.
+ std::string reason;
+ if (!Type::are_compatible_for_assign(fntype->receiver()->type(),
+ first_arg_type, &reason))
+ {
+ if (reason.empty())
+ this->report_error("incompatible type for receiver");
+ else
+ {
+ error_at(this->location(),
+ "incompatible type for receiver (%s)",
+ reason.c_str());
+ this->set_is_error();
+ }
+ }
+ }
}
const Typed_identifier_list* parameters = fntype->parameters();