summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-24 05:00:34 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2011-10-24 05:00:34 +0000
commit4fd4fcf4215a8129c68c09d8afb2d986794853f6 (patch)
tree8e3eb8acc4725845f6194fbcd79918bf35440879 /gcc
parent7f42c28ed20af6fe96d8155505efb9dc9ec74ce9 (diff)
downloadppe42-gcc-4fd4fcf4215a8129c68c09d8afb2d986794853f6.tar.gz
ppe42-gcc-4fd4fcf4215a8129c68c09d8afb2d986794853f6.zip
Implement append([]byte, string...).
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180364 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/expressions.cc65
1 files changed, 48 insertions, 17 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 97c75584db9..e61dd3b5be6 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -8228,6 +8228,17 @@ Builtin_call_expression::do_check_types(Gogo*)
this->report_error(_("too many arguments"));
break;
}
+
+ // The language permits appending a string to a []byte, as a
+ // special case.
+ if (args->back()->type()->is_string_type())
+ {
+ const Array_type* at = args->front()->type()->array_type();
+ const Type* e = at->element_type()->forwarded();
+ if (e == Type::lookup_integer_type("uint8"))
+ break;
+ }
+
std::string reason;
if (!Type::are_assignable(args->front()->type(), args->back()->type(),
&reason))
@@ -8766,30 +8777,50 @@ Builtin_call_expression::do_get_tree(Translate_context* context)
return error_mark_node;
Array_type* at = arg1->type()->array_type();
- Type* element_type = at->element_type();
+ Type* element_type = at->element_type()->forwarded();
- arg2_tree = Expression::convert_for_assignment(context, at,
- arg2->type(),
- arg2_tree,
- location);
- if (arg2_tree == error_mark_node)
- return error_mark_node;
+ tree arg2_val;
+ tree arg2_len;
+ tree element_size;
+ if (arg2->type()->is_string_type()
+ && element_type == Type::lookup_integer_type("uint8"))
+ {
+ arg2_tree = save_expr(arg2_tree);
+ arg2_val = String_type::bytes_tree(gogo, arg2_tree);
+ arg2_len = String_type::length_tree(gogo, arg2_tree);
+ element_size = size_int(1);
+ }
+ else
+ {
+ arg2_tree = Expression::convert_for_assignment(context, at,
+ arg2->type(),
+ arg2_tree,
+ location);
+ if (arg2_tree == error_mark_node)
+ return error_mark_node;
+
+ arg2_tree = save_expr(arg2_tree);
+
+ arg2_val = at->value_pointer_tree(gogo, arg2_tree);
+ arg2_len = at->length_tree(gogo, arg2_tree);
+
+ Btype* element_btype = element_type->get_backend(gogo);
+ tree element_type_tree = type_to_tree(element_btype);
+ if (element_type_tree == error_mark_node)
+ return error_mark_node;
+ element_size = TYPE_SIZE_UNIT(element_type_tree);
+ }
- arg2_tree = save_expr(arg2_tree);
- tree arg2_val = at->value_pointer_tree(gogo, arg2_tree);
- tree arg2_len = at->length_tree(gogo, arg2_tree);
- if (arg2_val == error_mark_node || arg2_len == error_mark_node)
- return error_mark_node;
arg2_val = fold_convert_loc(location, ptr_type_node, arg2_val);
arg2_len = fold_convert_loc(location, size_type_node, arg2_len);
-
- tree element_type_tree = type_to_tree(element_type->get_backend(gogo));
- if (element_type_tree == error_mark_node)
- return error_mark_node;
- tree element_size = TYPE_SIZE_UNIT(element_type_tree);
element_size = fold_convert_loc(location, size_type_node,
element_size);
+ if (arg2_val == error_mark_node
+ || arg2_len == error_mark_node
+ || element_size == error_mark_node)
+ return error_mark_node;
+
// We rebuild the decl each time since the slice types may
// change.
tree append_fndecl = NULL_TREE;
OpenPOWER on IntegriCloud