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*, ...@@ -8735,7 +8735,11 @@ Call_expression::do_flatten(Gogo* gogo, Named_object*,
// Add temporary variables for all arguments that require type // Add temporary variables for all arguments that require type
// conversion. // conversion.
Function_type* fntype = this->get_function_type(); 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() if (this->args_ != NULL && !this->args_->empty()
&& fntype->parameters() != NULL && !fntype->parameters()->empty()) && fntype->parameters() != NULL && !fntype->parameters()->empty())
{ {
...@@ -10901,9 +10905,8 @@ Interface_field_reference_expression::do_traverse(Traverse* traverse) ...@@ -10901,9 +10905,8 @@ Interface_field_reference_expression::do_traverse(Traverse* traverse)
// interface. So introduce a temporary variable if necessary. // interface. So introduce a temporary variable if necessary.
Expression* Expression*
Interface_field_reference_expression::do_lower(Gogo*, Named_object*, Interface_field_reference_expression::do_flatten(Gogo*, Named_object*,
Statement_inserter* inserter, Statement_inserter* inserter)
int)
{ {
if (!this->expr_->is_variable()) if (!this->expr_->is_variable())
{ {
......
...@@ -2397,7 +2397,7 @@ class Interface_field_reference_expression : public Expression ...@@ -2397,7 +2397,7 @@ class Interface_field_reference_expression : public Expression
do_traverse(Traverse* traverse); do_traverse(Traverse* traverse);
Expression* Expression*
do_lower(Gogo*, Named_object*, Statement_inserter*, int); do_flatten(Gogo*, Named_object*, Statement_inserter*);
Type* Type*
do_type(); do_type();
......
...@@ -6361,7 +6361,13 @@ Array_type::do_reflection(Gogo* gogo, std::string* ret) const ...@@ -6361,7 +6361,13 @@ Array_type::do_reflection(Gogo* gogo, std::string* ret) const
unsigned long val; unsigned long val;
if (!this->length_->numeric_constant_value(&nc) if (!this->length_->numeric_constant_value(&nc)
|| nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID) || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
error_at(this->length_->location(), "invalid array length"); {
if (!this->issued_length_error_)
{
error_at(this->length_->location(), "invalid array length");
this->issued_length_error_ = true;
}
}
else else
{ {
char buf[50]; char buf[50];
...@@ -6488,7 +6494,13 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const ...@@ -6488,7 +6494,13 @@ Array_type::do_mangled_name(Gogo* gogo, std::string* ret) const
unsigned long val; unsigned long val;
if (!this->length_->numeric_constant_value(&nc) if (!this->length_->numeric_constant_value(&nc)
|| nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID) || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
error_at(this->length_->location(), "invalid array length"); {
if (!this->issued_length_error_)
{
error_at(this->length_->location(), "invalid array length");
this->issued_length_error_ = true;
}
}
else else
{ {
char buf[50]; char buf[50];
...@@ -10221,7 +10233,12 @@ Type* ...@@ -10221,7 +10233,12 @@ Type*
Forward_declaration_type::real_type() Forward_declaration_type::real_type()
{ {
if (this->is_defined()) if (this->is_defined())
return this->named_object()->type_value(); {
Named_type* nt = this->named_object()->type_value();
if (!nt->is_valid())
return Type::make_error_type();
return this->named_object()->type_value();
}
else else
{ {
this->warn(); this->warn();
...@@ -10233,7 +10250,12 @@ const Type* ...@@ -10233,7 +10250,12 @@ const Type*
Forward_declaration_type::real_type() const Forward_declaration_type::real_type() const
{ {
if (this->is_defined()) if (this->is_defined())
return this->named_object()->type_value(); {
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 else
{ {
this->warn(); this->warn();
......
...@@ -2360,7 +2360,8 @@ class Array_type : public Type ...@@ -2360,7 +2360,8 @@ class Array_type : public Type
public: public:
Array_type(Type* element_type, Expression* length) Array_type(Type* element_type, Expression* length)
: Type(TYPE_ARRAY), : 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. // Return the element type.
...@@ -2479,6 +2480,9 @@ class Array_type : public Type ...@@ -2479,6 +2480,9 @@ class Array_type : public Type
// The backend representation of the length. // The backend representation of the length.
// We only want to compute this once. // We only want to compute this once.
Bexpression* blength_; 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. // The type of a map.
...@@ -2926,6 +2930,11 @@ class Named_type : public Type ...@@ -2926,6 +2930,11 @@ class Named_type : public Type
bool bool
is_alias() const; 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 // Whether this is a circular type: a pointer or function type that
// refers to itself, which is not possible in C. // refers to itself, which is not possible in C.
bool 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