aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2012-03-09 08:25:05 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2012-03-09 08:25:05 +0000
commit68c5d97bad2d405e2b27826bcb95f224baec6465 (patch)
treebd0a2765d69acdf83a414c1a6f425dc3adc2543d
parent762c279900efedc1407c3c38d98601ddbff575ae (diff)
downloadgcc-68c5d97bad2d405e2b27826bcb95f224baec6465.zip
gcc-68c5d97bad2d405e2b27826bcb95f224baec6465.tar.gz
gcc-68c5d97bad2d405e2b27826bcb95f224baec6465.tar.bz2
compiler: Be more careful to follow GENERIC type rules.
* go-gcc.cc (Gcc_backend::assignment_statement): Convert the rhs to the lhs type if necessary. From-SVN: r185128
-rw-r--r--gcc/go/ChangeLog5
-rw-r--r--gcc/go/go-gcc.cc24
-rw-r--r--gcc/go/gofrontend/expressions.cc15
3 files changed, 38 insertions, 6 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 2c0b3c2..f779e9b 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,8 @@
+2012-03-09 Ian Lance Taylor <iant@google.com>
+
+ * go-gcc.cc (Gcc_backend::assignment_statement): Convert the rhs
+ to the lhs type if necessary.
+
2012-03-08 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::init_statement): Don't initialize a
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 0cc167d..96c1718 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -918,6 +918,30 @@ Gcc_backend::assignment_statement(Bexpression* lhs, Bexpression* rhs,
return this->compound_statement(this->expression_statement(lhs),
this->expression_statement(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);
+ }
+ }
+
return this->make_statement(fold_build2_loc(location.gcc_location(),
MODIFY_EXPR,
void_type_node,
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 134b5ae..90cf6f3 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -205,9 +205,6 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
Type* rhs_type, tree rhs_tree,
Location location)
{
- if (lhs_type == rhs_type)
- return rhs_tree;
-
if (lhs_type->is_error() || rhs_type->is_error())
return error_mark_node;
@@ -220,7 +217,7 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
if (lhs_type_tree == error_mark_node)
return error_mark_node;
- if (lhs_type->interface_type() != NULL)
+ if (lhs_type != rhs_type && lhs_type->interface_type() != NULL)
{
if (rhs_type->interface_type() == NULL)
return Expression::convert_type_to_interface(context, lhs_type,
@@ -231,7 +228,7 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
rhs_type, rhs_tree,
false, location);
}
- else if (rhs_type->interface_type() != NULL)
+ else if (lhs_type != rhs_type && rhs_type->interface_type() != NULL)
return Expression::convert_interface_to_type(context, lhs_type, rhs_type,
rhs_tree, location);
else if (lhs_type->is_slice_type() && rhs_type->is_nil_type())
@@ -289,10 +286,16 @@ Expression::convert_for_assignment(Translate_context* context, Type* lhs_type,
|| (TREE_CODE(lhs_type_tree) == ARRAY_TYPE
&& TREE_CODE(TREE_TYPE(rhs_tree)) == ARRAY_TYPE))
{
+ // Avoid confusion from zero sized variables which may be
+ // represented as non-zero-sized.
+ if (int_size_in_bytes(lhs_type_tree) == 0
+ || int_size_in_bytes(TREE_TYPE(rhs_tree)) == 0)
+ return rhs_tree;
+
// This conversion must be permitted by Go, or we wouldn't have
// gotten here.
go_assert(int_size_in_bytes(lhs_type_tree)
- == int_size_in_bytes(TREE_TYPE(rhs_tree)));
+ == int_size_in_bytes(TREE_TYPE(rhs_tree)));
return fold_build1_loc(location.gcc_location(), VIEW_CONVERT_EXPR,
lhs_type_tree, rhs_tree);
}