Go patch committed: pass Gogo to more passes

Message ID CAOyqgcUQBLOre=--Mu_0onwxCETNX=3PP+eJL6j6Gch865pkew@mail.gmail.com
State Unresolved
Headers
Series Go patch committed: pass Gogo to more passes |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Ian Lance Taylor Oct. 23, 2023, 1:44 a.m. UTC
  This patch to the G frontend passes a pointer to the Gogo IR to the
determine types pass and the type verification pass.  This is a
straight refactoring that does not change the compiler behavior.  This
is in preparation for future CLs that rearrange the pass ordering.

This introduces one new call to go_get_gogo, which will be removed in
a future CL.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
b513aa235d6e5d7e2a36ee789c60891fce873340
  

Patch

diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index d24054e0d93..28683d6852b 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@ 
-967a215d6419c3db58f8f59a0c252c458abce395
+06ada1f2ab9b05e54641438db28c557c6900b2a3
 
 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 d276bd811cc..273831fabf3 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -205,18 +205,18 @@  Expression::report_error(const char* msg)
 // child class.
 
 void
-Expression::determine_type(const Type_context* context)
+Expression::determine_type(Gogo* gogo, const Type_context* context)
 {
-  this->do_determine_type(context);
+  this->do_determine_type(gogo, context);
 }
 
 // Set types when there is no context.
 
 void
-Expression::determine_type_no_context()
+Expression::determine_type_no_context(Gogo* gogo)
 {
   Type_context context;
-  this->do_determine_type(&context);
+  this->do_determine_type(gogo, &context);
 }
 
 // Return true if two expressions refer to the same variable or struct
@@ -842,7 +842,7 @@  class Error_expression : public Expression
   { return Type::make_error_type(); }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -897,7 +897,7 @@  Type_expression : public Expression
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   void
@@ -998,10 +998,10 @@  Var_expression::do_type()
 // Determine the type of a reference to a variable.
 
 void
-Var_expression::do_determine_type(const Type_context*)
+Var_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
   if (this->variable_->is_variable())
-    this->variable_->var_value()->determine_type();
+    this->variable_->var_value()->determine_type(gogo);
 }
 
 // Something takes the address of this variable.  This means that we
@@ -1303,9 +1303,10 @@  Set_and_use_temporary_expression::do_type()
 
 void
 Set_and_use_temporary_expression::do_determine_type(
+    Gogo* gogo,
     const Type_context* context)
 {
-  this->expr_->determine_type(context);
+  this->expr_->determine_type(gogo, context);
 }
 
 // Take the address.
@@ -1378,7 +1379,7 @@  class Sink_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   Expression*
   do_copy()
@@ -1410,7 +1411,7 @@  Sink_expression::do_type()
 // Determine the type of a sink expression.
 
 void
