Commit d73b8f84 by Ian Lance Taylor

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
parent a5768d38
2f21020c9f61b31bd04d5b814aaa27bf976bf07a d3997526dc0710e6b9b727a41184ce1770805794
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -1786,8 +1786,41 @@ Gogo::start_function(const std::string& name, Function_type* type, ...@@ -1786,8 +1786,41 @@ Gogo::start_function(const std::string& name, Function_type* type,
char buf[30]; char buf[30];
snprintf(buf, sizeof buf, ".$sink%d", sink_count); snprintf(buf, sizeof buf, ".$sink%d", sink_count);
++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(); 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()) else if (!type->is_method())
{ {
...@@ -6985,7 +7018,10 @@ Type_declaration::define_methods(Named_type* nt) ...@@ -6985,7 +7018,10 @@ Type_declaration::define_methods(Named_type* nt)
for (std::vector<Named_object*>::const_iterator p = this->methods_.begin(); for (std::vector<Named_object*>::const_iterator p = this->methods_.begin();
p != this->methods_.end(); p != this->methods_.end();
++p) ++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. // We are using the type. Return true if we should issue a warning.
......
...@@ -2114,6 +2114,11 @@ class Type_declaration ...@@ -2114,6 +2114,11 @@ class Type_declaration
add_method_declaration(const std::string& name, Package*, add_method_declaration(const std::string& name, Package*,
Function_type* type, Location location); 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. // Return whether any methods were defined.
bool bool
has_methods() const; has_methods() const;
......
...@@ -12210,6 +12210,17 @@ Forward_declaration_type::add_method_declaration(const std::string& name, ...@@ -12210,6 +12210,17 @@ Forward_declaration_type::add_method_declaration(const std::string& name,
return td->add_method_declaration(name, package, type, location); 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. // Traversal.
int int
......
...@@ -3379,6 +3379,10 @@ class Forward_declaration_type : public Type ...@@ -3379,6 +3379,10 @@ class Forward_declaration_type : public Type
add_method_declaration(const std::string& name, Package*, Function_type*, add_method_declaration(const std::string& name, Package*, Function_type*,
Location); Location);
// Add an already created object as a method to this type.
void
add_existing_method(Named_object*);
protected: protected:
int int
do_traverse(Traverse* traverse); do_traverse(Traverse* traverse);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment