// types.h -- Go frontend types.     -*- C++ -*-

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef GO_TYPES_H
#define GO_TYPES_H

#include <ostream>

#include "go-linemap.h"
#include "escape.h"

class Gogo;
class Package;
class Variable;
class Traverse;
class Typed_identifier;
class Typed_identifier_list;
class Integer_type;
class Float_type;
class Complex_type;
class String_type;
class Function_type;
class Backend_function_type;
class Struct_field;
class Struct_field_list;
class Struct_type;
class Pointer_type;
class Array_type;
class Map_type;
class Channel_type;
class Interface_type;
class Named_type;
class Forward_declaration_type;
class Method;
class Methods;
class Type_hash_identical;
class Type_identical;
class Expression;
class Expression_list;
class Call_expression;
class Field_reference_expression;
class Bound_method_expression;
class Bindings;
class Named_object;
class Function;
class Translate_context;
class Export;
class Import;
class Btype;
class Bexpression;
class Bvariable;

// Type codes used in type descriptors.  These must match the values
// in libgo/runtime/go-type.h.  They also match the values in the gc
// compiler in src/cmd/gc/reflect.c and src/pkg/runtime/type.go,
// although this is not required.

static const int RUNTIME_TYPE_KIND_BOOL = 1;
static const int RUNTIME_TYPE_KIND_INT = 2;
static const int RUNTIME_TYPE_KIND_INT8 = 3;
static const int RUNTIME_TYPE_KIND_INT16 = 4;
static const int RUNTIME_TYPE_KIND_INT32 = 5;
static const int RUNTIME_TYPE_KIND_INT64 = 6;
static const int RUNTIME_TYPE_KIND_UINT = 7;
static const int RUNTIME_TYPE_KIND_UINT8 = 8;
static const int RUNTIME_TYPE_KIND_UINT16 = 9;
static const int RUNTIME_TYPE_KIND_UINT32 = 10;
static const int RUNTIME_TYPE_KIND_UINT64 = 11;
static const int RUNTIME_TYPE_KIND_UINTPTR = 12;
static const int RUNTIME_TYPE_KIND_FLOAT32 = 13;
static const int RUNTIME_TYPE_KIND_FLOAT64 = 14;
static const int RUNTIME_TYPE_KIND_COMPLEX64 = 15;
static const int RUNTIME_TYPE_KIND_COMPLEX128 = 16;
static const int RUNTIME_TYPE_KIND_ARRAY = 17;
static const int RUNTIME_TYPE_KIND_CHAN = 18;
static const int RUNTIME_TYPE_KIND_FUNC = 19;
static const int RUNTIME_TYPE_KIND_INTERFACE = 20;
static const int RUNTIME_TYPE_KIND_MAP = 21;
static const int RUNTIME_TYPE_KIND_PTR = 22;
static const int RUNTIME_TYPE_KIND_SLICE = 23;
static const int RUNTIME_TYPE_KIND_STRING = 24;
static const int RUNTIME_TYPE_KIND_STRUCT = 25;
static const int RUNTIME_TYPE_KIND_UNSAFE_POINTER = 26;

static const int RUNTIME_TYPE_KIND_DIRECT_IFACE = (1 << 5);
static const int RUNTIME_TYPE_KIND_GC_PROG = (1 << 6);
static const int RUNTIME_TYPE_KIND_NO_POINTERS = (1 << 7);

// To build the complete list of methods for a named type we need to
// gather all methods from anonymous fields.  Those methods may
// require an arbitrary set of indirections and field offsets.  There
// is also the possibility of ambiguous methods, which we could ignore
// except that we want to give a better error message for that case.
// This is a base class.  There are two types of methods: named
// methods, and methods which are inherited from an anonymous field of
// interface type.

class Method
{
 public:
  // For methods in anonymous types we need to know the sequence of
  // field references used to extract the pointer to pass to the
  // method.  Since each method for a particular anonymous field will
  // have the sequence of field indexes, and since the indexes can be
  // shared going down the chain, we use a manually managed linked
  // list.  The first entry in the list is the field index for the
  // last field, the one passed to the method.

  struct Field_indexes
  {
    const Field_indexes* next;
    unsigned int field_index;
  };

  virtual ~Method()
  { }

  // Get the list of field indexes.
  const Field_indexes*
  field_indexes() const
  { return this->field_indexes_; }

  // Get the depth.
  unsigned int
  depth() const
  { return this->depth_; }

  // Return whether this is a value method--a method which does not
  // require a pointer expression.
  bool
  is_value_method() const
  { return this->is_value_method_; }

  // Return whether we need a stub method--this is true if we can't
  // just pass the main object to the method.
  bool
  needs_stub_method() const
  { return this->needs_stub_method_; }

  // Return whether this is an ambiguous method name.
  bool
  is_ambiguous() const
  { return this->is_ambiguous_; }

  // Note that this method is ambiguous.
  void
  set_is_ambiguous()
  { this->is_ambiguous_ = true; }

  // Return the type of the method.
  Function_type*
  type() const
  { return this->do_type(); }

  // Return the location of the method receiver.
  Location
  receiver_location() const
  { return this->do_receiver_location(); }

  // Return an expression which binds this method to EXPR.  This is
  // something which can be used with a function call.
  Expression*
  bind_method(Expression* expr, Location location) const;

  // Return the named object for this method.  This may only be called
  // after methods are finalized.
  Named_object*
  named_object() const;

  // Get the stub object.
  Named_object*
  stub_object() const
  {
    go_assert(this->stub_ != NULL);
    return this->stub_;
  }

  // Set the stub object.
  void
  set_stub_object(Named_object* no)
  {
    go_assert(this->stub_ == NULL);
    this->stub_ = no;
  }

  // Return true if this method should not participate in any
  // interfaces.
  bool
  nointerface() const
  { return this->do_nointerface(); }

 protected:
  // These objects are only built by the child classes.
  Method(const Field_indexes* field_indexes, unsigned int depth,
	 bool is_value_method, bool needs_stub_method)
    : field_indexes_(field_indexes), depth_(depth), stub_(NULL),
      is_value_method_(is_value_method), needs_stub_method_(needs_stub_method),
      is_ambiguous_(false)
  { }

  // The named object for this method.
  virtual Named_object*
  do_named_object() const = 0;

  // The type of the method.
  virtual Function_type*
  do_type() const = 0;

  // Return the location of the method receiver.
  virtual Location
  do_receiver_location() const = 0;

  // Bind a method to an object.
  virtual Expression*
  do_bind_method(Expression* expr, Location location) const = 0;

  // Return whether this method should not participate in interfaces.
  virtual bool
  do_nointerface() const = 0;

 private:
  // The sequence of field indexes used for this method.  If this is
  // NULL, then the method is defined for the current type.
  const Field_indexes* field_indexes_;
  // The depth at which this method was found.
  unsigned int depth_;
  // If a stub method is required, this is its object.  This is only
  // set after stub methods are built in finalize_methods.
  Named_object* stub_;
  // Whether this is a value method--a method that does not require a
  // pointer.
  bool is_value_method_;
  // Whether a stub method is required.
  bool needs_stub_method_;
  // Whether this method is ambiguous.
  bool is_ambiguous_;
};

// A named method.  This is what you get with a method declaration,
// either directly on the type, or inherited from some anonymous
// embedded field.

class Named_method : public Method
{
 public:
  Named_method(Named_object* named_object, const Field_indexes* field_indexes,
	       unsigned int depth, bool is_value_method,
	       bool needs_stub_method)
    : Method(field_indexes, depth, is_value_method, needs_stub_method),
      named_object_(named_object)
  { }

 protected:
  // Get the Named_object for the method.
  Named_object*
  do_named_object() const
  { return this->named_object_; }

  // The type of the method.
  Function_type*
  do_type() const;

  // Return the location of the method receiver.
  Location
  do_receiver_location() const;

  // Bind a method to an object.
  Expression*
  do_bind_method(Expression* expr, Location location) const;

  // Return whether this method should not participate in interfaces.
  bool
  do_nointerface() const;

 private:
  // The method itself.  For a method which needs a stub, this starts
  // out as the underlying method, and is later replaced with the stub
  // method.
  Named_object* named_object_;
};

// An interface method.  This is used when an interface appears as an
// anonymous field in a named struct.

class Interface_method : public Method
{
 public:
  Interface_method(const std::string& name, Location location,
		   Function_type* fntype, const Field_indexes* field_indexes,
		   unsigned int depth)
    : Method(field_indexes, depth, true, true),
      name_(name), location_(location), fntype_(fntype)
  { }

 protected:
  // Get the Named_object for the method.  This should never be
  // called, as we always create a stub.
  Named_object*
  do_named_object() const
  { go_unreachable(); }

  // The type of the method.
  Function_type*
  do_type() const
  { return this->fntype_; }

  // Return the location of the method receiver.
  Location
  do_receiver_location() const
  { return this->location_; }

  // Bind a method to an object.
  Expression*
  do_bind_method(Expression* expr, Location location) const;

  // Return whether this method should not participate in interfaces.
  bool
  do_nointerface() const
  { return false; }

 private:
  // The name of the interface method to call.
  std::string name_;
  // The location of the definition of the interface method.
  Location location_;
  // The type of the interface method.
  Function_type* fntype_;
};

// A mapping from method name to Method.  This is a wrapper around a
// hash table.

class Methods
{
 private:
  typedef Unordered_map(std::string, Method*) Method_map;

 public:
  typedef Method_map::const_iterator const_iterator;

  Methods()
    : methods_()
  { }

  // Insert a new method.  Returns true if it was inserted, false if
  // it was overidden or ambiguous.
  bool
  insert(const std::string& name, Method* m);

  // The number of (unambiguous) methods.
  size_t
  count() const;

  // Iterate.
  const_iterator
  begin() const
  { return this->methods_.begin(); }

  const_iterator
  end() const
  { return this->methods_.end(); }

  // Lookup.
  const_iterator
  find(const std::string& name) const
  { return this->methods_.find(name); }

  bool
  empty() const
  { return this->methods_.empty(); }

 private:
  Method_map methods_;
};

// The base class for all types.

class Type
{
 public:
  // The types of types.
  enum Type_classification
  {
    TYPE_ERROR,
    TYPE_VOID,
    TYPE_BOOLEAN,
    TYPE_INTEGER,
    TYPE_FLOAT,
    TYPE_COMPLEX,
    TYPE_STRING,
    TYPE_SINK,
    TYPE_FUNCTION,
    TYPE_POINTER,
    TYPE_NIL,
    TYPE_CALL_MULTIPLE_RESULT,
    TYPE_STRUCT,
    TYPE_ARRAY,
    TYPE_MAP,
    TYPE_CHANNEL,
    TYPE_INTERFACE,
    TYPE_NAMED,
    TYPE_FORWARD
  };

