aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc9
-rw-r--r--gcc/go/gofrontend/expressions.h17
-rw-r--r--gcc/go/gofrontend/statements.cc1
-rw-r--r--gcc/go/gofrontend/types.cc15
-rw-r--r--gcc/go/gofrontend/types.h2
6 files changed, 39 insertions, 7 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 17239fd..07127b0 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-ec49c69df1df4d62f3751fcd7e930d6508d67bf2
+884df09c3da0f39309ab13f2ad401628fb933050
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 97a39f5..fec206d 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -6470,7 +6470,8 @@ Expression::comparison(Translate_context* context, Type* result_type,
&& left_type->array_type()->length() == NULL)
{
Array_type* at = left_type->array_type();
- left = at->get_value_pointer(context->gogo(), left);
+ bool is_lvalue = false;
+ left = at->get_value_pointer(context->gogo(), left, is_lvalue);
}
else if (left_type->interface_type() != NULL)
{
@@ -11067,7 +11068,8 @@ Array_index_expression::do_get_backend(Translate_context* context)
{
// Slice.
Expression* valptr =
- array_type->get_value_pointer(gogo, this->array_);
+ array_type->get_value_pointer(gogo, this->array_,
+ this->is_lvalue_);
Bexpression* ptr = valptr->get_backend(context);
ptr = gogo->backend()->pointer_offset_expression(ptr, start, loc);
@@ -11143,7 +11145,8 @@ Array_index_expression::do_get_backend(Translate_context* context)
Bexpression* offset = gogo->backend()->conditional_expression(bfn, int_btype,
cond, zero,
start, loc);
- Expression* valptr = array_type->get_value_pointer(gogo, this->array_);
+ Expression* valptr = array_type->get_value_pointer(gogo, this->array_,
+ this->is_lvalue_);
Bexpression* val = valptr->get_backend(context);
val = gogo->backend()->pointer_offset_expression(val, offset, loc);
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 03bb085..5567605 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -2654,7 +2654,8 @@ class Array_index_expression : public Expression
Array_index_expression(Expression* array, Expression* start,
Expression* end, Expression* cap, Location location)
: Expression(EXPRESSION_ARRAY_INDEX, location),
- array_(array), start_(start), end_(end), cap_(cap), type_(NULL)
+ array_(array), start_(start), end_(end), cap_(cap), type_(NULL),
+ is_lvalue_(false)
{ }
// Return the array.
@@ -2686,6 +2687,18 @@ class Array_index_expression : public Expression
end() const
{ return this->end_; }
+ // Return whether this array index expression appears in an lvalue
+ // (left hand side of assignment) context.
+ bool
+ is_lvalue() const
+ { return this->is_lvalue_; }
+
+ // Update this array index expression to indicate that it appears
+ // in a left-hand-side or lvalue context.
+ void
+ set_is_lvalue()
+ { this->is_lvalue_ = true; }
+
protected:
int
do_traverse(Traverse*);
@@ -2753,6 +2766,8 @@ class Array_index_expression : public Expression
Expression* cap_;
// The type of the expression.
Type* type_;
+ // Whether expr appears in an lvalue context.
+ bool is_lvalue_;
};
// A string index. This is used for both indexing and slicing.
diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc
index 00367ef..ae3873e 100644
--- a/gcc/go/gofrontend/statements.cc
+++ b/gcc/go/gofrontend/statements.cc
@@ -903,6 +903,7 @@ int Mark_lvalue_varexprs::expression(Expression** ppexpr)
if (aie != NULL)
{
Mark_lvalue_varexprs mlve;
+ aie->set_is_lvalue();
aie->array()->traverse_subexpressions(&mlve);
return TRAVERSE_EXIT;
}
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 053e71d..a3ec52c 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -7611,7 +7611,7 @@ Array_type::finish_backend_element(Gogo* gogo)
// Return an expression for a pointer to the values in ARRAY.
Expression*
-Array_type::get_value_pointer(Gogo*, Expression* array) const
+Array_type::get_value_pointer(Gogo*, Expression* array, bool is_lvalue) const
{
if (this->length() != NULL)
{
@@ -7624,6 +7624,19 @@ Array_type::get_value_pointer(Gogo*, Expression* array) const
}
// Slice.
+
+ if (is_lvalue)
+ {
+ Temporary_reference_expression* tref =
+ array->temporary_reference_expression();
+ if (tref != NULL)
+ {
+ tref = tref->copy()->temporary_reference_expression();
+ tref->set_is_lvalue();
+ array = tref;
+ }
+ }
+
return Expression::make_slice_info(array,
Expression::SLICE_INFO_VALUE_POINTER,
array->location());
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index bfc0a8b..53d6a2c 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -2517,7 +2517,7 @@ class Array_type : public Type
// Return an expression for the pointer to the values in an array.
Expression*
- get_value_pointer(Gogo*, Expression* array) const;
+ get_value_pointer(Gogo*, Expression* array, bool is_lvalue) const;
// Return an expression for the length of an array with this type.
Expression*