OSDN Git Service

Don't crash on Sizeof of undefined type.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / expressions.cc
index 022f5ce..4f6e4ed 100644 (file)
@@ -3824,29 +3824,28 @@ Unary_expression::do_determine_type(const Type_context* context)
 void
 Unary_expression::do_check_types(Gogo*)
 {
+  Type* type = this->expr_->type();
+  if (type->is_error_type())
+    {
+      this->set_is_error();
+      return;
+    }
+
   switch (this->op_)
     {
     case OPERATOR_PLUS:
     case OPERATOR_MINUS:
-      {
-       Type* type = this->expr_->type();
-       if (type->integer_type() == NULL
-           && type->float_type() == NULL
-           && type->complex_type() == NULL
-           && !type->is_error_type())
-         this->report_error(_("expected numeric type"));
-      }
+      if (type->integer_type() == NULL
+         && type->float_type() == NULL
+         && type->complex_type() == NULL)
+       this->report_error(_("expected numeric type"));
       break;
 
     case OPERATOR_NOT:
     case OPERATOR_XOR:
-      {
-       Type* type = this->expr_->type();
-       if (type->integer_type() == NULL
-           && !type->is_boolean_type()
-           && !type->is_error_type())
-         this->report_error(_("expected integer or boolean type"));
-      }
+      if (type->integer_type() == NULL
+         && !type->is_boolean_type())
+       this->report_error(_("expected integer or boolean type"));
       break;
 
     case OPERATOR_AND:
@@ -3858,12 +3857,8 @@ Unary_expression::do_check_types(Gogo*)
 
     case OPERATOR_MULT:
       // Indirecting through a pointer.
-      {
-       Type* type = this->expr_->type();
-       if (type->points_to() == NULL
-           && !type->is_error_type())
-         this->report_error(_("expected pointer"));
-      }
+      if (type->points_to() == NULL)
+       this->report_error(_("expected pointer"));
       break;
 
     default:
@@ -5474,7 +5469,10 @@ 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())
-    return;
+    {
+      this->set_is_error();
+      return;
+    }
 
   if (this->op_ == OPERATOR_EQEQ
       || this->op_ == OPERATOR_NOTEQ
@@ -5940,9 +5938,8 @@ Expression::comparison_tree(Translate_context* context, Operator op,
       gcc_unreachable();
     }
 
-  if (left_type->is_string_type())
+  if (left_type->is_string_type() && right_type->is_string_type())
     {
-      gcc_assert(right_type->is_string_type());
       tree string_type = Type::make_string_type()->get_tree(context->gogo());
       static tree string_compare_decl;
       left_tree = Gogo::call_builtin(&string_compare_decl,
@@ -5956,13 +5953,12 @@ Expression::comparison_tree(Translate_context* context, Operator op,
                                     right_tree);
       right_tree = build_int_cst_type(integer_type_node, 0);
     }
-
-  if ((left_type->interface_type() != NULL
-       && right_type->interface_type() == NULL
-       && !right_type->is_nil_type())
-      || (left_type->interface_type() == NULL
-         && !left_type->is_nil_type()
-         && right_type->interface_type() != NULL))
+  else if ((left_type->interface_type() != NULL
+           && right_type->interface_type() == NULL
+           && !right_type->is_nil_type())
+          || (left_type->interface_type() == NULL
+              && !left_type->is_nil_type()
+              && right_type->interface_type() != NULL))
     {
       // Comparing an interface value to a non-interface value.
       if (left_type->interface_type() == NULL)
@@ -6113,6 +6109,9 @@ Expression::comparison_tree(Translate_context* context, Operator op,
        }
     }
 
+  if (left_tree == error_mark_node || right_tree == error_mark_node)
+    return error_mark_node;
+
   tree ret = fold_build2(code, boolean_type_node, left_tree, right_tree);
   if (CAN_HAVE_LOCATION_P(ret))
     SET_EXPR_LOCATION(ret, location);
@@ -6176,7 +6175,7 @@ Bound_method_expression::do_check_types(Gogo*)
                     ? this->expr_type_
                     : this->expr_->type());
       etype = etype->deref();
-      if (!Type::are_identical(rtype, etype, NULL))
+      if (!Type::are_identical(rtype, etype, true, NULL))
        this->report_error(_("method type does not match object type"));
     }
 }
