OSDN Git Service

Check for invalid uses of ... in builtin function calls.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / expressions.cc
index ebe4f28..e3a3ab5 100644 (file)
@@ -205,17 +205,9 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
   if (lhs_type == rhs_type)
     return rhs_tree;
 
-  if (lhs_type->is_error_type() || rhs_type->is_error_type())
+  if (lhs_type->is_error() || rhs_type->is_error())
     return error_mark_node;
 
-  if (lhs_type->is_undefined() || rhs_type->is_undefined())
-    {
-      // Make sure we report the error.
-      lhs_type->base();
-      rhs_type->base();
-      return error_mark_node;
-    }
-
   if (rhs_tree == error_mark_node || TREE_TYPE(rhs_tree) == error_mark_node)
     return error_mark_node;
 
@@ -362,6 +354,8 @@ Expression::convert_type_to_interface(Translate_context* context,
       first_field_value = fold_convert_loc(location, const_ptr_type_node,
                                           method_table);
     }
+  if (first_field_value == error_mark_node)
+    return error_mark_node;
 
   // Start building a constructor for the value we will return.
 
@@ -934,14 +928,6 @@ Var_expression::do_lower(Gogo* gogo, Named_object* function, int)
   return this;
 }
 
-// Return the name of the variable.
-
-const std::string&
-Var_expression::name() const
-{
-  return this->variable_->name();
-}
-
 // Return the type of a reference to a variable.
 
 Type*
@@ -955,6 +941,15 @@ Var_expression::do_type()
     gcc_unreachable();
 }
 
+// Determine the type of a reference to a variable.
+
+void
+Var_expression::do_determine_type(const Type_context*)
+{
+  if (this->variable_->is_variable())
+    this->variable_->var_value()->determine_type();
+}
+
 // Something takes the address of this variable.  This means that we
 // may want to move the variable onto the heap.
 
@@ -1114,14 +1109,6 @@ Expression::make_sink(source_location location)
 // a function seems like it could work, though there might be little
 // point to it.
 
-// Return the name of the function.
-
-const std::string&
-Func_expression::name() const
-{
-  return this->function_->name();
-}
-
 // Traversal.
 
 int
@@ -2348,15 +2335,14 @@ class Const_expression : public Expression
   named_object()
   { return this->constant_; }
 
-  const std::string&
-  name() const
-  { return this->constant_->name(); }
-
   // Check that the initializer does not refer to the constant itself.
   void
   check_for_init_loop();
 
  protected:
+  int
+  do_traverse(Traverse*);
+
   Expression*
   do_lower(Gogo*, Named_object*, int);
 
@@ -2412,6 +2398,16 @@ class Const_expression : public Expression
   mutable bool seen_;
 };
 
+// Traversal.
+
+int
+Const_expression::do_traverse(Traverse* traverse)
+{
+  if (this->type_ != NULL)
+    return Type::traverse(this->type_, traverse);
+  return TRAVERSE_CONTINUE;
+}
+
 // Lower a constant expression.  This is where we convert the
 // predeclared constant iota into an integer value.
 
