compiler: report correct errors for sink methods
If somebody writes func (s []int) _() {} we should report an error. Before this patch we were silently accepting this code, because we didn't report any errors about the receiver if the method was a sink. This patch is unfortunately slightly complex to handle the case of func (x int) _() {} which we can only detect after define_global_names. This fixes blank1.go in the current gc testsuite. Reviewed-on: https://go-review.googlesource.com/43456 From-SVN: r248081
This commit is contained in:
parent
a5768d38a6
commit
d73b8f8417
@ -1,4 +1,4 @@
|
||||
2f21020c9f61b31bd04d5b814aaa27bf976bf07a
|
||||
d3997526dc0710e6b9b727a41184ce1770805794
|
||||
|
||||
The first line of this file holds the git revision number of the last
|
||||
merge done from the gofrontend repository.
|
||||
|
@ -1786,8 +1786,41 @@ Gogo::start_function(const std::string& name, Function_type* type,
|
||||
char buf[30];
|
||||
snprintf(buf, sizeof buf, ".$sink%d", sink_count);
|
||||
++sink_count;
|
||||
ret = this->package_->bindings()->add_function(buf, NULL, function);
|
||||
ret = Named_object::make_function(buf, NULL, function);
|
||||
ret->func_value()->set_is_sink();
|
||||
|
||||
if (!type->is_method())
|
||||
ret = this->package_->bindings()->add_named_object(ret);
|
||||
else if (add_method_to_type)
|
||||
{
|
||||
// We should report errors even for sink methods.
|
||||
Type* rtype = type->receiver()->type();
|
||||
// Avoid points_to and deref to avoid getting an error if
|
||||
// the type is not yet defined.
|
||||
if (rtype->classification() == Type::TYPE_POINTER)
|
||||
rtype = rtype->points_to();
|
||||
while (rtype->named_type() != NULL
|
||||
&& rtype->named_type()->is_alias())
|
||||
rtype = rtype->named_type()->real_type()->forwarded();
|
||||
if (rtype->is_error_type())
|
||||
;
|
||||
else if (rtype->named_type() != NULL)
|
||||
{
|
||||
if (rtype->named_type()->named_object()->package() != NULL)
|
||||
go_error_at(type->receiver()->location(),
|
||||
"may not define methods on non-local type");
|
||||
}
|
||||
else if (rtype->forward_declaration_type() != NULL)
|
||||
{
|
||||
// Go ahead and add the method in case we need to report
|
||||
// an error when we see the definition.
|
||||
rtype->forward_declaration_type()->add_existing_method(ret);
|
||||
}
|
||||
else
|
||||
go_error_at(type->receiver()->location(),
|
||||
("invalid receiver type "
|
||||
"(receiver must be a named type)"));
|
||||
}
|
||||
}
|
||||
else if (!type->is_method())
|
||||
{
|
||||
@ -6985,7 +7018,10 @@ Type_declaration::define_methods(Named_type* nt)
|
||||
for (std::vector<Named_object*>::const_iterator p = this->methods_.begin();
|
||||
p != this->methods_.end();
|
||||
++p)
|
||||
nt->add_existing_method(*p);
|
||||
{
|
||||
if (!(*p)->func_value()->is_sink())
|
||||
nt->add_existing_method(*p);
|
||||
}
|
||||
}
|
||||
|
||||
// We are using the type. Return true if we should issue a warning.
|
||||
|
@ -2114,6 +2114,11 @@ class Type_declaration
|
||||
add_method_declaration(const std::string& name, Package*,
|
||||
Function_type* type, Location location);
|
||||
|
||||
// Add an already created object as a method.
|
||||
void
|
||||
add_existing_method(Named_object* no)
|
||||
{ this->methods_.push_back(no); }
|
||||
|
||||
// Return whether any methods were defined.
|
||||
bool
|
||||
has_methods() const;
|
||||
|
@ -12210,6 +12210,17 @@ Forward_declaration_type::add_method_declaration(const std::string& name,
|
||||
return td->add_method_declaration(name, package, type, location);
|
||||
}
|
||||
|
||||
// Add an already created object as a method.
|
||||
|
||||
void
|
||||
Forward_declaration_type::add_existing_method(Named_object* nom)
|
||||
{
|
||||
Named_object* no = this->named_object();
|
||||
if (no->is_unknown())
|
||||
no->declare_as_type();
|
||||
no->type_declaration_value()->add_existing_method(nom);
|
||||
}
|
||||
|
||||
// Traversal.
|
||||
|
||||
int
|
||||
|
@ -3379,6 +3379,10 @@ class Forward_declaration_type : public Type
|
||||
add_method_declaration(const std::string& name, Package*, Function_type*,
|
||||
Location);
|
||||
|
||||
// Add an already created object as a method to this type.
|
||||
void
|
||||
add_existing_method(Named_object*);
|
||||
|
||||
protected:
|
||||
int
|
||||
do_traverse(Traverse* traverse);
|
||||
|
Loading…
x
Reference in New Issue
Block a user