Patchwork Go patch committed: Permit converting to string to named []B

login
register
mail settings
Submitter Ian Taylor
Date Jan. 11, 2012, 11:43 p.m.
Message ID <mcraa5tx0sr.fsf@dhcp-172-18-216-180.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/135534/
State New
Headers show

Comments

Ian Taylor - Jan. 11, 2012, 11:43 p.m.
The Go language was tweaked to permit converting a string to a slice of
the byte or rune type even if the type is given a different name.  This
patch implements this tweak in the gccgo frontend.  Bootstrapped and ran
Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

Patch

diff -r 4a6f27be6981 go/expressions.cc
--- a/go/expressions.cc	Wed Jan 11 13:19:28 2012 -0800
+++ b/go/expressions.cc	Wed Jan 11 15:33:40 2012 -0800
@@ -3382,9 +3382,11 @@ 
   if (type->is_slice_type())
     {
       Type* element_type = type->array_type()->element_type()->forwarded();
-      bool is_byte = element_type == Type::lookup_integer_type("uint8");
-      bool is_int = element_type == Type::lookup_integer_type("int");
-      if (is_byte || is_int)
+      bool is_byte = (element_type->integer_type() != NULL
+		      && element_type->integer_type()->is_byte());
+      bool is_rune = (element_type->integer_type() != NULL
+		      && element_type->integer_type()->is_rune());
+      if (is_byte || is_rune)
 	{
 	  std::string s;
 	  if (val->string_constant_value(&s))
@@ -3690,8 +3692,7 @@ 
       tree len = a->length_tree(gogo, expr_tree);
       len = fold_convert_loc(this->location().gcc_location(), integer_type_node,
                              len);
-      if (e->integer_type()->is_unsigned()
-	  && e->integer_type()->bits() == 8)
+      if (e->integer_type()->is_byte())
 	{
 	  static tree byte_array_to_string_fndecl;
 	  ret = Gogo::call_builtin(&byte_array_to_string_fndecl,
@@ -3706,7 +3707,7 @@ 
 	}
       else
 	{
-	  go_assert(e == Type::lookup_integer_type("int"));
+	  go_assert(e->integer_type()->is_rune());
 	  static tree int_array_to_string_fndecl;
 	  ret = Gogo::call_builtin(&int_array_to_string_fndecl,
 				   this->location(),
@@ -3723,8 +3724,7 @@ 
     {
       Type* e = type->array_type()->element_type()->forwarded();
       go_assert(e->integer_type() != NULL);
-      if (e->integer_type()->is_unsigned()
-	  && e->integer_type()->bits() == 8)
+      if (e->integer_type()->is_byte())
 	{
 	  tree string_to_byte_array_fndecl = NULL_TREE;
 	  ret = Gogo::call_builtin(&string_to_byte_array_fndecl,
@@ -3737,7 +3737,7 @@ 
 	}
       else
 	{
-	  go_assert(e == Type::lookup_integer_type("int"));
+	  go_assert(e->integer_type()->is_rune());
 	  tree string_to_int_array_fndecl = NULL_TREE;
 	  ret = Gogo::call_builtin(&string_to_int_array_fndecl,
 				   this->location(),
@@ -8506,19 +8506,19 @@ 
 	    break;
 	  }
 
-	Type* e2;
 	if (arg2_type->is_slice_type())
-	  e2 = arg2_type->array_type()->element_type();
+	  {
+	    Type* e2 = arg2_type->array_type()->element_type();
+	    if (!Type::are_identical(e1, e2, true, NULL))
+	      this->report_error(_("element types must be the same"));
+	  }
 	else if (arg2_type->is_string_type())
-	  e2 = Type::lookup_integer_type("uint8");
+	  {
+	    if (e1->integer_type() == NULL || !e1->integer_type()->is_byte())
+	      this->report_error(_("first argument must be []byte"));
+	  }
 	else
-	  {
-	    this->report_error(_("right argument must be a slice or a string"));
-	    break;
-	  }
-
-	if (!Type::are_identical(e1, e2, true, NULL))
-	  this->report_error(_("element types must be the same"));
+	    this->report_error(_("second argument must be slice or string"));
       }
       break;
 
@@ -8542,7 +8542,7 @@ 
 	  {
 	    const Array_type* at = args->front()->type()->array_type();
 	    const Type* e = at->element_type()->forwarded();
-	    if (e == Type::lookup_integer_type("uint8"))
+	    if (e->integer_type() != NULL && e->integer_type()->is_byte())
 	      break;
 	  }
 
@@ -9100,7 +9100,8 @@ 
 	tree arg2_len;
 	tree element_size;
 	if (arg2->type()->is_string_type()
-	    && element_type == Type::lookup_integer_type("uint8"))
+	    && element_type->integer_type() != NULL
+	    && element_type->integer_type()->is_byte())
 	  {
 	    arg2_tree = save_expr(arg2_tree);
 	    arg2_val = String_type::bytes_tree(gogo, arg2_tree);
diff -r 4a6f27be6981 go/gogo.cc
--- a/go/gogo.cc	Wed Jan 11 13:19:28 2012 -0800
+++ b/go/gogo.cc	Wed Jan 11 15:33:40 2012 -0800
@@ -88,10 +88,12 @@ 
   // to the same Named_object.
   Named_object* byte_type = this->declare_type("byte", loc);
   byte_type->set_type_value(uint8_type);
+  uint8_type->integer_type()->set_is_byte();
 
   // "rune" is an alias for "int".
   Named_object* rune_type = this->declare_type("rune", loc);
   rune_type->set_type_value(int_type);
+  int_type->integer_type()->set_is_rune();
 
   this->add_named_type(Type::make_integer_type("uintptr", true,
 					       pointer_size,
diff -r 4a6f27be6981 go/types.cc
--- a/go/types.cc	Wed Jan 11 13:19:28 2012 -0800
+++ b/go/types.cc	Wed Jan 11 15:33:40 2012 -0800
@@ -767,7 +767,7 @@ 
   if (lhs->complex_type() != NULL && rhs->complex_type() != NULL)
     return true;
 
-  // An integer, or []byte, or []int, may be converted to a string.
+  // An integer, or []byte, or []rune, may be converted to a string.
   if (lhs->is_string_type())
     {
       if (rhs->integer_type() != NULL)
@@ -776,19 +776,18 @@ 
 	{
 	  const Type* e = rhs->array_type()->element_type()->forwarded();
 	  if (e->integer_type() != NULL
-	      && (e == Type::lookup_integer_type("uint8")
-		  || e == Type::lookup_integer_type("int")))
+	      && (e->integer_type()->is_byte()
+		  || e->integer_type()->is_rune()))
 	    return true;
 	}
     }
 
-  // A string may be converted to []byte or []int.
+  // A string may be converted to []byte or []rune.
   if (rhs->is_string_type() && lhs->is_slice_type())
     {
       const Type* e = lhs->array_type()->element_type()->forwarded();
       if (e->integer_type() != NULL
-	  && (e == Type::lookup_integer_type("uint8")
-	      || e == Type::lookup_integer_type("int")))
+	  && (e->integer_type()->is_byte() || e->integer_type()->is_rune()))
 	return true;
     }
 
diff -r 4a6f27be6981 go/types.h
--- a/go/types.h	Wed Jan 11 13:19:28 2012 -0800
+++ b/go/types.h	Wed Jan 11 15:33:40 2012 -0800
@@ -1386,7 +1386,27 @@ 
   bool
   is_identical(const Integer_type* t) const;
 
- protected:
+  // Whether this is the type "byte" or another name for "byte".
+  bool
+  is_byte() const
+  { return this->is_byte_; }
+
+  // Mark this as the "byte" type.
+  void
+  set_is_byte()
+  { this->is_byte_ = true; }
+
+  // Whether this is the type "rune" or another name for "rune".
+  bool
+  is_rune() const
+  { return this->is_rune_; }
+
+  // Mark this as the "rune" type.
+  void
+  set_is_rune()
+  { this->is_rune_ = true; }
+
+protected:
   bool
   do_compare_is_identity(Gogo*) const
   { return true; }
@@ -1410,8 +1430,8 @@ 
   Integer_type(bool is_abstract, bool is_unsigned, int bits,
 	       int runtime_type_kind)
     : Type(TYPE_INTEGER),
-      is_abstract_(is_abstract), is_unsigned_(is_unsigned), bits_(bits),
-      runtime_type_kind_(runtime_type_kind)
+      is_abstract_(is_abstract), is_unsigned_(is_unsigned), is_byte_(false),
+      is_rune_(false), bits_(bits), runtime_type_kind_(runtime_type_kind)
   { }
 
   // Map names of integer types to the types themselves.
@@ -1422,6 +1442,10 @@ 
   bool is_abstract_;
   // True if this is an unsigned type.
   bool is_unsigned_;
+  // True if this is the byte type.
+  bool is_byte_;
+  // True if this is the rune type.
+  bool is_rune_;
   // The number of bits.
   int bits_;
   // The runtime type code used in the type descriptor for this type.