aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2010-12-14 20:54:45 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2010-12-14 20:54:45 +0000
commitfd948ffb14a27a28cbe28d4beba267c9b5d3aeb0 (patch)
tree97ee748d325c348db58dddf215bc69c75278e28c
parentd4645ada25ab17809d3b2907b60af3040266f614 (diff)
downloadgcc-fd948ffb14a27a28cbe28d4beba267c9b5d3aeb0.zip
gcc-fd948ffb14a27a28cbe28d4beba267c9b5d3aeb0.tar.gz
gcc-fd948ffb14a27a28cbe28d4beba267c9b5d3aeb0.tar.bz2
Check for duplicate methods.
Don't get into an endless loop given invalid recursive types. From-SVN: r167816
-rw-r--r--gcc/go/gofrontend/types.cc72
-rw-r--r--gcc/go/gofrontend/types.h11
2 files changed, 71 insertions, 12 deletions
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 98c4a97..3695903 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -53,9 +53,9 @@ Type::base()
switch (this->classification_)
{
case TYPE_NAMED:
- return static_cast<Named_type*>(this)->real_type()->base();
+ return this->named_type()->named_base();
case TYPE_FORWARD:
- return static_cast<Forward_declaration_type*>(this)->real_type()->base();
+ return this->forward_declaration_type()->real_type()->base();
default:
return this;
}
@@ -67,13 +67,9 @@ Type::base() const
switch (this->classification_)
{
case TYPE_NAMED:
- return static_cast<const Named_type*>(this)->real_type()->base();
+ return this->named_type()->named_base();
case TYPE_FORWARD:
- {
- const Forward_declaration_type* ftype =
- static_cast<const Forward_declaration_type*>(this);
- return ftype->real_type()->base();
- }
+ return this->forward_declaration_type()->real_type()->base();
default:
return this;
}
@@ -224,7 +220,7 @@ Type::is_error_type() const
case TYPE_ERROR:
return true;
case TYPE_NAMED:
- return t->named_type()->real_type()->is_error_type();
+ return t->named_type()->is_named_error_type();
default:
return false;
}
@@ -5502,10 +5498,23 @@ Interface_type::finalize_methods()
const Typed_identifier* p = &this->methods_->at(from);
if (!p->name().empty())
{
- if (from != to)
- this->methods_->set(to, *p);
+ size_t i = 0;
+ for (i = 0; i < to; ++i)
+ {
+ if (this->methods_->at(i).name() == p->name())
+ {
+ error_at(p->location(), "duplicate method %qs",
+ Gogo::message_name(p->name()).c_str());
+ break;
+ }
+ }
+ if (i == to)
+ {
+ if (from != to)
+ this->methods_->set(to, *p);
+ ++to;
+ }
++from;
- ++to;
continue;
}
Interface_type* it = p->type()->interface_type();
@@ -6448,6 +6457,45 @@ Named_type::message_name() const
return this->named_object_->message_name();
}
+// Return the base type for this type. We have to be careful about
+// circular type definitions, which are invalid but may be seen here.
+
+Type*
+Named_type::named_base()
+{
+ if (this->seen_)
+ return this;
+ this->seen_ = true;
+ Type* ret = this->type_->base();
+ this->seen_ = false;
+ return ret;
+}
+
+const Type*
+Named_type::named_base() const
+{
+ if (this->seen_)
+ return this;
+ this->seen_ = true;
+ const Type* ret = this->type_->base();
+ this->seen_ = false;
+ return ret;
+}
+
+// Return whether this is an error type. We have to be careful about
+// circular type definitions, which are invalid but may be seen here.
+
+bool
+Named_type::is_named_error_type() const
+{
+ if (this->seen_)
+ return false;
+ this->seen_ = true;
+ bool ret = this->type_->is_error_type();
+ this->seen_ = false;
+ return ret;
+}
+
// Add a method to this type.
Named_object*
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 025f85f..3f1b8ba 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -2457,6 +2457,17 @@ class Named_type : public Type
is_builtin() const
{ return this->location_ == BUILTINS_LOCATION; }
+ // Return the base type for this type.
+ Type*
+ named_base();
+
+ const Type*
+ named_base() const;
+
+ // Return whether this is an error type.
+ bool
+ is_named_error_type() const;
+
// Add a method to this type.
Named_object*
add_method(const std::string& name, Function*);