aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-10-24 05:00:34 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-10-24 05:00:34 +0000
commita1ee0aafc7f7f3f9dcba3378b951905e19aa1ac7 (patch)
tree8e3eb8acc4725845f6194fbcd79918bf35440879
parent703f56e5cbcfc5d64fac26b2d55f127d363e67b6 (diff)
downloadgcc-a1ee0aafc7f7f3f9dcba3378b951905e19aa1ac7.zip
gcc-a1ee0aafc7f7f3f9dcba3378b951905e19aa1ac7.tar.gz
gcc-a1ee0aafc7f7f3f9dcba3378b951905e19aa1ac7.tar.bz2
Implement append([]byte, string...).
From-SVN: r180364
-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 97c7558..e61dd3b 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;