  virtual ~Type();

  // Creators.

  static Type*
  make_error_type();

  static Type*
  make_void_type();

  // Get the unnamed bool type.
  static Type*
  make_boolean_type();

  // Get the named type "bool".
  static Named_type*
  lookup_bool_type();

  // Make the named type "bool".
  static Named_type*
  make_named_bool_type();

  // Make an abstract integer type.
  static Integer_type*
  make_abstract_integer_type();

  // Make an abstract type for a character constant.
  static Integer_type*
  make_abstract_character_type();

  // Make a named integer type with a specified size.
  // RUNTIME_TYPE_KIND is the code to use in reflection information,
  // to distinguish int and int32.
  static Named_type*
  make_integer_type(const char* name, bool is_unsigned, int bits,
		    int runtime_type_kind);

  // Look up a named integer type.
  static Named_type*
  lookup_integer_type(const char* name);

  // Make an abstract floating point type.
  static Float_type*
  make_abstract_float_type();

  // Make a named floating point type with a specific size.
  // RUNTIME_TYPE_KIND is the code to use in reflection information,
  // to distinguish float and float32.
  static Named_type*
  make_float_type(const char* name, int bits, int runtime_type_kind);

  // Look up a named float type.
  static Named_type*
  lookup_float_type(const char* name);

  // Make an abstract complex type.
  static Complex_type*
  make_abstract_complex_type();

  // Make a named complex type with a specific size.
  // RUNTIME_TYPE_KIND is the code to use in reflection information,
  // to distinguish complex and complex64.
  static Named_type*
  make_complex_type(const char* name, int bits, int runtime_type_kind);

  // Look up a named complex type.
  static Named_type*
  lookup_complex_type(const char* name);

  // Get the unnamed string type.
  static Type*
  make_string_type();

  // Get the named type "string".
  static Named_type*
  lookup_string_type();

  // Make the named type "string".
  static Named_type*
  make_named_string_type();

  static Type*
  make_sink_type();

  static Function_type*
  make_function_type(Typed_identifier* receiver,
		     Typed_identifier_list* parameters,
		     Typed_identifier_list* results,
		     Location);

  static Backend_function_type*
  make_backend_function_type(Typed_identifier* receiver,
                             Typed_identifier_list* parameters,
                             Typed_identifier_list* results,
                             Location);

  static Pointer_type*
  make_pointer_type(Type*);

  static Type*
  make_nil_type();

  static Type*
  make_call_multiple_result_type(Call_expression*);

  static Struct_type*
  make_struct_type(Struct_field_list* fields, Location);

  static Array_type*
  make_array_type(Type* element_type, Expression* length);

  static Map_type*
  make_map_type(Type* key_type, Type* value_type, Location);

  static Channel_type*
  make_channel_type(bool send, bool receive, Type*);

  static Interface_type*
  make_interface_type(Typed_identifier_list* methods, Location);

  static Interface_type*
  make_empty_interface_type(Location);

  static Type*
  make_type_descriptor_type();

  static Type*
  make_type_descriptor_ptr_type();

  static Named_type*
  make_named_type(Named_object*, Type*, Location);

  static Type*
  make_forward_declaration(Named_object*);

  // Make a builtin struct type from a list of fields.
  static Struct_type*
  make_builtin_struct_type(int nfields, ...);

  // Make a builtin named type.
  static Named_type*
  make_builtin_named_type(const char* name, Type* type);

  // Traverse a type.
  static int
  traverse(Type*, Traverse*);

  // Verify the type.  This is called after parsing, and verifies that
  // types are complete and meet the language requirements.  This
  // returns false if the type is invalid and we should not continue
  // traversing it.
  bool
  verify()
  { return this->do_verify(); }

  // Return true if two types are identical.  If ERRORS_ARE_IDENTICAL,
  // returns that an erroneous type is identical to any other type;
  // this is used to avoid cascading errors.  If this returns false,
  // and REASON is not NULL, it may set *REASON.
  static bool
  are_identical(const Type* lhs, const Type* rhs, bool errors_are_identical,
		std::string* reason);

  // An argument to are_identical_cmp_tags, indicating whether or not
  // to compare struct field tags.
  enum Cmp_tags {
    COMPARE_TAGS,
    IGNORE_TAGS
  };

  // Return true if two types are identical.  This is like the
  // are_identical function, but also takes a CMP_TAGS argument
  // indicating whether to compare struct tags.  Otherwise the
  // parameters are as for are_identical.
  static bool
  are_identical_cmp_tags(const Type* lhs, const Type* rhs,
			 Cmp_tags, bool errors_are_identical,
			 std::string* reason);

  // Return true if two types are compatible for use in a binary
  // operation, other than a shift, comparison, or channel send.  This
  // is an equivalence relation.
  static bool
  are_compatible_for_binop(const Type* t1, const Type* t2);

  // Return true if two types are compatible for use with the
  // comparison operator.  IS_EQUALITY_OP is true if this is an
  // equality comparison, false if it is an ordered comparison.  This
  // is an equivalence relation.  If this returns false, and REASON is
  // not NULL, it sets *REASON.
  static bool
  are_compatible_for_comparison(bool is_equality_op, const Type *t1,
				const Type *t2, std::string* reason);

  // Return true if a type is comparable with itself.  This is true of
  // most types, but false for, e.g., function types.
  bool
  is_comparable() const
  { return Type::are_compatible_for_comparison(true, this, this, NULL); }

  // Return true if a value with type RHS is assignable to a variable
  // with type LHS.  This is not an equivalence relation.  If this
  // returns false, and REASON is not NULL, it sets *REASON.
  static bool
  are_assignable(const Type* lhs, const Type* rhs, std::string* reason);

  // Return true if a value with type RHS may be converted to type
  // LHS.  If this returns false, and REASON is not NULL, it sets
  // *REASON.
  static bool
  are_convertible(const Type* lhs, const Type* rhs, std::string* reason);

  // Return true if values of this type can be compared using an
  // identity function which gets nothing but a pointer to the value
  // and a size.
  bool
  compare_is_identity(Gogo* gogo)
  { return this->do_compare_is_identity(gogo); }

  // Return whether values of this type are reflexive: if a comparison
  // of a value with itself always returns true.
  bool
  is_reflexive()
  { return this->do_is_reflexive(); }

  // Return whether values of this, when used as a key in map,
  // requires the key to be updated when an assignment is made.
  bool
  needs_key_update()
  { return this->do_needs_key_update(); }

  // Return a hash code for this type for the method hash table.
  // Types which are equivalent according to are_identical will have
  // the same hash code.
  unsigned int
  hash_for_method(Gogo*) const;

  // Return the type classification.
  Type_classification
  classification() const
  { return this->classification_; }

  // Return the base type for this type.  This looks through forward
  // declarations and names.  Using this with a forward declaration
  // which has not been defined will return an error type.
  Type*
  base();

  const Type*
  base() const;

  // Return the type skipping defined forward declarations.  If this
  // type is a forward declaration which has not been defined, it will
  // return the Forward_declaration_type.  This differs from base() in
  // that it will return a Named_type, and for a
  // Forward_declaration_type which is not defined it will return that
  // type rather than an error type.
  Type*
  forwarded();

  const Type*
  forwarded() const;

  // Return true if this is a basic type: a type which is not composed
  // of other types, and is not void.
  bool
  is_basic_type() const;

  // Return true if this is an abstract type--an integer, floating
  // point, or complex type whose size has not been determined.
  bool
  is_abstract() const;

  // Return a non-abstract version of an abstract type.
  Type*
  make_non_abstract_type();

  // Return true if this type is or contains a pointer.  This
  // determines whether the garbage collector needs to look at a value
  // of this type.
  bool
  has_pointer() const
  { return this->do_has_pointer(); }

  // Return true if this is the error type.  This returns false for a
  // type which is not defined, as it is called by the parser before
  // all types are defined.
  bool
  is_error_type() const;

  // Return true if this is the error type or if the type is
  // undefined.  If the type is undefined, this will give an error.
  // This should only be called after parsing is complete.
  bool
  is_error() const
  { return this->base()->is_error_type(); }

  // Return true if this is a void type.
  bool
  is_void_type() const
  { return this->classification_ == TYPE_VOID; }

  // If this is an integer type, return the Integer_type.  Otherwise,
  // return NULL.  This is a controlled dynamic_cast.
  Integer_type*
  integer_type()
  { return this->convert<Integer_type, TYPE_INTEGER>(); }

  const Integer_type*
  integer_type() const
  { return this->convert<const Integer_type, TYPE_INTEGER>(); }

  // If this is a floating point type, return the Float_type.
  // Otherwise, return NULL.  This is a controlled dynamic_cast.
  Float_type*
  float_type()
  { return this->convert<Float_type, TYPE_FLOAT>(); }

  const Float_type*
  float_type() const
  { return this->convert<const Float_type, TYPE_FLOAT>(); }

  // If this is a complex type, return the Complex_type.  Otherwise,
  // return NULL.
  Complex_type*
  complex_type()
  { return this->convert<Complex_type, TYPE_COMPLEX>(); }

  const Complex_type*
  complex_type() const
  { return this->convert<const Complex_type, TYPE_COMPLEX>(); }

  // Return whether this is a numeric type.
  bool
  is_numeric_type() const
  {
    Type_classification tc = this->base()->classification_;
    return tc == TYPE_INTEGER || tc == TYPE_FLOAT || tc == TYPE_COMPLEX;
  }

  // Return true if this is a boolean type.
  bool
  is_boolean_type() const
  { return this->base()->classification_ == TYPE_BOOLEAN; }

  // Return true if this is an abstract boolean type.
  bool
  is_abstract_boolean_type() const
  { return this->classification_ == TYPE_BOOLEAN; }

  // Return true if this is a string type.
  bool
  is_string_type() const
  { return this->base()->classification_ == TYPE_STRING; }

  // Return true if this is an abstract string type.
  bool
  is_abstract_string_type() const
  { return this->classification_ == TYPE_STRING; }

  // Return true if this is the sink type.  This is the type of the
  // blank identifier _.
  bool
  is_sink_type() const
  { return this->base()->classification_ == TYPE_SINK; }

  // If this is a function type, return it.  Otherwise, return NULL.
  Function_type*
  function_type()
  { return this->convert<Function_type, TYPE_FUNCTION>(); }

  const Function_type*
  function_type() const
  { return this->convert<const Function_type, TYPE_FUNCTION>(); }

