This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gccgo] Several small fixups


I committed this patch to the gccgo branch to fix several small
issues.

* Avoid a crash when converting a constant string to an interface.
  The code was taking the address of a CONST_DECL.

* Correctly report an attempt to refer to an unexported name.  Don't
  get confused if the name is local.

* Fix package names in type descriptors.

* Adjust the interface and function type reflection strings to match
  the ones generated by 6g.  This is just a spacing adjustment, and
  avoiding parentheses if there is only one result type.

* Permit converting an unnamed struct with methods to an interface
  which requires those methods.

Ian

diff -r bd0100e4882a go/expressions.cc
--- a/go/expressions.cc	Sat Feb 13 00:35:21 2010 -0800
+++ b/go/expressions.cc	Fri Feb 19 20:53:49 2010 -0800
@@ -297,7 +297,8 @@
 	      // going to copy the value into the interface.
 	      tree make_tmp;
 	      tree object;
-	      if (TREE_ADDRESSABLE(TREE_TYPE(rhs_tree)) || DECL_P(rhs_tree))
+	      if (TREE_ADDRESSABLE(TREE_TYPE(rhs_tree))
+		  || (DECL_P(rhs_tree) && TREE_CODE(rhs_tree) != CONST_DECL))
 		{
 		  make_tmp = NULL_TREE;
 		  object = build_fold_addr_expr(rhs_tree);
@@ -8298,7 +8299,7 @@
   Expression* left = this->left_;
   if (left->is_type_expression())
     return this->lower_method_expression(gogo);
-  return Type::bind_field_or_method(left->type(), left, this->name_,
+  return Type::bind_field_or_method(gogo, left->type(), left, this->name_,
 				    this->location());
 }
 
@@ -8393,7 +8394,7 @@
   Named_object* vno = gogo->lookup(receiver_name, NULL);
   gcc_assert(vno != NULL);
   Expression* ve = Expression::make_var_reference(vno, location);
-  Expression* bm = Type::bind_field_or_method(nt, ve, name, location);
+  Expression* bm = Type::bind_field_or_method(gogo, nt, ve, name, location);
   gcc_assert(bm != NULL && !bm->is_error_expression());
 
   Expression_list* args;
diff -r bd0100e4882a go/gogo.h
--- a/go/gogo.h	Sat Feb 13 00:35:21 2010 -0800
+++ b/go/gogo.h	Fri Feb 19 20:53:49 2010 -0800
@@ -144,7 +144,7 @@
   hidden_name_prefix(const std::string& name)
   {
     gcc_assert(Gogo::is_hidden_name(name));
-    return name.substr(1, name.rfind('.', 1) - 1);
+    return name.substr(1, name.rfind('.') - 1);
   }
 
   // Return whether a name is the blank identifier _.
diff -r bd0100e4882a go/types.cc
--- a/go/types.cc	Sat Feb 13 00:35:21 2010 -0800
+++ b/go/types.cc	Fri Feb 19 20:53:49 2010 -0800
@@ -1868,9 +1868,12 @@
   ret->push_back(')');
 
   const Typed_identifier_list* results = this->results();
-  if (results != NULL)
-    {
-      ret->append(" (");
+  if (results != NULL && !results->empty())
+    {
+      if (results->size() == 1)
+	ret->push_back(' ');
+      else
+	ret->append(" (");
       for (Typed_identifier_list::const_iterator p = results->begin();
 	   p != results->end();
 	   ++p)
@@ -1879,7 +1882,8 @@
 	    ret->append(", ");
 	  this->append_reflection(p->type(), gogo, ret);
 	}
-      ret->push_back(')');
+      if (results->size() > 1)
+	ret->push_back(')');
     }
 }
 
@@ -2706,7 +2710,8 @@
 // Return whether NAME is an unexported field, for better error reporting.
 
 bool
-Struct_type::is_unexported_local_field(const std::string& name) const
+Struct_type::is_unexported_local_field(Gogo* gogo,
+				       const std::string& name) const
 {
   const Struct_field_list* fields = this->fields_;
   if (fields != NULL)
@@ -2717,7 +2722,8 @@
 	{
 	  const std::string& field_name(pf->field_name());
 	  if (Gogo::is_hidden_name(field_name)
-	      && name == Gogo::unpack_hidden_name(field_name))
+	      && name == Gogo::unpack_hidden_name(field_name)
+	      && gogo->pack_hidden_name(name, false) != field_name)
 	    return true;
 	}
     }