@@ -2624,7 +2620,7 @@ Const_expression::do_determine_type(const Type_context* context)
 void
 Const_expression::check_for_init_loop()
 {
-  if (this->type_ != NULL && this->type_->is_error_type())
+  if (this->type_ != NULL && this->type_->is_error())
     return;
 
   if (this->seen_)
@@ -2643,7 +2639,7 @@ Const_expression::check_for_init_loop()
 
   if (find_named_object.found())
     {
-      if (this->type_ == NULL || !this->type_->is_error_type())
+      if (this->type_ == NULL || !this->type_->is_error())
        {
          this->report_error(_("constant refers to itself"));
          this->type_ = Type::make_error_type();
@@ -2657,7 +2653,7 @@ Const_expression::check_for_init_loop()
 void
 Const_expression::do_check_types(Gogo*)
 {
-  if (this->type_ != NULL && this->type_->is_error_type())
+  if (this->type_ != NULL && this->type_->is_error())
     return;
 
   this->check_for_init_loop();
@@ -3307,14 +3303,8 @@ Type_conversion_expression::do_check_types(Gogo*)
   Type* expr_type = this->expr_->type();
   std::string reason;
 
-  if (type->is_error_type()
-      || type->is_undefined()
-      || expr_type->is_error_type()
-      || expr_type->is_undefined())
+  if (type->is_error() || expr_type->is_error())
     {
-      // Make sure we emit an error for an undefined type.
-      type->base();
-      expr_type->base();
       this->set_is_error();
       return;
     }
@@ -4023,7 +4013,7 @@ void
 Unary_expression::do_check_types(Gogo*)
 {
   Type* type = this->expr_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     {
       this->set_is_error();
       return;
@@ -4434,7 +4424,7 @@ Binary_expression::eval_integer(Operator op, Type* left_type, mpz_t left_val,
     case OPERATOR_LSHIFT:
       {
        unsigned long shift = mpz_get_ui(right_val);
-       if (mpz_cmp_ui(right_val, shift) != 0)
+       if (mpz_cmp_ui(right_val, shift) != 0 || shift > 0x100000)
          {
            error_at(location, "shift count overflow");
            mpz_set_ui(val, 0);
@@ -5443,9 +5433,9 @@ Binary_expression::do_type()
       {
        Type* left_type = this->left_->type();
        Type* right_type = this->right_->type();
-       if (left_type->is_error_type())
+       if (left_type->is_error())
          return left_type;
-       else if (right_type->is_error_type())
+       else if (right_type->is_error())
          return right_type;
        else if (!Type::are_compatible_for_binop(left_type, right_type))
          {
@@ -5684,7 +5674,7 @@ Binary_expression::do_check_types(Gogo*)
 
   Type* left_type = this->left_->type();
   Type* right_type = this->right_->type();
-  if (left_type->is_error_type() || right_type->is_error_type())
+  if (left_type->is_error() || right_type->is_error())
     {
       this->set_is_error();
       return;
@@ -5743,7 +5733,13 @@ Binary_expression::do_check_types(Gogo*)
          if (this->right_->integer_constant_value(true, val, &type))
            {
              if (mpz_sgn(val) < 0)
-               this->report_error(_("negative shift count"));
+               {
+                 this->report_error(_("negative shift count"));
+                 mpz_set_ui(val, 0);
+                 source_location rloc = this->right_->location();
+                 this->right_ = Expression::make_integer(&val, right_type,
+                                                         rloc);
+               }
            }
          mpz_clear(val);
        }
@@ -5859,13 +5855,21 @@ Binary_expression::do_get_tree(Translate_context* context)
   tree eval_saved = NULL_TREE;
   if (is_shift_op)
     {
-      if (!DECL_P(left))
-       left = save_expr(left);
-      if (!DECL_P(right))
-       right = save_expr(right);
       // Make sure the values are evaluated.
-      eval_saved = fold_build2_loc(this->location(), COMPOUND_EXPR,
-                                  void_type_node, left, right);
+      if (!DECL_P(left) && TREE_SIDE_EFFECTS(left))
+       {
+         left = save_expr(left);
+         eval_saved = left;
+       }
+      if (!DECL_P(right) && TREE_SIDE_EFFECTS(right))
+       {
+         right = save_expr(right);
+         if (eval_saved == NULL_TREE)
+           eval_saved = right;
+         else
+           eval_saved = fold_build2_loc(this->location(), COMPOUND_EXPR,
+                                        void_type_node, eval_saved, right);
+       }
     }
 
   tree ret = fold_build2_loc(this->location(),
@@ -5914,8 +5918,9 @@ Binary_expression::do_get_tree(Translate_context* context)
       ret = fold_build3_loc(this->location(), COND_EXPR, TREE_TYPE(left),
                            compare, ret, overflow_result);
 
-      ret = fold_build2_loc(this->location(), COMPOUND_EXPR,
-                           TREE_TYPE(ret), eval_saved, ret);
+      if (eval_saved != NULL_TREE)
+       ret = fold_build2_loc(this->location(), COMPOUND_EXPR,
+                             TREE_TYPE(ret), eval_saved, ret);
     }
 
   return ret;
@@ -6261,9 +6266,9 @@ Expression::comparison_tree(Translate_context* context, Operator op,
   else if (left_type->interface_type() != NULL
           && right_type->interface_type() != NULL)
     {
-      if (left_type->interface_type()->is_empty())
+      if (left_type->interface_type()->is_empty()
+         && right_type->interface_type()->is_empty())
        {
-         gcc_assert(right_type->interface_type()->is_empty());
          static tree empty_interface_compare_decl;
          left_tree = Gogo::call_builtin(&empty_interface_compare_decl,
                                         location,
@@ -6279,9 +6284,9 @@ Expression::comparison_tree(Translate_context* context, Operator op,
          // This can panic if the type is uncomparable.
          TREE_NOTHROW(empty_interface_compare_decl) = 0;
        }
-      else
+      else if (!left_type->interface_type()->is_empty()
+              && !right_type->interface_type()->is_empty())
        {
-         gcc_assert(!right_type->interface_type()->is_empty());
          static tree interface_compare_decl;
          left_tree = Gogo::call_builtin(&interface_compare_decl,
                                         location,
@@ -6297,6 +6302,32 @@ Expression::comparison_tree(Translate_context* context, Operator op,
          // This can panic if the type is uncomparable.
          TREE_NOTHROW(interface_compare_decl) = 0;
        }
+      else
+       {
+         if (left_type->interface_type()->is_empty())
+           {
+             gcc_assert(op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ);
+             std::swap(left_type, right_type);
+             std::swap(left_tree, right_tree);
+           }
+         gcc_assert(!left_type->interface_type()->is_empty());
+         gcc_assert(right_type->interface_type()->is_empty());
+         static tree interface_empty_compare_decl;
+         left_tree = Gogo::call_builtin(&interface_empty_compare_decl,
+                                        location,
+                                        "__go_interface_empty_compare",
+                                        2,
+                                        integer_type_node,
+                                        TREE_TYPE(left_tree),
+                                        left_tree,
+                                        TREE_TYPE(right_tree),
+                                        right_tree);
+         if (left_tree == error_mark_node)
+           return error_mark_node;
+         // This can panic if the type is uncomparable.
+         TREE_NOTHROW(interface_empty_compare_decl) = 0;
+       }
+
       right_tree = build_int_cst_type(integer_type_node, 0);
     }
 
@@ -6491,7 +6522,6 @@ class Builtin_call_expression : public Call_expression
       BUILTIN_APPEND,
       BUILTIN_CAP,
       BUILTIN_CLOSE,
-      BUILTIN_CLOSED,
       BUILTIN_COMPLEX,
       BUILTIN_COPY,
       BUILTIN_IMAG,
@@ -6549,8 +6579,6 @@ Builtin_call_expression::Builtin_call_expression(Gogo* gogo,
     this->code_ = BUILTIN_CAP;
   else if (name == "close")
     this->code_ = BUILTIN_CLOSE;
-  else if (name == "closed")
-    this->code_ = BUILTIN_CLOSED;
   else if (name == "complex")
     this->code_ = BUILTIN_COMPLEX;
   else if (name == "copy")
@@ -6644,6 +6672,12 @@ Find_call_expression::expression(Expression** pexpr)
 Expression*
 Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, int)
 {
+  if (this->is_varargs() && this->code_ != BUILTIN_APPEND)
+    {
+      this->report_error(_("invalid use of %<...%> with builtin function"));
+      return Expression::make_error(this->location());
+    }
+
   if (this->code_ == BUILTIN_NEW)
     {
       const Expression_list* args = this->args();
@@ -6959,10 +6993,12 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant,
       if (arg == NULL)
        return false;
       Type* arg_type = arg->type();
-      if (arg_type->is_error_type() || arg_type->is_undefined())
+      if (arg_type->is_error())
        return false;
       if (arg_type->is_abstract())
        return false;
+      if (arg_type->named_type() != NULL)
+       arg_type->named_type()->convert(this->gogo_);
       tree arg_type_tree = arg_type->get_tree(this->gogo_);
       if (arg_type_tree == error_mark_node)
        return false;
@@ -7007,6 +7043,8 @@ Builtin_call_expression::do_integer_constant_value(bool iota_is_constant,
       Type* st = struct_expr->type();
       if (st->struct_type() == NULL)
        return false;
+      if (st->named_type() != NULL)
+       st->named_type()->convert(this->gogo_);
       tree struct_tree = st->get_tree(this->gogo_);
       gcc_assert(TREE_CODE(struct_tree) == RECORD_TYPE);
       tree field = TYPE_FIELDS(struct_tree);
@@ -7142,9 +7180,6 @@ Builtin_call_expression::do_type()
     case BUILTIN_PRINTLN:
       return Type::make_void_type();
 
-    case BUILTIN_CLOSED:
-      return Type::lookup_bool_type();
-
     case BUILTIN_RECOVER:
       return Type::make_interface_type(NULL, BUILTINS_LOCATION);
 
@@ -7196,6 +7231,9 @@ Builtin_call_expression::do_type()
 void
 Builtin_call_expression::do_determine_type(const Type_context* context)
 {
+  if (!this->determining_types())
+    return;
+
   this->fn()->determine_type_no_context();
 
   const Expression_list* args = this->args();
@@ -7308,8 +7346,7 @@ Builtin_call_expression::check_one_arg()
       return false;
     }
   if (args->front()->is_error_expression()
-      || args->front()->type()->is_error_type()
-      || args->front()->type()->is_undefined())
+      || args->front()->type()->is_error())
     {
       this->set_is_error();
       return false;
@@ -7343,7 +7380,7 @@ Builtin_call_expression::do_check_types(Gogo*)
              arg_type = arg_type->points_to();
            if (this->code_ == BUILTIN_CAP)
              {
-               if (!arg_type->is_error_type()
+               if (!arg_type->is_error()
                    && arg_type->array_type() == NULL
                    && arg_type->channel_type() == NULL)
                  this->report_error(_("argument must be array or slice "
@@ -7351,7 +7388,7 @@ Builtin_call_expression::do_check_types(Gogo*)
              }
            else
              {
-               if (!arg_type->is_error_type()
+               if (!arg_type->is_error()
                    && !arg_type->is_string_type()
                    && arg_type->array_type() == NULL
                    && arg_type->map_type() == NULL
@@ -7383,7 +7420,7 @@ Builtin_call_expression::do_check_types(Gogo*)
                 ++p)
              {
                Type* type = (*p)->type();
-               if (type->is_error_type()
+               if (type->is_error()
                    || type->is_string_type()
                    || type->integer_type() != NULL
                    || type->float_type() != NULL
@@ -7405,7 +7442,6 @@ Builtin_call_expression::do_check_types(Gogo*)
       break;
 
     case BUILTIN_CLOSE:
-    case BUILTIN_CLOSED:
       if (this->check_one_arg())
        {
          if (this->one_arg()->type()->channel_type() == NULL)
@@ -7448,7 +7484,7 @@ Builtin_call_expression::do_check_types(Gogo*)
          }
        Type* arg1_type = args->front()->type();
        Type* arg2_type = args->back()->type();
-       if (arg1_type->is_error_type() || arg2_type->is_error_type())
+       if (arg1_type->is_error() || arg2_type->is_error())
          break;
 
        Type* e1;
@@ -7523,9 +7559,9 @@ Builtin_call_expression::do_check_types(Gogo*)
        else if (args->size() > 2)
          this->report_error(_("too many arguments"));
        else if (args->front()->is_error_expression()
-                || args->front()->type()->is_error_type()
+                || args->front()->type()->is_error()
                 || args->back()->is_error_expression()
-                || args->back()->type()->is_error_type())
+                || args->back()->type()->is_error())
          this->set_is_error();
        else if (!Type::are_identical(args->front()->type(),
                                      args->back()->type(), true, NULL))
@@ -7890,7 +7926,6 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
       }
 
     case BUILTIN_CLOSE:
-    case BUILTIN_CLOSED:
       {
        const Expression_list* args = this->args();
        gcc_assert(args != NULL && args->size() == 1);
@@ -7898,28 +7933,14 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
        tree arg_tree = arg->get_tree(context);
        if (arg_tree == error_mark_node)
          return error_mark_node;
-       if (this->code_ == BUILTIN_CLOSE)
-         {
-           static tree close_fndecl;
-           return Gogo::call_builtin(&close_fndecl,
-                                     location,
-                                     "__go_builtin_close",
-                                     1,
-                                     void_type_node,
-                                     TREE_TYPE(arg_tree),
-                                     arg_tree);
-         }
-       else
-         {
-           static tree closed_fndecl;
-           return Gogo::call_builtin(&closed_fndecl,
-                                     location,
-                                     "__go_builtin_closed",
-                                     1,
-                                     boolean_type_node,
-                                     TREE_TYPE(arg_tree),
-                                     arg_tree);
-         }
+       static tree close_fndecl;
+       return Gogo::call_builtin(&close_fndecl,
+                                 location,
+                                 "__go_builtin_close",
+                                 1,
+                                 void_type_node,
+                                 TREE_TYPE(arg_tree),
+                                 arg_tree);
       }
 
     case BUILTIN_SIZEOF:
@@ -7930,7 +7951,11 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
        mpz_init(val);
        Type* dummy;
        bool b = this->integer_constant_value(true, val, &dummy);
-       gcc_assert(b);
+       if (!b)
+         {
+           gcc_assert(saw_errors());
+           return error_mark_node;
+         }
        tree type = Type::lookup_integer_type("int")->get_tree(gogo);
        tree ret = Expression::integer_constant_tree(val, type);
        mpz_clear(val);
@@ -8227,8 +8252,9 @@ Call_expression::do_lower(Gogo* gogo, Named_object* function, int)
          for (size_t i = 0; i < rc; ++i)
            args->push_back(Expression::make_call_result(call, i));
          // We can't return a new call expression here, because this
-         // one may be referenced by Call_result expressions.  FIXME.
-         delete this->args_;
+         // one may be referenced by Call_result expressions.  We
+         // also can't delete the old arguments, because we may still
+         // traverse them somewhere up the call stack.  FIXME.
          this->args_ = args;
        }
     }
@@ -8427,6 +8453,9 @@ Call_expression::do_type()
 void
 Call_expression::do_determine_type(const Type_context*)
 {
+  if (!this->determining_types())
+    return;
+
   this->fn_->determine_type_no_context();
   Function_type* fntype = this->get_function_type();
   const Typed_identifier_list* parameters = NULL;
@@ -8453,6 +8482,21 @@ Call_expression::do_determine_type(const Type_context*)
     }
 }
 
+// Called when determining types for a Call_expression.  Return true
+// if we should go ahead, false if they have already been determined.
+
+bool
+Call_expression::determining_types()
+{
+  if (this->types_are_determined_)
+    return false;
+  else
+    {
+      this->types_are_determined_ = true;
+      return true;
+    }
+}
+
 // Check types for parameter I.
 
 bool
@@ -8487,7 +8531,7 @@ Call_expression::do_check_types(Gogo*)
   Function_type* fntype = this->get_function_type();
   if (fntype == NULL)
     {
-      if (!this->fn_->type()->is_error_type())
+      if (!this->fn_->type()->is_error())
        this->report_error(_("expected function"));
       return;
     }
@@ -8738,10 +8782,21 @@ Call_expression::do_get_tree(Translate_context* context)
       return error_mark_node;
     }
 
-  // This is to support builtin math functions when using 80387 math.
   tree fndecl = fn;
   if (TREE_CODE(fndecl) == ADDR_EXPR)
     fndecl = TREE_OPERAND(fndecl, 0);
+
+  // Add a type cast in case the type of the function is a recursive
+  // type which refers to itself.
+  if (!DECL_P(fndecl) || !DECL_IS_BUILTIN(fndecl))
+    {
+      tree fnt = fntype->get_tree(gogo);
+      if (fnt == error_mark_node)
+       return error_mark_node;
+      fn = fold_convert_loc(location, fnt, fn);
+    }
+
+  // This is to support builtin math functions when using 80387 math.
   tree excess_type = NULL_TREE;
   if (DECL_P(fndecl)
       && DECL_IS_BUILTIN(fndecl)
@@ -8787,7 +8842,7 @@ Call_expression::do_get_tree(Translate_context* context)
   // to the correct type.
   if (TREE_TYPE(ret) == ptr_type_node)
     {
-      tree t = this->type()->get_tree(gogo);
+      tree t = this->type()->base()->get_tree(gogo);
       ret = fold_convert_loc(location, t, ret);
     }
 
@@ -8934,8 +8989,7 @@ Call_result_expression::do_check_types(Gogo*)
 void
 Call_result_expression::do_determine_type(const Type_context*)
 {
-  if (this->index_ == 0)
-    this->call_->determine_type_no_context();
+  this->call_->determine_type_no_context();
 }
 
 // Return the tree.
@@ -8997,8 +9051,13 @@ Index_expression::do_lower(Gogo*, Named_object*, int)
   Expression* end = this->end_;
 
   Type* type = left->type();
-  if (type->is_error_type())
+  if (type->is_error())
     return Expression::make_error(location);
+  else if (left->is_type_expression())
+    {
+      error_at(location, "attempt to index type expression");
+      return Expression::make_error(location);
+    }
   else if (type->array_type() != NULL)
     return Expression::make_array_index(left, start, end, location);
   else if (type->points_to() != NULL
@@ -9168,7 +9227,7 @@ Array_index_expression::do_check_types(Gogo*)
   Array_type* array_type = this->array_->type()->array_type();
   if (array_type == NULL)
     {
-      gcc_assert(this->array_->type()->is_error_type());
+      gcc_assert(this->array_->type()->is_error());
       return;
     }
 
@@ -9250,7 +9309,7 @@ Array_index_expression::do_get_tree(Translate_context* context)
   Array_type* array_type = this->array_->type()->array_type();
   if (array_type == NULL)
     {
-      gcc_assert(this->array_->type()->is_error_type());
+      gcc_assert(this->array_->type()->is_error());
       return error_mark_node;
     }
 
@@ -9527,10 +9586,9 @@ void
 String_index_expression::do_determine_type(const Type_context*)
 {
   this->string_->determine_type_no_context();
-  Type_context subcontext(NULL, true);
-  this->start_->determine_type(&subcontext);
+  this->start_->determine_type_no_context();
   if (this->end_ != NULL)
-    this->end_->determine_type(&subcontext);
+    this->end_->determine_type_no_context();
 }
 
 // Check types of a string index.
@@ -9830,12 +9888,39 @@ Map_index_expression::get_value_pointer(Translate_context* context,
 
   // We need to pass in a pointer to the key, so stuff it into a
   // variable.
-  tree tmp = create_tmp_var(TREE_TYPE(index_tree), get_name(index_tree));
-  DECL_IGNORED_P(tmp) = 0;
-  DECL_INITIAL(tmp) = index_tree;
-  tree make_tmp = build1(DECL_EXPR, void_type_node, tmp);
-  tree tmpref = fold_convert(const_ptr_type_node, build_fold_addr_expr(tmp));
-  TREE_ADDRESSABLE(tmp) = 1;
+  tree tmp;
+  tree make_tmp;
+  if (current_function_decl != NULL)
+    {
+      tmp = create_tmp_var(TREE_TYPE(index_tree), get_name(index_tree));
+      DECL_IGNORED_P(tmp) = 0;
+      DECL_INITIAL(tmp) = index_tree;
+      make_tmp = build1(DECL_EXPR, void_type_node, tmp);
+      TREE_ADDRESSABLE(tmp) = 1;
+    }
+  else
+    {
+      tmp = build_decl(this->location(), VAR_DECL, create_tmp_var_name("M"),
+                      TREE_TYPE(index_tree));
+      DECL_EXTERNAL(tmp) = 0;
+      TREE_PUBLIC(tmp) = 0;
+      TREE_STATIC(tmp) = 1;
+      DECL_ARTIFICIAL(tmp) = 1;
+      if (!TREE_CONSTANT(index_tree))
+       make_tmp = fold_build2_loc(this->location(), INIT_EXPR, void_type_node,
+                                  tmp, index_tree);
+      else
+       {
+         TREE_READONLY(tmp) = 1;
+         TREE_CONSTANT(tmp) = 1;
+         DECL_INITIAL(tmp) = index_tree;
+         make_tmp = NULL_TREE;
+       }
+      rest_of_decl_compilation(tmp, 1, 0);
+    }
+  tree tmpref = fold_convert_loc(this->location(), const_ptr_type_node,
+                                build_fold_addr_expr_loc(this->location(),
+                                                         tmp));
 
   static tree map_index_fndecl;
   tree call = Gogo::call_builtin(&map_index_fndecl,
@@ -9862,9 +9947,10 @@ Map_index_expression::get_value_pointer(Translate_context* context,
     return error_mark_node;
   tree ptr_val_type_tree = build_pointer_type(val_type_tree);
 
-  return build2(COMPOUND_EXPR, ptr_val_type_tree,
-               make_tmp,
-               fold_convert(ptr_val_type_tree, call));
+  tree ret = fold_convert_loc(this->location(), ptr_val_type_tree, call);
+  if (make_tmp != NULL_TREE)
+    ret = build2(COMPOUND_EXPR, ptr_val_type_tree, make_tmp, ret);
+  return ret;
 }
 
 // Make a map index expression.
@@ -9884,7 +9970,7 @@ Type*
 Field_reference_expression::do_type()
 {
   Type* type = this->expr_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     return type;
   Struct_type* struct_type = type->struct_type();
   gcc_assert(struct_type != NULL);
@@ -9897,7 +9983,7 @@ void
 Field_reference_expression::do_check_types(Gogo*)
 {
   Type* type = this->expr_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     return;
   Struct_type* struct_type = type->struct_type();
   gcc_assert(struct_type != NULL);
@@ -11045,7 +11131,7 @@ Open_array_construction_expression::do_get_tree(Translate_context* context)
   Array_type* array_type = this->type()->array_type();
   if (array_type == NULL)
     {
-      gcc_assert(this->type()->is_error_type());
+      gcc_assert(this->type()->is_error());
       return error_mark_node;
     }
 
@@ -11514,7 +11600,7 @@ class Composite_literal_expression : public Parser_expression
 
  private:
   Expression*
-  lower_struct(Type*);
+  lower_struct(Gogo*, Type*);
 
   Expression*
   lower_array(Type*);
@@ -11564,7 +11650,7 @@ Composite_literal_expression::do_lower(Gogo* gogo, Named_object* function, int)
        type = type->map_type()->val_type();
       else
        {
-         if (!type->is_error_type())
+         if (!type->is_error())
            error_at(this->location(),
                     ("may only omit types within composite literals "
                      "of slice, array, or map type"));
@@ -11572,10 +11658,10 @@ Composite_literal_expression::do_lower(Gogo* gogo, Named_object* function, int)
        }
     }
 
-  if (type->is_error_type())
+  if (type->is_error())
     return Expression::make_error(this->location());
   else if (type->struct_type() != NULL)
-    return this->lower_struct(type);
+    return this->lower_struct(gogo, type);
   else if (type->array_type() != NULL)
     return this->lower_array(type);
   else if (type->map_type() != NULL)
@@ -11592,7 +11678,7 @@ Composite_literal_expression::do_lower(Gogo* gogo, Named_object* function, int)
 // Lower a struct composite literal.
 
 Expression*
-Composite_literal_expression::lower_struct(Type* type)
+Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
 {
   source_location location = this->location();
   Struct_type* st = type->struct_type();
@@ -11620,6 +11706,7 @@ Composite_literal_expression::lower_struct(Type* type)
 
       bool bad_key = false;
       std::string name;
+      const Named_object* no = NULL;
       switch (name_expr->classification())
        {
        case EXPRESSION_UNKNOWN_REFERENCE:
@@ -11627,7 +11714,7 @@ Composite_literal_expression::lower_struct(Type* type)
          break;
 
        case EXPRESSION_CONST_REFERENCE:
-         name = static_cast<Const_expression*>(name_expr)->name();
+         no = static_cast<Const_expression*>(name_expr)->named_object();
          break;
 
        case EXPRESSION_TYPE:
@@ -11637,16 +11724,16 @@ Composite_literal_expression::lower_struct(Type* type)
            if (nt == NULL)
              bad_key = true;
            else
-             name = nt->name();
+             no = nt->named_object();
          }
          break;
 
        case EXPRESSION_VAR_REFERENCE:
-         name = name_expr->var_expression()->name();
+         no = name_expr->var_expression()->named_object();
          break;
 
        case EXPRESSION_FUNC_REFERENCE:
-         name = name_expr->func_expression()->name();
+         no = name_expr->func_expression()->named_object();
          break;
 
        case EXPRESSION_UNARY:
@@ -11694,6 +11781,23 @@ Composite_literal_expression::lower_struct(Type* type)
          return Expression::make_error(location);
        }
 
+      if (no != NULL)
+       {
+         name = no->name();
+
+         // A predefined name won't be packed.  If it starts with a
+         // lower case letter we need to check for that case, because
+         // the field name will be packed.
+         if (!Gogo::is_hidden_name(name)
+             && name[0] >= 'a'
+             && name[0] <= 'z')
+           {
+             Named_object* gno = gogo->lookup_global(name.c_str());
+             if (gno == no)
+               name = gogo->pack_hidden_name(name, false);
+           }
+       }
+
       unsigned int index;
       const Struct_field* sf = st->find_local_field(name, &index);
       if (sf == NULL)
@@ -11754,6 +11858,7 @@ Composite_literal_expression::lower_array(Type* type)
        {
          mpz_t ival;
          mpz_init(ival);
+
          Type* dummy;
          if (!index_expr->integer_constant_value(true, ival, &dummy))
            {
@@ -11762,12 +11867,14 @@ Composite_literal_expression::lower_array(Type* type)
                       "index expression is not integer constant");
              return Expression::make_error(location);
            }
+
          if (mpz_sgn(ival) < 0)
            {
              mpz_clear(ival);
              error_at(index_expr->location(), "index expression is negative");
              return Expression::make_error(location);
            }
+
          index = mpz_get_ui(ival);
          if (mpz_cmp_ui(ival, index) != 0)
            {
@@ -11775,7 +11882,30 @@ Composite_literal_expression::lower_array(Type* type)
              error_at(index_expr->location(), "index value overflow");
              return Expression::make_error(location);
            }
+
+         Named_type* ntype = Type::lookup_integer_type("int");
+         Integer_type* inttype = ntype->integer_type();
+         mpz_t max;
+         mpz_init_set_ui(max, 1);
+         mpz_mul_2exp(max, max, inttype->bits() - 1);
+         bool ok = mpz_cmp(ival, max) < 0;
+         mpz_clear(max);
+         if (!ok)
+           {
+             mpz_clear(ival);
+             error_at(index_expr->location(), "index value overflow");
+             return Expression::make_error(location);
+           }
+
          mpz_clear(ival);
+
+         // FIXME: Our representation isn't very good; this avoids
+         // thrashing.
+         if (index > 0x1000000)
+           {
+             error_at(index_expr->location(), "index too large for compiler");
+             return Expression::make_error(location);
+           }
        }
 
       if (index == vals.size())
@@ -11993,7 +12123,7 @@ Type_guard_expression::do_check_types(Gogo*)
     }
   else if (expr_type->interface_type() == NULL)
     {
-      if (!expr_type->is_error_type() && !this->type_->is_error_type())
+      if (!expr_type->is_error() && !this->type_->is_error())
        this->report_error(_("type assertion only valid for interface types"));
       this->set_is_error();
     }
@@ -12003,7 +12133,7 @@ Type_guard_expression::do_check_types(Gogo*)
       if (!expr_type->interface_type()->implements_interface(this->type_,
                                                             &reason))
        {
-         if (!this->type_->is_error_type())
+         if (!this->type_->is_error())
            {
              if (reason.empty())
                this->report_error(_("impossible type assertion: "
@@ -12155,7 +12285,7 @@ void
 Receive_expression::do_check_types(Gogo*)
 {
   Type* type = this->channel_->type();
-  if (type->is_error_type())
+  if (type->is_error())
     {
       this->set_is_error();
       return;
@@ -12178,7 +12308,11 @@ tree
 Receive_expression::do_get_tree(Translate_context* context)
 {
   Channel_type* channel_type = this->channel_->type()->channel_type();
-  gcc_assert(channel_type != NULL);
+  if (channel_type == NULL)
+    {
+      gcc_assert(this->channel_->type()->is_error());
+      return error_mark_node;
+    }
   Type* element_type = channel_type->element_type();
   tree element_type_tree = element_type->get_tree(context->gogo());
 
@@ -12198,100 +12332,6 @@ Expression::make_receive(Expression* channel, source_location location)
   return new Receive_expression(channel, location);
 }
 
-// Class Send_expression.
-
-// Traversal.
-
-int
-Send_expression::do_traverse(Traverse* traverse)
-{
-  if (Expression::traverse(&this->channel_, traverse) == TRAVERSE_EXIT)
-    return TRAVERSE_EXIT;
-  return Expression::traverse(&this->val_, traverse);
-}
-
-// Get the type.
-
-Type*
-Send_expression::do_type()
-{
-  return Type::lookup_bool_type();
-}
-
-// Set types.
-
-void
-Send_expression::do_determine_type(const Type_context*)
-{
-  this->channel_->determine_type_no_context();
-
-  Type* type = this->channel_->type();
-  Type_context subcontext;
-  if (type->channel_type() != NULL)
-    subcontext.type = type->channel_type()->element_type();
-  this->val_->determine_type(&subcontext);
-}
-
-// Check types.
-
-void
-Send_expression::do_check_types(Gogo*)
-{
-  Type* type = this->channel_->type();
-  if (type->is_error_type())
-    {
-      this->set_is_error();
-      return;
-    }
-  Channel_type* channel_type = type->channel_type();
-  if (channel_type == NULL)
-    {
-      error_at(this->location(), "left operand of %<<-%> must be channel");
-      this->set_is_error();
-      return;
-    }
-  Type* element_type = channel_type->element_type();
-  if (element_type != NULL
-      && !Type::are_assignable(element_type, this->val_->type(), NULL))
-    {
-      this->report_error(_("incompatible types in send"));
-      return;
-    }
-  if (!channel_type->may_send())
-    {
-      this->report_error(_("invalid send on receive-only channel"));
-      return;
-    }
-}
-
-// Get a tree for a send expression.
-
-tree
-Send_expression::do_get_tree(Translate_context* context)
-{
-  tree channel = this->channel_->get_tree(context);
-  tree val = this->val_->get_tree(context);
-  if (channel == error_mark_node || val == error_mark_node)
-    return error_mark_node;
-  Channel_type* channel_type = this->channel_->type()->channel_type();
-  val = Expression::convert_for_assignment(context,
-                                          channel_type->element_type(),
-                                          this->val_->type(),
-                                          val,
-                                          this->location());
-  return Gogo::send_on_channel(channel, val, this->is_value_discarded_,
-                              this->for_select_, this->location());
-}
-
-// Make a send expression
-
-Send_expression*
-Expression::make_send(Expression* channel, Expression* val,
-                     source_location location)
-{
-  return new Send_expression(channel, val, location);
-}
-
 // An expression which evaluates to a pointer to the type descriptor
 // of a type.