Rewrite conversion of named types to backend representation.
[gcc.git] / gcc / go / gofrontend / types.h
index 025f85f401b169ac427c525bfa971eefce58912c..8e91dfcab072edf11caedbf3aff1a330a7c2d484 100644 (file)
@@ -60,22 +60,20 @@ 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_FLOAT = 13;
-static const int RUNTIME_TYPE_KIND_FLOAT32 = 14;
-static const int RUNTIME_TYPE_KIND_FLOAT64 = 15;
-static const int RUNTIME_TYPE_KIND_COMPLEX = 16;
-static const int RUNTIME_TYPE_KIND_COMPLEX64 = 17;
-static const int RUNTIME_TYPE_KIND_COMPLEX128 = 18;
-static const int RUNTIME_TYPE_KIND_ARRAY = 19;
-static const int RUNTIME_TYPE_KIND_CHAN = 20;
-static const int RUNTIME_TYPE_KIND_FUNC = 21;
-static const int RUNTIME_TYPE_KIND_INTERFACE = 22;
-static const int RUNTIME_TYPE_KIND_MAP = 23;
-static const int RUNTIME_TYPE_KIND_PTR = 24;
-static const int RUNTIME_TYPE_KIND_SLICE = 25;
-static const int RUNTIME_TYPE_KIND_STRING = 26;
-static const int RUNTIME_TYPE_KIND_STRUCT = 27;
-static const int RUNTIME_TYPE_KIND_UNSAFE_POINTER = 28;
+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;
 
 // To build the complete list of methods for a named type we need to
 // gather all methods from anonymous fields.  Those methods may
@@ -503,10 +501,13 @@ class Type
   verify()
   { return this->do_verify(); }
 
-  // Return true if two types are identical.  If this returns false,
+  // 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, std::string* reason);
+  are_identical(const Type* lhs, const Type* rhs, 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
@@ -788,7 +789,8 @@ class Type
 
   // 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&);
+  is_unexported_field_or_method(Gogo*, const Type*, const std::string&,
+                               std::vector<const Named_type*>*);
 
   // This type was passed to the builtin function make.  ARGS are the
   // arguments passed to make after the type; this may be NULL if
@@ -797,6 +799,10 @@ class Type
   check_make_expression(Expression_list* args, source_location location)
   { return this->do_check_make_expression(args, location); }
 
+  // Convert the builtin named types.
+  static void
+  convert_builtin_named_types(Gogo*);
+
   // Return a tree representing this type.
   tree
   get_tree(Gogo*);
@@ -1064,8 +1070,8 @@ class Type
   static bool
   find_field_or_method(const Type* type, const std::string& name,
                       bool receiver_can_be_pointer,
-                      int* level, bool* is_method,
-                      bool* found_pointer_method,
+                      std::vector<const Named_type*>*, int* level,
+                      bool* is_method, bool* found_pointer_method,
                       std::string* ambig1, std::string* ambig2);
 
   // Get a tree for a type without looking in the hash table for
@@ -1080,6 +1086,9 @@ class Type
 
   static Type_trees type_trees;
 
+  // A list of builtin named types.
+  static std::vector<Named_type*> named_builtin_types;
+
   // The type classification.
   Type_classification classification_;
   // The tree representation of the type, once it has been determined.
@@ -1104,7 +1113,7 @@ class Type_identical
  public:
   bool
   operator()(const Type* t1, const Type* t2) const
-  { return Type::are_identical(t1, t2, NULL); }
+  { return Type::are_identical(t1, t2, false, NULL); }
 };
 
 // An identifier with a type.
@@ -1577,7 +1586,7 @@ class Function_type : public Type
   // Whether this type is the same as T.
   bool
   is_identical(const Function_type* t, bool ignore_receiver,
-              std::string*) const;
+              bool errors_are_identical, std::string*) const;
 
   // Record that this is a varargs function.
   void
@@ -1603,6 +1612,9 @@ class Function_type : public Type
   Function_type*
   copy_with_receiver(Type*) const;
 