@@ -2737,9 +2743,9 @@
 // ambiguous.
 
 Method*
-Struct_type::method_function(const std::string& name) const
-{
-  return Type::method_function(this->all_methods_, name, NULL);
+Struct_type::method_function(const std::string& name, bool* is_ambiguous) const
+{
+  return Type::method_function(this->all_methods_, name, is_ambiguous);
 }
 
 // Get the tree for a struct type.
@@ -4188,7 +4194,7 @@
 // reporting.
 
 bool
-Interface_type::is_unexported_method(const std::string& name) const
+Interface_type::is_unexported_method(Gogo* gogo, const std::string& name) const
 {
   if (this->methods_ == NULL)
     return false;
@@ -4198,7 +4204,8 @@
     {
       const std::string& method_name(p->name());
       if (Gogo::is_hidden_name(method_name)
-	  && name == Gogo::unpack_hidden_name(method_name))
+	  && name == Gogo::unpack_hidden_name(method_name)
+	  && gogo->pack_hidden_name(name, false) != method_name)
 	return true;
     }
   return false;
@@ -4323,6 +4330,7 @@
 
   bool is_pointer = false;
   const Named_type* nt = t->named_type();
+  const Struct_type* st = t->struct_type();
   // If we start with a named type, we don't dereference it to find
   // methods.
   if (nt == NULL)
@@ -4334,18 +4342,24 @@
 	  // the type to which it points.
 	  is_pointer = true;
 	  nt = pt->named_type();
-	}
-    }
-
-  // Only named types have methods.
-  if (nt == NULL)
+	  st = pt->struct_type();
+	}
+    }
+
+  // If we have a named type, get the methods from it rather than from
+  // any struct type.
+  if (nt != NULL)
+    st = NULL;
+
+  // Only named and struct types have methods.
+  if (nt == NULL && st == NULL)
     {
       if (reason != NULL)
 	reason->assign(_("type has no methods"));
       return false;
     }
 
-  if (!nt->has_any_methods())
+  if (nt != NULL ? !nt->has_any_methods() : !st->has_any_methods())
     {
       if (reason != NULL)
 	reason->assign(_("type has no methods"));
@@ -4357,7 +4371,9 @@
        ++p)
     {
       bool is_ambiguous = false;
-      Method* m = nt->method_function(p->name(), &is_ambiguous);
+      Method* m = (nt != NULL
+		   ? nt->method_function(p->name(), &is_ambiguous)
+		   : st->method_function(p->name(), &is_ambiguous));
       if (m == NULL)
 	{
 	  if (reason != NULL)
@@ -4543,7 +4559,6 @@
 	    ret->append(";");
 	  ret->push_back(' ');
 	  ret->append(Gogo::unpack_hidden_name(p->name()));
-	  ret->push_back(' ');
 	  std::string sub = p->type()->reflection(gogo);
 	  gcc_assert(sub.compare(0, 4, "func") == 0);
 	  sub = sub.substr(4);
@@ -4967,7 +4982,8 @@
 // error reporting.
 
 bool
-Named_type::is_unexported_local_method(const std::string& name) const
+Named_type::is_unexported_local_method(Gogo* gogo,
+				       const std::string& name) const
 {
   Bindings* methods = this->local_methods_;
   if (methods != NULL)
@@ -4978,7 +4994,8 @@
 	   ++p)
 	{
 	  if (Gogo::is_hidden_name(p->first)
-	      && name == Gogo::unpack_hidden_name(p->first))
+	      && name == Gogo::unpack_hidden_name(p->first)
+	      && gogo->pack_hidden_name(name, false) != p->first)
 	    return true;
 	}
     }
@@ -5882,7 +5899,7 @@
 // method, give an appropriate error and return an error expression.
 
 Expression*
