OSDN Git Service

Fix inheriting hidden methods with arguments of hidden type.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / expressions.h
index 4780a8b..c6ae12c 100644 (file)
@@ -15,6 +15,7 @@
 class Gogo;
 class Translate_context;
 class Traverse;
+class Statement_inserter;
 class Type;
 struct Type_context;
 class Function_type;
@@ -36,12 +37,13 @@ class Field_reference_expression;
 class Interface_field_reference_expression;
 class Type_guard_expression;
 class Receive_expression;
-class Send_expression;
 class Named_object;
 class Export;
 class Import;
 class Temporary_statement;
 class Label;
+class Ast_dump_context;
+class String_dump;
 
 // The base class for all expressions.
 
@@ -79,9 +81,9 @@ class Expression
     EXPRESSION_FIELD_REFERENCE,
     EXPRESSION_INTERFACE_FIELD_REFERENCE,
     EXPRESSION_ALLOCATION,
-    EXPRESSION_MAKE,
     EXPRESSION_TYPE_GUARD,
     EXPRESSION_CONVERSION,
+    EXPRESSION_UNSAFE_CONVERSION,
     EXPRESSION_STRUCT_CONSTRUCTION,
     EXPRESSION_FIXED_ARRAY_CONSTRUCTION,
     EXPRESSION_OPEN_ARRAY_CONSTRUCTION,
@@ -89,10 +91,10 @@ class Expression
     EXPRESSION_COMPOSITE_LITERAL,
     EXPRESSION_HEAP_COMPOSITE,
     EXPRESSION_RECEIVE,
-    EXPRESSION_SEND,
     EXPRESSION_TYPE_DESCRIPTOR,
     EXPRESSION_TYPE_INFO,
     EXPRESSION_STRUCT_FIELD_OFFSET,
+    EXPRESSION_MAP_DESCRIPTOR,
     EXPRESSION_LABEL_ADDR
   };
 
@@ -129,7 +131,7 @@ class Expression
   // Make a reference to a temporary variable.  Temporary variables
   // are always created by a single statement, which is what we use to
   // refer to them.
-  static Expression*
+  static Temporary_reference_expression*
   make_temporary_reference(Temporary_statement*, source_location);
 
   // Make a sink expression--a reference to the blank identifier _.
@@ -190,7 +192,7 @@ class Expression
   // Make an expression which is a method bound to its first
   // parameter.
   static Bound_method_expression*
-  make_bound_method(Expression* object, Expression* method, source_location);
+  make_bound_method(Expression* object, Named_object* method, source_location);
 
   // Make an index or slice expression.  This is a parser expression
   // which represents LEFT[START:END].  END may be NULL, meaning an
@@ -237,10 +239,6 @@ class Expression
   static Expression*
   make_allocation(Type*, source_location);
 
-  // Make a call to the builtin function make.
-  static Expression*
-  make_make(Type*, Expression_list*, source_location);
-
   // Make a type guard expression.
   static Expression*
   make_type_guard(Expression*, Type*, source_location);
@@ -249,6 +247,12 @@ class Expression
   static Expression*
   make_cast(Type*, Expression*, source_location);
 
+  // Make an unsafe type cast expression.  This is only used when
+  // passing parameter to builtin functions that are part of the Go
+  // runtime.
+  static Expression*
+  make_unsafe_cast(Type*, Expression*, source_location);
+
   // Make a composite literal.  The DEPTH parameter is how far down we
   // are in a list of composite literals with omitted types.
   static Expression*
@@ -271,12 +275,8 @@ class Expression
   static Receive_expression*
   make_receive(Expression* channel, source_location);
 
-  // Make a send expression.
-  static Send_expression*
-  make_send(Expression* channel, Expression* val, source_location);
-
-  // Make an expression which evaluates to the type descriptor of a
-  // type.
+  // Make an expression which evaluates to the address of the type
+  // descriptor for TYPE.
   static Expression*
   make_type_descriptor(Type* type, source_location);
 
@@ -303,6 +303,11 @@ class Expression
   static Expression*
   make_struct_field_offset(Struct_type*, const Struct_field*);
 
+  // Make an expression which evaluates to the address of the map
+  // descriptor for TYPE.
+  static Expression*
+  make_map_descriptor(Map_type* type, source_location);
+
   // Make an expression which evaluates to the address of an unnamed
   // label.
   static Expression*
@@ -356,8 +361,7 @@ class Expression
 
   // This is called by the parser if the value of this expression is
   // being discarded.  This issues warnings about computed values
-  // being unused, and handles send expressions which act differently
-  // depending upon whether the value is used.
+  // being unused.
   void
   discarding_value()
   { this->do_discarding_value(); }
@@ -520,13 +524,18 @@ class Expression
   traverse_subexpressions(Traverse*);
 
   // Lower an expression.  This is called immediately after parsing.
-  // IOTA_VALUE is the value that we should give to any iota
-  // expressions.  This function must resolve expressions which could
-  // not be fully parsed into their final form.  It returns the same
-  // Expression or a new one.
+  // FUNCTION is the function we are in; it will be NULL for an
+  // expression initializing a global variable.  INSERTER may be used
+  // to insert statements before the statement or initializer
+  // containing this expression; it is normally used to create
+  // temporary variables.  IOTA_VALUE is the value that we should give
+  // to any iota expressions.  This function must resolve expressions
+  // which could not be fully parsed into their final form.  It
+  // returns the same Expression or a new one.
   Expression*
-  lower(Gogo* gogo, Named_object* function, int iota_value)
-  { return this->do_lower(gogo, function, iota_value); }
+  lower(Gogo* gogo, Named_object* function, Statement_inserter* inserter,
+       int iota_value)
+  { return this->do_lower(gogo, function, inserter, iota_value); }
 
   // Determine the real type of an expression with abstract integer,
   // floating point, or complex type.  TYPE_CONTEXT describes the
@@ -628,6 +637,10 @@ class Expression
   static tree
   check_bounds(tree val, tree bound_type, tree sofar, source_location);
 
+  // Dump an expression to a dump constext.
+  void
+  dump_expression(Ast_dump_context*) const;
+
  protected:
   // May be implemented by child class: traverse the expressions.
   virtual int
@@ -635,7 +648,7 @@ class Expression
 
   // Return a lowered expression.
   virtual Expression*
-  do_lower(Gogo*, Named_object*, int)
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int)
   { return this; }
 
   // Return whether this is a constant expression.
@@ -724,6 +737,10 @@ class Expression
   void
   report_error(const char*);
 
+  // Child class implements dumping to a dump context.
+  virtual void
+  do_dump_expression(Ast_dump_context*) const = 0;
+
  private:
   // Convert to the desired statement classification, or return NULL.
   // This is a controlled dynamic cast.
@@ -870,23 +887,22 @@ class Parser_expression : public Expression
 
  protected:
   virtual Expression*
-  do_lower(Gogo*, Named_object*, int) = 0;
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int) = 0;
 
   Type*
-  do_type()
-  { gcc_unreachable(); }
+  do_type();
 
   void
   do_determine_type(const Type_context*)
-  { gcc_unreachable(); }
+  { go_unreachable(); }
 
   void
   do_check_types(Gogo*)
-  { gcc_unreachable(); }
+  { go_unreachable(); }
 
   tree
   do_get_tree(Translate_context*)
-  { gcc_unreachable(); }
+  { go_unreachable(); }
 };
 
 // An expression which is simply a variable.
@@ -904,20 +920,15 @@ class Var_expression : public Expression
   named_object() const
   { return this->variable_; }
 
-  // Return the name of the variable.
-  const std::string&
-  name() const;
-
  protected:
   Expression*
-  do_lower(Gogo*, Named_object*, int);
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
 
   Type*
   do_type();
 
   void
-  do_determine_type(const Type_context*)
-  { }
+  do_determine_type(const Type_context*);
 
   Expression*
   do_copy()
@@ -933,6 +944,9 @@ class Var_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The variable we are referencing.
   Named_object* variable_;
@@ -946,9 +960,15 @@ class Temporary_reference_expression : public Expression
   Temporary_reference_expression(Temporary_statement* statement,
                                 source_location location)
     : Expression(EXPRESSION_TEMPORARY_REFERENCE, location),
-      statement_(statement)
+      statement_(statement), is_lvalue_(false)
   { }
 
+  // Indicate that this reference appears on the left hand side of an
+  // assignment statement.
+  void
+  set_is_lvalue()
+  { this->is_lvalue_ = true; }
+
  protected:
   Type*
   do_type();
@@ -971,9 +991,15 @@ class Temporary_reference_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The statement where the temporary variable is defined.
   Temporary_statement* statement_;
+  // Whether this reference appears on the left hand side of an
+  // assignment statement.
+  bool is_lvalue_;
 };
 
 // A string expression.
@@ -1018,9 +1044,16 @@ class String_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  // Write string literal to a string dump.
+  static void
+  export_string(String_dump* exp, const String_expression* str);
+
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The string value.  This is immutable.
   const std::string val_;
@@ -1104,7 +1137,7 @@ class Binary_expression : public Expression
   do_traverse(Traverse* traverse);
 
   Expression*
-  do_lower(Gogo*, Named_object*, int);
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
 
   bool
   do_is_constant() const
@@ -1144,6 +1177,9 @@ class Binary_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The binary operator to apply.
   Operator op_;
@@ -1161,9 +1197,10 @@ class Call_expression : public Expression
   Call_expression(Expression* fn, Expression_list* args, bool is_varargs,
                  source_location location)
     : Expression(EXPRESSION_CALL, location),
-      fn_(fn), args_(args), type_(NULL), tree_(NULL), is_varargs_(is_varargs),
-      is_value_discarded_(false), varargs_are_lowered_(false),
-      is_deferred_(false)
+      fn_(fn), args_(args), type_(NULL), results_(NULL), tree_(NULL),
+      is_varargs_(is_varargs), are_hidden_fields_ok_(false),
+      varargs_are_lowered_(false), types_are_determined_(false),
+      is_deferred_(false), issued_error_(false)
   { }
 
   // The function to call.
@@ -1188,6 +1225,12 @@ class Call_expression : public Expression
   size_t
   result_count() const;
 
+  // Return the temporary variable which holds result I.  This is only
+  // valid after the expression has been lowered, and is only valid
+  // for calls which return multiple results.
+  Temporary_statement*
+  result(size_t i) const;
+
   // Return whether this is a call to the predeclared function
   // recover.
   bool
@@ -1202,6 +1245,17 @@ class Call_expression : public Expression
   is_varargs() const
   { return this->is_varargs_; }
 
+  // Note that varargs have already been lowered.
+  void
+  set_varargs_are_lowered()
+  { this->varargs_are_lowered_ = true; }
+
+  // Note that it is OK for this call to set hidden fields when
+  // passing arguments.
+  void
+  set_hidden_fields_are_ok()
+  { this->are_hidden_fields_ok_ = true; }
+
   // Whether this call is being deferred.
   bool
   is_deferred() const
@@ -1212,16 +1266,21 @@ class Call_expression : public Expression
   set_is_deferred()
   { this->is_deferred_ = true; }
 
+  // We have found an error with this call expression; return true if
+  // we should report it.
+  bool
+  issue_error();
+
  protected:
   int
   do_traverse(Traverse*);
 
   virtual Expression*
-  do_lower(Gogo*, Named_object*, int);
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
 
   void
   do_discarding_value()
-  { this->is_value_discarded_ = true; }
+  { }
 
   virtual Type*
   do_type();
@@ -1260,25 +1319,30 @@ class Call_expression : public Expression
   { this->args_ = args; }
 
   // Let a builtin expression lower varargs.
-  Expression*
-  lower_varargs(Gogo*, Named_object* function, Type* varargs_type,
-               size_t param_count);
+  void
+  lower_varargs(Gogo*, Named_object* function, Statement_inserter* inserter,
+               Type* varargs_type, size_t param_count);
 
