aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2021-03-16 22:34:20 -0700
committerIan Lance Taylor <iant@golang.org>2021-03-17 12:17:51 -0700
commitf3e9c98a9f40fc24bb4ecef6aaa94ff799c8d587 (patch)
treea3451277603bc8fbe2eddce5f4ad63f790129a01 /gcc/go/gofrontend
parentc86c5195c8c02f5891a222f498c074b373aa946c (diff)
downloadgcc-f3e9c98a9f40fc24bb4ecef6aaa94ff799c8d587.zip
gcc-f3e9c98a9f40fc24bb4ecef6aaa94ff799c8d587.tar.gz
gcc-f3e9c98a9f40fc24bb4ecef6aaa94ff799c8d587.tar.bz2
compiler: copy receiver argument for go/defer of method call
Test case is https://golang.org/cl/302371. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/302270
Diffstat (limited to 'gcc/go/gofrontend')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc2
-rw-r--r--gcc/go/gofrontend/statements.cc27
3 files changed, 29 insertions, 2 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index c0bfa1f..a3eef23 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-10b00ad87303d37c68b2d54dd25d655bd316946e
+4bdff733a0c2a9ddc3eff104b1be03df058a79c4
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/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 101cbe7..5409d26 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -11017,7 +11017,7 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function,
// If this is call to a method, call the method directly passing the
// object as the first parameter.
Bound_method_expression* bme = this->fn_->bound_method_expression();
- if (bme != NULL)
+ if (bme != NULL && !this->is_deferred_ && !this->is_concurrent_)
{
Named_object* methodfn = bme->function();
Function_type* mft = (methodfn->is_function()
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 7ad7339..b066011 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -2524,6 +2524,8 @@ Thunk_statement::is_constant_function() const
return fn->func_expression()->closure() == NULL;
if (fn->interface_field_reference_expression() != NULL)
return true;
+ if (fn->bound_method_expression() != NULL)
+ return true;
return false;
}
@@ -2566,6 +2568,7 @@ Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
Expression* fn = ce->fn();
Interface_field_reference_expression* interface_method =
fn->interface_field_reference_expression();
+ Bound_method_expression* bme = fn->bound_method_expression();
Location location = this->location();
@@ -2594,6 +2597,8 @@ Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
if (interface_method != NULL)
vals->push_back(interface_method->expr());
+ if (bme != NULL)
+ vals->push_back(bme->first_argument());
if (ce->args() != NULL)
{
@@ -2714,6 +2719,16 @@ Thunk_statement::build_struct(Function_type* fntype)
fields->push_back(Struct_field(tid));
}
+ // If this thunk statement calls a bound method expression, as in
+ // "go s.m()", we pass the bound method argument to the thunk,
+ // to ensure that we make a copy of it if needed.
+ Bound_method_expression* bme = fn->bound_method_expression();
+ if (bme != NULL)
+ {
+ Typed_identifier tid("object", bme->first_argument()->type(), location);
+ fields->push_back(Struct_field(tid));
+ }
+
// The predeclared recover function has no argument. However, we
// add an argument when building recover thunks. Handle that here.
if (ce->is_recover_call())
@@ -2843,6 +2858,7 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
Interface_field_reference_expression* interface_method =
ce->fn()->interface_field_reference_expression();
+ Bound_method_expression* bme = ce->fn()->bound_method_expression();
Expression* func_to_call;
unsigned int next_index;
@@ -2870,6 +2886,17 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name)
next_index = 1;
}
+ if (bme != NULL)
+ {
+ // This is a call to a method.
+ go_assert(next_index == 0);
+ Expression* r = Expression::make_field_reference(thunk_parameter, 0,
+ location);
+ func_to_call = Expression::make_bound_method(r, bme->method(),
+ bme->function(), location);
+ next_index = 1;
+ }
+
Expression_list* call_params = new Expression_list();
const Struct_field_list* fields = this->struct_type_->fields();
Struct_field_list::const_iterator p = fields->begin();