  // If this is a pointer type, return the type to which it points.
  // Otherwise, return NULL.
  Type*
  points_to() const;

  // If this is a pointer type, return the type to which it points.
  // Otherwise, return the type itself.
  Type*
  deref()
  {
    Type* pt = this->points_to();
    return pt != NULL ? pt : this;
  }

  const Type*
  deref() const
  {
    const Type* pt = this->points_to();
    return pt != NULL ? pt : this;
  }

  // Return true if this is the nil type.  We don't use base() here,
  // because this can be called during parse, and there is no way to
  // name the nil type anyhow.
  bool
  is_nil_type() const
  { return this->classification_ == TYPE_NIL; }

  // Return true if this is the predeclared constant nil being used as
  // a type.  This is what the parser produces for type switches which
  // use "case nil".
  bool
  is_nil_constant_as_type() const;

  // Return true if this is the return type of a function which
  // returns multiple values.
  bool
  is_call_multiple_result_type() const
  { return this->base()->classification_ == TYPE_CALL_MULTIPLE_RESULT; }

  // If this is a struct type, return it.  Otherwise, return NULL.
  Struct_type*
  struct_type()
  { return this->convert<Struct_type, TYPE_STRUCT>(); }

  const Struct_type*
  struct_type() const
  { return this->convert<const Struct_type, TYPE_STRUCT>(); }

  // If this is an array type, return it.  Otherwise, return NULL.
  Array_type*
  array_type()
  { return this->convert<Array_type, TYPE_ARRAY>(); }

  const Array_type*
  array_type() const
  { return this->convert<const Array_type, TYPE_ARRAY>(); }

  // Return whether if this is a slice type.
  bool
  is_slice_type() const;

  // If this is a map type, return it.  Otherwise, return NULL.
  Map_type*
  map_type()
  { return this->convert<Map_type, TYPE_MAP>(); }

  const Map_type*
  map_type() const
  { return this->convert<const Map_type, TYPE_MAP>(); }

  // If this is a channel type, return it.  Otherwise, return NULL.
  Channel_type*
  channel_type()
  { return this->convert<Channel_type, TYPE_CHANNEL>(); }

  const Channel_type*
  channel_type() const
  { return this->convert<const Channel_type, TYPE_CHANNEL>(); }

  // If this is an interface type, return it.  Otherwise, return NULL.
  Interface_type*
  interface_type()
  { return this->convert<Interface_type, TYPE_INTERFACE>(); }

  const Interface_type*
  interface_type() const
  { return this->convert<const Interface_type, TYPE_INTERFACE>(); }

  // If this is a named type, return it.  Otherwise, return NULL.
  Named_type*
  named_type();

  const Named_type*
  named_type() const;

  // If this is a forward declaration, return it.  Otherwise, return
  // NULL.
  Forward_declaration_type*
  forward_declaration_type()
  { return this->convert_no_base<Forward_declaration_type, TYPE_FORWARD>(); }

  const Forward_declaration_type*
  forward_declaration_type() const
  {
    return this->convert_no_base<const Forward_declaration_type,
				 TYPE_FORWARD>();
  }

  // Return true if this type is not yet defined.
  bool
  is_undefined() const;

  // Return true if this is the unsafe.pointer type.  We currently
  // represent that as pointer-to-void.
  bool
  is_unsafe_pointer_type() const
  { return this->points_to() != NULL && this->points_to()->is_void_type(); }

  // Look for field or method NAME for TYPE.  Return an expression for
  // it, bound to EXPR.
  static Expression*
  bind_field_or_method(Gogo*, const Type* type, Expression* expr,
		       const std::string& name, Location);

  // Return true if NAME is an unexported field or method of TYPE.
  static bool
  is_unexported_field_or_method(Gogo*, const Type*, const std::string&,
				std::vector<const Named_type*>*);

  // Convert the builtin named types.
  static void
  convert_builtin_named_types(Gogo*);

  // Return the backend representation of this type.
  Btype*
  get_backend(Gogo*);

  // Return a placeholder for the backend representation of the type.
  // This will return a type of the correct size, but for which some
  // of the fields may still need to be completed.
  Btype*
  get_backend_placeholder(Gogo*);

  // Finish the backend representation of a placeholder.
  void
  finish_backend(Gogo*, Btype*);

  // Build a type descriptor entry for this type.  Return a pointer to
  // it.  The location is the location which causes us to need the
  // entry.
  Bexpression*
  type_descriptor_pointer(Gogo* gogo, Location);

  // Build the Garbage Collection symbol for this type.  Return a pointer to it.
  Bexpression*
  gc_symbol_pointer(Gogo* gogo);

  // Return whether this type needs a garbage collection program.
  // Sets *PTRSIZE and *PTRDATA.
  bool
  needs_gcprog(Gogo*, int64_t* ptrsize, int64_t* ptrdata);

  // Return a ptrmask variable for this type.
  Bvariable*
  gc_ptrmask_var(Gogo*, int64_t ptrsize, int64_t ptrdata);

  // Return the type reflection string for this type.
  std::string
  reflection(Gogo*) const;

  // Return a mangled name for the type.  This is a name which can be
  // used in assembler code.  Identical types should have the same
  // manged name.
  std::string
  mangled_name(Gogo*) const;

  // If the size of the type can be determined, set *PSIZE to the size
  // in bytes and return true.  Otherwise, return false.  This queries
  // the backend.
  bool
  backend_type_size(Gogo*, int64_t* psize);

  // If the alignment of the type can be determined, set *PALIGN to
  // the alignment in bytes and return true.  Otherwise, return false.
  bool
  backend_type_align(Gogo*, int64_t* palign);

  // If the alignment of a struct field of this type can be
  // determined, set *PALIGN to the alignment in bytes and return
  // true.  Otherwise, return false.
  bool
  backend_type_field_align(Gogo*, int64_t* palign);

  // Determine the ptrdata size for the backend version of this type:
  // the length of the prefix of the type that can contain a pointer
  // value.  If it can be determined, set *PPTRDATA to the value in
  // bytes and return true.  Otherwise, return false.
  bool
  backend_type_ptrdata(Gogo*, int64_t* pptrdata);

  // Determine the ptrdata size that we are going to set in the type
  // descriptor.  This is normally the same as backend_type_ptrdata,
  // but differs if we use a gcprog for an array.  The arguments and
  // results are as for backend_type_ptrdata.
  bool
  descriptor_ptrdata(Gogo*, int64_t* pptrdata);

  // Whether the backend size is known.
  bool
  is_backend_type_size_known(Gogo*);

  // Return whether the type needs specially built type functions.
  bool
  needs_specific_type_functions(Gogo*);

  // Get the hash and equality functions for a type.
  void
  type_functions(Gogo*, Named_type* name, Function_type* hash_fntype,
		 Function_type* equal_fntype, Named_object** hash_fn,
		 Named_object** equal_fn);

  // Write the hash and equality type functions.
  void
  write_specific_type_functions(Gogo*, Named_type*, int64_t size,
				const std::string& hash_name,
				Function_type* hash_fntype,
				const std::string& equal_name,
				Function_type* equal_fntype);

  // Return the alignment required by the memequalN function.
  static int64_t memequal_align(Gogo*, int size);

  // Export the type.
  void
  export_type(Export* exp) const
  { this->do_export(exp); }

  // Import a type.
  static Type*
  import_type(Import*);

 protected:
  Type(Type_classification);

  // Functions implemented by the child class.

  // Traverse the subtypes.
  virtual int
  do_traverse(Traverse*);

  // Verify the type.
  virtual bool
  do_verify()
  { return true; }

  virtual bool
  do_has_pointer() const
  { return false; }

  virtual bool
  do_compare_is_identity(Gogo*) = 0;

  virtual bool
  do_is_reflexive()
  { return true; }

  virtual bool
  do_needs_key_update()
  { return false; }

  virtual unsigned int
  do_hash_for_method(Gogo*) const;

  virtual Btype*
  do_get_backend(Gogo*) = 0;

  virtual Expression*
  do_type_descriptor(Gogo*, Named_type* name) = 0;

  virtual void
  do_reflection(Gogo*, std::string*) const = 0;

  virtual void
  do_mangled_name(Gogo*, std::string*) const = 0;

  virtual void
  do_export(Export*) const;

  // Return whether a method expects a pointer as the receiver.
  static bool
  method_expects_pointer(const Named_object*);

  // Finalize the methods for a type.
  static void
  finalize_methods(Gogo*, const Type*, Location, Methods**);

  // Return a method from a set of methods.
  static Method*
  method_function(const Methods*, const std::string& name,
		  bool* is_ambiguous);

  // A mapping from interfaces to the associated interface method
  // tables for this type.  This maps to a decl.
  typedef Unordered_map_hash(Interface_type*, Expression*, Type_hash_identical,
			     Type_identical) Interface_method_tables;

  // Return a pointer to the interface method table for TYPE for the
  // interface INTERFACE.
  static Expression*
  interface_method_table(Type* type,
			 Interface_type *interface, bool is_pointer,
			 Interface_method_tables** method_tables,
			 Interface_method_tables** pointer_tables);

  // Return a composite literal for the type descriptor entry for a
  // type.
  static Expression*
  type_descriptor(Gogo*, Type*);

  // Return a composite literal for the type descriptor entry for
  // TYPE, using NAME as the name of the type.
  static Expression*
  named_type_descriptor(Gogo*, Type* type, Named_type* name);

  // Return a composite literal for a plain type descriptor for this
  // type with the given kind and name.
  Expression*
  plain_type_descriptor(Gogo*, int runtime_type_kind, Named_type* name);

  // Build a composite literal for the basic type descriptor.
  Expression*
  type_descriptor_constructor(Gogo*, int runtime_type_kind, Named_type*,
			      const Methods*, bool only_value_methods);

  // For the benefit of child class reflection string generation.
  void
  append_reflection(const Type* type, Gogo* gogo, std::string* ret) const
  { type->do_reflection(gogo, ret); }

  // For the benefit of child class mangling.
  void
  append_mangled_name(const Type* type, Gogo* gogo, std::string* ret) const
  { type->do_mangled_name(gogo, ret); }

  // Incorporate a string into a hash code.
  static unsigned int
  hash_string(const std::string&, unsigned int);

  // Return the backend representation for the underlying type of a
  // named type.
  static Btype*
  get_named_base_btype(Gogo* gogo, Type* base_type)
  { return base_type->get_btype_without_hash(gogo); }

