Patchwork Go patch committed: Don't crash on erroneous thunk call

login
register
mail settings
Submitter Ian Taylor
Date Feb. 15, 2011, 10:37 p.m.
Message ID <mcroc6c53hm.fsf@google.com>
Download mbox | patch
Permalink /patch/83308/
State New
Headers show

Comments

Ian Taylor - Feb. 15, 2011, 10:37 p.m.
This patch to the Go frontend avoids crashing on an erroneous thunk
call.  This treats the calls built for thunks more like regular calls,
and runs the usual type checking pass on them.  Bootstrapped and ran Go
testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

Patch

diff -r b511d4c035b7 go/statements.cc
--- a/go/statements.cc	Tue Feb 15 11:52:43 2011 -0800
+++ b/go/statements.cc	Tue Feb 15 14:34:31 2011 -0800
@@ -2215,6 +2215,8 @@ 
   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 @@ 
       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 @@ 
   // 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