Patchwork Go patch committed: Fix unknown name in map composite literal

login
register
mail settings
Submitter Ian Taylor
Date Dec. 14, 2010, 8:53 p.m.
Message ID <mcripyw849u.fsf@google.com>
Download mbox | patch
Permalink /patch/75546/
State New
Headers show

Comments

Ian Taylor - Dec. 14, 2010, 8:53 p.m.
When an unknown name was used as the key in a map composite literal,
gccgo would crash.  This patch fixes the problem.  Bootstrapped and ran
Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

Patch

diff -r b5cc75949123 go/types.cc
--- a/go/types.cc	Tue Dec 14 11:34:18 2010 -0800
+++ b/go/types.cc	Tue Dec 14 12:47:02 2010 -0800
@@ -53,9 +53,9 @@ 
   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 @@ 
   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 @@ 
     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 @@ 
       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 @@ 
   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 -r b5cc75949123 go/types.h
--- a/go/types.h	Tue Dec 14 11:34:18 2010 -0800
+++ b/go/types.h	Tue Dec 14 12:47:02 2010 -0800
@@ -2457,6 +2457,17 @@ 
   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*);