From 975fbd84776bc813d2c6cc020682b1e692400d38 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 1 Dec 2014 01:29:45 +0000 Subject: [PATCH] compiler: Don't crash with self-referential types. Fixes issue 6637. From-SVN: r218199 --- gcc/go/gofrontend/expressions.cc | 11 +++++++---- gcc/go/gofrontend/expressions.h | 2 +- gcc/go/gofrontend/types.cc | 30 ++++++++++++++++++++++++++---- gcc/go/gofrontend/types.h | 11 ++++++++++- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index dba5ea0f9c9..024b2c4b2ee 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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()) { diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index b7e1806040d..d96df28bbc1 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -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(); diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index c85c72cb91b..7035524033a 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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) - 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 { 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) - 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 { char buf[50]; @@ -10221,7 +10233,12 @@ Type* Forward_declaration_type::real_type() { 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 { this->warn(); @@ -10233,7 +10250,12 @@ const Type* Forward_declaration_type::real_type() const { 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 { this->warn(); diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 60de22e1fe1..4f000b12717 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -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 -- 2.30.2