 private:
  // Convert to the desired type classification, or return NULL.  This
  // is a controlled dynamic_cast.
  template<typename Type_class, Type_classification type_classification>
  Type_class*
  convert()
  {
    Type* base = this->base();
    return (base->classification_ == type_classification
	    ? static_cast<Type_class*>(base)
	    : NULL);
  }

  template<typename Type_class, Type_classification type_classification>
  const Type_class*
  convert() const
  {
    const Type* base = this->base();
    return (base->classification_ == type_classification
	    ? static_cast<Type_class*>(base)
	    : NULL);
  }

  template<typename Type_class, Type_classification type_classification>
  Type_class*
  convert_no_base()
  {
    return (this->classification_ == type_classification
	    ? static_cast<Type_class*>(this)
	    : NULL);
  }

  template<typename Type_class, Type_classification type_classification>
  const Type_class*
  convert_no_base() const
  {
    return (this->classification_ == type_classification
	    ? static_cast<Type_class*>(this)
	    : NULL);
  }

  // Map unnamed types to type descriptor decls.
  typedef Unordered_map_hash(const Type*, Bvariable*, Type_hash_identical,
			     Type_identical) Type_descriptor_vars;

  static Type_descriptor_vars type_descriptor_vars;

  // Build the type descriptor variable for this type.
  void
  make_type_descriptor_var(Gogo*);

  // Map unnamed types to type descriptor decls.
  typedef Unordered_map_hash(const Type*, Bvariable*, Type_hash_identical,
			     Type_identical) GC_symbol_vars;

  static GC_symbol_vars gc_symbol_vars;

  // Map ptrmask symbol names to the ptrmask variable.
  typedef Unordered_map(std::string, Bvariable*) GC_gcbits_vars;

  static GC_gcbits_vars gc_gcbits_vars;

  // Build the GC symbol for this type.
  void
  make_gc_symbol_var(Gogo*);

  // Return the name of the type descriptor variable.  If NAME is not
  // NULL, it is the name to use.
  std::string
  type_descriptor_var_name(Gogo*, Named_type* name);

  // Return true if the type descriptor for this type should be
  // defined in some other package.  If NAME is not NULL, it is the
  // name of this type.  If this returns true it sets *PACKAGE to the
  // package where the type descriptor is defined.
  bool
  type_descriptor_defined_elsewhere(Named_type* name, const Package** package);

  // Make a composite literal for the garbage collection program for
  // this type.
  Expression*
  gcprog_constructor(Gogo*, int64_t ptrsize, int64_t ptrdata);

  // Build the hash and equality type functions for a type which needs
  // specific functions.
  void
  specific_type_functions(Gogo*, Named_type*, int64_t size,
			  Function_type* hash_fntype,
			  Function_type* equal_fntype, Named_object** hash_fn,
			  Named_object** equal_fn);

  void
  write_identity_hash(Gogo*, int64_t size);

  void
  write_identity_equal(Gogo*, int64_t size);

  void
  write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype,
		   Function_type* equal_fntype);

  void
  write_named_equal(Gogo*, Named_type*);

  // Build a composite literal for the uncommon type information.
  Expression*
  uncommon_type_constructor(Gogo*, Type* uncommon_type,
			    Named_type*, const Methods*,
			    bool only_value_methods) const;

  // Build a composite literal for the methods.
  Expression*
  methods_constructor(Gogo*, Type* methods_type, const Methods*,
		      bool only_value_methods) const;

  // Build a composite literal for one method.
  Expression*
  method_constructor(Gogo*, Type* method_type, const std::string& name,
		     const Method*, bool only_value_methods) const;

  // Add all methods for TYPE to the list of methods for THIS.
  static void
  add_methods_for_type(const Type* type, const Method::Field_indexes*,
		       unsigned int depth, bool, bool,
		       std::vector<const Named_type*>*,
		       Methods*);

  static void
  add_local_methods_for_type(const Named_type* type,
			     const Method::Field_indexes*,
			     unsigned int depth, bool, bool, Methods*);

  static void
  add_embedded_methods_for_type(const Type* type,
				const Method::Field_indexes*,
				unsigned int depth, bool, bool,
				std::vector<const Named_type*>*,
				Methods*);

  static void
  add_interface_methods_for_type(const Type* type,
				 const Method::Field_indexes*,
				 unsigned int depth, Methods*);

  // Build stub methods for a type.
  static void
  build_stub_methods(Gogo*, const Type* type, const Methods* methods,
		     Location);

  static void
  build_one_stub_method(Gogo*, Method*, const char* receiver_name,
			const Typed_identifier_list*, bool is_varargs,
			Location);

  static Expression*
  apply_field_indexes(Expression*, const Method::Field_indexes*,
		      Location);

  // Look for a field or method named NAME in TYPE.
  static bool
  find_field_or_method(const Type* type, const std::string& name,
		       bool receiver_can_be_pointer,
		       std::vector<const Named_type*>*, int* level,
		       bool* is_method, bool* found_pointer_method,
		       std::string* ambig1, std::string* ambig2);

  // Get the backend representation for a type without looking in the
  // hash table for identical types.
  Btype*
  get_btype_without_hash(Gogo*);

  // A backend type that may be a placeholder.
  struct Type_btype_entry
  {
    Btype *btype;
    bool is_placeholder;
  };

  // A mapping from Type to Btype*, used to ensure that the backend
  // representation of identical types is identical.  This is only
  // used for unnamed types.
  typedef Unordered_map_hash(const Type*, Type_btype_entry,
			     Type_hash_identical, Type_identical) Type_btypes;

  static Type_btypes type_btypes;

  // A list of builtin named types.
  static std::vector<Named_type*> named_builtin_types;

  // A map from types which need specific type functions to the type
  // functions themselves.
  typedef std::pair<Named_object*, Named_object*> Hash_equal_fn;
  typedef Unordered_map_hash(const Type*, Hash_equal_fn, Type_hash_identical,
			     Type_identical) Type_functions;

  static Type_functions type_functions_table;

  // The type classification.
  Type_classification classification_;
  // The backend representation of the type, once it has been
  // determined.
  Btype* btype_;
  // The type descriptor for this type.  This starts out as NULL and
  // is filled in as needed.
  Bvariable* type_descriptor_var_;
  // The GC symbol for this type.  This starts out as NULL and
  // is filled in as needed.
  Bvariable* gc_symbol_var_;
};

// Type hash table operations.

class Type_hash_identical
{
 public:
  unsigned int
  operator()(const Type* type) const
  { return type->hash_for_method(NULL); }
};

class Type_identical
{
 public:
  bool
  operator()(const Type* t1, const Type* t2) const
  { return Type::are_identical(t1, t2, false, NULL); }
};

// An identifier with a type.

class Typed_identifier
{
 public:
  Typed_identifier(const std::string& name, Type* type,
		   Location location)
    : name_(name), type_(type), location_(location), note_(NULL)
  { }

  // Get the name.
  const std::string&
  name() const
  { return this->name_; }

  // Get the type.
  Type*
  type() const
  { return this->type_; }

  // Return the location where the name was seen.  This is not always
  // meaningful.
  Location
  location() const
  { return this->location_; }

  // Set the type--sometimes we see the identifier before the type.
  void
  set_type(Type* type)
  {
    go_assert(this->type_ == NULL || type->is_error_type());
    this->type_ = type;
  }

  // Get the escape note.
  std::string*
  note() const
  { return this->note_; }

  // Set the escape note.
  void
  set_note(const std::string& note)
  { this->note_ = new std::string(note); }

 private:
  // Identifier name.
  std::string name_;
  // Type.
  Type* type_;
  // The location where the name was seen.
  Location location_;
  // Escape note for this typed identifier.  Used when importing and exporting
  // functions.
  std::string* note_;
};

// A list of Typed_identifiers.

class Typed_identifier_list
{
 public:
  Typed_identifier_list()
    : entries_()
  { }

  // Whether the list is empty.
  bool
  empty() const
  { return this->entries_.empty(); }

  // Return the number of entries in the list.
  size_t
  size() const
  { return this->entries_.size(); }

  // Add an entry to the end of the list.
  void
  push_back(const Typed_identifier& td)
  { this->entries_.push_back(td); }

  // Remove an entry from the end of the list.
  void
  pop_back()
  { this->entries_.pop_back(); }

  // Set the type of entry I to TYPE.
  void
  set_type(size_t i, Type* type)
  {
    go_assert(i < this->entries_.size());
    this->entries_[i].set_type(type);
  }

  // Sort the entries by name.
  void
  sort_by_name();

  // Traverse types.
  int
  traverse(Traverse*);

  // Return the first and last elements.
  Typed_identifier&
  front()
  { return this->entries_.front(); }

  const Typed_identifier&
  front() const
  { return this->entries_.front(); }

  Typed_identifier&
  back()
  { return this->entries_.back(); }

  const Typed_identifier&
  back() const
  { return this->entries_.back(); }

  Typed_identifier&
  at(size_t i)
  { return this->entries_.at(i); }

  const Typed_identifier&
  at(size_t i) const
  { return this->entries_.at(i); }

  void
  set(size_t i, const Typed_identifier& t)
  { this->entries_.at(i) = t; }

  void
  resize(size_t c)
  {
    go_assert(c <= this->entries_.size());
    this->entries_.resize(c, Typed_identifier("", NULL,
                                              Linemap::unknown_location()));
  }

  void
  reserve(size_t c)
  { this->entries_.reserve(c); }

  // Iterators.

  typedef std::vector<Typed_identifier>::iterator iterator;
  typedef std::vector<Typed_identifier>::const_iterator const_iterator;

  iterator
  begin()
  { return this->entries_.begin(); }

  const_iterator
  begin() const
  { return this->entries_.begin(); }

  iterator
  end()
  { return this->entries_.end(); }

  const_iterator
  end() const
  { return this->entries_.end(); }

  // Return a copy of this list.  This returns an independent copy of
  // the vector, but does not copy the types.
  Typed_identifier_list*
  copy() const;

 private:
  std::vector<Typed_identifier> entries_;
};

// The type of an integer.

class Integer_type : public Type
{
 public:
  // Create a new integer type.
  static Named_type*
  create_integer_type(const char* name, bool is_unsigned, int bits,
		      int runtime_type_kind);

  // Look up an existing integer type.
  static Named_type*
  lookup_integer_type(const char* name);

  // Create an abstract integer type.
  static Integer_type*
  create_abstract_integer_type();

  // Create an abstract character type.
  static Integer_type*
  create_abstract_character_type();

  // Whether this is an abstract integer type.
  bool
  is_abstract() const
  { return this->is_abstract_; }

  // Whether this is an unsigned type.
  bool
  is_unsigned() const
  { return this->is_unsigned_; }

