OSDN Git Service

compiler: Change alias handling, change rune alias to int32.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 21 Jan 2012 21:26:10 +0000 (21:26 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 21 Jan 2012 21:26:10 +0000 (21:26 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@183374 138bc75d-0d04-0410-961f-82ee72b054a4

19 files changed:
gcc/go/gofrontend/export.cc
gcc/go/gofrontend/export.h
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/import.cc
gcc/go/gofrontend/lex.cc
gcc/go/gofrontend/lex.h
gcc/go/gofrontend/parse.cc
gcc/go/gofrontend/runtime.cc
gcc/go/gofrontend/runtime.def
gcc/go/gofrontend/statements.cc
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h
gcc/testsuite/go.test/test/fixedbugs/bug204.go
gcc/testsuite/go.test/test/ken/string.go
gcc/testsuite/go.test/test/range.go
gcc/testsuite/go.test/test/solitaire.go
gcc/testsuite/go.test/test/string_lit.go

index 3fb7089..b6c0740 100644 (file)
@@ -338,6 +338,8 @@ Export::register_builtin_types(Gogo* gogo)
   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
+  this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
+  this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
 }
 
 // Register one builtin type in the export table.
 }
 
 // Register one builtin type in the export table.
@@ -352,10 +354,14 @@ Export::register_builtin_type(Gogo* gogo, const char* name, Builtin_code code)
   go_assert(ins.second);
 
   // We also insert the underlying type.  We can see the underlying
   go_assert(ins.second);
 
   // We also insert the underlying type.  We can see the underlying
-  // type at least for string and bool.
-  Type* real_type = named_object->type_value()->real_type();
-  ins = this->type_refs_.insert(std::make_pair(real_type, code));
-  go_assert(ins.second);
+  // type at least for string and bool.  We skip the type aliases byte
+  // and rune here.
+  if (code != BUILTIN_BYTE && code != BUILTIN_RUNE)
+    {
+      Type* real_type = named_object->type_value()->real_type();
+      ins = this->type_refs_.insert(std::make_pair(real_type, code));
+      go_assert(ins.second);
+    }
 }
 
 // Class Export::Stream.
 }
 
 // Class Export::Stream.
index a06b549..087f477 100644 (file)
@@ -40,8 +40,10 @@ enum Builtin_code
   BUILTIN_COMPLEX64 = -17,
   BUILTIN_COMPLEX128 = -18,
   BUILTIN_ERROR = -19,
   BUILTIN_COMPLEX64 = -17,
   BUILTIN_COMPLEX128 = -18,
   BUILTIN_ERROR = -19,
+  BUILTIN_BYTE = -20,
+  BUILTIN_RUNE = -21,
 
 
-  SMALLEST_BUILTIN_CODE = -19
+  SMALLEST_BUILTIN_CODE = -21
 };
 
 // This class manages exporting Go declarations.  It handles the main
 };
 
 // This class manages exporting Go declarations.  It handles the main
index 7550a56..fe361fb 100644 (file)
@@ -1740,9 +1740,10 @@ Expression::make_string(const std::string& val, Location location)
 class Integer_expression : public Expression
 {
  public:
 class Integer_expression : public Expression
 {
  public:
-  Integer_expression(const mpz_t* val, Type* type, Location location)
+  Integer_expression(const mpz_t* val, Type* type, bool is_character_constant,
+                    Location location)
     : Expression(EXPRESSION_INTEGER, location),
     : Expression(EXPRESSION_INTEGER, location),
-      type_(type)
+      type_(type), is_character_constant_(is_character_constant)
   { mpz_init_set(this->val_, *val); }
 
   static Expression*
   { mpz_init_set(this->val_, *val); }
 
   static Expression*
@@ -1782,8 +1783,14 @@ class Integer_expression : public Expression
 
   Expression*
   do_copy()
 
   Expression*
   do_copy()
-  { return Expression::make_integer(&this->val_, this->type_,
-                                   this->location()); }
+  {
+    if (this->is_character_constant_)
+      return Expression::make_character(&this->val_, this->type_,
+                                       this->location());
+    else
+      return Expression::make_integer(&this->val_, this->type_,
+                                     this->location());
+  }
 
   void
   do_export(Export*) const;
 
   void
   do_export(Export*) const;
@@ -1796,6 +1803,8 @@ class Integer_expression : public Expression
   mpz_t val_;
   // The type so far.
   Type* type_;
   mpz_t val_;
   // The type so far.
   Type* type_;
+  // Whether this is a character constant.
+  bool is_character_constant_;
 };
 
 // Return an integer constant value.
 };
 
 // Return an integer constant value.
@@ -1817,7 +1826,12 @@ Type*
 Integer_expression::do_type()
 {
   if (this->type_ == NULL)
 Integer_expression::do_type()
 {
   if (this->type_ == NULL)
-    this->type_ = Type::make_abstract_integer_type();
+    {
+      if (this->is_character_constant_)
+       this->type_ = Type::make_abstract_character_type();
+      else
+       this->type_ = Type::make_abstract_integer_type();
+    }
   return this->type_;
 }
 
   return this->type_;
 }
 