-Sink_expression::do_determine_type(const Type_context* context)
+Sink_expression::do_determine_type(Gogo*, const Type_context* context)
 {
   if (context->type != NULL)
     this->type_ = context->type;
@@ -1805,7 +1806,7 @@  class Func_code_reference_expression : public Expression
   { return Type::make_pointer_type(Type::make_void_type()); }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -1983,7 +1984,7 @@  class Boolean_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   Expression*
   do_copy()
@@ -2035,7 +2036,7 @@  Boolean_expression::do_type()
 // Set the type from the context.
 
 void
-Boolean_expression::do_determine_type(const Type_context* context)
+Boolean_expression::do_determine_type(Gogo*, const Type_context* context)
 {
   if (this->type_ != NULL && !this->type_->is_abstract())
     ;
@@ -2108,7 +2109,7 @@  String_expression::do_type()
 // Set the type from the context.
 
 void
-String_expression::do_determine_type(const Type_context* context)
+String_expression::do_determine_type(Gogo*, const Type_context* context)
 {
   if (this->type_ != NULL && !this->type_->is_abstract())
     ;
@@ -2278,7 +2279,7 @@  class String_info_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { go_unreachable(); }
 
   Expression*
@@ -2390,7 +2391,7 @@  class String_value_expression : public Expression
   { return Type::make_string_type(); }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { go_unreachable(); }
 
   Expression*
@@ -2499,7 +2500,7 @@  class Integer_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context* context);
+  do_determine_type(Gogo*, const Type_context* context);
 
   void
   do_check_types(Gogo*);
@@ -2587,7 +2588,7 @@  Integer_expression::do_type()
 // abstract type to a real type.
 
 void
-Integer_expression::do_determine_type(const Type_context* context)
+Integer_expression::do_determine_type(Gogo*, const Type_context* context)
 {
   if (this->type_ != NULL && !this->type_->is_abstract())
     ;
@@ -2934,7 +2935,7 @@  class Float_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -2993,7 +2994,7 @@  Float_expression::do_type()
 // abstract type to a real type.
 
 void
-Float_expression::do_determine_type(const Type_context* context)
+Float_expression::do_determine_type(Gogo*, const Type_context* context)
 {
   if (this->type_ != NULL && !this->type_->is_abstract())
     ;
@@ -3158,7 +3159,7 @@  class Complex_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -3219,7 +3220,7 @@  Complex_expression::do_type()
 // abstract type to a real type.
 
 void
-Complex_expression::do_determine_type(const Type_context* context)
+Complex_expression::do_determine_type(Gogo*, const Type_context* context)
 {
   if (this->type_ != NULL && !this->type_->is_abstract())
     ;
@@ -3507,7 +3508,7 @@  Const_expression::do_type()
 // Set the type of the const reference.
 
 void
-Const_expression::do_determine_type(const Type_context* context)
+Const_expression::do_determine_type(Gogo*, const Type_context* context)
 {
   Type* ctype = this->constant_->const_value()->type();
   Type* cetype = (ctype != NULL
@@ -3719,7 +3720,7 @@  class Nil_expression : public Expression
   { return Type::make_nil_type(); }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -4137,10 +4138,10 @@  Type_conversion_expression::do_boolean_constant_value(bool* val) const
 // Determine the resulting type of the conversion.
 
 void
-Type_conversion_expression::do_determine_type(const Type_context*)
+Type_conversion_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
   Type_context subcontext(this->type_, false);
-  this->expr_->determine_type(&subcontext);
+  this->expr_->determine_type(gogo, &subcontext);
 }
 
 // Check that types are convertible.
@@ -5087,7 +5088,7 @@  Unary_expression::do_type()
 // Determine abstract types for a unary expression.
 
 void
-Unary_expression::do_determine_type(const Type_context* context)
+Unary_expression::do_determine_type(Gogo* gogo, const Type_context* context)
 {
   switch (this->op_)
     {
@@ -5095,7 +5096,7 @@  Unary_expression::do_determine_type(const Type_context* context)
     case OPERATOR_MINUS:
     case OPERATOR_NOT:
     case OPERATOR_XOR:
-      this->expr_->determine_type(context);
+      this->expr_->determine_type(gogo, context);
       break;
 
     case OPERATOR_AND:
@@ -5105,7 +5106,7 @@  Unary_expression::do_determine_type(const Type_context* context)
 			 ? NULL
 			 : context->type->points_to());
 	Type_context subcontext(subtype, false);
-	this->expr_->determine_type(&subcontext);
+	this->expr_->determine_type(gogo, &subcontext);
       }
       break;
 
@@ -5116,7 +5117,7 @@  Unary_expression::do_determine_type(const Type_context* context)
 			 ? NULL
 			 : Type::make_pointer_type(context->type));
 	Type_context subcontext(subtype, false);
-	this->expr_->determine_type(&subcontext);
+	this->expr_->determine_type(gogo, &subcontext);
       }
       break;
 
@@ -6705,7 +6706,7 @@  Binary_expression::do_type()
 // Set type for a binary expression.
 
 void
-Binary_expression::do_determine_type(const Type_context* context)
+Binary_expression::do_determine_type(Gogo* gogo, const Type_context* context)
 {
   Type* tleft = this->left_->type();
   Type* tright = this->right_->type();
@@ -6782,7 +6783,7 @@  Binary_expression::do_determine_type(const Type_context* context)
 	subcontext.type = subcontext.type->make_non_abstract_type();
     }
 
-  this->left_->determine_type(&subcontext);
+  this->left_->determine_type(gogo, &subcontext);
 
   if (is_shift_op)
     {
@@ -6802,7 +6803,7 @@  Binary_expression::do_determine_type(const Type_context* context)
       subcontext.may_be_abstract = false;
     }
 
-  this->right_->determine_type(&subcontext);
+  this->right_->determine_type(gogo, &subcontext);
 
   if (is_comparison)
     {
@@ -7689,7 +7690,8 @@  String_concat_expression::do_type()
 }
 
 void
-String_concat_expression::do_determine_type(const Type_context* context)
+String_concat_expression::do_determine_type(Gogo* gogo,
+					    const Type_context* context)
 {
   Type_context subcontext(*context);
   for (Expression_list::iterator pe = this->exprs_->begin();
@@ -7708,7 +7710,7 @@  String_concat_expression::do_determine_type(const Type_context* context)
   for (Expression_list::iterator pe = this->exprs_->begin();
        pe != this->exprs_->end();
        ++pe)
-    (*pe)->determine_type(&subcontext);
+    (*pe)->determine_type(gogo, &subcontext);
 }
 
 void
@@ -7862,7 +7864,7 @@  Bound_method_expression::do_type()
 // Determine the types of a method expression.
 
 void
-Bound_method_expression::do_determine_type(const Type_context*)
+Bound_method_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
   Named_object* fn = this->method_->named_object();
   Function_type* fntype;
@@ -7873,11 +7875,11 @@  Bound_method_expression::do_determine_type(const Type_context*)
   else
     fntype = NULL;
   if (fntype == NULL || !fntype->is_method())
-    this->expr_->determine_type_no_context();
+    this->expr_->determine_type_no_context(gogo);
   else
     {
       Type_context subcontext(fntype->receiver()->type(), false);
-      this->expr_->determine_type(&subcontext);
+      this->expr_->determine_type(gogo, &subcontext);
     }
 }
 
@@ -8310,7 +8312,7 @@  Builtin_call_expression::do_set_recover_arg(Expression* arg)
 // specific expressions.  We also convert to a constant if we can.
 
 Expression*
-Builtin_call_expression::do_lower(Gogo*, Named_object* function,
+Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
 				  Statement_inserter* inserter, int)
 {
   if (this->is_error_expression())
@@ -8388,7 +8390,7 @@  Builtin_call_expression::do_lower(Gogo*, Named_object* function,
       break;
 
     case BUILTIN_MAKE:
-      return this->lower_make(inserter);
+      return this->lower_make(gogo, inserter);
 
     case BUILTIN_RECOVER:
       if (function != NULL)
@@ -8840,7 +8842,7 @@  Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
 // Lower a make expression.
 
 Expression*
-Builtin_call_expression::lower_make(Statement_inserter* inserter)
+Builtin_call_expression::lower_make(Gogo* gogo, Statement_inserter* inserter)
 {
   Location loc = this->location();
 
@@ -8899,7 +8901,7 @@  Builtin_call_expression::lower_make(Statement_inserter* inserter)
   else
     {
       len_arg = *parg;
-      len_arg->determine_type(&int_context);
+      len_arg->determine_type(gogo, &int_context);
       if (len_arg->type()->integer_type() == NULL)
 	{
 	  go_error_at(len_arg->location(), "non-integer len argument in make");
@@ -8919,7 +8921,7 @@  Builtin_call_expression::lower_make(Statement_inserter* inserter)
   if (is_slice && parg != args->end())
     {
       cap_arg = *parg;
-      cap_arg->determine_type(&int_context);
+      cap_arg->determine_type(gogo, &int_context);
       if (cap_arg->type()->integer_type() == NULL)
 	{
 	  go_error_at(cap_arg->location(), "non-integer cap argument in make");
@@ -9709,7 +9711,8 @@  Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const
 	  // We may be replacing this expression with a constant
 	  // during lowering, so verify the type to report any errors.
 	  // It's OK to verify an array type more than once.
-	  arg_type->verify();
+	  // FIXME: Remove this reference to go_get_gogo.
+	  arg_type->verify(go_get_gogo());
 	  if (!arg_type->is_error())
 	    {
 	      Expression* e = arg_type->array_type()->length();
@@ -10048,12 +10051,13 @@  Builtin_call_expression::do_type()
 // Determine the type.
 
 void
-Builtin_call_expression::do_determine_type(const Type_context* context)
+Builtin_call_expression::do_determine_type(Gogo* gogo,
+					   const Type_context* context)
 {
   if (!this->determining_types())
     return;
 
-  this->fn()->determine_type_no_context();
+  this->fn()->determine_type_no_context(gogo);
 
   const Expression_list* args = this->args();
 
@@ -10113,16 +10117,16 @@  Builtin_call_expression::do_determine_type(const Type_context* context)
       if (args != NULL && args->size() == 2)
 	{
 	  if (this->code_ == BUILTIN_SLICE)
-	    args->front()->determine_type_no_context();
+	    args->front()->determine_type_no_context(gogo);
 	  else
 	    {
 	      Type* pointer = Type::make_pointer_type(Type::make_void_type());
 	      Type_context subcontext(pointer, false);
-	      args->front()->determine_type(&subcontext);
+	      args->front()->determine_type(gogo, &subcontext);
 	    }
 	  Type* int_type = Type::lookup_integer_type("int");
 	  Type_context subcontext(int_type, false);
-	  args->back()->determine_type(&subcontext);
+	  args->back()->determine_type(gogo, &subcontext);
 	  return;
 	}
       is_print = false;
@@ -10183,7 +10187,7 @@  Builtin_call_expression::do_determine_type(const Type_context* context)
 		}
 	    }
 
-	  (*pa)->determine_type(&subcontext);
+	  (*pa)->determine_type(gogo, &subcontext);
 
 	  if (trailing_arg_types != NULL)
 	    {
@@ -12513,12 +12517,12 @@  Call_expression::do_type()
 // parameter types to set the types of the arguments.
 
 void
-Call_expression::do_determine_type(const Type_context* context)
+Call_expression::do_determine_type(Gogo* gogo, const Type_context* context)
 {
   if (!this->determining_types())
     return;
 
-  this->fn_->determine_type_no_context();
+  this->fn_->determine_type_no_context(gogo);
   Function_type* fntype = this->get_function_type();
   const Typed_identifier_list* parameters = NULL;
   if (fntype != NULL)
@@ -12545,7 +12549,7 @@  Call_expression::do_determine_type(const Type_context* context)
 		  if (rtype->points_to() == NULL)
 		    rtype = Type::make_pointer_type(rtype);
 		  Type_context subcontext(rtype, false);
-		  (*pa)->determine_type(&subcontext);
+		  (*pa)->determine_type(gogo, &subcontext);
 		  continue;
 		}
 	    }
@@ -12553,11 +12557,11 @@  Call_expression::do_determine_type(const Type_context* context)
 	  if (parameters != NULL && pt != parameters->end())
 	    {
 	      Type_context subcontext(pt->type(), false);
-	      (*pa)->determine_type(&subcontext);
+	      (*pa)->determine_type(gogo, &subcontext);
 	      ++pt;
 	    }
 	  else
-	    (*pa)->determine_type_no_context();
+	    (*pa)->determine_type_no_context(gogo);
 	}
     }
 
@@ -13110,9 +13114,9 @@  Call_result_expression::do_check_types(Gogo*)
 // needs to pass down to the caller.
 
 void
-Call_result_expression::do_determine_type(const Type_context*)
+Call_result_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
-  this->call_->determine_type_no_context();
+  this->call_->determine_type_no_context(gogo);
 }
 
 // Return the backend representation.  We just refer to the temporary set by the
@@ -13358,16 +13362,16 @@  Array_index_expression::do_type()
 // Set the type of an array index.
 
 void
-Array_index_expression::do_determine_type(const Type_context*)
+Array_index_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
-  this->array_->determine_type_no_context();
+  this->array_->determine_type_no_context(gogo);
 
   Type_context index_context(Type::lookup_integer_type("int"), false);
-  this->start_->determine_type(&index_context);
+  this->start_->determine_type(gogo, &index_context);
   if (this->end_ != NULL)
-    this->end_->determine_type(&index_context);
+    this->end_->determine_type(gogo, &index_context);
   if (this->cap_ != NULL)
-    this->cap_->determine_type(&index_context);
+    this->cap_->determine_type(gogo, &index_context);
 }
 
 // Check types of an array index.
@@ -14031,14 +14035,14 @@  String_index_expression::do_type()
 // Determine the type of a string index.
 
 void
-String_index_expression::do_determine_type(const Type_context*)
+String_index_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
-  this->string_->determine_type_no_context();
+  this->string_->determine_type_no_context(gogo);
 
   Type_context index_context(Type::lookup_integer_type("int"), false);
-  this->start_->determine_type(&index_context);
+  this->start_->determine_type(gogo, &index_context);
   if (this->end_ != NULL)
-    this->end_->determine_type(&index_context);
+    this->end_->determine_type(gogo, &index_context);
 }
 
 // Check types of a string index.
@@ -14331,13 +14335,13 @@  Map_index_expression::do_type()
 // Fix the type of a map index.
 
 void
-Map_index_expression::do_determine_type(const Type_context*)
+Map_index_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
-  this->map_->determine_type_no_context();
+  this->map_->determine_type_no_context(gogo);
   Map_type* mt = this->get_map_type();
   Type* key_type = mt == NULL ? NULL : mt->key_type();
   Type_context subcontext(key_type, false);
-  this->index_->determine_type(&subcontext);
+  this->index_->determine_type(gogo, &subcontext);
 }
 
 // Check types of a map index.
@@ -14770,9 +14774,10 @@  Interface_field_reference_expression::do_type()
 // Determine types.
 
 void
-Interface_field_reference_expression::do_determine_type(const Type_context*)
+Interface_field_reference_expression::do_determine_type(Gogo* gogo,
+							const Type_context*)
 {
-  this->expr_->determine_type_no_context();
+  this->expr_->determine_type_no_context(gogo);
 }
 
 // Check the types for an interface field reference.
@@ -15541,7 +15546,8 @@  Struct_construction_expression::do_is_static_initializer() const
 // Final type determination.
 
 void
-Struct_construction_expression::do_determine_type(const Type_context*)
+Struct_construction_expression::do_determine_type(Gogo* gogo,
+						  const Type_context*)
 {
   if (this->vals() == NULL)
     return;
@@ -15556,13 +15562,13 @@  Struct_construction_expression::do_determine_type(const Type_context*)
       if (*pv != NULL)
 	{
 	  Type_context subcontext(pf->type(), false);
-	  (*pv)->determine_type(&subcontext);
+	  (*pv)->determine_type(gogo, &subcontext);
 	}
     }
   // Extra values are an error we will report elsewhere; we still want
   // to determine the type to avoid knockon errors.
   for (; pv != this->vals()->end(); ++pv)
-    (*pv)->determine_type_no_context();
+    (*pv)->determine_type_no_context(gogo);
 }
 
 // Check types.
@@ -15827,7 +15833,8 @@  Array_construction_expression::do_is_static_initializer() const
 // Final type determination.
 
 void
-Array_construction_expression::do_determine_type(const Type_context*)
+Array_construction_expression::do_determine_type(Gogo* gogo,
+						 const Type_context*)
 {
   if (this->is_error_expression())
     {
@@ -15850,7 +15857,7 @@  Array_construction_expression::do_determine_type(const Type_context*)
        ++pv)
     {
       if (*pv != NULL)
-	(*pv)->determine_type(&subcontext);
+	(*pv)->determine_type(gogo, &subcontext);
     }
 }
 
@@ -16378,7 +16385,7 @@  Map_construction_expression::do_flatten(Gogo* gogo, Named_object*,
 // Final type determination.
 
 void
-Map_construction_expression::do_determine_type(const Type_context*)
+Map_construction_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
   if (this->vals_ == NULL)
     return;
@@ -16390,9 +16397,9 @@  Map_construction_expression::do_determine_type(const Type_context*)
        pv != this->vals_->end();
        ++pv)
     {
-      (*pv)->determine_type(&key_context);
+      (*pv)->determine_type(gogo, &key_context);
       ++pv;
-      (*pv)->determine_type(&val_context);
+      (*pv)->determine_type(gogo, &val_context);
     }
 }
 
@@ -17910,7 +17917,7 @@  class Type_descriptor_expression : public Expression
   { return true; }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -17978,7 +17985,7 @@  class GC_symbol_expression : public Expression
   { return true; }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -18037,7 +18044,7 @@  class Ptrmask_symbol_expression : public Expression
   { return true; }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -18124,7 +18131,7 @@  class Type_info_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -18311,11 +18318,11 @@  Slice_value_expression::do_traverse(Traverse* traverse)
 // Determine type of a slice value.
 
 void
-Slice_value_expression::do_determine_type(const Type_context*)
+Slice_value_expression::do_determine_type(Gogo* gogo, const Type_context*)
 {
-  this->valmem_->determine_type_no_context();
-  this->len_->determine_type_no_context();
-  this->cap_->determine_type_no_context();
+  this->valmem_->determine_type_no_context(gogo);
+  this->len_->determine_type_no_context(gogo);
+  this->cap_->determine_type_no_context(gogo);
 }
 
 Expression*
@@ -18421,7 +18428,7 @@  class Interface_info_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -18591,7 +18598,7 @@  class Interface_value_expression : public Expression
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { go_unreachable(); }
 
   Expression*
@@ -18686,7 +18693,7 @@  class Interface_mtable_expression : public Expression
   { return true; }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { go_unreachable(); }
 
   Expression*
@@ -18932,7 +18939,7 @@  class Struct_field_offset_expression : public Expression
   { return Type::lookup_integer_type("uintptr"); }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -19017,7 +19024,7 @@  class Label_addr_expression : public Expression
   { return Type::make_pointer_type(Type::make_void_type()); }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -19080,11 +19087,12 @@  Conditional_expression::do_type()
 // Determine type for a conditional expression.
 
 void
-Conditional_expression::do_determine_type(const Type_context* context)
+Conditional_expression::do_determine_type(Gogo* gogo,
+					  const Type_context* context)
 {
-  this->cond_->determine_type_no_context();
-  this->then_->determine_type(context);
-  this->else_->determine_type(context);
+  this->cond_->determine_type_no_context(gogo);
+  this->then_->determine_type(gogo, context);
+  this->else_->determine_type(gogo, context);
 }
 
 // Get the backend representation of a conditional expression.
@@ -19150,10 +19158,10 @@  Compound_expression::do_type()
 // Determine type for a compound expression.
 
 void
-Compound_expression::do_determine_type(const Type_context* context)
+Compound_expression::do_determine_type(Gogo* gogo, const Type_context* context)
 {
-  this->init_->determine_type_no_context();
-  this->expr_->determine_type(context);
+  this->init_->determine_type_no_context(gogo);
+  this->expr_->determine_type(gogo, context);
 }
 
 // Get the backend representation of a compound expression.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index bdb7ccd010d..2abc9cb8425 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -1002,7 +1002,7 @@  class Expression
   // floating point, or complex type.  TYPE_CONTEXT describes the
   // expected type.
   void
-  determine_type(const Type_context*);
+  determine_type(Gogo*, const Type_context*);
 
   // Check types in an expression.
   void
@@ -1011,7 +1011,7 @@  class Expression
 
   // Determine the type when there is no context.
   void
-  determine_type_no_context();
+  determine_type_no_context(Gogo*);
 
   // Return the current type of the expression.  This may be changed
   // by determine_type.  This should not be called before the lowering
@@ -1208,7 +1208,7 @@  class Expression
 
   // Child class implements determining type information.
   virtual void
-  do_determine_type(const Type_context*) = 0;
+  do_determine_type(Gogo*, const Type_context*) = 0;
 
   // Child class implements type checking if needed.
   virtual void
@@ -1456,7 +1456,7 @@  class Parser_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { go_unreachable(); }
 
   void
@@ -1522,7 +1522,7 @@  class Const_expression : public Expression
 
   // The type of a const is set by the declaration, not the use.
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -1581,7 +1581,7 @@  class Var_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   Expression*
   do_copy()
@@ -1649,8 +1649,8 @@  class Enclosed_var_expression : public Expression
   { return this->reference_->type(); }
 
   void
-  do_determine_type(const Type_context* context)
-  { return this->reference_->determine_type(context); }
+  do_determine_type(Gogo* gogo, const Type_context* context)
+  { return this->reference_->determine_type(gogo, context); }
 
   Expression*
   do_copy()
@@ -1707,7 +1707,7 @@  class Temporary_reference_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -1772,7 +1772,7 @@  class Set_and_use_temporary_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   Expression*
   do_copy()
@@ -1849,7 +1849,7 @@  class String_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   Expression*
   do_copy()
@@ -1954,7 +1954,7 @@  class Type_conversion_expression : public Expression
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -2021,8 +2021,8 @@  class Unsafe_type_conversion_expression : public Expression
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*)
-  { this->expr_->determine_type_no_context(); }
+  do_determine_type(Gogo* gogo, const Type_context*)
+  { this->expr_->determine_type_no_context(gogo); }
 
   Expression*
   do_copy();
@@ -2149,7 +2149,7 @@  class Unary_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -2309,7 +2309,7 @@  class Binary_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -2425,7 +2425,7 @@  class String_concat_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -2599,7 +2599,7 @@  class Call_expression : public Expression
   do_type();
 
   virtual void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   virtual void
   do_check_types(Gogo*);
@@ -2777,7 +2777,7 @@  class Builtin_call_expression : public Call_expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -2815,7 +2815,7 @@  class Builtin_call_expression : public Call_expression
   complex_type(Type*);
 
   Expression*
-  lower_make(Statement_inserter*);
+  lower_make(Gogo*, Statement_inserter*);
 
   bool
   check_int_value(Expression*, bool is_length, bool* small);
@@ -2874,7 +2874,7 @@  class Call_result_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -2955,10 +2955,10 @@  class Func_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo* gogo, const Type_context*)
   {
     if (this->closure_ != NULL)
-      this->closure_->determine_type_no_context();
+      this->closure_->determine_type_no_context(gogo);
   }
 
   Expression*
@@ -3015,7 +3015,7 @@  class Func_descriptor_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
@@ -3207,7 +3207,7 @@  class Array_index_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -3312,7 +3312,7 @@  class String_index_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -3408,7 +3408,7 @@  class Map_index_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -3511,7 +3511,7 @@  class Bound_method_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -3601,8 +3601,8 @@  class Field_reference_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
-  { this->expr_->determine_type_no_context(); }
+  do_determine_type(Gogo* gogo, const Type_context*)
+  { this->expr_->determine_type_no_context(gogo); }
 
   void
   do_check_types(Gogo*);
@@ -3697,7 +3697,7 @@  class Interface_field_reference_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -3759,7 +3759,7 @@  class Allocation_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   void
@@ -3925,7 +3925,7 @@  class Struct_construction_expression : public Expression,
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -3992,7 +3992,7 @@  protected:
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -4124,7 +4124,7 @@  class Map_construction_expression : public Expression
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   void
   do_check_types(Gogo*);
@@ -4187,8 +4187,8 @@  class Type_guard_expression : public Expression
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*)
-  { this->expr_->determine_type_no_context(); }
+  do_determine_type(Gogo* gogo, const Type_context*)
+  { this->expr_->determine_type_no_context(gogo); }
 
   void
   do_check_types(Gogo*);