@@ -6723,7 +6722,7 @@ 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())
+      if (arg_type->is_error_type() || arg_type->is_undefined())
        return false;
       if (arg_type->is_abstract())
        return false;
@@ -6853,7 +6852,7 @@ Builtin_call_expression::do_complex_constant_value(mpfr_t real, mpfr_t imag,
       bool ret = false;
       Type* itype;
       if (args->back()->float_constant_value(i, &itype)
-         && Type::are_identical(rtype, itype, NULL))
+         && Type::are_identical(rtype, itype, false, NULL))
        {
          mpfr_set(real, r, GMP_RNDN);
          mpfr_set(imag, i, GMP_RNDN);
@@ -7232,7 +7231,7 @@ Builtin_call_expression::do_check_types(Gogo*)
            break;
          }
 
-       if (!Type::are_identical(e1, e2, NULL))
+       if (!Type::are_identical(e1, e2, true, NULL))
          this->report_error(_("element types must be the same"));
       }
       break;
@@ -7286,7 +7285,7 @@ Builtin_call_expression::do_check_types(Gogo*)
                 || args->back()->type()->is_error_type())
          this->set_is_error();
        else if (!Type::are_identical(args->front()->type(),
-                                     args->back()->type(), NULL))
+                                     args->back()->type(), true, NULL))
          this->report_error(_("cmplx arguments must have identical types"));
        else if (args->front()->type()->float_type() == NULL)
          this->report_error(_("cmplx arguments must have "
@@ -7384,6 +7383,9 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
              gcc_unreachable();
          }
 
+       if (val_tree == error_mark_node)
+         return error_mark_node;
+
        tree type_tree = Type::lookup_integer_type("int")->get_tree(gogo);
        if (type_tree == TREE_TYPE(val_tree))
          return val_tree;
@@ -7510,7 +7512,8 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
                                               void_type_node,
                                               TREE_TYPE(arg),
                                               arg);
-               append_to_statement_list(call, &stmt_list);
+               if (call != error_mark_node)
+                 append_to_statement_list(call, &stmt_list);
              }
          }
 
@@ -7669,6 +7672,8 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
        arg1_tree = save_expr(arg1_tree);
        tree arg1_val = at->value_pointer_tree(gogo, arg1_tree);
        tree arg1_len = at->length_tree(gogo, arg1_tree);
+       if (arg1_val == error_mark_node || arg1_len == error_mark_node)
+         return error_mark_node;
 
        Type* arg2_type = arg2->type();
        tree arg2_val;
@@ -7686,6 +7691,8 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
            arg2_val = String_type::bytes_tree(gogo, arg2_tree);
            arg2_len = String_type::length_tree(gogo, arg2_tree);
          }
+       if (arg2_val == error_mark_node || arg2_len == error_mark_node)
+         return error_mark_node;
 
        arg1_len = save_expr(arg1_len);
        arg2_len = save_expr(arg2_len);
@@ -7698,6 +7705,8 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
 
        Type* element_type = at->element_type();
        tree element_type_tree = element_type->get_tree(gogo);
+       if (element_type_tree == error_mark_node)
+         return error_mark_node;
        tree element_size = TYPE_SIZE_UNIT(element_type_tree);
        tree bytecount = fold_convert_loc(location, TREE_TYPE(element_size),
                                          len);
@@ -8089,7 +8098,7 @@ Call_expression::is_compatible_varargs_argument(Named_object* function,
   Array_type* param_at = param_type->array_type();
   if (param_at != NULL
       && Type::are_identical(var_at->element_type(),
-                            param_at->element_type(), NULL))
+                            param_at->element_type(), true, NULL))
     return true;
   error_at(arg->location(), "... mismatch: passing ...T as ...");
   *issued_error = true;
@@ -8662,8 +8671,7 @@ Call_result_expression::do_check_types(Gogo*)
       ok = false;
     }
   if (!ok)
-    error_at(this->location(),
-            "number of results does not match number of values");
+    this->report_error(_("number of results does not match number of values"));
 }
 
 // Determine the type.  We have nothing to do here, but the 0 result
