compiler: Report errors from very large types.
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
This commit is contained in:
parent
8b66114510
commit
ec23e5b395
|
@ -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>
|
2015-08-24 Marek Polacek <polacek@redhat.com>
|
||||||
|
|
||||||
PR tree-optimization/67284
|
PR tree-optimization/67284
|
||||||
|
|
|
@ -1099,7 +1099,8 @@ Gcc_backend::type_size(Btype* btype)
|
||||||
gcc_assert(tree_fits_uhwi_p (t));
|
gcc_assert(tree_fits_uhwi_p (t));
|
||||||
unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t);
|
unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW(t);
|
||||||
int64_t ret = static_cast<int64_t>(val_wide);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
913b47c957ea91db2f724491d88cb20e8f9be8c7
|
7ba569544420d1de0eb607707ced6d23f8865186
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the last
|
The first line of this file holds the git revision number of the last
|
||||||
merge done from the gofrontend repository.
|
merge done from the gofrontend repository.
|
||||||
|
|
|
@ -3626,8 +3626,13 @@ Unary_expression::do_flatten(Gogo* gogo, Named_object*,
|
||||||
Type* ptype = this->expr_->type()->points_to();
|
Type* ptype = this->expr_->type()->points_to();
|
||||||
if (!ptype->is_void_type())
|
if (!ptype->is_void_type())
|
||||||
{
|
{
|
||||||
Btype* pbtype = ptype->get_backend(gogo);
|
int64_t s;
|
||||||
int64_t s = gogo->backend()->type_size(pbtype);
|
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_)
|
if (s >= 4096 || this->issue_nil_check_)
|
||||||
{
|
{
|
||||||
Temporary_statement* temp =
|
Temporary_statement* temp =
|
||||||
|
@ -4131,7 +4136,13 @@ Unary_expression::do_get_backend(Translate_context* context)
|
||||||
Btype* pbtype = ptype->get_backend(gogo);
|
Btype* pbtype = ptype->get_backend(gogo);
|
||||||
if (!ptype->is_void_type())
|
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_)
|
if (s >= 4096 || this->issue_nil_check_)
|
||||||
{
|
{
|
||||||
go_assert(this->expr_->is_variable());
|
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);
|
Expression::make_conditional(cond, arg1_len, arg2_len, location);
|
||||||
|
|
||||||
Type* element_type = at->element_type();
|
Type* element_type = at->element_type();
|
||||||
Btype* element_btype = element_type->get_backend(gogo);
|
int64_t element_size;
|
||||||
int64_t element_size = gogo->backend()->type_size(element_btype);
|
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,
|
Expression* size_expr = Expression::make_integer_int64(element_size,
|
||||||
length->type(),
|
length->type(),
|
||||||
location);
|
location);
|
||||||
|
@ -8381,8 +8398,12 @@ Builtin_call_expression::do_get_backend(Translate_context* context)
|
||||||
{
|
{
|
||||||
arg2_val = at->get_value_pointer(gogo, arg2);
|
arg2_val = at->get_value_pointer(gogo, arg2);
|
||||||
arg2_len = at->get_length(gogo, arg2);
|
arg2_len = at->get_length(gogo, arg2);
|
||||||
Btype* element_btype = element_type->get_backend(gogo);
|
bool ok = element_type->backend_type_size(gogo, &size);
|
||||||
size = gogo->backend()->type_size(element_btype);
|
if (!ok)
|
||||||
|
{
|
||||||
|
go_assert(saw_errors());
|
||||||
|
return gogo->backend()->error_expression();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Expression* element_size =
|
Expression* element_size =
|
||||||
Expression::make_integer_int64(size, NULL, location);
|
Expression::make_integer_int64(size, NULL, location);
|
||||||
|
@ -11539,14 +11560,20 @@ Allocation_expression::do_get_backend(Translate_context* context)
|
||||||
Gogo* gogo = context->gogo();
|
Gogo* gogo = context->gogo();
|
||||||
Location loc = this->location();
|
Location loc = this->location();
|
||||||
|
|
||||||
Btype* btype = this->type_->get_backend(gogo);
|
|
||||||
if (this->allocate_on_stack_)
|
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);
|
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);
|
gogo->allocate_memory(this->type_, loc)->get_backend(context);
|
||||||
Btype* pbtype = gogo->backend()->pointer_type(btype);
|
Btype* pbtype = gogo->backend()->pointer_type(btype);
|
||||||
return gogo->backend()->convert_expression(pbtype, space, loc);
|
return gogo->backend()->convert_expression(pbtype, space, loc);
|
||||||
|
@ -13731,23 +13758,28 @@ Type_info_expression::do_type()
|
||||||
Bexpression*
|
Bexpression*
|
||||||
Type_info_expression::do_get_backend(Translate_context* context)
|
Type_info_expression::do_get_backend(Translate_context* context)
|
||||||
{
|
{
|
||||||
Btype* btype = this->type_->get_backend(context->gogo());
|
|
||||||
Gogo* gogo = context->gogo();
|
Gogo* gogo = context->gogo();
|
||||||
|
bool ok = true;
|
||||||
int64_t val;
|
int64_t val;
|
||||||
switch (this->type_info_)
|
switch (this->type_info_)
|
||||||
{
|
{
|
||||||
case TYPE_INFO_SIZE:
|
case TYPE_INFO_SIZE:
|
||||||
val = gogo->backend()->type_size(btype);
|
ok = this->type_->backend_type_size(gogo, &val);
|
||||||
break;
|
break;
|
||||||
case TYPE_INFO_ALIGNMENT:
|
case TYPE_INFO_ALIGNMENT:
|
||||||
val = gogo->backend()->type_alignment(btype);
|
ok = this->type_->backend_type_align(gogo, &val);
|
||||||
break;
|
break;
|
||||||
case TYPE_INFO_FIELD_ALIGNMENT:
|
case TYPE_INFO_FIELD_ALIGNMENT:
|
||||||
val = gogo->backend()->type_field_alignment(btype);
|
ok = this->type_->backend_type_field_align(gogo, &val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
go_unreachable();
|
go_unreachable();
|
||||||
}
|
}
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
go_assert(saw_errors());
|
||||||
|
return gogo->backend()->error_expression();
|
||||||
|
}
|
||||||
Expression* e = Expression::make_integer_int64(val, this->type(),
|
Expression* e = Expression::make_integer_int64(val, this->type(),
|
||||||
this->location());
|
this->location());
|
||||||
return e->get_backend(context);
|
return e->get_backend(context);
|
||||||
|
|
|
@ -2524,6 +2524,20 @@ Type::backend_type_size(Gogo* gogo, int64_t *psize)
|
||||||
return false;
|
return false;
|
||||||
Btype* bt = this->get_backend_placeholder(gogo);
|
Btype* bt = this->get_backend_placeholder(gogo);
|
||||||
*psize = gogo->backend()->type_size(bt);
|
*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;
|
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.
|
// Differentiate between slices with zero-length and non-zero-length values.
|
||||||
Type* element_type = this->element_type();
|
Type* element_type = this->element_type();
|
||||||
Btype* ebtype = element_type->get_backend(gogo);
|
int64_t element_size;
|
||||||
int64_t element_size = gogo->backend()->type_size(ebtype);
|
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");
|
Type* uintptr_type = Type::lookup_integer_type("uintptr");
|
||||||
unsigned long opval = element_size == 0 ? GC_APTR : GC_SLICE;
|
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());
|
Btype* pbtype = gogo->backend()->pointer_type(gogo->backend()->void_type());
|
||||||
int64_t pwidth = gogo->backend()->type_size(pbtype);
|
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();
|
Type* element_type = this->element_type();
|
||||||
if (bound < 1 || !element_type->has_pointer())
|
if (bound < 1 || !element_type->has_pointer())
|
||||||
|
|
Loading…
Reference in New Issue