  // The number of bits.
  int
  bits() const
  { return this->bits_; }

  // Whether this type is the same as T.
  bool
  is_identical(const Integer_type* t) const;

  // Whether this is the type "byte" or another name for "byte".
  bool
  is_byte() const
  { return this->is_byte_; }

  // Mark this as the "byte" type.
  void
  set_is_byte()
  { this->is_byte_ = true; }

  // Whether this is the type "rune" or another name for "rune".
  bool
  is_rune() const
  { return this->is_rune_; }

  // Mark this as the "rune" type.
  void
  set_is_rune()
  { this->is_rune_ = true; }

protected:
  bool
  do_compare_is_identity(Gogo*)
  { return true; }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

 private:
  Integer_type(bool is_abstract, bool is_unsigned, int bits,
	       int runtime_type_kind)
    : Type(TYPE_INTEGER),
      is_abstract_(is_abstract), is_unsigned_(is_unsigned), is_byte_(false),
      is_rune_(false), bits_(bits), runtime_type_kind_(runtime_type_kind)
  { }

  // Map names of integer types to the types themselves.
  typedef std::map<std::string, Named_type*> Named_integer_types;
  static Named_integer_types named_integer_types;

  // True if this is an abstract type.
  bool is_abstract_;
  // True if this is an unsigned type.
  bool is_unsigned_;
  // True if this is the byte type.
  bool is_byte_;
  // True if this is the rune type.
  bool is_rune_;
  // The number of bits.
  int bits_;
  // The runtime type code used in the type descriptor for this type.
  int runtime_type_kind_;
};

// The type of a floating point number.

class Float_type : public Type
{
 public:
  // Create a new float type.
  static Named_type*
  create_float_type(const char* name, int bits, int runtime_type_kind);

  // Look up an existing float type.
  static Named_type*
  lookup_float_type(const char* name);

  // Create an abstract float type.
  static Float_type*
  create_abstract_float_type();

  // Whether this is an abstract float type.
  bool
  is_abstract() const
  { return this->is_abstract_; }

  // The number of bits.
  int
  bits() const
  { return this->bits_; }

  // Whether this type is the same as T.
  bool
  is_identical(const Float_type* t) const;

 protected:
  bool
  do_compare_is_identity(Gogo*)
  { return false; }

  bool
  do_is_reflexive()
  { return false; }

  // Distinction between +0 and -0 requires a key update.
  bool
  do_needs_key_update()
  { return true; }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

 private:
  Float_type(bool is_abstract, int bits, int runtime_type_kind)
    : Type(TYPE_FLOAT),
      is_abstract_(is_abstract), bits_(bits),
      runtime_type_kind_(runtime_type_kind)
  { }

  // Map names of float types to the types themselves.
  typedef std::map<std::string, Named_type*> Named_float_types;
  static Named_float_types named_float_types;

  // True if this is an abstract type.
  bool is_abstract_;
  // The number of bits in the floating point value.
  int bits_;
  // The runtime type code used in the type descriptor for this type.
  int runtime_type_kind_;
};

// The type of a complex number.

class Complex_type : public Type
{
 public:
  // Create a new complex type.
  static Named_type*
  create_complex_type(const char* name, int bits, int runtime_type_kind);

  // Look up an existing complex type.
  static Named_type*
  lookup_complex_type(const char* name);

  // Create an abstract complex type.
  static Complex_type*
  create_abstract_complex_type();

  // Whether this is an abstract complex type.
  bool
  is_abstract() const
  { return this->is_abstract_; }

  // The number of bits: 64 or 128.
  int bits() const
  { return this->bits_; }

  // Whether this type is the same as T.
  bool
  is_identical(const Complex_type* t) const;

 protected:
  bool
  do_compare_is_identity(Gogo*)
  { return false; }

  bool
  do_is_reflexive()
  { return false; }

  // Distinction between +0 and -0 requires a key update.
  bool
  do_needs_key_update()
  { return true; }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

 private:
  Complex_type(bool is_abstract, int bits, int runtime_type_kind)
    : Type(TYPE_COMPLEX),
      is_abstract_(is_abstract), bits_(bits),
      runtime_type_kind_(runtime_type_kind)
  { }

  // Map names of complex types to the types themselves.
  typedef std::map<std::string, Named_type*> Named_complex_types;
  static Named_complex_types named_complex_types;

  // True if this is an abstract type.
  bool is_abstract_;
  // The number of bits in the complex value--64 or 128.
  int bits_;
  // The runtime type code used in the type descriptor for this type.
  int runtime_type_kind_;
};

// The type of a string.

class String_type : public Type
{
 public:
  String_type()
    : Type(TYPE_STRING)
  { }

 protected:
  bool
  do_has_pointer() const
  { return true; }

  bool
  do_compare_is_identity(Gogo*)
  { return false; }

  // New string might have a smaller backing store.
  bool
  do_needs_key_update()
  { return true; }

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string* ret) const;

 private:
  // The named string type.
  static Named_type* string_type_;
};

// The type of a function.

class Function_type : public Type
{
 public:
  Function_type(Typed_identifier* receiver, Typed_identifier_list* parameters,
		Typed_identifier_list* results, Location location)
    : Type(TYPE_FUNCTION),
      receiver_(receiver), parameters_(parameters), results_(results),
      location_(location), is_varargs_(false), is_builtin_(false),
      fnbtype_(NULL), is_tagged_(false)
  { }

  // Get the receiver.
  const Typed_identifier*
  receiver() const
  { return this->receiver_; }

  // Add an escape note for the receiver.
  void
  add_receiver_note(int encoding)
  { this->receiver_->set_note(Escape_note::make_tag(encoding)); }

  // Get the return names and types.
  const Typed_identifier_list*
  results() const
  { return this->results_; }

  // Get the parameter names and types.
  const Typed_identifier_list*
  parameters() const
  { return this->parameters_; }

  // Add an escape note for the ith parameter.
  void
  add_parameter_note(int index, int encoding)
  { this->parameters_->at(index).set_note(Escape_note::make_tag(encoding)); }

  // Whether this function has been tagged during escape analysis.
  bool
  is_tagged() const
  { return this->is_tagged_; }

  // Mark this function as tagged after analyzing its escape.
  void
  set_is_tagged()
  { this->is_tagged_ = true; }

  // Whether this is a varargs function.
  bool
  is_varargs() const
  { return this->is_varargs_; }

  // Whether this is a builtin function.
  bool
  is_builtin() const
  { return this->is_builtin_; }

  // The location where this type was defined.
  Location
  location() const
  { return this->location_; }

  // Return whether this is a method type.
  bool
  is_method() const
  { return this->receiver_ != NULL; }

  // Whether T is a valid redeclaration of this type.  This is called
  // when a function is declared more than once.
  bool
  is_valid_redeclaration(const Function_type* t, std::string*) const;

  // Whether this type is the same as T.
  bool
  is_identical(const Function_type* t, bool ignore_receiver,
	       Cmp_tags, bool errors_are_identical, std::string*) const;

  // Record that this is a varargs function.
  void
  set_is_varargs()
  { this->is_varargs_ = true; }

  // Record that this is a builtin function.
  void
  set_is_builtin()
  { this->is_builtin_ = true; }

  // Import a function type.
  static Function_type*
  do_import(Import*);

  // Return a copy of this type without a receiver.  This is only
  // valid for a method type.
  Function_type*
  copy_without_receiver() const;

  // Return a copy of this type with a receiver.  This is used when an
  // interface method is attached to a named or struct type.
  Function_type*
  copy_with_receiver(Type*) const;

  // Return a copy of this type with the receiver treated as the first
  // parameter.  If WANT_POINTER_RECEIVER is true, the receiver is
  // forced to be a pointer.
  Function_type*
  copy_with_receiver_as_param(bool want_pointer_receiver) const;

  // Return a copy of this type ignoring any receiver and using dummy
  // names for all parameters.  This is used for thunks for method
  // values.
  Function_type*
  copy_with_names() const;

  static Type*
  make_function_type_descriptor_type();

  // Return the backend representation of this function type. This is used
  // as the real type of a backend function declaration or defintion.
  Btype*
  get_backend_fntype(Gogo*);

 protected:
  int
  do_traverse(Traverse*);

  // A function descriptor may be allocated on the heap.
  bool
  do_has_pointer() const
  { return true; }

  bool
  do_compare_is_identity(Gogo*)
  { return false; }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

  void
  do_export(Export*) const;

 private:
  Expression*
  type_descriptor_params(Type*, const Typed_identifier*,
			 const Typed_identifier_list*);

  // A mapping from a list of result types to a backend struct type.
  class Results_hash
  {
  public:
    unsigned int
    operator()(const Typed_identifier_list*) const;
  };

  class Results_equal
  {
  public:
    bool
    operator()(const Typed_identifier_list*,
	       const Typed_identifier_list*) const;
  };

  typedef Unordered_map_hash(Typed_identifier_list*, Btype*,
			     Results_hash, Results_equal) Results_structs;

  static Results_structs results_structs;

  // The receiver name and type.  This will be NULL for a normal
  // function, non-NULL for a method.
  Typed_identifier* receiver_;
  // The parameter names and types.
  Typed_identifier_list* parameters_;
  // The result names and types.  This will be NULL if no result was
  // specified.
  Typed_identifier_list* results_;
  // The location where this type was defined.  This exists solely to
  // give a location for the fields of the struct if this function
  // returns multiple values.
  Location location_;
  // Whether this function takes a variable number of arguments.
  bool is_varargs_;
  // Whether this is a special builtin function which can not simply
  // be called.  This is used for len, cap, etc.
  bool is_builtin_;
  // The backend representation of this type for backend function
  // declarations and definitions.
  Btype* fnbtype_;
  // Whether this function has been analyzed by escape analysis.  If this is
  // TRUE, this function type's parameters contain a summary of the analysis.
  bool is_tagged_;
};

// The type of a function's backend representation.

class Backend_function_type : public Function_type
{
 public:
  Backend_function_type(Typed_identifier* receiver,
                        Typed_identifier_list* parameters,
                        Typed_identifier_list* results, Location location)
      : Function_type(receiver, parameters, results, location)
  { }

 protected:
  Btype*
  do_get_backend(Gogo* gogo)
  { return this->get_backend_fntype(gogo); }
};

// The type of a pointer.

class Pointer_type : public Type
{
 public:
  Pointer_type(Type* to_type)
    : Type(TYPE_POINTER),
      to_type_(to_type)
  {}

  Type*
  points_to() const
  { return this->to_type_; }

  // Import a pointer type.
  static Pointer_type*
  do_import(Import*);

