The Go compiler could crash when an invalid type occurred within an invalid type, because the type verification pass was not recurring into such types. This patch fixes the problem and actually removes more lines than it adds. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 5bf5cc73ac14 go/types.cc --- a/go/types.cc Wed Feb 29 11:58:27 2012 -0800 +++ b/go/types.cc Wed Feb 29 14:40:08 2012 -0800 @@ -4116,7 +4116,6 @@ Struct_field_list* fields = this->fields_; if (fields == NULL) return true; - bool ret = true; for (Struct_field_list::iterator p = fields->begin(); p != fields->end(); ++p) @@ -4126,7 +4125,6 @@ { error_at(p->location(), "struct field type is incomplete"); p->set_type(Type::make_error_type()); - ret = false; } else if (p->is_anonymous()) { @@ -4134,19 +4132,17 @@ { error_at(p->location(), "embedded type may not be a pointer"); p->set_type(Type::make_error_type()); - return false; } - if (t->points_to() != NULL - && t->points_to()->interface_type() != NULL) + else if (t->points_to() != NULL + && t->points_to()->interface_type() != NULL) { error_at(p->location(), "embedded type may not be pointer to interface"); p->set_type(Type::make_error_type()); - return false; } } } - return ret; + return true; } // Whether this contains a pointer. @@ -5206,10 +5202,7 @@ Array_type::do_verify() { if (!this->verify_length()) - { - this->length_ = Expression::make_error(this->length_->location()); - return false; - } + this->length_ = Expression::make_error(this->length_->location()); return true; } @@ -5899,10 +5892,7 @@ { // The runtime support uses "map[void]void". if (!this->key_type_->is_comparable() && !this->key_type_->is_void_type()) - { - error_at(this->location_, "invalid map key type"); - return false; - } + error_at(this->location_, "invalid map key type"); return true; } @@ -7885,7 +7875,6 @@ if (this->local_methods_ != NULL) { Struct_type* st = this->type_->struct_type(); - bool found_dup = false; if (st != NULL) { for (Bindings::const_declarations_iterator p = @@ -7899,12 +7888,9 @@ error_at(p->second->location(), "method %qs redeclares struct field name", Gogo::message_name(name).c_str()); - found_dup = true; } } } - if (found_dup) - return false; } return true; diff -r 5bf5cc73ac14 go/types.h --- a/go/types.h Wed Feb 29 11:58:27 2012 -0800 +++ b/go/types.h Wed Feb 29 14:40:08 2012 -0800 @@ -510,7 +510,8 @@ // Verify the type. This is called after parsing, and verifies that // types are complete and meet the language requirements. This - // returns false if the type is invalid. + // returns false if the type is invalid and we should not continue + // traversing it. bool verify() { return this->do_verify(); }