@@ -8982,6 +8990,8 @@ Array_index_expression::do_get_tree(Translate_context* context)
   gcc_assert(array_type != NULL);
 
   tree type_tree = array_type->get_tree(gogo);
+  if (type_tree == error_mark_node)
+    return error_mark_node;
 
   tree array_tree = this->array_->get_tree(context);
   if (array_tree == error_mark_node)
@@ -8990,6 +9000,8 @@ Array_index_expression::do_get_tree(Translate_context* context)
   if (array_type->length() == NULL && !DECL_P(array_tree))
     array_tree = save_expr(array_tree);
   tree length_tree = array_type->length_tree(gogo, array_tree);
+  if (length_tree == error_mark_node)
+    return error_mark_node;
   length_tree = save_expr(length_tree);
   tree length_type = TREE_TYPE(length_tree);
 
@@ -9045,6 +9057,8 @@ Array_index_expression::do_get_tree(Translate_context* context)
          // Open array.
          tree values = array_type->value_pointer_tree(gogo, array_tree);
          tree element_type_tree = array_type->element_type()->get_tree(gogo);
+         if (element_type_tree == error_mark_node)
+           return error_mark_node;
          tree element_size = TYPE_SIZE_UNIT(element_type_tree);
          tree offset = fold_build2_loc(loc, MULT_EXPR, sizetype,
                                        start_tree, element_size);
@@ -9057,6 +9071,8 @@ Array_index_expression::do_get_tree(Translate_context* context)
   // Array slice.
 
   tree capacity_tree = array_type->capacity_tree(gogo, array_tree);
+  if (capacity_tree == error_mark_node)
+    return error_mark_node;
   capacity_tree = fold_convert_loc(loc, length_type, capacity_tree);
 
   tree end_tree;
@@ -9090,6 +9106,8 @@ Array_index_expression::do_get_tree(Translate_context* context)
     }
 
   tree element_type_tree = array_type->element_type()->get_tree(gogo);
+  if (element_type_tree == error_mark_node)
+    return error_mark_node;
   tree element_size = TYPE_SIZE_UNIT(element_type_tree);
 
   tree offset = fold_build2_loc(loc, MULT_EXPR, sizetype,
@@ -9097,6 +9115,8 @@ Array_index_expression::do_get_tree(Translate_context* context)
                                element_size);
 
   tree value_pointer = array_type->value_pointer_tree(gogo, array_tree);