+  static Type*
+  make_function_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse*);
@@ -1634,9 +1646,6 @@ class Function_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_function_type_descriptor_type();
-
   Expression*
   type_descriptor_params(Type*, const Typed_identifier*,
                         const Typed_identifier_list*);
@@ -1678,6 +1687,9 @@ class Pointer_type : public Type
   static Pointer_type*
   do_import(Import*);
 
+  static Type*
+  make_pointer_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse*);
@@ -1708,9 +1720,6 @@ class Pointer_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_pointer_type_descriptor_type();
-
   // The type to which this type points.
   Type* to_type_;
 };
@@ -1884,7 +1893,7 @@ class Struct_type : public Type
 
   // Whether this type is identical with T.
   bool
-  is_identical(const Struct_type* t) const;
+  is_identical(const Struct_type* t, bool errors_are_identical) const;
 
   // Whether this struct type has any hidden fields.  This returns
   // true if any fields have hidden names, or if any non-pointer
@@ -1934,6 +1943,9 @@ class Struct_type : public Type
   tree
   fill_in_tree(Gogo*, tree);
 
+  static Type*
+  make_struct_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse*);
@@ -1966,12 +1978,17 @@ class Struct_type : public Type
   do_export(Export*) const;
 
  private:
+  // 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,
-                       source_location, unsigned int* depth) const;
-
-  static Type*
-  make_struct_type_descriptor_type();
+                       source_location, Saw_named_type*,
+                       unsigned int* depth) const;
 
   // The fields of the struct.
   Struct_field_list* fields_;
@@ -2003,7 +2020,7 @@ class Array_type : public Type
 
   // Whether this type is identical with T.
   bool
-  is_identical(const Array_type* t) const;
+  is_identical(const Array_type* t, bool errors_are_identical) const;
 
   // Whether this type has any hidden fields.
   bool
@@ -2026,9 +2043,19 @@ class Array_type : public Type
   static Array_type*
   do_import(Import*);
 
+  // Fill in the fields for a named array type.
+  tree
+  fill_in_array_tree(Gogo*, tree);
+
   // Fill in the fields for a named slice type.
   tree
-  fill_in_tree(Gogo*, tree);
+  fill_in_slice_tree(Gogo*, tree);
+
+  static Type*
+  make_array_type_descriptor_type();
+
+  static Type*
+  make_slice_type_descriptor_type();
 
  protected:
   int
@@ -2078,12 +2105,6 @@ class Array_type : public Type
   tree
   get_length_tree(Gogo*);
 
-  Type*
-  make_array_type_descriptor_type();
-
-  Type*
-  make_slice_type_descriptor_type();
-
   Expression*
   array_type_descriptor(Gogo*, Named_type*);
 
@@ -2120,12 +2141,15 @@ class Map_type : public Type
 
   // Whether this type is identical with T.
   bool
-  is_identical(const Map_type* t) const;
+  is_identical(const Map_type* t, 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*);
@@ -2166,9 +2190,6 @@ class Map_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_map_type_descriptor_type();
-
   // The key type.
   Type* key_type_;
   // The value type.
@@ -2206,12 +2227,15 @@ class Channel_type : public Type
 
   // Whether this type is identical with T.
   bool
-  is_identical(const Channel_type* t) const;
+  is_identical(const Channel_type* t, bool errors_are_identical) const;
 
   // Import a channel type.
   static Channel_type*
   do_import(Import*);
 
+  static Type*
+  make_chan_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse* traverse)
@@ -2250,9 +2274,6 @@ class Channel_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_chan_type_descriptor_type();
-
   // Whether this channel can send data.
   bool may_send_;
   // Whether this channel can receive data.
@@ -2272,6 +2293,11 @@ class Interface_type : public Type
       methods_(methods), location_(location)
   { gcc_assert(methods == NULL || !methods->empty()); }
 
+  // The location where the interface type was defined.
+  source_location
+  location() const
+  { return this->location_; }
+
   // Return whether this is an empty interface.
   bool
   is_empty() const
@@ -2309,7 +2335,7 @@ class Interface_type : public Type
   // Whether this type is identical with T.  REASON is as in
   // implements_interface.
   bool
-  is_identical(const Interface_type* t) const;
+  is_identical(const Interface_type* t, bool errors_are_identical) const;
 
   // Whether we can assign T to this type.  is_identical is known to
   // be false.
@@ -2325,10 +2351,21 @@ class Interface_type : public Type
   static Interface_type*
   do_import(Import*);
 
+  // Make a struct for an empty interface type.
+  static tree
+  empty_type_tree(Gogo*);
+
+  // Make a struct for non-empty interface type.
+  static tree
+  non_empty_type_tree(source_location);
+
   // Fill in the fields for a named interface type.
   tree
   fill_in_tree(Gogo*, tree);
 
+  static Type*
+  make_interface_type_descriptor_type();
+
  protected:
   int
   do_traverse(Traverse*);
@@ -2359,9 +2396,6 @@ class Interface_type : public Type
   do_export(Export*) const;
 
  private:
-  static Type*
-  make_interface_type_descriptor_type();
-
   // The list of methods associated with the interface.  This will be
   // NULL for the empty interface.
   Typed_identifier_list* methods_;
@@ -2383,8 +2417,9 @@ class Named_type : public Type
       named_object_(named_object), in_function_(NULL), type_(type),
       local_methods_(NULL), all_methods_(NULL),
       interface_method_tables_(NULL), pointer_interface_method_tables_(NULL),
-      location_(location), named_tree_(NULL), is_visible_(true),
-      is_error_(false), seen_(false)
+      location_(location), named_tree_(NULL), dependencies_(),
+      is_visible_(true), is_error_(false), is_converted_(false),
+      is_circular_(false), seen_(0)
   { }
 
   // Return the associated Named_object.  This holds the actual name.
@@ -2457,6 +2492,23 @@ class Named_type : public Type
   is_builtin() const
   { return this->location_ == BUILTINS_LOCATION; }
 
+  // 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;
+
   // Add a method to this type.
   Named_object*
   add_method(const std::string& name, Function*);
@@ -2520,6 +2572,12 @@ class Named_type : public Type
   bool
   named_type_has_hidden_fields(std::string* reason) const;
 
+  // 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); }
+
   // Export the type.
   void
   export_named_type(Export*, const std::string& name) const;
@@ -2528,6 +2586,10 @@ class Named_type : public Type
   static void
   import_named_type(Import*, Named_type**);
 
+  // Initial conversion to backend representation.
+  void
+  convert(Gogo*);
+
  protected:
   int
   do_traverse(Traverse* traverse)
@@ -2537,8 +2599,7 @@ class Named_type : public Type
   do_verify();
 
   bool
-  do_has_pointer() const
-  { return this->type_->has_pointer(); }
+  do_has_pointer() const;
 
   unsigned int
   do_hash_for_method(Gogo*) const;
@@ -2572,6 +2633,10 @@ class Named_type : public Type
   do_export(Export*) const;
 
  private:
+  // Create the placeholder during conversion.
+  void
+  create_placeholder(Gogo*);
+
   // A mapping from interfaces to the associated interface method
   // tables for this type.  This maps to a decl.
   typedef Unordered_map_hash(const Interface_type*, tree, Type_hash_identical,
@@ -2601,6 +2666,14 @@ class Named_type : public Type
   // The tree for this type while converting to GENERIC.  This is used
   // to avoid endless recursion when a named type refers to itself.
   tree named_tree_;
+  // 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 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
@@ -2608,11 +2681,17 @@ class Named_type : public Type
   bool is_visible_;
   // Whether this type is erroneous.
   bool is_error_;
+  // Whether this type has been converted to the backend
+  // representation.
+  bool is_converted_;
+  // Whether this is a pointer or function type which refers to the
+  // type itself.
+  bool is_circular_;
   // In a recursive operation such as has_hidden_fields, 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_;
+  mutable int seen_;
 };
 
 // A forward declaration.  This handles a type which has been declared
@@ -2662,7 +2741,7 @@ class Forward_declaration_type : public Type
 
   bool
   do_has_pointer() const
-  { return this->base()->has_pointer(); }
+  { return this->real_type()->has_pointer(); }
 
   unsigned int
   do_hash_for_method(Gogo* gogo) const