@@ -4238,8 +4238,8 @@  class Heap_expression : public Expression
   Type*
   do_type();
   void
-  do_determine_type(const Type_context*)
-  { this->expr_->determine_type_no_context(); }
+  do_determine_type(Gogo* gogo, const Type_context*)
+  { this->expr_->determine_type_no_context(gogo); }
 
   Expression*
   do_copy()
@@ -4301,8 +4301,8 @@  class Receive_expression : public Expression
   do_flatten(Gogo*, Named_object*, Statement_inserter*);
 
   void
-  do_determine_type(const Type_context*)
-  { this->channel_->determine_type_no_context(); }
+  do_determine_type(Gogo* gogo, const Type_context*)
+  { this->channel_->determine_type_no_context(gogo); }
 
   void
   do_check_types(Gogo*);
@@ -4364,7 +4364,7 @@  class Slice_value_expression : public Expression
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   Expression*
   do_copy();
@@ -4417,8 +4417,8 @@  class Slice_info_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*)
-  { this->slice_->determine_type_no_context(); }
+  do_determine_type(Gogo* gogo, const Type_context*)
+  { this->slice_->determine_type_no_context(gogo); }
 
   Expression*
   do_copy()
@@ -4475,7 +4475,7 @@  class Conditional_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   Expression*
   do_copy()
