compiler: Report errors from very large types.
authorChris Manghane <cmang@google.com>
Thu, 10 Sep 2015 18:24:28 +0000 (18:24 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 10 Sep 2015 18:24:28 +0000 (18:24 +0000)
    The gcc backend throws an internal error when trying to get the size
    of a type which is larger than the amount of address space on the
    machine.  This patch catches this error and reports it in a user
    friendly way.

    Fixes golang/go#11554.

    Reviewed-on: https://go-review.googlesource.com/13684

* go-gcc.cc (Gcc_backend::type_size): Return -1 for
unrepresentable size.

From-SVN: r227656

gcc/go/ChangeLog
gcc/go/go-gcc.cc
gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/types.cc

index 90520ded45557af0daa35bdff644cde1a2f224ce..2fa56ab0ac0591e0440e8c9ff1c33f4b0eb530ff 100644 (file)
@@ -1,3 +1,8 @@
+2015-09-10  Chris Manghane  <cmang@google.com>
+
+       * go-gcc.cc (Gcc_backend::type_size): Return -1 for
+       unrepresentable size.
+
 2015-08-24  Marek Polacek  <polacek@redhat.com>
 
        PR tree-optimization/67284
index cb4c2e5c73a6170d4f4b5132c44162211ef638da..131434407610cb0bb876a72472641cfe458da221 100644 (file)
@@ -1099,7 +1099,8 @@ Gcc_backend::type_size(Btype* btype)
   gcc_assert(tree_fits_uhwi_p (t));
   unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t);
   int64_t ret = static_cast<int64_t>(val_wide);
-  gcc_assert(ret >= 0 && static_cast<unsigned HOST_WIDE_INT>(ret) == val_wide);
+  if (ret < 0 || static_cast<unsigned HOST_WIDE_INT>(ret) != val_wide)
+    return -1;
   return ret;
 }
 