- private:
+  // Let a builtin expression check whether types have been
+  // determined.
   bool
-  is_compatible_varargs_argument(Named_object*, Expression*, Type*, bool*);
+  determining_types();
+
+  void
+  do_dump_expression(Ast_dump_context*) const;
 
+ private:
   bool
   check_argument_type(int, const Type*, const Type*, source_location, bool);
 
   tree
-  bound_method_function(Translate_context*, Bound_method_expression*, tree*);
-
-  tree
   interface_method_function(Translate_context*,
                            Interface_field_reference_expression*,
                            tree*);
 
+  tree
+  set_results(Translate_context*, tree);
+
   // The function to call.
   Expression* fn_;
   // The arguments to pass.  This may be NULL if there are no
@@ -1286,16 +1350,26 @@ class Call_expression : public Expression
   Expression_list* args_;
   // The type of the expression, to avoid recomputing it.
   Type* type_;
+  // The list of temporaries which will hold the results if the
+  // function returns a tuple.
+  std::vector<Temporary_statement*>* results_;
   // The tree for the call, used for a call which returns a tuple.
   tree tree_;
   // True if the last argument is a varargs argument (f(a...)).
   bool is_varargs_;
-  // True if the value is being discarded.
-  bool is_value_discarded_;
+  // True if this statement may pass hidden fields in the arguments.
+  // This is used for generated method stubs.
+  bool are_hidden_fields_ok_;
   // True if varargs have already been lowered.
   bool varargs_are_lowered_;
+  // True if types have been determined.
+  bool types_are_determined_;
   // True if the call is an argument to a defer statement.
   bool is_deferred_;
+  // True if we reported an error about a mismatch between call
+  // results and uses.  This is to avoid producing multiple errors
+  // when there are multiple Call_result_expressions.
+  bool issued_error_;
 };
 
 // An expression which represents a pointer to a function.
@@ -1314,10 +1388,6 @@ class Func_expression : public Expression
   named_object() const
   { return this->function_; }
 
-  // Return the name of the function.
-  const std::string&
-  name() const;
-
   // Return the closure for this function.  This will return NULL if
   // the function has no closure, which is the normal case.
   Expression*
@@ -1355,6 +1425,9 @@ class Func_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The function itself.
   Named_object* function_;
@@ -1397,12 +1470,15 @@ class Unknown_expression : public Parser_expression
 
  protected:
   Expression*
-  do_lower(Gogo*, Named_object*, int);
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
 
   Expression*
   do_copy()
   { return new Unknown_expression(this->named_object_, this->location()); }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+  
  private:
   // The unknown name.
   Named_object* named_object_;
@@ -1427,12 +1503,18 @@ class Index_expression : public Parser_expression
   set_is_lvalue()
   { this->is_lvalue_ = true; }
 
+  // Dump an index expression, i.e. an expression of the form
+  // expr[expr] or expr[expr:expr], to a dump context.
+  static void
+  dump_index_expression(Ast_dump_context*, const Expression* expr, 
+                        const Expression* start, const Expression* end);
+
  protected:
   int
   do_traverse(Traverse*);
 
   Expression*
-  do_lower(Gogo*, Named_object*, int);
+  do_lower(Gogo*, Named_object*, Statement_inserter*, int);
 
   Expression*
   do_copy()
@@ -1444,6 +1526,9 @@ class Index_expression : public Parser_expression
                                this->location());
   }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The expression being indexed.
   Expression* left_;
@@ -1543,6 +1628,9 @@ class Map_index_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The map we are looking into.
   Expression* map_;