@@ -4524,7 +4524,7 @@  class Compound_expression : public Expression
   do_type();
 
   void
-  do_determine_type(const Type_context*);
+  do_determine_type(Gogo*, const Type_context*);
 
   Expression*
   do_copy()
@@ -4571,7 +4571,7 @@  class Backend_expression : public Expression
   { return this->type_; }
 
   void
-  do_determine_type(const Type_context*)
+  do_determine_type(Gogo*, const Type_context*)
   { }
 
   Expression*
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index fa3cd6ebe9f..499459b5366 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -2865,12 +2865,16 @@  Gogo::add_type_to_verify(Type* type)
 class Verify_types : public Traverse
 {
  public:
-  Verify_types()
-    : Traverse(traverse_types)
+  Verify_types(Gogo* gogo)
+    : Traverse(traverse_types),
+      gogo_(gogo)
   { }
 
   int
   type(Type*);
+
+ private:
+  Gogo* gogo_;
 };
 
 // Verify that a type is correct.
@@ -2878,7 +2882,7 @@  class Verify_types : public Traverse
 int
 Verify_types::type(Type* t)
 {
-  if (!t->verify())
+  if (!t->verify(this->gogo_))
     return TRAVERSE_SKIP_COMPONENTS;
   return TRAVERSE_CONTINUE;
 }
