compiler: update iota handling, fix using iota in array length
authorIan Lance Taylor <ian@gcc.gnu.org>
Mon, 5 Feb 2018 01:57:42 +0000 (01:57 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 5 Feb 2018 01:57:42 +0000 (01:57 +0000)
    CL 71750 changed the definition of how iota works.  This patch updates
    gccgo for the new definition.

    We've been mishandling iota appearing in a type that appears in a
    const expression, as in `c = len([iota]int{})`.  Correct that by copying
    type expressions when we copy an expression.  For simplicity only copy
    when it can change the size of a type, as that is the only case where
    iota in a type can affect the value of a constant (I think).  This is
    still a bunch of changes, but almost all boilerplate.

    Fixes golang/go#22341

    Reviewed-on: https://go-review.googlesource.com/91475

From-SVN: r257379

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/parse.cc
gcc/go/gofrontend/parse.h
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index c0f977a44c4b9a885c73afe761bff4e5872a050b..3588a8a7a6ac69c4e741cfc4081738de6aee9245 100644 (file)
@@ -1,4 +1,4 @@
-d9f33a479f8012f7495d197e4b7417cba4d477fa
+36594b69b94326014c331fe50a5a345ef4f8de16
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 3bcc5ae1471c1d270c71f9035f505a7ee586ba25..8555c052980812559fc21c62eb36150ce555f6a0 100644 (file)
@@ -1928,10 +1928,16 @@ class Integer_expression : public Expression
   do_copy()
   {
     if (this->is_character_constant_)
-      return Expression::make_character(&this->val_, this->type_,
+      return Expression::make_character(&this->val_,
+                                       (this->type_ == NULL
+                                        ? NULL
+                                        : this->type_->copy_expressions()),
                                        this->location());
     else
-      return Expression::make_integer_z(&this->val_, this->type_,
+      return Expression::make_integer_z(&this->val_,
+                                       (this->type_ == NULL
+                                        ? NULL
+                                        : this->type_->copy_expressions()),
                                        this->location());
   }
 
@@ -2323,7 +2329,10 @@ class Float_expression : public Expression
 
   Expression*
   do_copy()
-  { return Expression::make_float(&this->val_, this->type_,
+  { return Expression::make_float(&this->val_,
+                                 (this->type_ == NULL
+                                  ? NULL
+                                  : this->type_->copy_expressions()),
                                  this->location()); }
 
   Bexpression*
@@ -2514,7 +2523,10 @@ class Complex_expression : public Expression
   Expression*
   do_copy()
   {
-    return Expression::make_complex(&this->val_, this->type_,
+    return Expression::make_complex(&this->val_,
+                                   (this->type_ == NULL
+                                    ? NULL
+                                    : this->type_->copy_expressions()),
                                    this->location());
   }
 
@@ -3420,6 +3432,16 @@ Type_conversion_expression::do_check_types(Gogo*)
   this->set_is_error();
 }
 
+// Copy.
+
+Expression*
+Type_conversion_expression::do_copy()
+{
+  return new Type_conversion_expression(this->type_->copy_expressions(),
+                                       this->expr_->copy(),
+                                       this->location());
+}
+
 // Get the backend representation for a type conversion.
 
 Bexpression*
@@ -3621,6 +3643,16 @@ Unsafe_type_conversion_expression::do_is_static_initializer() const
   return false;
 }
 
+// Copy.
+
+Expression*
+Unsafe_type_conversion_expression::do_copy()
+{
+  return new Unsafe_type_conversion_expression(this->type_->copy_expressions(),
+                                              this->expr_->copy(),
+                                              this->location());
+}
+
 // Convert to backend representation.
 
 Bexpression*
@@ -12401,7 +12433,8 @@ Expression*
 Allocation_expression::do_copy()
 {
   Allocation_expression* alloc =
-    new Allocation_expression(this->type_, this->location());
+    new Allocation_expression(this->type_->copy_expressions(),
+                             this->location());
   if (this->allocate_on_stack_)
     alloc->set_allocate_on_stack();
   return alloc;
@@ -12641,6 +12674,22 @@ Struct_construction_expression::do_check_types(Gogo*)
   go_assert(pv == this->vals()->end());
 }
 
+// Copy.
+
+Expression*
+Struct_construction_expression::do_copy()
+{
+  Struct_construction_expression* ret =
+    new Struct_construction_expression(this->type_->copy_expressions(),
+                                      (this->vals() == NULL
+                                       ? NULL
+                                       : this->vals()->copy()),
+                                      this->location());
+  if (this->traverse_order() != NULL)
+    ret->set_traverse_order(this->traverse_order());
+  return ret;
+}
+
 // Flatten a struct construction expression.  Store the values into
 // temporaries in case they need interface conversion.
 
@@ -13032,6 +13081,20 @@ Fixed_array_construction_expression::Fixed_array_construction_expression(
                                  type, indexes, vals, location)
 { go_assert(type->array_type() != NULL && !type->is_slice_type()); }
 
+
+// Copy.
+
+Expression*
+Fixed_array_construction_expression::do_copy()
+{
+  Type* t = this->type()->copy_expressions();
+  return new Fixed_array_construction_expression(t, this->indexes(),
+                                                (this->vals() == NULL
+                                                 ? NULL
+                                                 : this->vals()->copy()),
+                                                this->location());
+}
+
 // Return the backend representation for constructing a fixed array.
 
 Bexpression*
@@ -13166,6 +13229,19 @@ dump_slice_storage_expression(Ast_dump_context* ast_dump_context) const
   ast_dump_context->dump_expression(this->slice_storage_);
 }
 
+// Copy.
+
+Expression*
+Slice_construction_expression::do_copy()
+{
+  return new Slice_construction_expression(this->type()->copy_expressions(),
+                                          this->indexes(),
+                                          (this->vals() == NULL
+                                           ? NULL
+                                           : this->vals()->copy()),
+                                          this->location());
+}
+
 // Return the backend representation for constructing a slice.
 
 Bexpression*
@@ -13379,6 +13455,18 @@ Map_construction_expression::do_check_types(Gogo*)
     }
 }
 
+// Copy.
+
+Expression*
+Map_construction_expression::do_copy()
+{
+  return new Map_construction_expression(this->type_->copy_expressions(),
+                                        (this->vals_ == NULL
+                                         ? NULL
+                                         : this->vals_->copy()),
+                                        this->location());
+}
+
 // Return the backend representation for constructing a map.
 
 Bexpression*
@@ -14058,6 +14146,23 @@ Composite_literal_expression::lower_map(Gogo* gogo, Named_object* function,
   return new Map_construction_expression(type, this->vals_, location);
 }
 
+// Copy.
+
+Expression*
+Composite_literal_expression::do_copy()
+{
+  Composite_literal_expression* ret =
+    new Composite_literal_expression(this->type_->copy_expressions(),
+                                    this->depth_, this->has_keys_,
+                                    (this->vals_ == NULL
+                                     ? NULL
+                                     : this->vals_->copy()),
+                                    this->all_are_names_,
+                                    this->location());
+  ret->key_path_ = this->key_path_;
+  return ret;
+}
+
 // Dump ast representation for a composite literal expression.
 
 void
@@ -14234,6 +14339,16 @@ Type_guard_expression::do_check_types(Gogo*)
     }
 }
 
