This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Go patch committed: Fix various crashes
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org, gofrontend-dev at googlegroups dot com
- Date: Fri, 18 Feb 2011 19:23:25 -0800
- Subject: Go patch committed: Fix various crashes
This patch fixes several different crashes. I wrote the patch on the
plane so it combines several fixes at once, rather than my usual
practice of committing each fix separately.
* If a struct has a field whose type is an array of struct, and the
latter struct has a field whose type is a pointer to the first
struct, then if the structs were converted to GENERIC in the wrong
order the size of the array might be computed using an incomplete
struct. I fixed this using the existing prerequisite mechanism.
* Avoid a crash if an untyped complex constant is converted to an
integer or floating point type.
* Avoid a crash when using unsafe.Sizeof with an erroneous type.
* Avoid a crash when using a method expression of an erroneous type,
in which the method might appear in the list of all methods of the
type but might itself be erroneous.
* Avoid a crash when a sink variable and a global variable are
initialized from a type guard, when there is no explicitly specified
type for the global variable.
* Avoid a crash when initializing a value for a slice whose element
type is erroneous.
* Avoid crashing when an erroneous method is defined for a type before
the actual definition of the type is seen.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.
Ian
diff -r 8c0f3339bc97 go/expressions.cc
--- a/go/expressions.cc Tue Feb 15 14:35:42 2011 -0800
+++ b/go/expressions.cc Fri Feb 18 19:01:03 2011 -0800
@@ -716,7 +716,11 @@
tree
Expression::complex_constant_tree(mpfr_t real, mpfr_t imag, tree type)
{
- if (TREE_CODE(type) == COMPLEX_TYPE)
+ if (type == error_mark_node)
+ return error_mark_node;
+ else if (TREE_CODE(type) == INTEGER_TYPE || TREE_CODE(type) == REAL_TYPE)
+ return Expression::float_constant_tree(real, type);
+ else if (TREE_CODE(type) == COMPLEX_TYPE)
{
REAL_VALUE_TYPE r1;
real_from_mpfr(&r1, real, TREE_TYPE(type), GMP_RNDN);
@@ -6960,6 +6964,8 @@
if (arg_type->is_abstract())
return false;
tree arg_type_tree = arg_type->get_tree(this->gogo_);
+ if (arg_type_tree == error_mark_node)
+ return false;
unsigned long val_long;
if (this->code_ == BUILTIN_SIZEOF)
{
@@ -10325,7 +10331,11 @@
gcc_assert(vno != NULL);
Expression* ve = Expression::make_var_reference(vno, location);
Expression* bm = Type::bind_field_or_method(gogo, nt, ve, name, location);
- gcc_assert(bm != NULL && !bm->is_error_expression());
+
+ // Even though we found the method above, if it has an error type we
+ // may see an error here.
+ if (bm->is_error_expression())
+ return bm;
Expression_list* args;
if (method_parameters == NULL)
diff -r 8c0f3339bc97 go/parse.cc
--- a/go/parse.cc Tue Feb 15 14:35:42 2011 -0800
+++ b/go/parse.cc Fri Feb 18 19:01:03 2011 -0800
@@ -1865,6 +1865,8 @@
Parse::create_dummy_global(Type* type, Expression* init,
source_location location)
{
+ if (type == NULL && init == NULL)
+ type = Type::lookup_bool_type();
Variable* var = new Variable(type, init, true, false, false, location);
static int count;
char buf[30];
diff -r 8c0f3339bc97 go/types.cc
--- a/go/types.cc Tue Feb 15 14:35:42 2011 -0800
+++ b/go/types.cc Fri Feb 18 19:01:03 2011 -0800
@@ -4473,6 +4473,8 @@
gcc_assert(this->length_ == NULL);
tree element_type_tree = this->element_type_->get_tree(gogo);
+ if (element_type_tree == error_mark_node)
+ return error_mark_node;
tree field = TYPE_FIELDS(struct_type);
gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__values") == 0);
gcc_assert(POINTER_TYPE_P(TREE_TYPE(field))
@@ -6923,12 +6925,12 @@
}
// If this is a struct, then if any of the fields of the struct
- // themselves have struct type, then this struct must be converted
- // to the backend representation before the field's type is
- // converted. That may seem backward, but it works because if the
- // field's type refers to this one, e.g., via a pointer, then the
- // conversion process will pick up the half-built struct and do the
- // right thing.
+ // themselves have struct type, or array of struct type, then this
+ // struct must be converted to the backend representation before the
+ // field's type is converted. That may seem backward, but it works
+ // because if the field's type refers to this one, e.g., via a
+ // pointer, then the conversion process will pick up the half-built
+ // struct and do the right thing.
if (this->struct_type() != NULL)
{
const Struct_field_list* fields = this->struct_type()->fields();
@@ -6939,6 +6941,16 @@
Struct_type* st = p->type()->struct_type();
if (st != NULL)
st->add_prerequisite(this);
+ else
+ {
+ Array_type* at = p->type()->array_type();
+ if (at != NULL && !at->is_open_array_type())
+ {
+ st = at->element_type()->struct_type();
+ if (st != NULL)
+ st->add_prerequisite(this);
+ }
+ }
}
}
@@ -7488,7 +7500,13 @@
++pm)
{
Function_type* fntype = pm->type()->function_type();
- gcc_assert(fntype != NULL && !fntype->is_method());
+ if (fntype == NULL)
+ {
+ // This is an error, but it should be reported elsewhere
+ // when we look at the methods for IT.
+ continue;
+ }
+ gcc_assert(!fntype->is_method());
fntype = fntype->copy_with_receiver(const_cast<Type*>(type));
Method* m = new Interface_method(pm->name(), pm->location(), fntype,
field_indexes, depth);