@@ -2888,13 +2892,13 @@  Verify_types::type(Type* t)
 void
 Gogo::verify_types()
 {
-  Verify_types traverse;
+  Verify_types traverse(this);
   this->traverse(&traverse);
 
   for (std::vector<Type*>::iterator p = this->verify_types_.begin();
        p != this->verify_types_.end();
        ++p)
-    (*p)->verify();
+    (*p)->verify(this);
   this->verify_types_.clear();
 }
 
@@ -3224,9 +3228,10 @@  Gogo::add_conversions_in_block(Block *b)
 class Remove_deadcode : public Traverse
 {
  public:
-  Remove_deadcode()
+  Remove_deadcode(Gogo* gogo)
     : Traverse(traverse_statements
-               | traverse_expressions)
+               | traverse_expressions),
+      gogo_(gogo)
   { }
 
   int
@@ -3234,6 +3239,9 @@  class Remove_deadcode : public Traverse
 
   int
   expression(Expression**);
+
+ private:
+  Gogo* gogo_;
 };
 
 // Remove deadcode in a statement.
@@ -3283,7 +3291,7 @@  Remove_deadcode::expression(Expression** pexpr)
     {
       *pexpr = Expression::make_boolean(bval, be->location());
       Type_context context(NULL, false);
-      (*pexpr)->determine_type(&context);
+      (*pexpr)->determine_type(this->gogo_, &context);
     }
   return TRAVERSE_CONTINUE;
 }
@@ -3293,7 +3301,7 @@  Remove_deadcode::expression(Expression** pexpr)
 void
 Gogo::remove_deadcode()
 {
-  Remove_deadcode remove_deadcode;
+  Remove_deadcode remove_deadcode(this);
   this->traverse(&remove_deadcode);
 }
 
@@ -3622,11 +3630,11 @@  Gogo::determine_types()
        ++p)
     {
       if ((*p)->is_function())
-	(*p)->func_value()->determine_types();
+	(*p)->func_value()->determine_types(this);
       else if ((*p)->is_variable())
-	(*p)->var_value()->determine_type();
+	(*p)->var_value()->determine_type(this);
       else if ((*p)->is_const())
-	(*p)->const_value()->determine_type();
+	(*p)->const_value()->determine_type(this);
 
       // See if a variable requires us to build an initialization
       // function.  We know that we will see all global variables
@@ -3662,7 +3670,7 @@  Gogo::determine_types()
   for (Packages::const_iterator p = this->packages_.begin();
        p != this->packages_.end();
        ++p)
-    p->second->determine_types();
+    p->second->determine_types(this);
 }
 
 // Traversal class used for type checking.
@@ -4809,7 +4817,7 @@  Build_recover_thunks::function(Named_object* orig_no)
   call->set_varargs_are_lowered();
 
   Statement* s = Statement::make_return_from_call(call, location);
-  s->determine_types();
+  s->determine_types(this->gogo_);
   gogo->add_statement(s);
 
   Block* b = gogo->finish_block(location);
@@ -5882,10 +5890,10 @@  Function::traverse(Traverse* traverse)
 // Work out types for unspecified variables and constants.
 
 void
-Function::determine_types()
+Function::determine_types(Gogo* gogo)
 {
   if (this->block_ != NULL)
-    this->block_->determine_types();
+    this->block_->determine_types(gogo);
 }
 
 // Return the function descriptor, the value you get when you refer to
@@ -6961,7 +6969,7 @@  Block::traverse(Traverse* traverse)
 // Work out types for unspecified variables and constants.
 
 void
-Block::determine_types()
+Block::determine_types(Gogo* gogo)
 {
   for (Bindings::const_definitions_iterator pb =
 	 this->bindings_->begin_definitions();
@@ -6969,15 +6977,15 @@  Block::determine_types()
        ++pb)
     {
       if ((*pb)->is_variable())
-	(*pb)->var_value()->determine_type();
+	(*pb)->var_value()->determine_type(gogo);
       else if ((*pb)->is_const())
-	(*pb)->const_value()->determine_type();
+	(*pb)->const_value()->determine_type(gogo);
     }
 
   for (std::vector<Statement*>::const_iterator ps = this->statements_.begin();
        ps != this->statements_.end();
        ++ps)
-    (*ps)->determine_types();
+    (*ps)->determine_types(gogo);
 }
 
 // Return true if the statements in this block may fall through.
@@ -7456,7 +7464,7 @@  Function_declaration::import_function_body(Gogo* gogo, Named_object* no)
     return;
 
   gogo->lower_block(no, outer);
-  outer->determine_types();
+  outer->determine_types(gogo);
 
   gogo->add_imported_inline_function(no);
 }
@@ -7826,14 +7834,14 @@  Variable::type() const
 // Set the type if necessary.
 
 void
