diff options
author | Ian Lance Taylor <iant@golang.org> | 2021-03-17 12:19:01 -0700 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2021-03-17 12:19:01 -0700 |
commit | f10c7c4596dda99d2ee872c995ae4aeda65adbdf (patch) | |
tree | a3451277603bc8fbe2eddce5f4ad63f790129a01 /gcc/go/gofrontend/statements.cc | |
parent | bc636c218f2b28da06cd1404d5b35d1f8cc43fd1 (diff) | |
parent | f3e9c98a9f40fc24bb4ecef6aaa94ff799c8d587 (diff) | |
download | gcc-f10c7c4596dda99d2ee872c995ae4aeda65adbdf.zip gcc-f10c7c4596dda99d2ee872c995ae4aeda65adbdf.tar.gz gcc-f10c7c4596dda99d2ee872c995ae4aeda65adbdf.tar.bz2 |
Merge from trunk revision f3e9c98a9f40fc24bb4ecef6aaa94ff799c8d587.
Diffstat (limited to 'gcc/go/gofrontend/statements.cc')
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 27 |
1 files changed, 27 insertions, 0 deletions
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(); |