  static Type*
  make_pointer_type_descriptor_type();

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_verify()
  { return this->to_type_->verify(); }

  bool
  do_has_pointer() const
  { return true; }

  bool
  do_compare_is_identity(Gogo*)
  { return true; }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

  void
  do_export(Export*) const;

 private:
  // The type to which this type points.
  Type* to_type_;
};

// The type of a field in a struct.

class Struct_field
{
 public:
  explicit Struct_field(const Typed_identifier& typed_identifier)
    : typed_identifier_(typed_identifier), tag_(NULL), is_imported_(false)
  { }

  // The field name.
  const std::string&
  field_name() const;

  // Return whether this struct field is named NAME.
  bool
  is_field_name(const std::string& name) const;

  // Return whether this struct field is an unexported field named NAME.
  bool
  is_unexported_field_name(Gogo*, const std::string& name) const;

  // Return whether this struct field is an embedded built-in type.
  bool
  is_embedded_builtin(Gogo*) const;

  // The field type.
  Type*
  type() const
  { return this->typed_identifier_.type(); }

  // The field location.
  Location
  location() const
  { return this->typed_identifier_.location(); }

  // Whether the field has a tag.
  bool
  has_tag() const
  { return this->tag_ != NULL; }

  // The tag.
  const std::string&
  tag() const
  {
    go_assert(this->tag_ != NULL);
    return *this->tag_;
  }

  // Whether this is an anonymous field.
  bool
  is_anonymous() const
  { return this->typed_identifier_.name().empty(); }

  // Set the tag.  FIXME: This is never freed.
  void
  set_tag(const std::string& tag)
  { this->tag_ = new std::string(tag); }

  // Record that this field is defined in an imported struct.
  void
  set_is_imported()
  { this->is_imported_ = true; }

  // Set the type.  This is only used in error cases.
  void
  set_type(Type* type)
  { this->typed_identifier_.set_type(type); }

 private:
  // The field name, type, and location.
  Typed_identifier typed_identifier_;
  // The field tag.  This is NULL if the field has no tag.
  std::string* tag_;
  // Whether this field is defined in an imported struct.
  bool is_imported_;
};

// A list of struct fields.

class Struct_field_list
{
 public:
  Struct_field_list()
    : entries_()
  { }

  // Whether the list is empty.
  bool
  empty() const
  { return this->entries_.empty(); }

  // Return the number of entries.
  size_t
  size() const
  { return this->entries_.size(); }

  // Add an entry to the end of the list.
  void
  push_back(const Struct_field& sf)
  { this->entries_.push_back(sf); }

  // Index into the list.
  const Struct_field&
  at(size_t i) const
  { return this->entries_.at(i); }

  // Last entry in list.
  Struct_field&
  back()
  { return this->entries_.back(); }

  // Iterators.

  typedef std::vector<Struct_field>::iterator iterator;
  typedef std::vector<Struct_field>::const_iterator const_iterator;

  iterator
  begin()
  { return this->entries_.begin(); }

  const_iterator
  begin() const
  { return this->entries_.begin(); }

  iterator
  end()
  { return this->entries_.end(); }

  const_iterator
  end() const
  { return this->entries_.end(); }

 private:
  std::vector<Struct_field> entries_;
};

// The type of a struct.

class Struct_type : public Type
{
 public:
  Struct_type(Struct_field_list* fields, Location location)
    : Type(TYPE_STRUCT),
      fields_(fields), location_(location), all_methods_(NULL),
      is_struct_incomparable_(false)
  { }

  // Return the field NAME.  This only looks at local fields, not at
  // embedded types.  If the field is found, and PINDEX is not NULL,
  // this sets *PINDEX to the field index.  If the field is not found,
  // this returns NULL.
  const Struct_field*
  find_local_field(const std::string& name, unsigned int *pindex) const;

  // Return the field number INDEX.
  const Struct_field*
  field(unsigned int index) const
  { return &this->fields_->at(index); }

  // Get the struct fields.
  const Struct_field_list*
  fields() const
  { return this->fields_; }

  // Return the number of fields.
  size_t
  field_count() const
  { return this->fields_->size(); }

  // Push a new field onto the end of the struct.  This is used when
  // building a closure variable.
  void
  push_field(const Struct_field& sf)
  { this->fields_->push_back(sf); }

  // Return an expression referring to field NAME in STRUCT_EXPR, or
  // NULL if there is no field with that name.
  Field_reference_expression*
  field_reference(Expression* struct_expr, const std::string& name,
		  Location) const;

  // Return the total number of fields, including embedded fields.
  // This is the number of values that can appear in a conversion to
  // this type.
  unsigned int
  total_field_count() const;

  // Whether this type is identical with T.
  bool
  is_identical(const Struct_type* t, Cmp_tags,
	       bool errors_are_identical) const;

  // Return whether NAME is a local field which is not exported.  This
  // is only used for better error reporting.
  bool
  is_unexported_local_field(Gogo*, const std::string& name) const;

  // If this is an unnamed struct, build the complete list of methods,
  // including those from anonymous fields, and build methods stubs if
  // needed.
  void
  finalize_methods(Gogo*);

  // Return whether this type has any methods.  This should only be
  // called after the finalize_methods pass.
  bool
  has_any_methods() const
  { return this->all_methods_ != NULL; }

  // Return the methods for tihs type.  This should only be called
  // after the finalize_methods pass.
  const Methods*
  methods() const
  { return this->all_methods_; }

  // Return the method to use for NAME.  This returns NULL if there is
  // no such method or if the method is ambiguous.  When it returns
  // NULL, this sets *IS_AMBIGUOUS if the method name is ambiguous.
  Method*
  method_function(const std::string& name, bool* is_ambiguous) const;

  // Return a pointer to the interface method table for this type for
  // the interface INTERFACE.  If IS_POINTER is true, set the type
  // descriptor to a pointer to this type, otherwise set it to this
  // type.
  Expression*
  interface_method_table(Interface_type* interface, bool is_pointer);

  // Traverse just the field types of a struct type.
  int
  traverse_field_types(Traverse* traverse)
  { return this->do_traverse(traverse); }

  // If the offset of field INDEX in the backend implementation can be
  // determined, set *POFFSET to the offset in bytes and return true.
  // Otherwise, return false.
  bool
  backend_field_offset(Gogo*, unsigned int index, int64_t* poffset);

  // Finish the backend representation of all the fields.
  void
  finish_backend_fields(Gogo*);

  // Import a struct type.
  static Struct_type*
  do_import(Import*);

  static Type*
  make_struct_type_descriptor_type();

  // Return whether this is a generated struct that is not comparable.
  bool
  is_struct_incomparable() const
  { return this->is_struct_incomparable_; }

  // Record that this is a generated struct that is not comparable.
  void
  set_is_struct_incomparable()
  { this->is_struct_incomparable_ = true; }

  // Write the hash function for this type.
  void
  write_hash_function(Gogo*, Named_type*, Function_type*, Function_type*);

  // Write the equality function for this type.
  void
  write_equal_function(Gogo*, Named_type*);

  // Whether we can write this type to a C header file, to implement
  // -fgo-c-header.
  bool
  can_write_to_c_header(std::vector<const Named_object*>*,
			std::vector<const Named_object*>*) const;

  // Write this type to a C header file, to implement -fgo-c-header.
  void
  write_to_c_header(std::ostream&) const;

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_verify();

  bool
  do_has_pointer() const;

  bool
  do_compare_is_identity(Gogo*);

  bool
  do_is_reflexive();

  bool
  do_needs_key_update();

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

  void
  do_export(Export*) const;

 private:
  bool
  can_write_type_to_c_header(const Type*,
			     std::vector<const Named_object*>*,
			     std::vector<const Named_object*>*) const;

  void
  write_field_to_c_header(std::ostream&, const std::string&, const Type*) const;

  // Used to merge method sets of identical unnamed structs.
  typedef Unordered_map_hash(Struct_type*, Struct_type*, Type_hash_identical,
			     Type_identical) Identical_structs;

  static Identical_structs identical_structs;

  // Used to manage method tables for identical unnamed structs.
  typedef std::pair<Interface_method_tables*, Interface_method_tables*>
    Struct_method_table_pair;

  typedef Unordered_map_hash(Struct_type*, Struct_method_table_pair*,
			     Type_hash_identical, Type_identical)
    Struct_method_tables;

  static Struct_method_tables struct_method_tables;

  // Used to avoid infinite loops in field_reference_depth.
  struct Saw_named_type
  {
    Saw_named_type* next;
    Named_type* nt;
  };

  Field_reference_expression*
  field_reference_depth(Expression* struct_expr, const std::string& name,
			Location, Saw_named_type*,
			unsigned int* depth) const;

  // The fields of the struct.
  Struct_field_list* fields_;
  // The place where the struct was declared.
  Location location_;
  // If this struct is unnamed, a list of methods.
  Methods* all_methods_;
  // True if this is a generated struct that is not considered to be
  // comparable.
  bool is_struct_incomparable_;
};

// The type of an array.

class Array_type : public Type
{
 public:
  Array_type(Type* element_type, Expression* length)
    : Type(TYPE_ARRAY),
      element_type_(element_type), length_(length), blength_(NULL),
      issued_length_error_(false), is_array_incomparable_(false)
  { }

  // Return the element type.
  Type*
  element_type() const
  { return this->element_type_; }

  // Return the length.  This will return NULL for a slice.
  Expression*
  length() const
  { return this->length_; }

  // Store the length as an int64_t into *PLEN.  Return false if the
  // length can not be determined.  This will assert if called for a
  // slice.
  bool
  int_length(int64_t* plen);

  // Whether this type is identical with T.
  bool
  is_identical(const Array_type* t, Cmp_tags,
	       bool errors_are_identical) const;

  // Return an expression for the pointer to the values in an array.
  Expression*
  get_value_pointer(Gogo*, Expression* array, bool is_lvalue) const;

  // Return an expression for the length of an array with this type.
  Expression*
  get_length(Gogo*, Expression* array) const;

  // Return an expression for the capacity of an array with this type.
  Expression*
  get_capacity(Gogo*, Expression* array) const;

  // Import an array type.
  static Array_type*
  do_import(Import*);

  // Return the backend representation of the element type.
  Btype*
  get_backend_element(Gogo*, bool use_placeholder);

  // Return the backend representation of the length.
  Bexpression*
  get_backend_length(Gogo*);

  // Finish the backend representation of the element type.
  void
  finish_backend_element(Gogo*);

  static Type*
  make_array_type_descriptor_type();

  static Type*
  make_slice_type_descriptor_type();

  // Return whether this is a generated array that is not comparable.
  bool
  is_array_incomparable() const
  { return this->is_array_incomparable_; }