@@ -1835,7 +1849,12 @@ Integer_expression::do_determine_type(const Type_context* context)
               || context->type->complex_type() != NULL))
     this->type_ = context->type;
   else if (!context->may_be_abstract)
               || context->type->complex_type() != NULL))
     this->type_ = context->type;
   else if (!context->may_be_abstract)
-    this->type_ = Type::lookup_integer_type("int");
+    {
+      if (this->is_character_constant_)
+       this->type_ = Type::lookup_integer_type("int32");
+      else
+       this->type_ = Type::lookup_integer_type("int");
+    }
 }
 
 // Return true if the integer VAL fits in the range of the type TYPE.
 }
 
 // Return true if the integer VAL fits in the range of the type TYPE.
@@ -1950,6 +1969,8 @@ void
 Integer_expression::do_export(Export* exp) const
 {
   Integer_expression::export_integer(exp, this->val_);
 Integer_expression::do_export(Export* exp) const
 {
   Integer_expression::export_integer(exp, this->val_);
+  if (this->is_character_constant_)
+    exp->write_c_string("'");
   // A trailing space lets us reliably identify the end of the number.
   exp->write_c_string(" ");
 }
   // A trailing space lets us reliably identify the end of the number.
   exp->write_c_string(" ");
 }
@@ -2013,6 +2034,10 @@ Integer_expression::do_import(Import* imp)
   else if (num.find('.') == std::string::npos
           && num.find('E') == std::string::npos)
     {
   else if (num.find('.') == std::string::npos
           && num.find('E') == std::string::npos)
     {
+      bool is_character_constant = (!num.empty()
+                                   && num[num.length() - 1] == '\'');
+      if (is_character_constant)
+       num = num.substr(0, num.length() - 1);
       mpz_t val;
       if (mpz_init_set_str(val, num.c_str(), 10) != 0)
        {
       mpz_t val;
       if (mpz_init_set_str(val, num.c_str(), 10) != 0)
        {
@@ -2020,7 +2045,11 @@ Integer_expression::do_import(Import* imp)
                   num.c_str());
          return Expression::make_error(imp->location());
        }
                   num.c_str());
          return Expression::make_error(imp->location());
        }
-      Expression* ret = Expression::make_integer(&val, NULL, imp->location());
+      Expression* ret;
+      if (is_character_constant)
+       ret = Expression::make_character(&val, NULL, imp->location());
+      else
+       ret = Expression::make_integer(&val, NULL, imp->location());
       mpz_clear(val);
       return ret;
     }
       mpz_clear(val);
       return ret;
     }
@@ -2043,16 +2072,27 @@ Integer_expression::do_import(Import* imp)
 void
 Integer_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
 {
 void
 Integer_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
 {
+  if (this->is_character_constant_)
+    ast_dump_context->ostream() << '\'';
   Integer_expression::export_integer(ast_dump_context, this->val_);
   Integer_expression::export_integer(ast_dump_context, this->val_);
+  if (this->is_character_constant_)
+    ast_dump_context->ostream() << '\'';
 }
 
 // Build a new integer value.
 
 Expression*
 }
 
 // Build a new integer value.
 
 Expression*
-Expression::make_integer(const mpz_t* val, Type* type,
-                        Location location)
+Expression::make_integer(const mpz_t* val, Type* type, Location location)
+{
+  return new Integer_expression(val, type, false, location);
+}
+
+// Build a new character constant value.
+
+Expression*
+Expression::make_character(const mpz_t* val, Type* type, Location location)
 {
 {
-  return new Integer_expression(val, type, location);
+  return new Integer_expression(val, type, true, location);
 }
 
 // Floats.
 }
 
 // Floats.
index 668f8a1..efe54d1 100644 (file)
@@ -164,6 +164,11 @@ class Expression
   static Expression*
   make_string(const std::string&, Location);
 
   static Expression*
   make_string(const std::string&, Location);
 
+  // Make a character constant expression.  TYPE should be NULL for an
+  // abstract type.
+  static Expression*
+  make_character(const mpz_t*, Type*, Location);
+
   // Make a constant integer expression.  TYPE should be NULL for an
   // abstract type.
   static Expression*
   // Make a constant integer expression.  TYPE should be NULL for an
   // abstract type.
   static Expression*
index 9d9bef1..e995be4 100644 (file)
@@ -58,8 +58,9 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
                                               RUNTIME_TYPE_KIND_INT8));
   this->add_named_type(Type::make_integer_type("int16", false,  16,
                                               RUNTIME_TYPE_KIND_INT16));
                                               RUNTIME_TYPE_KIND_INT8));
   this->add_named_type(Type::make_integer_type("int16", false,  16,
                                               RUNTIME_TYPE_KIND_INT16));
-  this->add_named_type(Type::make_integer_type("int32", false,  32,
-                                              RUNTIME_TYPE_KIND_INT32));
+  Named_type* int32_type = Type::make_integer_type("int32", false,  32,
+                                                  RUNTIME_TYPE_KIND_INT32);
+  this->add_named_type(int32_type);
   this->add_named_type(Type::make_integer_type("int64", false,  64,
                                               RUNTIME_TYPE_KIND_INT64));
 
   this->add_named_type(Type::make_integer_type("int64", false,  64,
                                               RUNTIME_TYPE_KIND_INT64));
 
@@ -82,23 +83,22 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size,
                                                 RUNTIME_TYPE_KIND_INT);
   this->add_named_type(int_type);
 
                                                 RUNTIME_TYPE_KIND_INT);
   this->add_named_type(int_type);
 
-  // "byte" is an alias for "uint8".  Construct a Named_object which
-  // points to UINT8_TYPE.  Note that this breaks the normal pairing
-  // in which a Named_object points to a Named_type which points back
-  // 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,
                                               RUNTIME_TYPE_KIND_UINTPTR));
 
   this->add_named_type(Type::make_integer_type("uintptr", true,
                                               pointer_size,
                                               RUNTIME_TYPE_KIND_UINTPTR));
 
+  // "byte" is an alias for "uint8".
+  uint8_type->integer_type()->set_is_byte();
+  Named_object* byte_type = Named_object::make_type("byte", NULL, uint8_type,
+                                                   loc);
+  this->add_named_type(byte_type->type_value());
+
+  // "rune" is an alias for "int32".
+  int32_type->integer_type()->set_is_rune();
+  Named_object* rune_type = Named_object::make_type("rune", NULL, int32_type,
+                                                   loc);
+  this->add_named_type(rune_type->type_value());
+
   this->add_named_type(Type::make_named_bool_type());
 
   this->add_named_type(Type::make_named_string_type());
   this->add_named_type(Type::make_named_bool_type());
 
   this->add_named_type(Type::make_named_string_type());
@@ -3830,7 +3830,12 @@ Variable::type_from_range(Expression* expr, bool get_index_type,
        return t->deref()->array_type()->element_type();
     }
   else if (t->is_string_type())
        return t->deref()->array_type()->element_type();
     }
   else if (t->is_string_type())
-    return Type::lookup_integer_type("int");
+    {
+      if (get_index_type)
+       return Type::lookup_integer_type("int");
+      else
+       return Type::lookup_integer_type("int32");
+    }
   else if (t->map_type() != NULL)
     {
       if (get_index_type)
   else if (t->map_type() != NULL)
     {
       if (get_index_type)
index fc9c150..de7edc9 100644 (file)
@@ -696,6 +696,8 @@ Import::register_builtin_types(Gogo* gogo)
   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
   this->register_builtin_type(gogo, "bool", BUILTIN_BOOL);
   this->register_builtin_type(gogo, "string", BUILTIN_STRING);
   this->register_builtin_type(gogo, "error", BUILTIN_ERROR);
+  this->register_builtin_type(gogo, "byte", BUILTIN_BYTE);
+  this->register_builtin_type(gogo, "rune", BUILTIN_RUNE);
 }
 
 // Register a single builtin type.
 }
 
 // Register a single builtin type.
