diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-22 16:05:23 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2010-12-22 16:05:23 +0000 |
commit | 1d9fa70c34069d3b341e07ada11dde6cd029207b (patch) | |
tree | a16ffe268e870891a4bab8b6bae94345b9be5b03 /gcc | |
parent | f39c772f2ee579fc42707bffd0480c01f8bc2bd7 (diff) | |
download | gcc-1d9fa70c34069d3b341e07ada11dde6cd029207b.zip gcc-1d9fa70c34069d3b341e07ada11dde6cd029207b.tar.gz gcc-1d9fa70c34069d3b341e07ada11dde6cd029207b.tar.bz2 |
More tweaking of recursive name types when converting to GENERIC.
From-SVN: r168172
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/go/gofrontend/types.cc | 59 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 4 |
2 files changed, 37 insertions, 26 deletions
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 8d4730e..c0914ca 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -6511,22 +6511,22 @@ Named_type::message_name() const Type* Named_type::named_base() { - if (this->seen_) + if (this->seen_ > 0) return this; - this->seen_ = true; + ++this->seen_; Type* ret = this->type_->base(); - this->seen_ = false; + --this->seen_; return ret; } const Type* Named_type::named_base() const { - if (this->seen_) + if (this->seen_ > 0) return this; - this->seen_ = true; + ++this->seen_; const Type* ret = this->type_->base(); - this->seen_ = false; + --this->seen_; return ret; } @@ -6536,11 +6536,11 @@ Named_type::named_base() const bool Named_type::is_named_error_type() const { - if (this->seen_) + if (this->seen_ > 0) return false; - this->seen_ = true; + ++this->seen_; bool ret = this->type_->is_error_type(); - this->seen_ = false; + --this->seen_; return ret; } @@ -6690,11 +6690,11 @@ Named_type::interface_method_table(Gogo* gogo, const Interface_type* interface, bool Named_type::named_type_has_hidden_fields(std::string* reason) const { - if (this->seen_) + if (this->seen_ > 0) return false; - this->seen_ = true; + ++this->seen_; bool ret = this->type_->has_hidden_fields(this, reason); - this->seen_ = false; + --this->seen_; return ret; } @@ -6896,18 +6896,24 @@ Named_type::do_get_tree(Gogo* gogo) case TYPE_FUNCTION: // GENERIC can't handle a pointer to a function type whose // return type is a pointer to the function type itself. It - // does into infinite loops when walking the types. - if (this->seen_) + // goes into an infinite loop when walking the types. + if (this->seen_ > 0) { Function_type* fntype = this->type_->function_type(); if (fntype->results() != NULL && fntype->results()->size() == 1 && fntype->results()->front().type()->forwarded() == this) return ptr_type_node; + + // We can legitimately see ourselves here twice when a named + // type is defined using a struct which refers to the named + // type. If we see ourselves too often we are in a loop. + if (this->seen_ > 3) + return ptr_type_node; } - this->seen_ = true; + ++this->seen_; t = Type::get_named_type_tree(gogo, this->type_); - this->seen_ = false; + --this->seen_; if (t == error_mark_node) return error_mark_node; t = build_variant_type_copy(t); @@ -6917,11 +6923,17 @@ Named_type::do_get_tree(Gogo* gogo) // Don't recur infinitely if a pointer type refers to itself. // Ideally we would build a circular data structure here, but // GENERIC can't handle them. - if (this->seen_) - return ptr_type_node; - this->seen_ = true; + if (this->seen_ > 0) + { + if (this->type_->points_to()->forwarded() == this) + return ptr_type_node; + + if (this->seen_ > 3) + return ptr_type_node; + } + ++this->seen_; t = Type::get_named_type_tree(gogo, this->type_); - this->seen_ = false; + --this->seen_; if (t == error_mark_node) return error_mark_node; t = build_variant_type_copy(t); @@ -6980,11 +6992,10 @@ Named_type::do_get_tree(Gogo* gogo) // definition of T2 may refer to T1, then we must simply // return the type for T2 here. It's not precisely correct, // but it's as close as we can get with GENERIC. - bool was_seen = this->seen_; - this->seen_ = true; + ++this->seen_; t = Type::get_named_type_tree(gogo, this->type_); - this->seen_ = was_seen; - if (was_seen) + --this->seen_; + if (this->seen_ > 0) return t; if (t == error_mark_node) return error_mark_node; diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 2a713b0..dbcf0ff 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -2387,7 +2387,7 @@ class Named_type : public Type local_methods_(NULL), all_methods_(NULL), interface_method_tables_(NULL), pointer_interface_method_tables_(NULL), location_(location), named_tree_(NULL), is_visible_(true), - is_error_(false), seen_(false) + is_error_(false), seen_(0) { } // Return the associated Named_object. This holds the actual name. @@ -2626,7 +2626,7 @@ class Named_type : public Type // used to prevent infinite recursion when a type refers to itself. // This is mutable because it is always reset to false when the // function exits. - mutable bool seen_; + mutable int seen_; }; // A forward declaration. This handles a type which has been declared |