-Variable::determine_type()
+Variable::determine_type(Gogo* gogo)
 {
   if (this->determined_type_)
     return;
   this->determined_type_ = true;
 
   if (this->preinit_ != NULL)
-    this->preinit_->determine_types();
+    this->preinit_->determine_types(gogo);
 
   // A variable in a type switch with a nil case will have the wrong
   // type here.  It will have an initializer which is a type guard.
@@ -7854,14 +7862,14 @@  Variable::determine_type()
   else if (this->type_from_init_tuple_)
     {
       Expression *init = this->init_;
-      init->determine_type_no_context();
+      init->determine_type_no_context(gogo);
       this->type_ = this->type_from_tuple(init, true);
       this->init_ = NULL;
     }
   else if (this->type_from_range_index_ || this->type_from_range_value_)
     {
       Expression* init = this->init_;
-      init->determine_type_no_context();
+      init->determine_type_no_context(gogo);
       this->type_ = this->type_from_range(init, this->type_from_range_index_,
 					  true);
       this->init_ = NULL;
@@ -7869,14 +7877,14 @@  Variable::determine_type()
   else if (this->type_from_chan_element_)
     {
       Expression* init = this->init_;
-      init->determine_type_no_context();
+      init->determine_type_no_context(gogo);
       this->type_ = this->type_from_chan_element(init, true);
       this->init_ = NULL;
     }
   else
     {
       Type_context context(this->type_, false);
-      this->init_->determine_type(&context);
+      this->init_->determine_type(gogo, &context);
       if (this->type_ == NULL)
 	{
 	  Type* type = this->init_->type();
@@ -8204,18 +8212,18 @@  Named_constant::traverse_expression(Traverse* traverse)
 // Determine the type of the constant.
 
 void
-Named_constant::determine_type()
+Named_constant::determine_type(Gogo* gogo)
 {
   if (this->type_ != NULL)
     {
       Type_context context(this->type_, false);
-      this->expr_->determine_type(&context);
+      this->expr_->determine_type(gogo, &context);
     }
   else
     {
       // A constant may have an abstract type.
       Type_context context(NULL, true);
-      this->expr_->determine_type(&context);
+      this->expr_->determine_type(gogo, &context);
       this->type_ = this->expr_->type();
       go_assert(this->type_ != NULL);
     }
@@ -9566,7 +9574,7 @@  Package::add_alias(const std::string& alias, Location location)
 // type.  Constants may have abstract types.
 
 void
-Package::determine_types()
+Package::determine_types(Gogo* gogo)
 {
   Bindings* bindings = this->bindings_;
   for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
@@ -9574,7 +9582,7 @@  Package::determine_types()
        ++p)
     {
       if ((*p)->is_const())
-	(*p)->const_value()->determine_type();
+	(*p)->const_value()->determine_type(gogo);
     }
 }
 
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 4fd45bfa040..f254a615dbb 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -1429,7 +1429,7 @@  class Block
 
   // Set final types for unspecified variables and constants.
   void
-  determine_types();
+  determine_types(Gogo*);
 
   // Return true if execution of this block may fall through to the
   // next block.
@@ -1760,7 +1760,7 @@  class Function
 
   // Determine types in the function.
   void
-  determine_types();
+  determine_types(Gogo*);
 
   // Return an expression for the function descriptor, given the named
   // object for this function.  This may only be called for functions
@@ -2365,7 +2365,7 @@  class Variable
 
   // Determine the type of the variable if necessary.
   void
-  determine_type();
+  determine_type(Gogo*);
 
   // Get the backend representation of the variable.
   Bvariable*
@@ -2620,7 +2620,7 @@  class Named_constant
 
   // Determine the type of the constant if necessary.
   void
-  determine_type();
+  determine_type(Gogo*);
 
   // Indicate that we found and reported an error for this constant.
   void
@@ -3687,7 +3687,7 @@  class Package
 
   // Determine types of constants.
   void
-  determine_types();
+  determine_types(Gogo*);
 
  private:
   // The package path for type reflection data.
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 3cc5ded3617..e113a1adfc9 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -317,7 +317,7 @@  Runtime::convert_types(Gogo* gogo)
       Type* t = runtime_function_types[i];
       if (t != NULL && t->named_type() != NULL)
 	{
-	  bool r = t->verify();
+	  bool r = t->verify(gogo);
 	  go_assert(r);
 	  t->named_type()->convert(gogo);
 	}
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index af8c7d15998..33b568e3eeb 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -117,9 +117,9 @@  Statement::traverse_type(Traverse* traverse, Type* type)
 // the child class.
 
 void
-Statement::determine_types()
+Statement::determine_types(Gogo* gogo)
 {
-  this->do_determine_types();
+  this->do_determine_types(gogo);
 }
 
 // Read a statement from export data.
@@ -524,7 +524,7 @@  Temporary_statement::do_traverse_assignments(Traverse_assignments* tassign)
 // Determine types.
 
 void
-Temporary_statement::do_determine_types()
+Temporary_statement::do_determine_types(Gogo* gogo)
 {
   if (this->type_ != NULL && this->type_->is_abstract())
     this->type_ = this->type_->make_non_abstract_type();
@@ -532,11 +532,11 @@  Temporary_statement::do_determine_types()
   if (this->init_ != NULL)
     {
       if (this->type_ == NULL)
-	this->init_->determine_type_no_context();
+	this->init_->determine_type_no_context(gogo);
       else
 	{
 	  Type_context context(this->type_, false);
-	  this->init_->determine_type(&context);
+	  this->init_->determine_type(gogo, &context);
 	}
     }
 
@@ -1046,14 +1046,14 @@  Assignment_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
 // Set types for the assignment.
 
 void
-Assignment_statement::do_determine_types()
+Assignment_statement::do_determine_types(Gogo* gogo)
 {
-  this->lhs_->determine_type_no_context();
+  this->lhs_->determine_type_no_context(gogo);
   Type* rhs_context_type = this->lhs_->type();
   if (rhs_context_type->is_sink_type())
     rhs_context_type = NULL;
   Type_context context(rhs_context_type, false);
-  this->rhs_->determine_type(&context);
+  this->rhs_->determine_type(gogo, &context);
 }
 
 // Check types for an assignment.
@@ -2080,9 +2080,9 @@  Expression_statement::Expression_statement(Expression* expr, bool is_ignored)
 // Determine types.
 
 void
-Expression_statement::do_determine_types()
+Expression_statement::do_determine_types(Gogo* gogo)
 {
-  this->expr_->determine_type_no_context();
+  this->expr_->determine_type_no_context(gogo);
 }
 
 // Check the types of an expression statement.  The only check we do
@@ -2427,9 +2427,9 @@  Thunk_statement::do_traverse_assignments(Traverse_assignments* tassign)
 // Determine types in a thunk statement.
 
 void
-Thunk_statement::do_determine_types()
+Thunk_statement::do_determine_types(Gogo* gogo)
 {
-  this->call_->determine_type_no_context();
+  this->call_->determine_type_no_context(gogo);
 }
 
 // Check types in a thunk statement.
@@ -2679,7 +2679,7 @@  Thunk_statement::simplify_statement(Gogo* gogo, Named_object* function,
 
   // We already ran the determine_types pass, so we need to run it now
   // for the new statement.
-  s->determine_types();
+  s->determine_types(gogo);
 
   // Sanity check.
   gogo->check_types_in_block(block);
@@ -2833,11 +2833,11 @@  Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
       gogo->add_statement(Statement::make_goto_statement(retaddr_label,
 							 location));
       Block* then_block = gogo->finish_block(location);
-      then_block->determine_types();
+      then_block->determine_types(gogo);
 
       Statement* s = Statement::make_if_statement(call, then_block, NULL,
 						  location);
-      s->determine_types();
+      s->determine_types(gogo);
       gogo->add_statement(s);
 
       function->func_value()->set_calls_defer_retaddr();
@@ -2977,7 +2977,7 @@  Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name,
 
   // We already ran the determine_types pass, so we need to run it
   // just for the call statement now.  The other types are known.
-  call_statement->determine_types();
+  call_statement->determine_types(gogo);
 
   gogo->add_conversions_in_block(b);
 
@@ -3173,8 +3173,8 @@  Return_statement::do_traverse_assignments(Traverse_assignments* tassign)
 // return.  This lets panic/recover work correctly.
 
 Statement*
-Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
-			   Statement_inserter*)
+Return_statement::do_lower(Gogo* gogo, Named_object* function,
+			   Block* enclosing, Statement_inserter*)
 {
   if (this->is_lowered_)
     return this;
@@ -3253,7 +3253,7 @@  Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
 
       Type *rvtype = rv->result_var_value()->type();
       Type_context type_context(rvtype, false);
-      e->determine_type(&type_context);
+      e->determine_type(gogo, &type_context);
 
       std::string reason;
       if (Type::are_assignable(rvtype, e->type(), &reason))
@@ -3764,13 +3764,13 @@  If_statement::do_traverse(Traverse* traverse)
 }
 
 void
-If_statement::do_determine_types()
+If_statement::do_determine_types(Gogo* gogo)
 {
   Type_context context(Type::lookup_bool_type(), false);
-  this->cond_->determine_type(&context);
-  this->then_block_->determine_types();
+  this->cond_->determine_type(gogo, &context);
+  this->then_block_->determine_types(gogo);
   if (this->else_block_ != NULL)
-    this->else_block_->determine_types();
+    this->else_block_->determine_types(gogo);
 }
 
 // Check types.
@@ -4082,7 +4082,7 @@  Case_clauses::Case_clause::lower(Block* b, Temporary_statement* val_temp,
 // Determine types.
 
 void
-Case_clauses::Case_clause::determine_types(Type* type)
+Case_clauses::Case_clause::determine_types(Gogo* gogo, Type* type)
 {
   if (this->cases_ != NULL)
     {
@@ -4090,10 +4090,10 @@  Case_clauses::Case_clause::determine_types(Type* type)
       for (Expression_list::iterator p = this->cases_->begin();
 	   p != this->cases_->end();
 	   ++p)
-	(*p)->determine_type(&case_context);
+	(*p)->determine_type(gogo, &case_context);
     }
   if (this->statements_ != NULL)
-    this->statements_->determine_types();
+    this->statements_->determine_types(gogo);
 }
 
 // Check types.  Returns false if there was an error.
@@ -4319,12 +4319,12 @@  Case_clauses::lower(Block* b, Temporary_statement* val_temp,
 // Determine types.
 
 void
-Case_clauses::determine_types(Type* type)
+Case_clauses::determine_types(Gogo* gogo, Type* type)
 {
   for (Clauses::iterator p = this->clauses_.begin();
        p != this->clauses_.end();
        ++p)
-    p->determine_types(type);
+    p->determine_types(gogo, type);
 }
 
 // Check types.  Returns false if there was an error.
@@ -4425,7 +4425,7 @@  class Constant_switch_statement : public Statement
   do_traverse(Traverse*);
 
   void
-  do_determine_types();
+  do_determine_types(Gogo*);
 
   void
   do_check_types(Gogo*);
@@ -4458,10 +4458,10 @@  Constant_switch_statement::do_traverse(Traverse* traverse)
 // Determine types.
 
 void
-Constant_switch_statement::do_determine_types()
+Constant_switch_statement::do_determine_types(Gogo* gogo)
 {
-  this->val_->determine_type_no_context();
-  this->clauses_->determine_types(this->val_->type());
+  this->val_->determine_type_no_context(gogo);
+  this->clauses_->determine_types(gogo, this->val_->type());
 }
 
 // Check types.
@@ -5083,14 +5083,14 @@  Send_statement::do_traverse(Traverse* traverse)
 // Determine types.
 
 void
-Send_statement::do_determine_types()
+Send_statement::do_determine_types(Gogo* gogo)
 {
-  this->channel_->determine_type_no_context();
+  this->channel_->determine_type_no_context(gogo);
   Type* type = this->channel_->type();
   Type_context context;
   if (type->channel_type() != NULL)
     context.type = type->channel_type()->element_type();
-  this->val_->determine_type(&context);
+  this->val_->determine_type(gogo, &context);
 }
 
 // Check types.
@@ -5492,11 +5492,11 @@  Select_clauses::Select_clause::set_case(Block* b,
 // Determine types.
 
 void
-Select_clauses::Select_clause::determine_types()
+Select_clauses::Select_clause::determine_types(Gogo* gogo)
 {
   go_assert(this->is_lowered_);
   if (this->statements_ != NULL)
-    this->statements_->determine_types();
+    this->statements_->determine_types(gogo);
 }
 
 // Check types.
@@ -5676,12 +5676,12 @@  Select_clauses::lower(Gogo* gogo, Named_object* function, Block* b,
 // Determine types.
 
 void
-Select_clauses::determine_types()
+Select_clauses::determine_types(Gogo* gogo)
 {
   for (Clauses::iterator p = this->clauses_.begin();
        p != this->clauses_.end();
        ++p)
-    p->determine_types();
+    p->determine_types(gogo);
 }
 
 // Check types.
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h
index 3d1ee33a3e5..eb795c4b920 100644
--- a/gcc/go/gofrontend/statements.h
+++ b/gcc/go/gofrontend/statements.h
@@ -321,7 +321,7 @@  class Statement
 
   // Set type information for unnamed constants.
   void
-  determine_types();
+  determine_types(Gogo*);
 
   // Check types in a statement.  This simply checks that any
   // expressions used by the statement have the right type.
@@ -508,7 +508,7 @@  class Statement
   // constants.  Any statement which includes an expression needs to
   // implement this.
   virtual void
-  do_determine_types()
+  do_determine_types(Gogo*)
   { }
 
   // Implemented by child class: check types of expressions used in a
@@ -640,7 +640,7 @@  class Assignment_statement : public Statement
   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
 
   void
-  do_determine_types();
+  do_determine_types(Gogo*);
 
   void
   do_check_types(Gogo*);
@@ -757,7 +757,7 @@  class Temporary_statement : public Statement
   do_traverse_assignments(Traverse_assignments*);
 
   void
-  do_determine_types();
+  do_determine_types(Gogo*);
 
   void
   do_check_types(Gogo*);
@@ -916,7 +916,7 @@  class Expression_statement : public Statement
   { return this->traverse_expression(traverse, &this->expr_); }
 
   void
-  do_determine_types();
+  do_determine_types(Gogo*);
 
   void
   do_check_types(Gogo*);
@@ -983,8 +983,8 @@  class Block_statement : public Statement
   { return this->block_->traverse(traverse); }
 
   void
-  do_determine_types()
-  { this->block_->determine_types(); }
+  do_determine_types(Gogo* gogo)
+  { this->block_->determine_types(gogo); }
 
   int
   do_inlining_cost()
@@ -1033,7 +1033,7 @@  class Send_statement : public Statement
   do_traverse(Traverse* traverse);
 
   void
-  do_determine_types();
+  do_determine_types(Gogo*);
 
   void
   do_check_types(Gogo*);
@@ -1106,7 +1106,7 @@  class Select_clauses
 
   // Determine types.
   void
-  determine_types();
+  determine_types(Gogo*);
 
   // Check types.
   void
@@ -1157,7 +1157,7 @@  class Select_clauses
 
     // Determine types.
     void
-    determine_types();
+    determine_types(Gogo*);
 
     // Check types.
     void
@@ -1326,8 +1326,8 @@  class Select_statement : public Statement
   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
 
   void
-  do_determine_types()
-  { this->clauses_->determine_types(); }
+  do_determine_types(Gogo* gogo)
+  { this->clauses_->determine_types(gogo); }
 
   void
   do_check_types(Gogo*)
@@ -1387,7 +1387,7 @@  class Thunk_statement : public Statement
   do_traverse_assignments(Traverse_assignments*);
 
   void
-  do_determine_types();
+  do_determine_types(Gogo*);
 
   void
   do_check_types(Gogo*);
@@ -1655,7 +1655,7 @@  class If_statement : public Statement
   do_traverse(Traverse*);
 
   void
-  do_determine_types();
+  do_determine_types(Gogo*);
 
   void
   do_check_types(Gogo*);
@@ -1894,7 +1894,7 @@  class Case_clauses
   // Determine types of expressions.  The Type parameter is the type
   // of the switch value.
   void
-  determine_types(Type*);
+  determine_types(Gogo*, Type*);
 
   // Check types.  The Type parameter is the type of the switch value.
   bool
@@ -1968,7 +1968,7 @@  class Case_clauses
 
     // Determine types.
     void
-    determine_types(Type*);
+    determine_types(Gogo*, Type*);
 
     // Check types.
     bool
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 7f471eab428..e6b1250ba38 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -1555,7 +1555,7 @@  Type::convert_builtin_named_types(Gogo* gogo)
        p != Type::named_builtin_types.end();
        ++p)
     {
-      bool r = (*p)->verify();
+      bool r = (*p)->verify(gogo);
       go_assert(r);
       (*p)->convert(gogo);
     }
@@ -5950,7 +5950,7 @@  Struct_type::do_traverse(Traverse* traverse)
 // Verify that the struct type is complete and valid.
 
 bool
-Struct_type::do_verify()
+Struct_type::do_verify(Gogo*)
 {
   Struct_field_list* fields = this->fields_;
   if (fields == NULL)
@@ -7337,13 +7337,13 @@  Array_type::do_traverse(Traverse* traverse)
 // Check that the length is valid.
 
 bool
-Array_type::verify_length()
+Array_type::verify_length(Gogo* gogo)
 {
   if (this->length_ == NULL)
     return true;
 
   Type_context context(Type::lookup_integer_type("int"), false);
-  this->length_->determine_type(&context);
+  this->length_->determine_type(gogo, &context);
 
   if (this->length_->is_error_expression()
       || this->length_->type()->is_error())
@@ -7421,14 +7421,14 @@  Array_type::verify_length()
 // Verify the type.
 
 bool
-Array_type::do_verify()
+Array_type::do_verify(Gogo* gogo)
 {
   if (this->element_type()->is_error_type())
     {
       this->set_is_error();
       return false;
     }
-  if (!this->verify_length())
+  if (!this->verify_length(gogo))
     {
       this->length_ = Expression::make_error(this->length_->location());
       this->set_is_error();
@@ -8225,7 +8225,7 @@  Map_type::do_traverse(Traverse* traverse)
 // Check that the map type is OK.
 
 bool
-Map_type::do_verify()
+Map_type::do_verify(Gogo*)
 {
   // The runtime support uses "map[void]void".
   if (!this->key_type_->is_comparable() && !this->key_type_->is_void_type())
@@ -8768,7 +8768,7 @@  Type::make_map_type(Type* key_type, Type* val_type, Location location)
 // Verify.
 
 bool
-Channel_type::do_verify()
+Channel_type::do_verify(Gogo*)
 {
   // We have no location for this error, but this is not something the
   // ordinary user will see.
@@ -10833,7 +10833,7 @@  Find_alias::type(Type* type)
 // Verify that a named type does not refer to itself.
 
 bool
-Named_type::do_verify()
+Named_type::do_verify(Gogo*)
 {
   if (this->is_verified_)
     return true;
@@ -11016,7 +11016,7 @@  Named_type::convert(Gogo* gogo)
   // If we are called to turn unsafe.Sizeof into a constant, we may
   // not have verified the type yet.  We have to make sure it is
   // verified, since that sets the list of dependencies.
-  this->verify();
+  this->verify(gogo);
 
   // Convert all the dependencies.  If they refer indirectly back to
   // this type, they will pick up the intermediate representation we just
@@ -12791,7 +12791,7 @@  Forward_declaration_type::do_traverse(Traverse* traverse)
 // Verify the type.
 
 bool
-Forward_declaration_type::do_verify()
+Forward_declaration_type::do_verify(Gogo*)
 {
   if (!this->is_defined() && !this->is_nil_constant_as_type())
     {
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 057fa014cee..15f29f76b8c 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -584,8 +584,8 @@  class Type
   // returns false if the type is invalid and we should not continue
   // traversing it.
   bool
-  verify()
-  { return this->do_verify(); }
+  verify(Gogo* gogo)
+  { return this->do_verify(gogo); }
 
   // Bit flags to pass to are_identical and friends.
 
@@ -1101,7 +1101,7 @@  class Type
 
   // Verify the type.
   virtual bool
-  do_verify()
+  do_verify(Gogo*)
   { return true; }
 
   virtual bool
@@ -2297,8 +2297,8 @@  class Pointer_type : public Type
   do_traverse(Traverse*);
 
   bool
-  do_verify()
-  { return this->to_type_->verify(); }
+  do_verify(Gogo* gogo)
+  { return this->to_type_->verify(gogo); }
 
   // If this is a pointer to a type that can't be in the heap, then
   // the garbage collector does not have to look at this, so pretend
@@ -2675,7 +2675,7 @@  class Struct_type : public Type
   do_traverse(Traverse*);
 
   bool
-  do_verify();
+  do_verify(Gogo*);
 
   bool
   do_has_pointer() const;
@@ -2855,7 +2855,7 @@  class Array_type : public Type
   do_traverse(Traverse* traverse);
 
   bool
-  do_verify();
+  do_verify(Gogo*);
 
   bool
   do_has_pointer() const;
@@ -2901,7 +2901,7 @@  class Array_type : public Type
 
  private:
   bool
-  verify_length();
+  verify_length(Gogo*);
 
   Expression*
   array_type_descriptor(Gogo*, Named_type*);
@@ -3003,7 +3003,7 @@  class Map_type : public Type
   do_traverse(Traverse*);
 
   bool
-  do_verify();
+  do_verify(Gogo*);
 
   bool
   do_has_pointer() const
@@ -3123,7 +3123,7 @@  class Channel_type : public Type
   { return Type::traverse(this->element_type_, traverse); }
 
   bool
-  do_verify();
+  do_verify(Gogo*);
 
   bool
   do_has_pointer() const
@@ -3604,7 +3604,7 @@  class Named_type : public Type
   { return Type::traverse(this->type_, traverse); }
 
   bool
-  do_verify();
+  do_verify(Gogo*);
 
   bool
   do_has_pointer() const;
@@ -3762,7 +3762,7 @@  class Forward_declaration_type : public Type
   do_traverse(Traverse* traverse);
 
   bool
-  do_verify();
+  do_verify(Gogo*);
 
   bool
   do_has_pointer() const