From: Ian Lance Taylor Date: Thu, 23 Dec 2010 00:18:50 +0000 (+0000) Subject: Avoid infinite recursion checking whether field is exported. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=34d9bc34c507503dd71996b2d0a8a7824ba6ef68;p=gcc.git Avoid infinite recursion checking whether field is exported. From-SVN: r168191 --- diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 9bdb92612b1..17399659e4c 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* 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_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 45297e1822f..fea864a2e3b 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*); // This type was passed to the builtin function make. ARGS are the // arguments passed to make after the type; this may be NULL if