diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-02-24 04:30:34 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-02-24 04:30:34 +0000 |
commit | cd34c8436057524c36b1999828643da0bd41601b (patch) | |
tree | dea5d961e05999b43cf8c2f3a02eb91f44091a60 /gcc | |
parent | acabc10c983db7b55fda3b02f7c0a9d779e0245a (diff) | |
download | gcc-cd34c8436057524c36b1999828643da0bd41601b.zip gcc-cd34c8436057524c36b1999828643da0bd41601b.tar.gz gcc-cd34c8436057524c36b1999828643da0bd41601b.tar.bz2 |
Avoid infinite loop in field_reference.
From-SVN: r170457
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/go/gofrontend/types.cc | 32 | ||||
-rw-r--r-- | 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 1e39731..806226f 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 b428077..b0dbefe 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(); |