+// Copy.
+
+Expression*
+Type_guard_expression::do_copy()
+{
+  return new Type_guard_expression(this->expr_->copy(),
+                                  this->type_->copy_expressions(),
+                                  this->location());
+}
+
 // Return the backend representation for a type guard expression.
 
 Bexpression*
@@ -14961,7 +15076,8 @@ class Slice_value_expression : public Expression
   Expression*
   do_copy()
   {
-    return new Slice_value_expression(this->type_, this->valptr_->copy(),
+    return new Slice_value_expression(this->type_->copy_expressions(),
+                                     this->valptr_->copy(),
                                       this->len_->copy(), this->cap_->copy(),
                                       this->location());
   }
@@ -15222,7 +15338,7 @@ class Interface_value_expression : public Expression
   Expression*
   do_copy()
   {
-    return new Interface_value_expression(this->type_,
+    return new Interface_value_expression(this->type_->copy_expressions(),
                                           this->first_field_->copy(),
                                           this->obj_->copy(), this->location());
   }
@@ -15317,7 +15433,9 @@ class Interface_mtable_expression : public Expression
   Expression*
   do_copy()
   {
-    return new Interface_mtable_expression(this->itype_, this->type_,
+    Interface_type* itype = this->itype_->copy_expressions()->interface_type();
+    return new Interface_mtable_expression(itype,
+                                          this->type_->copy_expressions(),
                                            this->is_pointer_, this->location());
   }
 
@@ -15805,6 +15923,13 @@ Backend_expression::do_traverse(Traverse*)
   return TRAVERSE_CONTINUE;
 }
 
+Expression*
+Backend_expression::do_copy()
+{
+  return new Backend_expression(this->bexpr_, this->type_->copy_expressions(),
+                               this->location());
+}
+
 void
 Backend_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
 {
index 18fd91b054fff1790c65613f3eea8a0f31379aa3..d16a284b6b04c766430f7b0c6ee3c4ad11b0480c 100644 (file)
@@ -1664,11 +1664,7 @@ class Type_conversion_expression : public Expression
   do_check_types(Gogo*);
 
   Expression*
-  do_copy()
-  {
-    return new Type_conversion_expression(this->type_, this->expr_->copy(),
-                                         this->location());
-  }
+  do_copy();
 
   Bexpression*
   do_get_backend(Translate_context* context);
@@ -1720,12 +1716,7 @@ class Unsafe_type_conversion_expression : public Expression
   { this->expr_->determine_type_no_context(); }
 
   Expression*
-  do_copy()
-  {
-    return new Unsafe_type_conversion_expression(this->type_,
-                                                this->expr_->copy(),
-                                                this->location());
-  }
+  do_copy();
 
   Bexpression*
   do_get_backend(Translate_context*);
@@ -3430,19 +3421,7 @@ class Composite_literal_expression : public Parser_expression
   do_lower(Gogo*, Named_object*, Statement_inserter*, int);
 
   Expression*
-  do_copy()
-  {
-    Composite_literal_expression *ret =
-      new Composite_literal_expression(this->type_, this->depth_,
-                                      this->has_keys_,
-                                      (this->vals_ == NULL
-                                       ? NULL
-                                       : this->vals_->copy()),
-                                      this->all_are_names_,
-                                      this->location());
-    ret->key_path_ = this->key_path_;
-    return ret;
-  }
+  do_copy();
 
   void
   do_dump_expression(Ast_dump_context*) const;
@@ -3556,18 +3535,7 @@ class Struct_construction_expression : public Expression,
   do_check_types(Gogo*);
 
   Expression*
-  do_copy()
-  {
-    Struct_construction_expression* ret =
-      new Struct_construction_expression(this->type_,
-                                        (this->vals() == NULL
-                                         ? NULL
-                                         : this->vals()->copy()),
-                                        this->location());
-    if (this->traverse_order() != NULL)
-      ret->set_traverse_order(this->traverse_order());
-    return ret;
-  }
+  do_copy();
 
   Expression*
   do_flatten(Gogo*, Named_object*, Statement_inserter*);
@@ -3671,15 +3639,7 @@ class Fixed_array_construction_expression :
 
  protected:
   Expression*
-  do_copy()
-  {
-    return new Fixed_array_construction_expression(this->type(),
-                                                  this->indexes(),
-                                                  (this->vals() == NULL
-                                                   ? NULL
-                                                   : this->vals()->copy()),
-                                                  this->location());
-  }
+  do_copy();
 
   Bexpression*
   do_get_backend(Translate_context*);
@@ -3712,14 +3672,7 @@ class Slice_construction_expression : public Array_construction_expression
   do_traverse(Traverse* traverse);
 
   Expression*
-  do_copy()
-  {
-    return new Slice_construction_expression(this->type(), this->indexes(),
-                                            (this->vals() == NULL
-                                             ? NULL
-                                             : this->vals()->copy()),
-                                            this->location());
-  }
+  do_copy();
 
   Bexpression*
   do_get_backend(Translate_context*);
@@ -3778,14 +3731,7 @@ class Map_construction_expression : public Expression
   do_check_types(Gogo*);
 
   Expression*
-  do_copy()
-  {
-    return new Map_construction_expression(this->type_,
-                                          (this->vals_ == NULL
-                                           ? NULL
-                                           : this->vals_->copy()),
-                                          this->location());
-  }
+  do_copy();
 
   Bexpression*
   do_get_backend(Translate_context*);
@@ -3846,11 +3792,7 @@ class Type_guard_expression : public Expression
   do_check_types(Gogo*);
 
   Expression*
-  do_copy()
-  {
-    return new Type_guard_expression(this->expr_->copy(), this->type_,
-                                    this->location());
-  }
+  do_copy();
 
   Bexpression*
   do_get_backend(Translate_context*);
@@ -4102,10 +4044,7 @@ class Backend_expression : public Expression
   { }
 
   Expression*
-  do_copy()
-  {
-    return new Backend_expression(this->bexpr_, this->type_, this->location());
-  }
+  do_copy();
 
   Bexpression*
   do_get_backend(Translate_context*)
index cc3791bb84da8f5c90b6e9906577b8c51ebf8df2..4891e758f792fe72dd42c7a2e32a5159cd9cb5da 100644 (file)
@@ -50,7 +50,6 @@ Parse::Parse(Lex* lex, Gogo* gogo)
     gogo_(gogo),
     break_stack_(NULL),
     continue_stack_(NULL),
-    iota_(0),
     enclosing_vars_()
 {
 }
@@ -1407,19 +1406,20 @@ Parse::const_decl()
 {
   go_assert(this->peek_token()->is_keyword(KEYWORD_CONST));
   this->advance_token();
-  this->reset_iota();
 
+  int iota = 0;
   Type* last_type = NULL;
   Expression_list* last_expr_list = NULL;
 
   if (!this->peek_token()->is_op(OPERATOR_LPAREN))
-    this->const_spec(&last_type, &last_expr_list);
+    this->const_spec(iota, &last_type, &last_expr_list);
   else
     {
       this->advance_token();
       while (!this->peek_token()->is_op(OPERATOR_RPAREN))
        {
-         this->const_spec(&last_type, &last_expr_list);
+         this->const_spec(iota, &last_type, &last_expr_list);
+         ++iota;
          if (this->peek_token()->is_op(OPERATOR_SEMICOLON))
            this->advance_token();
          else if (!this->peek_token()->is_op(OPERATOR_RPAREN))
@@ -1440,7 +1440,7 @@ Parse::const_decl()
 // ConstSpec = IdentifierList [ [ CompleteType ] "=" ExpressionList ] .
 
 void
-Parse::const_spec(Type** last_type, Expression_list** last_expr_list)
+Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list)
 {
   Typed_identifier_list til;
   this->identifier_list(&til);
@@ -1492,7 +1492,7 @@ Parse::const_spec(Type** last_type, Expression_list** last_expr_list)
        pi->set_type(type);
 
       if (!Gogo::is_sink_name(pi->name()))
-       this->gogo_->add_constant(*pi, *pe, this->iota_value());
+       this->gogo_->add_constant(*pi, *pe, iota);
       else
        {
          static int count;
@@ -1500,15 +1500,13 @@ Parse::const_spec(Type** last_type, Expression_list** last_expr_list)
          snprintf(buf, sizeof buf, ".$sinkconst%d", count);
          ++count;
          Typed_identifier ti(std::string(buf), type, pi->location());
-         Named_object* no = this->gogo_->add_constant(ti, *pe, this->iota_value());
+         Named_object* no = this->gogo_->add_constant(ti, *pe, iota);
          no->const_value()->set_is_sink();
        }
     }
   if (pe != expr_list->end())
     go_error_at(this->location(), "too many initializers");
 
-  this->increment_iota();
-
   return;
 }
 
@@ -5838,30 +5836,6 @@ Parse::program()
     }
 }
 
-// Reset the current iota value.
-
-void
-Parse::reset_iota()
-{
-  this->iota_ = 0;
-}
-
-// Return the current iota value.
-
-int
-Parse::iota_value()
-{
-  return this->iota_;
-}
-
-// Increment the current iota value.
-
-void
-Parse::increment_iota()
-{
-  ++this->iota_;
-}
-
 // Skip forward to a semicolon or OP.  OP will normally be
 // OPERATOR_RPAREN or OPERATOR_RCURLY.  If we find a semicolon, move
 // past it and return.  If we find OP, it will be the next token to
index 2ba84579e6c0dd29661d7de57eb1af8605026418..f309ee05469a4cba48a5af2db0c28f9791e129a6 100644 (file)
@@ -7,7 +7,6 @@
 #ifndef GO_PARSE_H
 #define GO_PARSE_H
 
-class Set_iota_traverse;
 class Lex;
 class Gogo;
 class Named_object;
@@ -185,7 +184,7 @@ class Parse
   void decl(void (Parse::*)(void*, unsigned int), void*, unsigned int pragmas);
   void list(void (Parse::*)(void*, unsigned int), void*, bool);
   void const_decl();
-  void const_spec(Type**, Expression_list**);
+  void const_spec(int, Type**, Expression_list**);
   void type_decl(unsigned int pragmas);
   void type_spec(void*, unsigned int pragmas);
   void var_decl();
@@ -280,10 +279,6 @@ class Parse
   void import_decl();
   void import_spec(void*, unsigned int pragmas);
 
-  void reset_iota();
-  int iota_value();
-  void increment_iota();
-
   // Skip past an error looking for a semicolon or OP.  Return true if
   // all is well, false if we found EOF.
   bool
@@ -319,8 +314,6 @@ class Parse
   Bc_stack* break_stack_;
   // A stack of statements for which continue may be used.
   Bc_stack* continue_stack_;
-  // The current iota value.
-  int iota_;
   // References from the local function to variables defined in
   // enclosing functions.
   Enclosing_vars enclosing_vars_;
index ea9d81d4e24dfd13d9e51a50b5a3efe4c8b60763..34edf7628352eb7a8cd1359e76fa3c612439427f 100644 (file)
@@ -868,6 +868,68 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
   return false;
 }
 
+// Copy expressions if it may change the size.
+//
+// The only type that has an expression is an array type.  The only
+// types whose size can be changed by the size of an array type are an
+// array type itself, or a struct type with an array field.
+Type*
+Type::copy_expressions()
+{
+  // This is run during parsing, so types may not be valid yet.
+  // We only have to worry about array type literals.
+  switch (this->classification_)
+    {
+    default:
+      return this;
+
+    case TYPE_ARRAY:
+      {
+       Array_type* at = this->array_type();
+       if (at->length() == NULL)
+         return this;
+       Expression* len = at->length()->copy();
+       if (at->length() == len)
+         return this;
+       return Type::make_array_type(at->element_type(), len);
+      }
+
+    case TYPE_STRUCT:
+      {
+       Struct_type* st = this->struct_type();
+       const Struct_field_list* sfl = st->fields();
+       if (sfl == NULL)
+         return this;
+       bool changed = false;
+       Struct_field_list *nsfl = new Struct_field_list();
+       for (Struct_field_list::const_iterator pf = sfl->begin();
+            pf != sfl->end();
+            ++pf)
+         {
+           Type* ft = pf->type()->copy_expressions();
+           Struct_field nf(Typed_identifier((pf->is_anonymous()
+                                             ? ""
+                                             : pf->field_name()),
+                                            ft,
+                                            pf->location()));
+           if (pf->has_tag())
+             nf.set_tag(pf->tag());
+           nsfl->push_back(nf);
+           if (ft != pf->type())
+             changed = true;
+         }
+       if (!changed)
+         {
+           delete(nsfl);
+           return this;
+         }
+       return Type::make_struct_type(nsfl, st->location());
+      }
+    }
+
+  go_unreachable();
+}
+
 // Return a hash code for the type to be used for method lookup.
 
 unsigned int
index 4e060a4db110e3f86ca904e5beec7f134f5d895f..648773131ca6f43da3a6a466f763fde05bfd17cb 100644 (file)
@@ -916,6 +916,15 @@ class Type
   is_unsafe_pointer_type() const
   { return this->points_to() != NULL && this->points_to()->is_void_type(); }
 
+  // Return a version of this type with any expressions copied, but
+  // only if copying the expressions will affect the size of the type.
+  // If there are no such expressions in the type (expressions can
+  // only occur in array types), just return the same type.  If any
+  // expressions can not affect the size of the type, just return the
+  // same type.
+  Type*
+  copy_expressions();
+
   // Look for field or method NAME for TYPE.  Return an expression for
   // it, bound to EXPR.
   static Expression*
@@ -2444,6 +2453,11 @@ class Struct_type : public Type
   field_count() const
   { return this->fields_->size(); }
 
+  // Location of struct definition.
+  Location
+  location() const
+  { return this->location_; }
+
   // Push a new field onto the end of the struct.  This is used when
   // building a closure variable.
   void