This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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();

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]