OSDN Git Service

Don't crash on Sizeof of undefined type.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / expressions.cc
index 7470907..4f6e4ed 100644 (file)
@@ -6109,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);
@@ -6172,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"));
     }
 }
@@ -6719,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;
@@ -6849,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);
@@ -7228,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;
@@ -7282,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 "
@@ -7380,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;
@@ -7506,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);
              }
          }
 
@@ -7665,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;
@@ -7682,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);
@@ -7694,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);
@@ -8085,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;
@@ -8977,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)
@@ -8985,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);
 
@@ -9040,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);
@@ -9052,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;
@@ -9085,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,
@@ -9092,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),
@@ -9603,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);