index effa087..af23e9b 100644 (file)
@@ -163,7 +163,8 @@ Token::~Token()
 void
 Token::clear()
 {
 void
 Token::clear()
 {
-  if (this->classification_ == TOKEN_INTEGER)
+  if (this->classification_ == TOKEN_INTEGER
+      || this->classification_ == TOKEN_CHARACTER)
     mpz_clear(this->u_.integer_value);
   else if (this->classification_ == TOKEN_FLOAT
           || this->classification_ == TOKEN_IMAGINARY)
     mpz_clear(this->u_.integer_value);
   else if (this->classification_ == TOKEN_FLOAT
           || this->classification_ == TOKEN_IMAGINARY)
@@ -190,6 +191,7 @@ Token::Token(const Token& tok)
     case TOKEN_OPERATOR:
       this->u_.op = tok.u_.op;
       break;
     case TOKEN_OPERATOR:
       this->u_.op = tok.u_.op;
       break;
+    case TOKEN_CHARACTER:
     case TOKEN_INTEGER:
       mpz_init_set(this->u_.integer_value, tok.u_.integer_value);
       break;
     case TOKEN_INTEGER:
       mpz_init_set(this->u_.integer_value, tok.u_.integer_value);
       break;
@@ -229,6 +231,7 @@ Token::operator=(const Token& tok)
     case TOKEN_OPERATOR:
       this->u_.op = tok.u_.op;
       break;
     case TOKEN_OPERATOR:
       this->u_.op = tok.u_.op;
       break;
+    case TOKEN_CHARACTER:
     case TOKEN_INTEGER:
       mpz_init_set(this->u_.integer_value, tok.u_.integer_value);
       break;
     case TOKEN_INTEGER:
       mpz_init_set(this->u_.integer_value, tok.u_.integer_value);
       break;
@@ -264,6 +267,10 @@ Token::print(FILE* file) const
     case TOKEN_STRING:
       fprintf(file, "quoted string \"%s\"", this->u_.string_value->c_str());
       break;
     case TOKEN_STRING:
       fprintf(file, "quoted string \"%s\"", this->u_.string_value->c_str());
       break;
+    case TOKEN_CHARACTER:
+      fprintf(file, "character ");
+      mpz_out_str(file, 10, this->u_.integer_value);
+      break;
     case TOKEN_INTEGER:
       fprintf(file, "integer ");
       mpz_out_str(file, 10, this->u_.integer_value);
     case TOKEN_INTEGER:
       fprintf(file, "integer ");
       mpz_out_str(file, 10, this->u_.integer_value);
@@ -1320,7 +1327,7 @@ Lex::gather_character()
 
   Location location = this->location();
   this->lineoff_ = p + 1 - this->linebuf_;
 
   Location location = this->location();
   this->lineoff_ = p + 1 - this->linebuf_;
-  Token ret = Token::make_integer_token(val, location);
+  Token ret = Token::make_character_token(val, location);
   mpz_clear(val);
   return ret;
 }
   mpz_clear(val);
   return ret;
 }
index 6341e1e..b9b4b1f 100644 (file)
@@ -70,6 +70,8 @@ class Token
     TOKEN_STRING,
     // Token is an operator.
     TOKEN_OPERATOR,
     TOKEN_STRING,
     // Token is an operator.
     TOKEN_OPERATOR,
+    // Token is a character constant.
+    TOKEN_CHARACTER,
     // Token is an integer.
     TOKEN_INTEGER,
     // Token is a floating point number.
     // Token is an integer.
     TOKEN_INTEGER,
     // Token is a floating point number.
@@ -135,6 +137,16 @@ class Token
     return tok;
   }
 
     return tok;
   }
 
+  // Make a character constant token.
+  static Token
+  make_character_token(mpz_t val, Location location)
+  {
+    Token tok(TOKEN_CHARACTER, location);
+    mpz_init(tok.u_.integer_value);
+    mpz_swap(tok.u_.integer_value, val);
+    return tok;
+  }
+
   // Make an integer token.
   static Token
   make_integer_token(mpz_t val, Location location)
   // Make an integer token.
   static Token
   make_integer_token(mpz_t val, Location location)
@@ -225,6 +237,14 @@ class Token
     return *this->u_.string_value;
   }
 
     return *this->u_.string_value;
   }
 
+  // Return the value of a character constant.
+  const mpz_t*
+  character_value() const
+  {
+    go_assert(this->classification_ == TOKEN_CHARACTER);
+    return &this->u_.integer_value;
+  }
+
   // Return the value of an integer.
   const mpz_t*
   integer_value() const
   // Return the value of an integer.
   const mpz_t*
   integer_value() const
@@ -300,7 +320,7 @@ class Token
     } identifier_value;
     // The string value for TOKEN_STRING.
     std::string* string_value;
     } identifier_value;
     // The string value for TOKEN_STRING.
     std::string* string_value;
-    // The token value for TOKEN_INTEGER.
+    // The token value for TOKEN_CHARACTER or TOKEN_INTEGER.
     mpz_t integer_value;
     // The token value for TOKEN_FLOAT or TOKEN_IMAGINARY.
     mpfr_t float_value;
     mpz_t integer_value;
     // The token value for TOKEN_FLOAT or TOKEN_IMAGINARY.
     mpfr_t float_value;
index 49e42de..21cd764 100644 (file)
@@ -2391,6 +2391,12 @@ Parse::operand(bool may_be_sink)
       this->advance_token();
       return ret;
 
       this->advance_token();
       return ret;
 
+    case Token::TOKEN_CHARACTER:
+      ret = Expression::make_character(token->character_value(), NULL,
+                                      token->location());
+      this->advance_token();
+      return ret;
+
     case Token::TOKEN_INTEGER:
       ret = Expression::make_integer(token->integer_value(), NULL,
                                     token->location());
     case Token::TOKEN_INTEGER:
       ret = Expression::make_integer(token->integer_value(), NULL,
                                     token->location());
@@ -3168,6 +3174,7 @@ Parse::expression_may_start_here()
        default:
          return false;
        }
        default:
          return false;
        }
+    case Token::TOKEN_CHARACTER:
     case Token::TOKEN_INTEGER:
     case Token::TOKEN_FLOAT:
     case Token::TOKEN_IMAGINARY:
     case Token::TOKEN_INTEGER:
     case Token::TOKEN_FLOAT:
     case Token::TOKEN_IMAGINARY:
