@@ -1,4 +1,4 @@
-adcf10890833026437a94da54934ce50c0018309
+920549b6382a2623538d31001271941f0e9e5a51
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
@@ -5763,6 +5763,26 @@ Function::check_labels() const
}
}
+// Set the receiver type. This is used to remove aliases.
+
+void
+Function::set_receiver_type(Type* rtype)
+{
+ Function_type* oft = this->type_;
+ Typed_identifier* rec = new Typed_identifier(oft->receiver()->name(),
+ rtype,
+ oft->receiver()->location());
+ Typed_identifier_list* parameters = NULL;
+ if (oft->parameters() != NULL)
+ parameters = oft->parameters()->copy();
+ Typed_identifier_list* results = NULL;
+ if (oft->results() != NULL)
+ results = oft->results()->copy();
+ Function_type* nft = Type::make_function_type(rec, parameters, results,
+ oft->location());
+ this->type_ = nft;
+}
+
// Swap one function with another. This is used when building the
// thunk we use to call a function which calls recover. It may not
// work for any other case.
@@ -7285,6 +7305,26 @@ Function_declaration::set_nointerface()
this->pragmas_ |= GOPRAGMA_NOINTERFACE;
}
+// Set the receiver type. This is used to remove aliases.
+
+void
+Function_declaration::set_receiver_type(Type* rtype)
+{
+ Function_type* oft = this->fntype_;
+ Typed_identifier* rec = new Typed_identifier(oft->receiver()->name(),
+ rtype,
+ oft->receiver()->location());
+ Typed_identifier_list* parameters = NULL;
+ if (oft->parameters() != NULL)
+ parameters = oft->parameters()->copy();
+ Typed_identifier_list* results = NULL;
+ if (oft->results() != NULL)
+ results = oft->results()->copy();
+ Function_type* nft = Type::make_function_type(rec, parameters, results,
+ oft->location());
+ this->fntype_ = nft;
+}
+
// Import an inlinable function. This is used for an inlinable
// function whose body is recorded in the export data. Parse the
// export data into a Block and create a regular function using that
@@ -1724,6 +1724,10 @@ class Function
set_is_referenced_by_inline()
{ this->is_referenced_by_inline_ = true; }
+ // Set the receiver type. This is used to remove aliases.
+ void
+ set_receiver_type(Type* rtype);
+
// Swap with another function. Used only for the thunk which calls
// recover.
void
@@ -1990,6 +1994,10 @@ class Function_declaration
set_is_on_inlinable_list()
{ this->is_on_inlinable_list_ = true; }
+ // Set the receiver type. This is used to remove aliases.
+ void
+ set_receiver_type(Type* rtype);
+
// Import the function body, creating a function.
void
import_function_body(Gogo*, Named_object*);
@@ -10416,6 +10416,57 @@ Named_type::finalize_methods(Gogo* gogo)
return;
}
+ // Remove any aliases in the local method receiver types.
+ Bindings* methods = this->local_methods_;
+ if (methods != NULL)
+ {
+ for (Bindings::const_declarations_iterator p =
+ methods->begin_declarations();
+ p != methods->end_declarations();
+ ++p)
+ {
+ Named_object* no = p->second;
+ Function_type* fntype;
+ if (no->is_function())
+ fntype = no->func_value()->type();
+ else if (no->is_function_declaration())
+ fntype = no->func_declaration_value()->type();
+ else
+ {
+ go_assert(saw_errors());
+ continue;
+ }
+
+ Type* rtype = fntype->receiver()->type();
+ bool is_pointer = false;
+ Type* pt = rtype->points_to();
+ if (pt != NULL)
+ {
+ rtype = pt;
+ is_pointer = true;
+ }
+ if (rtype->named_type() != this)
+ {
+ if (rtype->unalias() != this)
+ {
+ go_assert(saw_errors());
+ continue;
+ }
+
+ rtype = this;
+ if (is_pointer)
+ rtype = Type::make_pointer_type(rtype);
+
+ if (no->is_function())
+ no->func_value()->set_receiver_type(rtype);
+ else if (no->is_function_declaration())
+ no->func_declaration_value()->set_receiver_type(rtype);
+ else
+ go_unreachable();
+ }
+ }
+ }
+
Type::finalize_methods(gogo, this, this->location_, &this->all_methods_);
}