diff options
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 40 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.h | 8 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 51 |
4 files changed, 100 insertions, 1 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 4d0f44f..5323e18 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 2872d2e..95b76bd 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -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 diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index f4155a2..c49bc92 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -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*); diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index d08cbc9..ab7166b 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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_); } |