Commit 56efdb45 by Ian Lance Taylor

compiler: identify array index expressions in lvalue context

    
    Update the Mark_lvalue_varexprs visitor class (used in
    Assignment_statement::do_get_backend) to identify
    Array_index_expression's that appear on the left hand side of
    assignments, then pass this context info on when invoking
    Array_type::get_value_pointer.
    
    Reviewed-on: https://go-review.googlesource.com/44170

From-SVN: r248528
parent 7d66e265
ec49c69df1df4d62f3751fcd7e930d6508d67bf2
884df09c3da0f39309ab13f2ad401628fb933050
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
......@@ -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);
......
......@@ -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.
......
......@@ -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;
}
......
......@@ -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());
......
......@@ -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*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment