diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-02-15 22:37:07 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-02-15 22:37:07 +0000 |
commit | fdd6f94b11a377119dc23c679a1985737a2ae6d7 (patch) | |
tree | 655af659633c6288e1246526c2d3e83d0206ef53 /gcc/go | |
parent | 69eb61d47a9c6dae5308134ee809d85882fbeb10 (diff) | |
download | gcc-fdd6f94b11a377119dc23c679a1985737a2ae6d7.zip gcc-fdd6f94b11a377119dc23c679a1985737a2ae6d7.tar.gz gcc-fdd6f94b11a377119dc23c679a1985737a2ae6d7.tar.bz2 |
Don't crash on erroneous thunk call.
From-SVN: r170201
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 31 |
1 files changed, 24 insertions, 7 deletions
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 268c728..bb5a6a0 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -2215,6 +2215,8 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name, Struct_field_list::const_iterator p = fields->begin(); for (unsigned int i = 0; i < next_index; ++i) ++p; + bool is_recover_call = ce->is_recover_call(); + Expression* recover_arg = NULL; for (; p != fields->end(); ++p, ++next_index) { Expression* thunk_param = Expression::make_var_reference(named_parameter, @@ -2224,19 +2226,28 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name, Expression* param = Expression::make_field_reference(thunk_param, next_index, location); - call_params->push_back(param); + if (!is_recover_call) + call_params->push_back(param); + else + { + gcc_assert(call_params->empty()); + recover_arg = param; + } + } + + if (call_params->empty()) + { + delete call_params; + call_params = NULL; } Expression* call = Expression::make_call(func_to_call, call_params, false, location); // We need to lower in case this is a builtin function. call = call->lower(gogo, function, -1); - if (may_call_recover) - { - Call_expression* ce = call->call_expression(); - if (ce != NULL) - ce->set_is_deferred(); - } + Call_expression* call_ce = call->call_expression(); + if (call_ce != NULL && may_call_recover) + call_ce->set_is_deferred(); Statement* call_statement = Statement::make_statement(call); @@ -2244,6 +2255,12 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name, // just for this statement now. call_statement->determine_types(); + // Sanity check. + call->check_types(gogo); + + if (call_ce != NULL && recover_arg != NULL) + call_ce->set_recover_arg(recover_arg); + gogo->add_statement(call_statement); // If this is a defer statement, the label comes immediately after |