OSDN Git Service

Check for duplicate methods.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 Dec 2010 20:54:45 +0000 (20:54 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 Dec 2010 20:54:45 +0000 (20:54 +0000)
Don't get into an endless loop given invalid recursive types.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@167816 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index 98c4a97..3695903 100644 (file)
@@ -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*
index 025f85f..3f1b8ba 100644 (file)
@@ -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*);