From 7b31a84d76aaed7715210c6dc7d50dc2c47afd79 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 11 Jan 2012 23:43:46 +0000 Subject: [PATCH] compiler: Permit type B byte; type S []B; var v = S("x"). From-SVN: r183112 --- gcc/go/gofrontend/expressions.cc | 43 ++++++++++++++++---------------- gcc/go/gofrontend/gogo.cc | 2 ++ gcc/go/gofrontend/types.cc | 11 ++++---- gcc/go/gofrontend/types.h | 30 +++++++++++++++++++--- 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 7166a56692d..5e66645c8d7 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3382,9 +3382,11 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*, 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 @@ Type_conversion_expression::do_get_tree(Translate_context* context) 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 @@ Type_conversion_expression::do_get_tree(Translate_context* context) } 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_conversion_expression::do_get_tree(Translate_context* context) { 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 @@ Type_conversion_expression::do_get_tree(Translate_context* context) } 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 @@ Builtin_call_expression::do_check_types(Gogo*) break; } - Type* e2; if (arg2_type->is_slice_type()) - e2 = arg2_type->array_type()->element_type(); - else if (arg2_type->is_string_type()) - e2 = Type::lookup_integer_type("uint8"); - else { - this->report_error(_("right argument must be a slice or a string")); - break; + 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")); } - - if (!Type::are_identical(e1, e2, true, NULL)) - this->report_error(_("element types must be the same")); + else if (arg2_type->is_string_type()) + { + if (e1->integer_type() == NULL || !e1->integer_type()->is_byte()) + this->report_error(_("first argument must be []byte")); + } + else + this->report_error(_("second argument must be slice or string")); } break; @@ -8542,7 +8542,7 @@ Builtin_call_expression::do_check_types(Gogo*) { 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 @@ Builtin_call_expression::do_get_tree(Translate_context* context) 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 --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index f6f22d44be3..a5de1750f43 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -88,10 +88,12 @@ Gogo::Gogo(Backend* backend, Linemap* linemap, int int_type_size, // 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 --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index c8600ac1baf..055bd67863d 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -767,7 +767,7 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason) 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 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason) { 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 --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 9de1b84334d..afb8a415564 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -1386,7 +1386,27 @@ class Integer_type : public Type 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 @@ class Integer_type : public Type 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 @@ class Integer_type : public Type 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.