go-gcc.cc (Gcc_backend::convert_tree): New private method.

* go-gcc.cc (Gcc_backend::convert_tree): New private method.
	(Gcc_backend::constructor_expression): Call it.
	(Gcc_backend::assignment_statement): Likewise.
	(Gcc_backend::temporary_variable): Likewise.

Fixes https://golang.org/issue/#23606

From-SVN: r257218
This commit is contained in:
Ian Lance Taylor 2018-01-31 06:17:25 +00:00 committed by Ian Lance Taylor
parent 5837571173
commit ebc2f4010d
2 changed files with 50 additions and 27 deletions

View File

@ -1,3 +1,10 @@
2018-01-30 Ian Lance Taylor <iant@golang.org>
* go-gcc.cc (Gcc_backend::convert_tree): New private method.
(Gcc_backend::constructor_expression): Call it.
(Gcc_backend::assignment_statement): Likewise.
(Gcc_backend::temporary_variable): Likewise.
2018-01-09 Cherry Zhang <cherryyz@google.com>
* go-gcc.cc (local_variable): Add decl_var parameter.

View File

@ -541,6 +541,9 @@ class Gcc_backend : public Backend
tree
non_zero_size_type(tree);
tree
convert_tree(tree, tree, Location);
private:
void
define_builtin(built_in_function bcode, const char* name, const char* libname,
@ -1785,8 +1788,7 @@ Gcc_backend::constructor_expression(Btype* btype,
constructor_elt empty = {NULL, NULL};
constructor_elt* elt = init->quick_push(empty);
elt->index = field;
elt->value = fold_convert_loc(location.gcc_location(), TREE_TYPE(field),
val);
elt->value = this->convert_tree(TREE_TYPE(field), val, location);
if (!TREE_CONSTANT(elt->value))
is_constant = false;
}
@ -2055,29 +2057,7 @@ Gcc_backend::assignment_statement(Bfunction* bfn, Bexpression* lhs,
return this->compound_statement(this->expression_statement(bfn, lhs),
this->expression_statement(bfn, rhs));
// Sometimes the same unnamed Go type can be created multiple times
// and thus have multiple tree representations. Make sure this does
// not confuse the middle-end.
if (TREE_TYPE(lhs_tree) != TREE_TYPE(rhs_tree))
{
tree lhs_type_tree = TREE_TYPE(lhs_tree);
gcc_assert(TREE_CODE(lhs_type_tree) == TREE_CODE(TREE_TYPE(rhs_tree)));
if (POINTER_TYPE_P(lhs_type_tree)
|| INTEGRAL_TYPE_P(lhs_type_tree)
|| SCALAR_FLOAT_TYPE_P(lhs_type_tree)
|| COMPLEX_FLOAT_TYPE_P(lhs_type_tree))
rhs_tree = fold_convert_loc(location.gcc_location(), lhs_type_tree,
rhs_tree);
else if (TREE_CODE(lhs_type_tree) == RECORD_TYPE
|| TREE_CODE(lhs_type_tree) == ARRAY_TYPE)
{
gcc_assert(int_size_in_bytes(lhs_type_tree)
== int_size_in_bytes(TREE_TYPE(rhs_tree)));
rhs_tree = fold_build1_loc(location.gcc_location(),
VIEW_CONVERT_EXPR,
lhs_type_tree, rhs_tree);
}
}
rhs_tree = this->convert_tree(TREE_TYPE(lhs_tree), rhs_tree, location);
return this->make_statement(fold_build2_loc(location.gcc_location(),
MODIFY_EXPR,
@ -2507,6 +2487,43 @@ Gcc_backend::non_zero_size_type(tree type)
gcc_unreachable();
}
// Convert EXPR_TREE to TYPE_TREE. Sometimes the same unnamed Go type
// can be created multiple times and thus have multiple tree
// representations. Make sure this does not confuse the middle-end.
tree
Gcc_backend::convert_tree(tree type_tree, tree expr_tree, Location location)
{
if (type_tree == TREE_TYPE(expr_tree))
return expr_tree;
if (type_tree == error_mark_node
|| expr_tree == error_mark_node
|| TREE_TYPE(expr_tree) == error_mark_node)
return error_mark_node;
gcc_assert(TREE_CODE(type_tree) == TREE_CODE(TREE_TYPE(expr_tree)));
if (POINTER_TYPE_P(type_tree)
|| INTEGRAL_TYPE_P(type_tree)
|| SCALAR_FLOAT_TYPE_P(type_tree)
|| COMPLEX_FLOAT_TYPE_P(type_tree))
return fold_convert_loc(location.gcc_location(), type_tree, expr_tree);
else if (TREE_CODE(type_tree) == RECORD_TYPE
|| TREE_CODE(type_tree) == ARRAY_TYPE)
{
gcc_assert(int_size_in_bytes(type_tree)
== int_size_in_bytes(TREE_TYPE(expr_tree)));
if (TYPE_MAIN_VARIANT(type_tree)
== TYPE_MAIN_VARIANT(TREE_TYPE(expr_tree)))
return fold_build1_loc(location.gcc_location(), NOP_EXPR,
type_tree, expr_tree);
return fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR,
type_tree, expr_tree);
}
gcc_unreachable();
}
// Make a global variable.
Bvariable*
@ -2717,8 +2734,7 @@ Gcc_backend::temporary_variable(Bfunction* function, Bblock* bblock,
}
if (this->type_size(btype) != 0 && init_tree != NULL_TREE)
DECL_INITIAL(var) = fold_convert_loc(location.gcc_location(), type_tree,
init_tree);
DECL_INITIAL(var) = this->convert_tree(type_tree, init_tree, location);
if (is_address_taken)
TREE_ADDRESSABLE(var) = 1;