diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-23 00:18:50 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-23 00:18:50 +0000 |
commit | 34d9bc34c507503dd71996b2d0a8a7824ba6ef68 (patch) | |
tree | fe5e3820b0bce6e2745e7122666f377f6bd771f3 /gcc | |
parent | 62d1a8f9040b90d1503a5495cf43b80027add792 (diff) | |
download | gcc-34d9bc34c507503dd71996b2d0a8a7824ba6ef68.zip gcc-34d9bc34c507503dd71996b2d0a8a7824ba6ef68.tar.gz gcc-34d9bc34c507503dd71996b2d0a8a7824ba6ef68.tar.bz2 |
Avoid infinite recursion checking whether field is exported.
From-SVN: r168191
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/go/gofrontend/types.cc | 39 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 3 |
2 files changed, 35 insertions, 7 deletions
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 9bdb926..1739965 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -7686,8 +7686,10 @@ Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr, else { std::string unpacked = Gogo::unpack_hidden_name(name); + seen.clear(); is_unexported = Type::is_unexported_field_or_method(gogo, type, - unpacked); + unpacked, + &seen); } if (is_unexported) error_at(location, "reference to unexported field or method %qs", @@ -7905,13 +7907,28 @@ Type::find_field_or_method(const Type* type, bool Type::is_unexported_field_or_method(Gogo* gogo, const Type* type, - const std::string& name) + const std::string& name, + std::vector<const Named_type*>* seen) { type = type->deref(); const Named_type* nt = type->named_type(); - if (nt != NULL && nt->is_unexported_local_method(gogo, name)) - return true; + if (nt != NULL) + { + if (nt->is_unexported_local_method(gogo, name)) + return true; + + for (std::vector<const Named_type*>::const_iterator p = seen->begin(); + p != seen->end(); + ++p) + { + if (*p == nt) + { + // We've already seen this type. + return false; + } + } + } const Interface_type* it = type->interface_type(); if (it != NULL && it->is_unexported_method(gogo, name)) @@ -7928,6 +7945,9 @@ Type::is_unexported_field_or_method(Gogo* gogo, const Type* type, if (fields == NULL) return false; + if (nt != NULL) + seen->push_back(nt); + for (Struct_field_list::const_iterator pf = fields->begin(); pf != fields->end(); ++pf) @@ -7938,11 +7958,18 @@ Type::is_unexported_field_or_method(Gogo* gogo, const Type* type, { Named_type* subtype = pf->type()->deref()->named_type(); gcc_assert(subtype != NULL); - if (Type::is_unexported_field_or_method(gogo, subtype, name)) - return true; + if (Type::is_unexported_field_or_method(gogo, subtype, name, seen)) + { + if (nt != NULL) + seen->pop_back(); + return true; + } } } + if (nt != NULL) + seen->pop_back(); + return false; } diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 45297e1..fea864a 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -791,7 +791,8 @@ class Type // Return true if NAME is an unexported field or method of TYPE. static bool - is_unexported_field_or_method(Gogo*, const Type*, const std::string&); + is_unexported_field_or_method(Gogo*, const Type*, const std::string&, + std::vector<const Named_type*>*); // This type was passed to the builtin function make. ARGS are the // arguments passed to make after the type; this may be NULL if |