Commit 975fbd84 by Ian Lance Taylor

compiler: Don't crash with self-referential types.

Fixes issue 6637.

From-SVN: r218199
parent 4368bc45
......@@ -8735,7 +8735,11 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
// Add temporary variables for all arguments that require type
// conversion.
Function_type* fntype = this->get_function_type();
go_assert(fntype != NULL);
if (fntype == NULL)
{
go_assert(saw_errors());
return this;
}
if (this->args_ != NULL && !this->args_->empty()
&& fntype->parameters() != NULL && !fntype->parameters()->empty())
{
......@@ -10901,9 +10905,8 @@ Interface_field_reference_expression::do_traverse(Traverse* traverse)
// interface. So introduce a temporary variable if necessary.
Expression*
Interface_field_reference_expression::do_lower(Gogo*, Named_object*,
Statement_inserter* inserter,
int)
Interface_field_reference_expression::do_flatten(Gogo*, Named_object*,
Statement_inserter* inserter)
{
if (!this->expr_->is_variable())
{
......
......@@ -2397,7 +2397,7 @@ class Interface_field_reference_expression : public Expression
do_traverse(Traverse* traverse);
Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int);
do_flatten(Gogo*, Named_object*, Statement_inserter*);
Type*
do_type();
......
......@@ -6361,7 +6361,13 @@ Array_type::do_reflection(Gogo* gogo, std::string* ret) const
unsigned long val;
if (!this->length_->numeric_constant_value(&nc)
|| nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
{
if (!this->issued_length_error_)
{
error_at(this->length_->location(), "invalid array length");
this->issued_length_error_ = true;
}
}
else
{
char buf[50];
......@@ -6488,7 +6494,13 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
unsigned long val;
if (!this->length_->numeric_constant_value(&nc)
|| nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
{
if (!this->issued_length_error_)
{
error_at(this->length_->location(), "invalid array length");
this->issued_length_error_ = true;
}
}
else
{
char buf[50];
......@@ -10221,7 +10233,12 @@ Type*
Forward_declaration_type::real_type()
{
if (this->is_defined())
{
Named_type* nt = this->named_object()->type_value();
if (!nt->is_valid())
return Type::make_error_type();
return this->named_object()->type_value();
}
else
{
this->warn();
......@@ -10233,7 +10250,12 @@ const Type*
Forward_declaration_type::real_type() const
{
if (this->is_defined())
{
const Named_type* nt = this->named_object()->type_value();
if (!nt->is_valid())
return Type::make_error_type();
return this->named_object()->type_value();
}
else
{
this->warn();
......
......@@ -2360,7 +2360,8 @@ class Array_type : public Type
public:
Array_type(Type* element_type, Expression* length)
: Type(TYPE_ARRAY),
element_type_(element_type), length_(length), blength_(NULL)
element_type_(element_type), length_(length), blength_(NULL),
issued_length_error_(false)
{ }
// Return the element type.
......@@ -2479,6 +2480,9 @@ class Array_type : public Type
// The backend representation of the length.
// We only want to compute this once.
Bexpression* blength_;
// Whether or not an invalid length error has been issued for this type,
// to avoid knock-on errors.
mutable bool issued_length_error_;
};
// The type of a map.
......@@ -2926,6 +2930,11 @@ class Named_type : public Type
bool
is_alias() const;
// Whether this named type is valid. A recursive named type is invalid.
bool
is_valid() const
{ return !this->is_error_; }
// Whether this is a circular type: a pointer or function type that
// refers to itself, which is not possible in C.
bool
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment