From 56efdb4596f2dd9aa568c6a160e81222c1d2a23c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 26 May 2017 21:48:49 +0000 Subject: [PATCH] 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 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 9 ++++++--- gcc/go/gofrontend/expressions.h | 17 ++++++++++++++++- gcc/go/gofrontend/statements.cc | 1 + gcc/go/gofrontend/types.cc | 15 ++++++++++++++- gcc/go/gofrontend/types.h | 2 +- 6 files changed, 39 insertions(+), 7 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 17239fd1e5c..07127b00e77 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 97a39f54239..fec206d4462 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 03bb08531f3..5567605b151 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 00367ef0553..ae3873ed189 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 053e71d6bfa..a3ec52c45cc 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 bfc0a8ba46a..53d6a2cd84f 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* -- 2.30.2