aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2010-12-23 00:18:50 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2010-12-23 00:18:50 +0000
commit34d9bc34c507503dd71996b2d0a8a7824ba6ef68 (patch)
treefe5e3820b0bce6e2745e7122666f377f6bd771f3
parent62d1a8f9040b90d1503a5495cf43b80027add792 (diff)
downloadgcc-34d9bc34c507503dd71996b2d0a8a7824ba6ef68.zip
gcc-34d9bc34c507503dd71996b2d0a8a7824ba6ef68.tar.gz
gcc-34d9bc34c507503dd71996b2d0a8a7824ba6ef68.tar.bz2
Avoid infinite recursion checking whether field is exported.
From-SVN: r168191
-rw-r--r--gcc/go/gofrontend/types.cc39
-rw-r--r--gcc/go/gofrontend/types.h3
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