diff mbox

Go patch committed: Mark array pointers as l-value when appropriate

Message ID CAOyqgcXKdTSFzDYUxjorSje_AHu-Jn4n0ZCe82hJz=k388u9-Q@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor May 26, 2017, 9:48 p.m. UTC
This patch by Than McIntosh fixes the Go frontend to consistent mark
array pointers as l-values when an array index expression is used in
an l-value context.  Bootstrapped and ran Go testsuite on
x86_64-pc-linux-gnu.  Committed to mainline.

Ian
diff mbox

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 248394)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 248082)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -6470,7 +6470,8 @@  Expression::comparison(Translate_context
 	  && 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(T
 	{
 	  // 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(T
   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: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 247848)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -2654,7 +2654,8 @@  class Array_index_expression : public Ex
   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 Ex
   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 Ex
   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: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 247848)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -903,6 +903,7 @@  int Mark_lvalue_varexprs::expression(Exp
   if (aie != NULL)
     {
       Mark_lvalue_varexprs mlve;
+      aie->set_is_lvalue();
       aie->array()->traverse_subexpressions(&mlve);
       return TRAVERSE_EXIT;
     }
Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 248248)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -7611,7 +7611,7 @@  Array_type::finish_backend_element(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*, Exp
     }
 
   // 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: gcc/go/gofrontend/types.h
===================================================================
--- gcc/go/gofrontend/types.h	(revision 248248)
+++ gcc/go/gofrontend/types.h	(working copy)
@@ -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*