  // Record that this is a generated array that is not comparable.
  void
  set_is_array_incomparable()
  { this->is_array_incomparable_ = true; }

  // Write the hash function for this type.
  void
  write_hash_function(Gogo*, Named_type*, Function_type*, Function_type*);

  // Write the equality function for this type.
  void
  write_equal_function(Gogo*, Named_type*);

 protected:
  int
  do_traverse(Traverse* traverse);

  bool
  do_verify();

  bool
  do_has_pointer() const;

  bool
  do_compare_is_identity(Gogo*);

  bool
  do_is_reflexive()
  {
    return this->length_ != NULL && this->element_type_->is_reflexive();
  }

  bool
  do_needs_key_update()
  { return this->element_type_->needs_key_update(); }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

  void
  do_export(Export*) const;

 private:
  bool
  verify_length();

  Expression*
  array_type_descriptor(Gogo*, Named_type*);

  Expression*
  slice_type_descriptor(Gogo*, Named_type*);

  // The type of elements of the array.
  Type* element_type_;
  // The number of elements.  This may be NULL.
  Expression* length_;
  // The backend representation of the length.
  // We only want to compute this once.
  Bexpression* blength_;
  // Whether or not an invalid length error has been issued for this type,
  // to avoid knock-on errors.
  mutable bool issued_length_error_;
  // True if this is a generated array that is not considered to be
  // comparable.
  bool is_array_incomparable_;
};

// The type of a map.

class Map_type : public Type
{
 public:
  Map_type(Type* key_type, Type* val_type, Location location)
    : Type(TYPE_MAP),
      key_type_(key_type), val_type_(val_type), hmap_type_(NULL),
      bucket_type_(NULL), hiter_type_(NULL), location_(location)
  { }

  // Return the key type.
  Type*
  key_type() const
  { return this->key_type_; }

  // Return the value type.
  Type*
  val_type() const
  { return this->val_type_; }

  // Return the type used for an iteration over this map.
  Type*
  hiter_type(Gogo*);

  // If this map requires the "fat" functions, returns the pointer to
  // pass as the zero value to those functions.  Otherwise, in the
  // normal case, returns NULL.
  Expression*
  fat_zero_value(Gogo*);

  // Return whether VAR is the map zero value.
  static bool
  is_zero_value(Variable* var);

  // Return the backend representation of the map zero value.
  static Bvariable*
  backend_zero_value(Gogo*);

  // Whether this type is identical with T.
  bool
  is_identical(const Map_type* t, Cmp_tags,
	       bool errors_are_identical) const;

  // Import a map type.
  static Map_type*
  do_import(Import*);

  static Type*
  make_map_type_descriptor_type();

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_verify();

  bool
  do_has_pointer() const
  { return true; }

  bool
  do_compare_is_identity(Gogo*)
  { return false; }

  bool
  do_is_reflexive()
  {
    return this->key_type_->is_reflexive() && this->val_type_->is_reflexive();
  }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

  void
  do_export(Export*) const;

 private:
  // These must be in sync with libgo/go/runtime/hashmap.go.
  static const int bucket_size = 8;
  static const int max_key_size = 128;
  static const int max_val_size = 128;
  static const int max_zero_size = 1024;

  // Maps with value types larger than max_zero_size require passing a
  // zero value pointer to the map functions.

  // The zero value variable.
  static Named_object* zero_value;

  // The current size of the zero value.
  static int64_t zero_value_size;

  // The current alignment of the zero value.
  static int64_t zero_value_align;

  Type*
  bucket_type(Gogo*, int64_t, int64_t);

  Type*
  hmap_type(Type*);

  // The key type.
  Type* key_type_;
  // The value type.
  Type* val_type_;
  // The hashmap type.  At run time a map is represented as a pointer
  // to this type.
  Type* hmap_type_;
  // The bucket type, the type used to hold keys and values at run time.
  Type* bucket_type_;
  // The iterator type.
  Type* hiter_type_;
  // Where the type was defined.
  Location location_;
};

// The type of a channel.

class Channel_type : public Type
{
 public:
  Channel_type(bool may_send, bool may_receive, Type* element_type)
    : Type(TYPE_CHANNEL),
      may_send_(may_send), may_receive_(may_receive),
      element_type_(element_type)
  { go_assert(may_send || may_receive); }

  // Whether this channel can send data.
  bool
  may_send() const
  { return this->may_send_; }

  // Whether this channel can receive data.
  bool
  may_receive() const
  { return this->may_receive_; }

  // The type of the values that may be sent on this channel.  This is
  // NULL if any type may be sent.
  Type*
  element_type() const
  { return this->element_type_; }

  // Whether this type is identical with T.
  bool
  is_identical(const Channel_type* t, Cmp_tags,
	       bool errors_are_identical) const;

  // Import a channel type.
  static Channel_type*
  do_import(Import*);

  static Type*
  make_chan_type_descriptor_type();

  static Type*
  select_type(int ncases);

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Type::traverse(this->element_type_, traverse); }

  bool
  do_has_pointer() const
  { return true; }

  bool
  do_compare_is_identity(Gogo*)
  { return true; }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

  void
  do_export(Export*) const;

 private:
  // Whether this channel can send data.
  bool may_send_;
  // Whether this channel can receive data.
  bool may_receive_;
  // The types of elements which may be sent on this channel.  If this
  // is NULL, it means that any type may be sent.
  Type* element_type_;
};

// An interface type.

class Interface_type : public Type
{
 public:
  Interface_type(Typed_identifier_list* methods, Location location)
    : Type(TYPE_INTERFACE),
      parse_methods_(methods), all_methods_(NULL), location_(location),
      interface_btype_(NULL), bmethods_(NULL), assume_identical_(NULL),
      methods_are_finalized_(false), bmethods_is_placeholder_(false),
      seen_(false)
  { go_assert(methods == NULL || !methods->empty()); }

  // The location where the interface type was defined.
  Location
  location() const
  { return this->location_; }

  // Return whether this is an empty interface.
  bool
  is_empty() const
  {
    go_assert(this->methods_are_finalized_);
    return this->all_methods_ == NULL;
  }

  // Return the list of methods.  This will return NULL for an empty
  // interface.
  const Typed_identifier_list*
  methods() const;

  // Return the number of methods.
  size_t
  method_count() const;

  // Return the method NAME, or NULL.
  const Typed_identifier*
  find_method(const std::string& name) const;

  // Return the zero-based index of method NAME.
  size_t
  method_index(const std::string& name) const;

  // Finalize the methods.  This sets all_methods_.  This handles
  // interface inheritance.
  void
  finalize_methods();

  // Return true if T implements this interface.  If this returns
  // false, and REASON is not NULL, it sets *REASON to the reason that
  // it fails.
  bool
  implements_interface(const Type* t, std::string* reason) const;

  // Whether this type is identical with T.  REASON is as in
  // implements_interface.
  bool
  is_identical(const Interface_type* t, Cmp_tags,
	       bool errors_are_identical) const;

  // Whether we can assign T to this type.  is_identical is known to
  // be false.
  bool
  is_compatible_for_assign(const Interface_type*, std::string* reason) const;

  // Return whether NAME is a method which is not exported.  This is
  // only used for better error reporting.
  bool
  is_unexported_method(Gogo*, const std::string& name) const;

  // Import an interface type.
  static Interface_type*
  do_import(Import*);

  // Make a struct for an empty interface type.
  static Btype*
  get_backend_empty_interface_type(Gogo*);

  // Get a pointer to the backend representation of the method table.
  Btype*
  get_backend_methods(Gogo*);

  // Return a placeholder for the backend representation of the
  // pointer to the method table.
  Btype*
  get_backend_methods_placeholder(Gogo*);

  // Finish the backend representation of the method types.
  void
  finish_backend_methods(Gogo*);

  static Type*
  make_interface_type_descriptor_type();

 protected:
  int
  do_traverse(Traverse*);

  bool
  do_has_pointer() const
  { return true; }

  bool
  do_compare_is_identity(Gogo*)
  { return false; }

  // Not reflexive if it contains a float.
  bool
  do_is_reflexive()
  { return false; }

  // Distinction between +0 and -0 requires a key update if it
  // contains a float.
  bool
  do_needs_key_update()
  { return true; }

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string*) const;

  void
  do_export(Export*) const;

 private:
  // This type guards against infinite recursion when comparing
  // interface types.  We keep a list of interface types assumed to be
  // identical during comparison.  We just keep the list on the stack.
  // This permits us to compare cases like
  // type I1 interface { F() interface{I1} }
  // type I2 interface { F() interface{I2} }
  struct Assume_identical
  {
    Assume_identical* next;
    const Interface_type* t1;
    const Interface_type* t2;
  };

  bool
  assume_identical(const Interface_type*, const Interface_type*) const;

  // The list of methods associated with the interface from the
  // parser.  This will be NULL for the empty interface.  This may
  // include unnamed interface types.
  Typed_identifier_list* parse_methods_;
  // The list of all methods associated with the interface.  This
  // expands any interface types listed in methods_.  It is set by
  // finalize_methods.  This will be NULL for the empty interface.
  Typed_identifier_list* all_methods_;
  // The location where the interface was defined.
  Location location_;
  // The backend representation of this type during backend conversion.
  Btype* interface_btype_;
  // The backend representation of the pointer to the method table.
  Btype* bmethods_;
  // A list of interface types assumed to be identical during
  // interface comparison.
  mutable Assume_identical* assume_identical_;
  // Whether the methods have been finalized.
  bool methods_are_finalized_;
  // Whether the bmethods_ field is a placeholder.
  bool bmethods_is_placeholder_;
  // Used to avoid endless recursion in do_mangled_name.
  mutable bool seen_;
};

// The value we keep for a named type.  This lets us get the right
// name when we convert to backend.  Note that we don't actually keep
// the name here; the name is in the Named_object which points to
// this.  This object exists to hold a unique backend representation for
// the type.

class Named_type : public Type
{
 public:
  Named_type(Named_object* named_object, Type* type, Location location)
    : Type(TYPE_NAMED),
      named_object_(named_object), in_function_(NULL), in_function_index_(0),
      type_(type), local_methods_(NULL), all_methods_(NULL),
      interface_method_tables_(NULL), pointer_interface_method_tables_(NULL),
      location_(location), named_btype_(NULL), dependencies_(),
      is_alias_(false), is_visible_(true), is_error_(false),
      is_placeholder_(false), is_converted_(false), is_circular_(false),
      is_verified_(false), seen_(false), seen_in_compare_is_identity_(false),
      seen_in_get_backend_(false), seen_alias_(false)
  { }