index a4ec9249bf7fa05e79cea099533a52f2c34882b9..ddf4637a775781c22a5216b55bfa491ef7af6350 100644 (file)
@@ -1,4 +1,4 @@
-913b47c957ea91db2f724491d88cb20e8f9be8c7
+7ba569544420d1de0eb607707ced6d23f8865186
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 21b4f143b778448310f6f7f57d1fe3ddf395ad67..dc37cf0b01ecc6bdd41580d375d92592f3e2596e 100644 (file)
@@ -3626,8 +3626,13 @@ Unary_expression::do_flatten(Gogo* gogo, Named_object*,
       Type* ptype = this->expr_->type()->points_to();
       if (!ptype->is_void_type())
         {
-          Btype* pbtype = ptype->get_backend(gogo);
-          int64_t s = gogo->backend()->type_size(pbtype);
+          int64_t s;
+          bool ok = ptype->backend_type_size(gogo, &s);
+          if (!ok)
+            {
+              go_assert(saw_errors());
+              return Expression::make_error(this->location());
+            }
           if (s >= 4096 || this->issue_nil_check_)
             {
               Temporary_statement* temp =
@@ -4131,7 +4136,13 @@ Unary_expression::do_get_backend(Translate_context* context)
         Btype* pbtype = ptype->get_backend(gogo);
         if (!ptype->is_void_type())
          {
-            int64_t s = gogo->backend()->type_size(pbtype);
+            int64_t s;
+            bool ok = ptype->backend_type_size(gogo, &s);
+            if (!ok)
+              {
+                go_assert(saw_errors());
+                return gogo->backend()->error_expression();
+              }
            if (s >= 4096 || this->issue_nil_check_)
              {
                 go_assert(this->expr_->is_variable());
@@ -8339,8 +8350,14 @@ Builtin_call_expression::do_get_backend(Translate_context* context)
             Expression::make_conditional(cond, arg1_len, arg2_len, location);
 
        Type* element_type = at->element_type();
-       Btype* element_btype = element_type->get_backend(gogo);
-       int64_t element_size = gogo->backend()->type_size(element_btype);
+       int64_t element_size;
+        bool ok = element_type->backend_type_size(gogo, &element_size);
+        if (!ok)
+          {
+            go_assert(saw_errors());
+            return gogo->backend()->error_expression();
+          }
+
        Expression* size_expr = Expression::make_integer_int64(element_size,
                                                               length->type(),
                                                               location);
@@ -8381,8 +8398,12 @@ Builtin_call_expression::do_get_backend(Translate_context* context)
          {
            arg2_val = at->get_value_pointer(gogo, arg2);
            arg2_len = at->get_length(gogo, arg2);
-           Btype* element_btype = element_type->get_backend(gogo);
-           size = gogo->backend()->type_size(element_btype);
+            bool ok = element_type->backend_type_size(gogo, &size);
+            if (!ok)
+              {
+                go_assert(saw_errors());
+                return gogo->backend()->error_expression();
+              }
          }
         Expression* element_size =
          Expression::make_integer_int64(size, NULL, location);
@@ -11539,14 +11560,20 @@ Allocation_expression::do_get_backend(Translate_context* context)
   Gogo* gogo = context->gogo();
   Location loc = this->location();
 
-  Btype* btype = this->type_->get_backend(gogo);
   if (this->allocate_on_stack_)
     {
-      int64_t size = gogo->backend()->type_size(btype);
+      int64_t size;
+      bool ok = this->type_->backend_type_size(gogo, &size);
+      if (!ok)
+        {
+          go_assert(saw_errors());
+          return gogo->backend()->error_expression();
+        }
       return gogo->backend()->stack_allocation_expression(size, loc);
     }
 
-  Bexpression* space = 
+  Btype* btype = this->type_->get_backend(gogo);
+  Bexpression* space =
     gogo->allocate_memory(this->type_, loc)->get_backend(context);
   Btype* pbtype = gogo->backend()->pointer_type(btype);
   return gogo->backend()->convert_expression(pbtype, space, loc);
@@ -13731,23 +13758,28 @@ Type_info_expression::do_type()
 Bexpression*
 Type_info_expression::do_get_backend(Translate_context* context)
 {
-  Btype* btype = this->type_->get_backend(context->gogo());
   Gogo* gogo = context->gogo();
+  bool ok = true;
   int64_t val;
   switch (this->type_info_)
     {
     case TYPE_INFO_SIZE:
-      val = gogo->backend()->type_size(btype);
+      ok = this->type_->backend_type_size(gogo, &val);
       break;
     case TYPE_INFO_ALIGNMENT:
-      val = gogo->backend()->type_alignment(btype);
+      ok = this->type_->backend_type_align(gogo, &val);
       break;
     case TYPE_INFO_FIELD_ALIGNMENT:
-      val = gogo->backend()->type_field_alignment(btype);
+      ok = this->type_->backend_type_field_align(gogo, &val);
       break;
     default:
       go_unreachable();
     }
+  if (!ok)
+    {
+      go_assert(saw_errors());
+      return gogo->backend()->error_expression();
+    }
   Expression* e = Expression::make_integer_int64(val, this->type(),
                                                 this->location());
   return e->get_backend(context);
index 8331678578d13aa921c8fa0f60d7297a37b213c4..dcc6bc829c62f6ec692fac9fd9cd356c6cf587b2 100644 (file)
@@ -2524,6 +2524,20 @@ Type::backend_type_size(Gogo* gogo, int64_t *psize)
     return false;
   Btype* bt = this->get_backend_placeholder(gogo);
   *psize = gogo->backend()->type_size(bt);
+  if (*psize == -1)
+    {
+      if (this->named_type() != NULL)
+        error_at(this->named_type()->location(),
+                 "type %s larger than address space",
+                 Gogo::message_name(this->named_type()->name()).c_str());
+      else
+        error("type %s larger than address space",
+              this->reflection(gogo).c_str());
+
+      // Make this an error type to avoid knock-on errors.
+      this->classification_ = TYPE_ERROR;
+      return false;
+    }
   return true;
 }
 
@@ -6400,8 +6414,12 @@ Array_type::slice_gc_symbol(Gogo* gogo, Expression_list** vals,
 
   // Differentiate between slices with zero-length and non-zero-length values.
   Type* element_type = this->element_type();
-  Btype* ebtype = element_type->get_backend(gogo);
-  int64_t element_size = gogo->backend()->type_size(ebtype);
+  int64_t element_size;
+  bool ok = element_type->backend_type_size(gogo, &element_size);
+  if (!ok) {
+    go_assert(saw_errors());
+    element_size = 4;
+  }
 
   Type* uintptr_type = Type::lookup_integer_type("uintptr");
   unsigned long opval = element_size == 0 ? GC_APTR : GC_SLICE;
@@ -6432,7 +6450,13 @@ Array_type::array_gc_symbol(Gogo* gogo, Expression_list** vals,
 
   Btype* pbtype = gogo->backend()->pointer_type(gogo->backend()->void_type());
   int64_t pwidth = gogo->backend()->type_size(pbtype);
-  int64_t iwidth = gogo->backend()->type_size(this->get_backend(gogo));
+  int64_t iwidth;
+  bool ok = this->backend_type_size(gogo, &iwidth);
+  if (!ok)
+    {
+      go_assert(saw_errors());
+      iwidth = 4;
+    }
 
   Type* element_type = this->element_type();
   if (bound < 1 || !element_type->has_pointer())