+  if (value_pointer == error_mark_node)
+    return error_mark_node;
 
   value_pointer = fold_build2_loc(loc, POINTER_PLUS_EXPR,
                                  TREE_TYPE(value_pointer),
@@ -9608,7 +9628,13 @@ Field_reference_expression::do_get_tree(Translate_context* context)
     return error_mark_node;
   gcc_assert(TREE_CODE(TREE_TYPE(struct_tree)) == RECORD_TYPE);
   tree field = TYPE_FIELDS(TREE_TYPE(struct_tree));
-  gcc_assert(field != NULL_TREE);
+  if (field == NULL_TREE)
+    {
+      // This can happen for a type which refers to itself indirectly
+      // and then turns out to be erroneous.
+      gcc_assert(saw_errors());
+      return error_mark_node;
+    }
   for (unsigned int i = this->field_index_; i > 0; --i)
     {
       field = DECL_CHAIN(field);
@@ -10714,6 +10740,9 @@ Open_array_construction_expression::do_get_tree(Translate_context* context)
 {
   Type* element_type = this->type()->array_type()->element_type();
   tree element_type_tree = element_type->get_tree(context->gogo());
+  if (element_type_tree == error_mark_node)
+    return error_mark_node;
+
   tree values;
   tree length_tree;
   if (this->vals() == NULL || this->vals()->empty())
@@ -10797,6 +10826,8 @@ Open_array_construction_expression::do_get_tree(Translate_context* context)
   // Build a constructor for the open array.
 
   tree type_tree = this->type()->get_tree(context->gogo());
+  if (type_tree == error_mark_node)
+    return error_mark_node;
   gcc_assert(TREE_CODE(type_tree) == RECORD_TYPE);
 
   VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 3);
@@ -10820,6 +10851,8 @@ Open_array_construction_expression::do_get_tree(Translate_context* context)
   elt->value = fold_convert(TREE_TYPE(field), length_tree);
 
   tree constructor = build_constructor(type_tree, init);
+  if (constructor == error_mark_node)
+    return error_mark_node;
   if (!is_in_function && is_constant_initializer)
     TREE_CONSTANT(constructor) = 1;
 
@@ -11162,7 +11195,7 @@ class Composite_literal_expression : public Parser_expression
   make_array(Type*, Expression_list*);
 
   Expression*
-  lower_map(Type*);
+  lower_map(Gogo*, Named_object*, Type*);
 
   // The type of the composite literal.
   Type* type_;
@@ -11191,7 +11224,7 @@ Composite_literal_expression::do_traverse(Traverse* traverse)
 // the type.
 
 Expression*
-Composite_literal_expression::do_lower(Gogo*, Named_object*, int)
+Composite_literal_expression::do_lower(Gogo* gogo, Named_object* function, int)
 {
   Type* type = this->type_;
 
@@ -11218,7 +11251,7 @@ Composite_literal_expression::do_lower(Gogo*, Named_object*, int)
   else if (type->array_type() != NULL)
     return this->lower_array(type);
   else if (type->map_type() != NULL)
-    return this->lower_map(type);
+    return this->lower_map(gogo, function, type);
   else
     {
       error_at(this->location(),
@@ -11477,7 +11510,8 @@ Composite_literal_expression::make_array(Type* type, Expression_list* vals)
 // Lower a map composite literal.
 
 Expression*
-Composite_literal_expression::lower_map(Type* type)
+Composite_literal_expression::lower_map(Gogo* gogo, Named_object* function,
+                                       Type* type)
 {
   source_location location = this->location();
   if (this->vals_ != NULL)
@@ -11488,7 +11522,7 @@ Composite_literal_expression::lower_map(Type* type)
          return Expression::make_error(location);
        }
 
-      for (Expression_list::const_iterator p = this->vals_->begin();
+      for (Expression_list::iterator p = this->vals_->begin();
           p != this->vals_->end();
           p += 2)
        {
@@ -11499,6 +11533,16 @@ Composite_literal_expression::lower_map(Type* type)
                       "map composite literal must have keys for every value");
              return Expression::make_error(location);
            }
+         // Make sure we have lowered the key; it may not have been
+         // lowered in order to handle keys for struct composite
+         // literals.  Lower it now to get the right error message.
+         if ((*p)->unknown_expression() != NULL)
+           {
+             (*p)->unknown_expression()->clear_is_composite_literal_key();
+             gogo->lower_expression(function, &*p);
+             gcc_assert((*p)->is_error_expression());
+             return Expression::make_error(location);
+           }
        }
     }
 
@@ -11620,24 +11664,29 @@ Type_guard_expression::do_check_types(Gogo*)
        this->report_error(_("invalid unsafe.Pointer conversion"));
     }
   else if (expr_type->interface_type() == NULL)
-    this->report_error(_("type assertion only valid for interface types"));
+    {
+      if (!expr_type->is_error_type() && !this->type_->is_error_type())
+       this->report_error(_("type assertion only valid for interface types"));
+      this->set_is_error();
+    }
   else if (this->type_->interface_type() == NULL)
     {
       std::string reason;
       if (!expr_type->interface_type()->implements_interface(this->type_,
                                                             &reason))
        {
-         if (reason.empty())
-           this->report_error(_("impossible type assertion: "
-                                "type does not implement interface"));
-         else
+         if (!this->type_->is_error_type())
            {
-             error_at(this->location(),
-                      ("impossible type assertion: "
-                       "type does not implement interface (%s)"),
-                      reason.c_str());
-             this->set_is_error();
+             if (reason.empty())
+               this->report_error(_("impossible type assertion: "
+                                    "type does not implement interface"));
+             else
+               error_at(this->location(),
+                        ("impossible type assertion: "
+                         "type does not implement interface (%s)"),
+                        reason.c_str());
            }
+         this->set_is_error();
        }
     }
 }