  // Return the associated Named_object.  This holds the actual name.
  Named_object*
  named_object()
  { return this->named_object_; }

  const Named_object*
  named_object() const
  { return this->named_object_; }

  // Set the Named_object.  This is used when we see a type
  // declaration followed by a type.
  void
  set_named_object(Named_object* no)
  { this->named_object_ = no; }

  // Whether this is an alias (type T1 = T2) rather than an ordinary
  // named type (type T1 T2).
  bool
  is_alias() const
  { return this->is_alias_; }

  // Record that this type is an alias.
  void
  set_is_alias()
  { this->is_alias_ = true; }

  // Return the function in which this type is defined.  This will
  // return NULL for a type defined in global scope.
  const Named_object*
  in_function(unsigned int *pindex) const
  {
    *pindex = this->in_function_index_;
    return this->in_function_;
  }

  // Set the function in which this type is defined.
  void
  set_in_function(Named_object* f, unsigned int index)
  {
    this->in_function_ = f;
    this->in_function_index_ = index;
  }

  // Return the name of the type.
  const std::string&
  name() const;

  // Return the name of the type for an error message.  The difference
  // is that if the type is defined in a different package, this will
  // return PACKAGE.NAME.
  std::string
  message_name() const;

  // Return the underlying type.
  Type*
  real_type()
  { return this->type_; }

  const Type*
  real_type() const
  { return this->type_; }

  // Return the location.
  Location
  location() const
  { return this->location_; }

  // Whether this type is visible.  This only matters when parsing.
  bool
  is_visible() const
  { return this->is_visible_; }

  // Mark this type as visible.
  void
  set_is_visible()
  { this->is_visible_ = true; }

  // Mark this type as invisible.
  void
  clear_is_visible()
  { this->is_visible_ = false; }

  // Whether this is a builtin type.
  bool
  is_builtin() const
  { return Linemap::is_predeclared_location(this->location_); }

  // Whether this named type is valid.  A recursive named type is invalid.
  bool
  is_valid() const
  { return !this->is_error_; }

  // Whether this is a circular type: a pointer or function type that
  // refers to itself, which is not possible in C.
  bool
  is_circular() const
  { return this->is_circular_; }

  // Return the base type for this type.
  Type*
  named_base();

  const Type*
  named_base() const;

  // Return whether this is an error type.
  bool
  is_named_error_type() const;

  // Return whether this type is comparable.  If REASON is not NULL,
  // set *REASON when returning false.
  bool
  named_type_is_comparable(std::string* reason) const;

  // Add a method to this type.
  Named_object*
  add_method(const std::string& name, Function*);

  // Add a method declaration to this type.
  Named_object*
  add_method_declaration(const std::string& name, Package* package,
			 Function_type* type, Location location);

  // Add an existing method--one defined before the type itself was
  // defined--to a type.
  void
  add_existing_method(Named_object*);

  // Look up a local method.
  Named_object*
  find_local_method(const std::string& name) const;

  // Return the list of local methods.
  const Bindings*
  local_methods() const;

  // Build the complete list of methods, including those from
  // anonymous fields, and build method stubs if needed.
  void
  finalize_methods(Gogo*);

  // Return whether this type has any methods.  This should only be
  // called after the finalize_methods pass.
  bool
  has_any_methods() const;

  // Return the methods for this type.  This should only be called
  // after the finalized_methods pass.
  const Methods*
  methods() const;

  // Return the method to use for NAME.  This returns NULL if there is
  // no such method or if the method is ambiguous.  When it returns
  // NULL, this sets *IS_AMBIGUOUS if the method name is ambiguous.
  Method*
  method_function(const std::string& name, bool *is_ambiguous) const;

  // Return whether NAME is a known field or method which is not
  // exported.  This is only used for better error reporting.
  bool
  is_unexported_local_method(Gogo*, const std::string& name) const;

  // Return a pointer to the interface method table for this type for
  // the interface INTERFACE.  If IS_POINTER is true, set the type
  // descriptor to a pointer to this type, otherwise set it to this
  // type.
  Expression*
  interface_method_table(Interface_type* interface, bool is_pointer);

  // Note that a type must be converted to the backend representation
  // before we convert this type.
  void
  add_dependency(Named_type* nt)
  { this->dependencies_.push_back(nt); }

  // Return true if the size and alignment of the backend
  // representation of this type is known.  This is always true after
  // types have been converted, but may be false beforehand.
  bool
  is_named_backend_type_size_known() const
  { return this->named_btype_ != NULL && !this->is_placeholder_; }

  // Add to the reflection string as for Type::append_reflection, but
  // if USE_ALIAS use the alias name rather than the alias target.
  void
  append_reflection_type_name(Gogo*, bool use_alias, std::string*) const;

  // Append the mangled type name as for Type::append_mangled_name,
  // but if USE_ALIAS use the alias name rather than the alias target.
  void
  append_mangled_type_name(Gogo*, bool use_alias, std::string*) const;

  // Export the type.
  void
  export_named_type(Export*, const std::string& name) const;

  // Import a named type.
  static void
  import_named_type(Import*, Named_type**);

  // Initial conversion to backend representation.
  void
  convert(Gogo*);

 protected:
  int
  do_traverse(Traverse* traverse)
  { return Type::traverse(this->type_, traverse); }

  bool
  do_verify();

  bool
  do_has_pointer() const;

  bool
  do_compare_is_identity(Gogo*);

  bool
  do_is_reflexive();

  bool
  do_needs_key_update();

  unsigned int
  do_hash_for_method(Gogo*) const;

  Btype*
  do_get_backend(Gogo*);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string* ret) const;

  void
  do_export(Export*) const;

 private:
  // Create the placeholder during conversion.
  void
  create_placeholder(Gogo*);

  // A pointer back to the Named_object for this type.
  Named_object* named_object_;
  // If this type is defined in a function, a pointer back to the
  // function in which it is defined.
  Named_object* in_function_;
  // The index of this type in IN_FUNCTION_.
  unsigned int in_function_index_;
  // The actual type.
  Type* type_;
  // The list of methods defined for this type.  Any named type can
  // have methods.
  Bindings* local_methods_;
  // The full list of methods for this type, including methods
  // declared for anonymous fields.
  Methods* all_methods_;
  // A mapping from interfaces to the associated interface method
  // tables for this type.
  Interface_method_tables* interface_method_tables_;
  // A mapping from interfaces to the associated interface method
  // tables for pointers to this type.
  Interface_method_tables* pointer_interface_method_tables_;
  // The location where this type was defined.
  Location location_;
  // The backend representation of this type during backend
  // conversion.  This is used to avoid endless recursion when a named
  // type refers to itself.
  Btype* named_btype_;
  // A list of types which must be converted to the backend
  // representation before this type can be converted.  This is for
  // cases like
  //   type S1 { p *S2 }
  //   type S2 { s S1 }
  // where we can't convert S2 to the backend representation unless we
  // have converted S1.
  std::vector<Named_type*> dependencies_;
  // Whether this is an alias type.
  bool is_alias_;
  // Whether this type is visible.  This is false if this type was
  // created because it was referenced by an imported object, but the
  // type itself was not exported.  This will always be true for types
  // created in the current package.
  bool is_visible_;
  // Whether this type is erroneous.
  bool is_error_;
  // Whether the current value of named_btype_ is a placeholder for
  // which the final size of the type is not known.
  bool is_placeholder_;
  // Whether this type has been converted to the backend
  // representation.  Implies that is_placeholder_ is false.
  bool is_converted_;
  // Whether this is a pointer or function type which refers to the
  // type itself.
  bool is_circular_;
  // Whether this type has been verified.
  bool is_verified_;
  // In a recursive operation such as has_pointer, this flag is used
  // to prevent infinite recursion when a type refers to itself.  This
  // is mutable because it is always reset to false when the function
  // exits.
  mutable bool seen_;
  // Like seen_, but used only by do_compare_is_identity.
  bool seen_in_compare_is_identity_;
  // Like seen_, but used only by do_get_backend.
  bool seen_in_get_backend_;
  // Like seen_, but used when resolving aliases.
  mutable bool seen_alias_;
};

// A forward declaration.  This handles a type which has been declared
// but not defined.

class Forward_declaration_type : public Type
{
 public:
  Forward_declaration_type(Named_object* named_object);

  // The named object associated with this type declaration.  This
  // will be resolved.
  Named_object*
  named_object();

  const Named_object*
  named_object() const;

  // Return the name of the type.
  const std::string&
  name() const;

  // Return the type to which this points.  Give an error if the type
  // has not yet been defined.
  Type*
  real_type();

  const Type*
  real_type() const;

  // Whether the base type has been defined.
  bool
  is_defined() const;

  // Add a method to this type.
  Named_object*
  add_method(const std::string& name, Function*);

  // Add a method declaration to this type.
  Named_object*
  add_method_declaration(const std::string& name, Package*, Function_type*,
			 Location);

  // Add an already created object as a method to this type.
  void
  add_existing_method(Named_object*);

 protected:
  int
  do_traverse(Traverse* traverse);

  bool
  do_verify();

  bool
  do_has_pointer() const
  { return this->real_type()->has_pointer(); }

  bool
  do_compare_is_identity(Gogo* gogo)
  { return this->real_type()->compare_is_identity(gogo); }

  bool
  do_is_reflexive()
  { return this->real_type()->is_reflexive(); }

  bool
  do_needs_key_update()
  { return this->real_type()->needs_key_update(); }

  unsigned int
  do_hash_for_method(Gogo* gogo) const
  { return this->real_type()->hash_for_method(gogo); }

  Btype*
  do_get_backend(Gogo* gogo);

  Expression*
  do_type_descriptor(Gogo*, Named_type*);

  void
  do_reflection(Gogo*, std::string*) const;

  void
  do_mangled_name(Gogo*, std::string* ret) const;

  void
  do_export(Export*) const;

 private:
  // Issue a warning about a use of an undefined type.
  void
  warn() const;

  // The type declaration.
  Named_object* named_object_;
  // Whether we have issued a warning about this type.
  mutable bool warned_;
};

// The Type_context struct describes what we expect for the type of an
// expression.

struct Type_context
{
  // The exact type we expect, if known.  This may be NULL.
  Type* type;
  // Whether an abstract type is permitted.
  bool may_be_abstract;

  // Constructors.
  Type_context()
    : type(NULL), may_be_abstract(false)
  { }

  Type_context(Type* a_type, bool a_may_be_abstract)
    : type(a_type), may_be_abstract(a_may_be_abstract)
  { }
};

#endif // !defined(GO_TYPES_H)
