compiler: identify array index expressions in lvalue context
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 26 May 2017 21:48:49 +0000 (21:48 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 26 May 2017 21:48:49 +0000 (21:48 +0000)
    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
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/statements.cc
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index 17239fd1e5ccc2440be5e261be4689a58ee48182..07127b00e77a41edc682e093faef6a18d3b6ecf6 100644 (file)
@@ -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.
index 97a39f54239e1bcd66d3b4534e630680420df9c0..fec206d4462864d11c5c3f21c6393095f54c3b4b 100644 (file)
@@ -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);
 
index 03bb08531f3cc85c4a714caa40302ec4f2646c70..5567605b151af91193c4429c43f38a608138ba47 100644 (file)
@@ -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.
index 00367ef0553973395b00eed89195ef5eadc06dd1..ae3873ed189aae4e923bc04e5fabb4121e4c43f2 100644 (file)
@@ -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;
     }
index 053e71d6bfab83e38eced1642b4ca2ffc8644ca9..a3ec52c45cc311b5df373d0f802e53096ed0ee66 100644 (file)
@@ -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());
index bfc0a8ba46a4e42f9ae1b4bd8b2e26e99f9fad8a..53d6a2cd84f1a3a7bd858ffa9eed740b93c30e26 100644 (file)
@@ -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*