@@ -3330,6 +3337,7 @@ Parse::statement(Label* label)
       break;
 
     case Token::TOKEN_STRING:
       break;
 
     case Token::TOKEN_STRING:
+    case Token::TOKEN_CHARACTER:
     case Token::TOKEN_INTEGER:
     case Token::TOKEN_FLOAT:
     case Token::TOKEN_IMAGINARY:
     case Token::TOKEN_INTEGER:
     case Token::TOKEN_FLOAT:
     case Token::TOKEN_IMAGINARY:
@@ -3389,6 +3397,7 @@ Parse::statement_may_start_here()
        return this->expression_may_start_here();
 
     case Token::TOKEN_STRING:
        return this->expression_may_start_here();
 
     case Token::TOKEN_STRING:
+    case Token::TOKEN_CHARACTER:
     case Token::TOKEN_INTEGER:
     case Token::TOKEN_FLOAT:
     case Token::TOKEN_IMAGINARY:
     case Token::TOKEN_INTEGER:
     case Token::TOKEN_FLOAT:
     case Token::TOKEN_IMAGINARY:
index 7893d45..9d19030 100644 (file)
@@ -38,6 +38,8 @@ enum Runtime_function_type
   RFT_UINT64,
   // Go type uintptr, C type uintptr_t.
   RFT_UINTPTR,
   RFT_UINT64,
   // Go type uintptr, C type uintptr_t.
   RFT_UINTPTR,
+  // Go type rune, C type int32_t.
+  RFT_RUNE,
   // Go type float64, C type double.
   RFT_FLOAT64,
   // Go type complex128, C type __complex double.
   // Go type float64, C type double.
   RFT_FLOAT64,
   // Go type complex128, C type __complex double.
@@ -108,6 +110,10 @@ runtime_function_type(Runtime_function_type bft)
          t = Type::lookup_integer_type("uint64");
          break;
 
          t = Type::lookup_integer_type("uint64");
          break;
 
+       case RFT_RUNE:
+         t = Type::lookup_integer_type("int32");
+         break;
+
        case RFT_UINTPTR:
          t = Type::lookup_integer_type("uintptr");
          break;
        case RFT_UINTPTR:
          t = Type::lookup_integer_type("uintptr");
          break;
@@ -203,6 +209,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
     case RFT_INT64:
     case RFT_UINT64:
     case RFT_UINTPTR:
     case RFT_INT64:
     case RFT_UINT64:
     case RFT_UINTPTR:
+    case RFT_RUNE:
     case RFT_FLOAT64:
     case RFT_COMPLEX128:
     case RFT_STRING:
     case RFT_FLOAT64:
     case RFT_COMPLEX128:
     case RFT_STRING:
index 438864c..57d5090 100644 (file)
@@ -36,7 +36,7 @@ DEF_GO_RUNTIME(STRINGITER, "runtime.stringiter", P2(STRING, INT), R1(INT))
 
 // Range over a string, returning the next index and character.
 DEF_GO_RUNTIME(STRINGITER2, "runtime.stringiter2", P2(STRING, INT),
 
 // Range over a string, returning the next index and character.
 DEF_GO_RUNTIME(STRINGITER2, "runtime.stringiter2", P2(STRING, INT),
-              R2(INT, INT))
+              R2(INT, RUNE))
 
 // Concatenate two strings.
 DEF_GO_RUNTIME(STRING_PLUS, "__go_string_plus", P2(STRING, STRING), R1(STRING))
 
 // Concatenate two strings.
 DEF_GO_RUNTIME(STRING_PLUS, "__go_string_plus", P2(STRING, STRING), R1(STRING))
