From cd34c8436057524c36b1999828643da0bd41601b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 24 Feb 2011 04:30:34 +0000 Subject: [PATCH] Avoid infinite loop in field_reference. From-SVN: r170457 --- gcc/go/gofrontend/types.cc | 32 +++++++++++++++++++++++++++++++- gcc/go/gofrontend/types.h | 10 +++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 1e3973167e8..806226f6f42 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -3583,7 +3583,8 @@ Struct_type::field_reference(Expression* struct_expr, const std::string& name, source_location location) const { unsigned int depth; - return this->field_reference_depth(struct_expr, name, location, &depth); + return this->field_reference_depth(struct_expr, name, location, NULL, + &depth); } // Return an expression for a field, along with the depth at which it @@ -3593,6 +3594,7 @@ Field_reference_expression* Struct_type::field_reference_depth(Expression* struct_expr, const std::string& name, source_location location, + Saw_named_type* saw, unsigned int* depth) const { const Struct_field_list* fields = this->fields_; @@ -3628,13 +3630,41 @@ Struct_type::field_reference_depth(Expression* struct_expr, if (st == NULL) continue; + Saw_named_type* hold_saw = saw; + Saw_named_type saw_here; + Named_type* nt = pf->type()->named_type(); + if (nt == NULL) + nt = pf->type()->deref()->named_type(); + if (nt != NULL) + { + Saw_named_type* q; + for (q = saw; q != NULL; q = q->next) + { + if (q->nt == nt) + { + // If this is an error, it will be reported + // elsewhere. + break; + } + } + if (q != NULL) + continue; + saw_here.next = saw; + saw_here.nt = nt; + saw = &saw_here; + } + // Look for a reference using a NULL struct expression. If we // find one, fill in the struct expression with a reference to // this field. unsigned int subdepth; Field_reference_expression* sub = st->field_reference_depth(NULL, name, location, + saw, &subdepth); + + saw = hold_saw; + if (sub == NULL) continue; diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index b4280774898..b0dbefed455 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -1980,9 +1980,17 @@ class Struct_type : public Type do_export(Export*) const; private: + // Used to avoid infinite loops in field_reference_depth. + struct Saw_named_type + { + Saw_named_type* next; + Named_type* nt; + }; + Field_reference_expression* field_reference_depth(Expression* struct_expr, const std::string& name, - source_location, unsigned int* depth) const; + source_location, Saw_named_type*, + unsigned int* depth) const; static Type* make_struct_type_descriptor_type(); -- 2.30.2