-Type::bind_field_or_method(const Type* type, Expression* expr,
+Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr,
 			   const std::string& name,
 			   source_location location)
 {
@@ -5920,7 +5937,7 @@
 	  if (nt != NULL)
 	    m = nt->method_function(name, NULL);
 	  else if (st != NULL)
-	    m = st->method_function(name);
+	    m = st->method_function(name, NULL);
 	  else
 	    gcc_unreachable();
 	  gcc_assert(m != NULL);
@@ -5951,7 +5968,8 @@
 	  if (!Gogo::is_hidden_name(name))
 	    is_unexported = false;
 	  else
-	    is_unexported = Type::is_unexported_field_or_method(type, name);
+	    is_unexported = Type::is_unexported_field_or_method(gogo, type,
+								unpacked);
 	  if (is_unexported)
 	    error_at(location, "reference to unexported field or method %qs",
 		     unpacked.c_str());
@@ -6139,20 +6157,21 @@
 // Return whether NAME is an unexported field or method for TYPE.
 
 bool
-Type::is_unexported_field_or_method(const Type* type, const std::string& name)
+Type::is_unexported_field_or_method(Gogo* gogo, const Type* type,
+				    const std::string& name)
 {
   type = type->deref();
 
   const Named_type* nt = type->named_type();
-  if (nt != NULL && nt->is_unexported_local_method(name))
+  if (nt != NULL && nt->is_unexported_local_method(gogo, name))
     return true;
 
   const Interface_type* it = type->interface_type();
-  if (it != NULL && it->is_unexported_method(name))
+  if (it != NULL && it->is_unexported_method(gogo, name))
     return true;
 
   const Struct_type* st = type->struct_type();
-  if (st != NULL && st->is_unexported_local_field(name))
+  if (st != NULL && st->is_unexported_local_field(gogo, name))
     return true;
 
   if (st == NULL)
@@ -6170,7 +6189,7 @@
 	{
 	  Named_type* subtype = pf->type()->deref()->named_type();
 	  gcc_assert(subtype != NULL);
-	  if (Type::is_unexported_field_or_method(subtype, name))
+	  if (Type::is_unexported_field_or_method(gogo, subtype, name))
 	    return true;
 	}
     }
diff -r bd0100e4882a go/types.h
--- a/go/types.h	Sat Feb 13 00:35:21 2010 -0800
+++ b/go/types.h	Fri Feb 19 20:53:49 2010 -0800
@@ -762,12 +762,12 @@
   // Look for field or method NAME for TYPE.  Return an expression for
   // it, bound to EXPR.
   static Expression*
-  bind_field_or_method(const Type* type, Expression* expr,
+  bind_field_or_method(Gogo*, const Type* type, Expression* expr,
 		       const std::string& name, source_location);
 
   // Return true if NAME is an unexported field or method of TYPE.
   static bool
-  is_unexported_field_or_method(const Type*, const std::string&);
+  is_unexported_field_or_method(Gogo*, const Type*, const std::string&);
 
   // This type was passed to the builtin function make.  ARGS are the
   // arguments passed to make after the type; this may be NULL if
@@ -1770,7 +1770,7 @@
   // Return whether NAME is a local field which is not exported.  This
   // is only used for better error reporting.
   bool
-  is_unexported_local_field(const std::string& name) const;
+  is_unexported_local_field(Gogo*, const std::string& name) const;
 
   // If this is an unnamed struct, build the complete list of methods,
   // including those from anonymous fields, and build methods stubs if
@@ -1791,9 +1791,10 @@
   { return this->all_methods_; }
 
   // Return the method to use for NAME.  This returns NULL if there is
-  // no such method or if the method is ambiguous.
+  // no such method or if the method is ambiguous.  When it returns
+  // NULL, this sets *IS_AMBIGUOUS if the method name is ambiguous.
   Method*
-  method_function(const std::string& name) const;
+  method_function(const std::string& name, bool* is_ambiguous) const;
 
   // Traverse just the field types of a struct type.
   int
@@ -2172,7 +2173,7 @@
   // Return whether NAME is a method which is not exported.  This is
   // only used for better error reporting.
   bool
-  is_unexported_method(const std::string& name) const;
+  is_unexported_method(Gogo*, const std::string& name) const;
 
   // Import an interface type.
   static Interface_type*
@@ -2351,7 +2352,7 @@
   // Return whether NAME is a known field or method which is not
   // exported.  This is only used for better error reporting.
   bool
-  is_unexported_local_method(const std::string& name) const;
+  is_unexported_local_method(Gogo*, const std::string& name) const;
 
   // Return a pointer to the interface method table for this type for
   // the interface INTERFACE.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]