index f6c0f82..bb74db8 100644 (file)
@@ -5194,7 +5194,7 @@ For_range_statement::do_lower(Gogo* gogo, Named_object*, Block* enclosing,
   else if (range_type->is_string_type())
     {
       index_type = Type::lookup_integer_type("int");
   else if (range_type->is_string_type())
     {
       index_type = Type::lookup_integer_type("int");
-      value_type = index_type;
+      value_type = Type::lookup_integer_type("int32");
     }
   else if (range_type->map_type() != NULL)
     {
     }
   else if (range_type->map_type() != NULL)
     {
index 3572e1d..29c3cd7 100644 (file)
@@ -192,7 +192,10 @@ Type::make_non_abstract_type()
   switch (this->classification())
     {
     case TYPE_INTEGER:
   switch (this->classification())
     {
     case TYPE_INTEGER:
-      return Type::lookup_integer_type("int");
+      if (this->integer_type()->is_rune())
+       return Type::lookup_integer_type("int32");
+      else
+       return Type::lookup_integer_type("int");
     case TYPE_FLOAT:
       return Type::lookup_float_type("float64");
     case TYPE_COMPLEX:
     case TYPE_FLOAT:
       return Type::lookup_float_type("float64");
     case TYPE_COMPLEX:
@@ -320,6 +323,12 @@ Type::are_identical(const Type* t1, const Type* t2, bool errors_are_identical,
   t1 = t1->forwarded();
   t2 = t2->forwarded();
 
   t1 = t1->forwarded();
   t2 = t2->forwarded();
 
+  // Ignore aliases for purposes of type identity.
+  if (t1->named_type() != NULL && t1->named_type()->is_alias())
+    t1 = t1->named_type()->real_type();
+  if (t2->named_type() != NULL && t2->named_type()->is_alias())
+    t2 = t2->named_type()->real_type();
+
   if (t1 == t2)
     return true;
 
   if (t1 == t2)
     return true;
 
@@ -963,6 +972,8 @@ tree
 Type::type_descriptor_pointer(Gogo* gogo, Location location)
 {
   Type* t = this->forwarded();
 Type::type_descriptor_pointer(Gogo* gogo, Location location)
 {
   Type* t = this->forwarded();
+  if (t->named_type() != NULL && t->named_type()->is_alias())
+    t = t->named_type()->real_type();
   if (t->type_descriptor_var_ == NULL)
     {
       t->make_type_descriptor_var(gogo);
   if (t->type_descriptor_var_ == NULL)
     {
       t->make_type_descriptor_var(gogo);
@@ -2317,6 +2328,21 @@ Integer_type::create_abstract_integer_type()
   return abstract_type;
 }
 
   return abstract_type;
 }
 
+// Create a new abstract character type.
+
+Integer_type*
+Integer_type::create_abstract_character_type()
+{
+  static Integer_type* abstract_type;
+  if (abstract_type == NULL)
+    {
+      abstract_type = new Integer_type(true, false, 32,
+                                      RUNTIME_TYPE_KIND_INT32);
+      abstract_type->set_is_rune();
+    }
+  return abstract_type;
+}
+
 // Integer type compatibility.
 
 bool
 // Integer type compatibility.
 
 bool
@@ -2399,6 +2425,14 @@ Type::make_abstract_integer_type()
   return Integer_type::create_abstract_integer_type();
 }
 
   return Integer_type::create_abstract_integer_type();
 }
 
+// Make an abstract character type.
+
+Integer_type*
+Type::make_abstract_character_type()
+{
+  return Integer_type::create_abstract_character_type();
+}
+
 // Look up an integer type.
 
 Named_type*
 // Look up an integer type.
 
 Named_type*
@@ -7215,6 +7249,18 @@ Named_type::message_name() const
   return this->named_object_->message_name();
 }
 
   return this->named_object_->message_name();
 }
 
+// Whether this is an alias.  There are currently only two aliases so
+// we just recognize them by name.
+
+bool
+Named_type::is_alias() const
+{
+  if (!this->is_builtin())
+    return false;
+  const std::string& name(this->name());
+  return name == "byte" || name == "rune";
+}
+
 // Return the base type for this type.  We have to be careful about
 // circular type definitions, which are invalid but may be seen here.
 
 // Return the base type for this type.  We have to be careful about
 // circular type definitions, which are invalid but may be seen here.
 
@@ -7615,6 +7661,9 @@ Named_type::do_compare_is_identity(Gogo* gogo) const
 unsigned int
 Named_type::do_hash_for_method(Gogo* gogo) const
 {
 unsigned int
 Named_type::do_hash_for_method(Gogo* gogo) const
 {
+  if (this->is_alias())
+    return this->type_->named_type()->do_hash_for_method(gogo);
+
   const std::string& name(this->named_object()->name());
   unsigned int ret = Type::hash_string(name, 0);
 
   const std::string& name(this->named_object()->name());
   unsigned int ret = Type::hash_string(name, 0);
 
@@ -7959,6 +8008,9 @@ Named_type::do_get_backend(Gogo* gogo)
 Expression*
 Named_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
 Expression*
 Named_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 {
+  if (name == NULL && this->is_alias())
+    return this->type_->type_descriptor(gogo, this->type_);
+
   // If NAME is not NULL, then we don't really want the type
   // descriptor for this type; we want the descriptor for the
   // underlying type, giving it the name NAME.
   // If NAME is not NULL, then we don't really want the type
   // descriptor for this type; we want the descriptor for the
   // underlying type, giving it the name NAME.
@@ -7973,7 +8025,12 @@ Named_type::do_type_descriptor(Gogo* gogo, Named_type* name)
 void
 Named_type::do_reflection(Gogo* gogo, std::string* ret) const
 {
 void
 Named_type::do_reflection(Gogo* gogo, std::string* ret) const
 {
-  if (!Linemap::is_predeclared_location(this->location()))
+  if (this->is_alias())
+    {
+      this->append_reflection(this->type_, gogo, ret);
+      return;
+    }
+  if (!this->is_builtin())
     {
       const Package* package = this->named_object_->package();
       if (package != NULL)
     {
       const Package* package = this->named_object_->package();
       if (package != NULL)
@@ -7995,9 +8052,14 @@ Named_type::do_reflection(Gogo* gogo, std::string* ret) const
 void
 Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
 {
 void
 Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
 {
+  if (this->is_alias())
+    {
+      this->append_mangled_name(this->type_, gogo, ret);
+      return;
+    }
   Named_object* no = this->named_object_;
   std::string name;
   Named_object* no = this->named_object_;
   std::string name;
-  if (Linemap::is_predeclared_location(this->location()))
+  if (this->is_builtin())
     go_assert(this->in_function_ == NULL);
   else
     {
     go_assert(this->in_function_ == NULL);
   else
     {
index b167451..4e45b99 100644 (file)
@@ -401,6 +401,10 @@ class Type
   static Integer_type*
   make_abstract_integer_type();
 
   static Integer_type*
   make_abstract_integer_type();
 
+  // Make an abstract type for a character constant.
+  static Integer_type*
+  make_abstract_character_type();
+
   // Make a named integer type with a specified size.
   // RUNTIME_TYPE_KIND is the code to use in reflection information,
   // to distinguish int and int32.
   // Make a named integer type with a specified size.
   // RUNTIME_TYPE_KIND is the code to use in reflection information,
   // to distinguish int and int32.
@@ -1374,6 +1378,10 @@ class Integer_type : public Type
   static Integer_type*
   create_abstract_integer_type();
 
   static Integer_type*
   create_abstract_integer_type();
 
+  // Create an abstract character type.
+  static Integer_type*
+  create_abstract_character_type();
+
   // Whether this is an abstract integer type.
   bool
   is_abstract() const
   // Whether this is an abstract integer type.
   bool
   is_abstract() const
@@ -2674,6 +2682,11 @@ class Named_type : public Type
   is_builtin() const
   { return Linemap::is_predeclared_location(this->location_); }
 
   is_builtin() const
   { return Linemap::is_predeclared_location(this->location_); }
 
+  // Whether this is an alias.  There are currently two aliases: byte
+  // and rune.
+  bool
+  is_alias() const;
+
   // Whether this is a circular type: a pointer or function type that
   // refers to itself, which is not possible in C.
   bool
   // Whether this is a circular type: a pointer or function type that
   // refers to itself, which is not possible in C.
   bool
index d4534c2..adf0aaf 100644 (file)
@@ -7,18 +7,18 @@
 package main
 
 func main() {
 package main
 
 func main() {
-       nchar := 0;
-       a := []int { '日', '本', '語', 0xFFFD };
+       nchar := 0
+       a := []rune{'日', '本', '語', 0xFFFD}
        for _, char := range "日本語\xc0" {
                if nchar >= len(a) {
        for _, char := range "日本語\xc0" {
                if nchar >= len(a) {
-                       println("BUG");
-                       break;
+                       println("BUG")
+                       break
                }
                if char != a[nchar] {
                }
                if char != a[nchar] {
-                       println("expected", a[nchar], "got", char);
-                       println("BUG");
-                       break;
+                       println("expected", a[nchar], "got", char)
+                       println("BUG")
+                       break
                }
                }
-               nchar++;
+               nchar++
        }
 }
        }
 }
index cbedad4..b74bd7d 100644 (file)
@@ -95,7 +95,7 @@ func main() {
        }
 
        /* create string with int array */
        }
 
        /* create string with int array */
-       var z2 [3]int
+       var z2 [3]rune
        z2[0] = 'a'
        z2[1] = '\u1234'
        z2[2] = 'c'
        z2[0] = 'a'
        z2[1] = '\u1234'
        z2[2] = 'c'
index 91ccd63..8411945 100644 (file)
@@ -172,7 +172,7 @@ func makestring() string {
 }
 
 func teststring() {
 }
 
 func teststring() {
-       s := 0
+       var s rune
        nmake = 0
        for _, v := range makestring() {
                s += v
        nmake = 0
        for _, v := range makestring() {
                s += v
@@ -208,7 +208,7 @@ func teststring1() {
 
 func makemap() map[int]int {
        nmake++
 
 func makemap() map[int]int {
        nmake++
-       return map[int]int{0:'a', 1:'b', 2:'c', 3:'d', 4:'☺'}
+       return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
 }
 
 func testmap() {
 }
 
 func testmap() {
index c789bf2..473a1d1 100644 (file)
@@ -14,7 +14,7 @@ const N = 11 + 1 // length of a board row (+1 for newline)
 // The board must be surrounded by 2 illegal fields in each direction
 // so that move() doesn't need to check the board boundaries. Periods
 // represent illegal fields, ● are pegs, and ○ are holes.
 // The board must be surrounded by 2 illegal fields in each direction
 // so that move() doesn't need to check the board boundaries. Periods
 // represent illegal fields, ● are pegs, and ○ are holes.
-var board = []int(
+var board = []rune(
        `...........
 ...........
 ....●●●....
        `...........
 ...........
 ....●●●....
@@ -28,7 +28,6 @@ var board = []int(
 ...........
 `)
 
 ...........
 `)
 
-
 // center is the position of the center hole if there is a single one;
 // otherwise it is -1.
 var center int
 // center is the position of the center hole if there is a single one;
 // otherwise it is -1.
 var center int
@@ -46,7 +45,6 @@ func init() {
        }
 }
 
        }
 }
 
-
 var moves int // number of times move is called
 
 // move tests if there is a peg at position pos that can jump over another peg
 var moves int // number of times move is called
 
 // move tests if there is a peg at position pos that can jump over another peg
@@ -63,7 +61,6 @@ func move(pos, dir int) bool {
        return false
 }
 
        return false
 }
 
-
 // unmove reverts a previously executed valid move.
 func unmove(pos, dir int) {
        board[pos] = '●'
 // unmove reverts a previously executed valid move.
 func unmove(pos, dir int) {
        board[pos] = '●'
@@ -71,7 +68,6 @@ func unmove(pos, dir int) {
        board[pos+2*dir] = '○'
 }
 
        board[pos+2*dir] = '○'
 }
 
-
 // solve tries to find a sequence of moves such that there is only one peg left
 // at the end; if center is >= 0, that last peg must be in the center position.
 // If a solution is found, solve prints the board after each move in a backward
 // solve tries to find a sequence of moves such that there is only one peg left
 // at the end; if center is >= 0, that last peg must be in the center position.
 // If a solution is found, solve prints the board after each move in a backward
@@ -110,7 +106,6 @@ func solve() bool {
        return false
 }
 
        return false
 }
 
-
 func main() {
        if !solve() {
                println("no solution found")
 func main() {
        if !solve() {
                println("no solution found")
index 4358dd8..c702a05 100644 (file)
@@ -35,14 +35,14 @@ func assert(a, b, c string) {
 }
 
 const (
 }
 
 const (
-       gx1 = "aä本☺"
-       gx2 = "aä\xFF\xFF本☺"
+       gx1    = "aä本☺"
+       gx2    = "aä\xFF\xFF本☺"
        gx2fix = "aä\uFFFD\uFFFD本☺"
 )
 
 var (
        gx2fix = "aä\uFFFD\uFFFD本☺"
 )
 
 var (
-       gr1 = []int(gx1)
-       gr2 = []int(gx2)
+       gr1 = []rune(gx1)
+       gr2 = []rune(gx2)
        gb1 = []byte(gx1)
        gb2 = []byte(gx2)
 )
        gb1 = []byte(gx1)
        gb2 = []byte(gx2)
 )
@@ -93,26 +93,26 @@ func main() {
 
        // test large runes. perhaps not the most logical place for this test.
        var r int32
 
        // test large runes. perhaps not the most logical place for this test.
        var r int32
-       r = 0x10ffff;   // largest rune value
+       r = 0x10ffff // largest rune value
        s = string(r)
        assert(s, "\xf4\x8f\xbf\xbf", "largest rune")
        r = 0x10ffff + 1
        s = string(r)
        assert(s, "\xef\xbf\xbd", "too-large rune")
 
        s = string(r)
        assert(s, "\xf4\x8f\xbf\xbf", "largest rune")
        r = 0x10ffff + 1
        s = string(r)
        assert(s, "\xef\xbf\xbd", "too-large rune")
 
-       assert(string(gr1), gx1, "global ->[]int")
-       assert(string(gr2), gx2fix, "global invalid ->[]int")
+       assert(string(gr1), gx1, "global ->[]rune")
+       assert(string(gr2), gx2fix, "global invalid ->[]rune")
        assert(string(gb1), gx1, "->[]byte")
        assert(string(gb2), gx2, "global invalid ->[]byte")
 
        var (
        assert(string(gb1), gx1, "->[]byte")
        assert(string(gb2), gx2, "global invalid ->[]byte")
 
        var (
-               r1 = []int(gx1)
-               r2 = []int(gx2)
+               r1 = []rune(gx1)
+               r2 = []rune(gx2)
                b1 = []byte(gx1)
                b2 = []byte(gx2)
        )
                b1 = []byte(gx1)
                b2 = []byte(gx2)
        )
-       assert(string(r1), gx1, "->[]int")
-       assert(string(r2), gx2fix, "invalid ->[]int")
+       assert(string(r1), gx1, "->[]rune")
+       assert(string(r2), gx2fix, "invalid ->[]rune")
        assert(string(b1), gx1, "->[]byte")
        assert(string(b2), gx2, "invalid ->[]byte")
 
        assert(string(b1), gx1, "->[]byte")
        assert(string(b2), gx2, "invalid ->[]byte")