@@ -1560,7 +1648,7 @@ class Map_index_expression : public Expression
 class Bound_method_expression : public Expression
 {
  public:
-  Bound_method_expression(Expression* expr, Expression* method,
+  Bound_method_expression(Expression* expr, Named_object* method,
                          source_location location)
     : Expression(EXPRESSION_BOUND_METHOD, location),
       expr_(expr), expr_type_(NULL), method_(method)
@@ -1578,8 +1666,8 @@ class Bound_method_expression : public Expression
   first_argument_type() const
   { return this->expr_type_; }
 
-  // Return the reference to the method function.
-  Expression*
+  // Return the method function.
+  Named_object*
   method()
   { return this->method_; }
 
@@ -1604,14 +1692,16 @@ class Bound_method_expression : public Expression
   Expression*
   do_copy()
   {
-    return new Bound_method_expression(this->expr_->copy(),
-                                      this->method_->copy(),
+    return new Bound_method_expression(this->expr_->copy(), this->method_,
                                       this->location());
   }
 
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The object used to find the method.  This is passed to the method
   // as the first argument.
@@ -1620,8 +1710,8 @@ class Bound_method_expression : public Expression
   // NULL in the normal case, non-NULL when using a method from an
   // anonymous field which does not require a stub.
   Type* expr_type_;
-  // The method itself.  This is a Func_expression.
-  Expression* method_;
+  // The method itself.
+  Named_object* method_;
 };
 
 // A reference to a field in a struct.
@@ -1649,7 +1739,7 @@ class Field_reference_expression : public Expression
   void
   set_struct_expression(Expression* expr)
   {
-    gcc_assert(this->expr_ == NULL);
+    go_assert(this->expr_ == NULL);
     this->expr_ = expr;
   }
 
@@ -1683,6 +1773,9 @@ class Field_reference_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The expression we are looking into.  This should have a type of
   // struct.
@@ -1748,6 +1841,9 @@ class Interface_field_reference_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The expression for the interface object.  This should have a type
   // of interface or pointer to interface.
@@ -1801,6 +1897,9 @@ class Type_guard_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The expression to convert.
   Expression* expr_;
@@ -1815,7 +1914,7 @@ class Receive_expression : public Expression
  public:
   Receive_expression(Expression* channel, source_location location)
     : Expression(EXPRESSION_RECEIVE, location),
-      channel_(channel), is_value_discarded_(false), for_select_(false)
+      channel_(channel), for_select_(false)
   { }
 
   // Return the channel.
@@ -1835,7 +1934,7 @@ class Receive_expression : public Expression
 
   void
   do_discarding_value()
-  { this->is_value_discarded_ = true; }
+  { }
 
   Type*
   do_type();
@@ -1860,70 +1959,12 @@ class Receive_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
- private:
-  // The channel from which we are receiving.
-  Expression* channel_;
-  // Whether the value is being discarded.
-  bool is_value_discarded_;
-  // Whether this is for a select statement.
-  bool for_select_;
-};
-
-// A send expression.
-
-class Send_expression : public Expression
-{
- public:
-  Send_expression(Expression* channel, Expression* val,
-                 source_location location)
-    : Expression(EXPRESSION_SEND, location),
-      channel_(channel), val_(val), is_value_discarded_(false),
-      for_select_(false)
-  { }
-
-  // Note that this is for a select statement.
-  void
-  set_for_select()
-  { this->for_select_ = true; }
-
- protected:
-  int
-  do_traverse(Traverse* traverse);
-
-  void
-  do_discarding_value()
-  { this->is_value_discarded_ = true; }
-
-  Type*
-  do_type();
-
-  void
-  do_determine_type(const Type_context*);
-
   void
-  do_check_types(Gogo*);
-
-  Expression*
-  do_copy()
-  {
-    return Expression::make_send(this->channel_->copy(), this->val_->copy(),
-                                this->location());
-  }
-
-  bool
-  do_must_eval_in_order() const
-  { return true; }
-
-  tree
-  do_get_tree(Translate_context*);
+  do_dump_expression(Ast_dump_context*) const;
 
  private:
-  // The channel on which to send the value.
+  // The channel from which we are receiving.
   Expression* channel_;
-  // The value to send.
-  Expression* val_;
-  // Whether the value is being discarded.
-  bool is_value_discarded_;
   // Whether this is for a select statement.
   bool for_select_;
 };