Back in December 2011 I changed the Go frontend to permit assigning
structs with hidden fields
(https://gcc.gnu.org/ml/gcc-patches/2011-12/msg00632.html).  At the
time the language change was somewhat experimental, so I left the old
code.  The language change has clearly stuck, and that old code is
never used.  This patch removes it.  Bootstrapped and ran Go testsuite
on x86_64-unknown-linux-gnu.  Committed to mainline.

Ian
diff -r dd6bc37fcf2d go/expressions.cc
--- a/go/expressions.cc Mon Oct 20 12:10:55 2014 -0700
+++ b/go/expressions.cc Tue Oct 21 08:34:29 2014 -0700
@@ -9305,13 +9305,7 @@
                                     bool issued_error)
 {
   std::string reason;
-  bool ok;
-  if (this->are_hidden_fields_ok_)
-    ok = Type::are_assignable_hidden_ok(parameter_type, argument_type,
-                                       &reason);
-  else
-    ok = Type::are_assignable(parameter_type, argument_type, &reason);
-  if (!ok)
+  if (!Type::are_assignable(parameter_type, argument_type, &reason))
     {
       if (!issued_error)
        {
@@ -9359,13 +9353,11 @@
       go_assert(this->args_ != NULL && !this->args_->empty());
       Type* rtype = fntype->receiver()->type();
       Expression* first_arg = this->args_->front();
-      // The language permits copying hidden fields for a method
-      // receiver.  We dereference the values since receivers are
-      // always passed as pointers.
+      // We dereference the values since receivers are always passed
+      // as pointers.
       std::string reason;
-      if (!Type::are_assignable_hidden_ok(rtype->deref(),
-                                         first_arg->type()->deref(),
-                                         &reason))
+      if (!Type::are_assignable(rtype->deref(), first_arg->type()->deref(),
+                               &reason))
        {
          if (reason.empty())
            this->report_error(_("incompatible type for receiver"));
diff -r dd6bc37fcf2d go/expressions.h
--- a/go/expressions.h  Mon Oct 20 12:10:55 2014 -0700
+++ b/go/expressions.h  Tue Oct 21 08:34:29 2014 -0700
@@ -1617,8 +1617,8 @@
     : Expression(EXPRESSION_CALL, location),
       fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL),
       call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs),
-      are_hidden_fields_ok_(false), varargs_are_lowered_(false),
-      types_are_determined_(false), is_deferred_(false), issued_error_(false)
+      varargs_are_lowered_(false), types_are_determined_(false),
+      is_deferred_(false), issued_error_(false)
   { }
 
   // The function to call.
@@ -1674,12 +1674,6 @@
   set_varargs_are_lowered()
   { this->varargs_are_lowered_ = true; }
 
-  // Note that it is OK for this call to set hidden fields when
-  // passing arguments.
-  void
-  set_hidden_fields_are_ok()
-  { this->are_hidden_fields_ok_ = true; }
-
   // Whether this call is being deferred.
   bool
   is_deferred() const
@@ -1788,9 +1782,6 @@
   size_t expected_result_count_;
   // True if the last argument is a varargs argument (f(a...)).
   bool is_varargs_;
-  // True if this statement may pass hidden fields in the arguments.
-  // This is used for generated method stubs.
-  bool are_hidden_fields_ok_;
   // True if varargs have already been lowered.
   bool varargs_are_lowered_;
   // True if types have been determined.
diff -r dd6bc37fcf2d go/statements.cc
--- a/go/statements.cc  Mon Oct 20 12:10:55 2014 -0700
+++ b/go/statements.cc  Tue Oct 21 08:34:29 2014 -0700
@@ -409,13 +409,7 @@
   if (this->type_ != NULL && this->init_ != NULL)
     {
       std::string reason;
-      bool ok;
-      if (this->are_hidden_fields_ok_)
-       ok = Type::are_assignable_hidden_ok(this->type_, this->init_->type(),
-                                           &reason);
-      else
-       ok = Type::are_assignable(this->type_, this->init_->type(), &reason);
-      if (!ok)
+      if (!Type::are_assignable(this->type_, this->init_->type(), &reason))
        {
          if (reason.empty())
            error_at(this->location(), "incompatible types in assignment");
@@ -511,15 +505,9 @@
   Assignment_statement(Expression* lhs, Expression* rhs,
                       Location location)
     : Statement(STATEMENT_ASSIGNMENT, location),
-      lhs_(lhs), rhs_(rhs), are_hidden_fields_ok_(false)
+      lhs_(lhs), rhs_(rhs)
   { }
 
-  // Note that it is OK for this assignment statement to set hidden
-  // fields.
-  void
-  set_hidden_fields_are_ok()
-  { this->are_hidden_fields_ok_ = true; }
-
  protected:
   int
   do_traverse(Traverse* traverse);
@@ -544,9 +532,6 @@
   Expression* lhs_;
   // Right hand side--the rvalue.
   Expression* rhs_;
-  // True if this statement may set hidden fields in the assignment
-  // statement.  This is used for generated method stubs.
-  bool are_hidden_fields_ok_;
 };
 
 // Traversal.
@@ -607,12 +592,7 @@
     }
 
   std::string reason;
-  bool ok;
-  if (this->are_hidden_fields_ok_)
-    ok = Type::are_assignable_hidden_ok(lhs_type, rhs_type, &reason);
-  else
-    ok = Type::are_assignable(lhs_type, rhs_type, &reason);
-  if (!ok)
+  if (!Type::are_assignable(lhs_type, rhs_type, &reason))
     {
       if (reason.empty())
        error_at(this->location(), "incompatible types in assignment");
@@ -905,15 +885,9 @@
   Tuple_assignment_statement(Expression_list* lhs, Expression_list* rhs,
                             Location location)
     : Statement(STATEMENT_TUPLE_ASSIGNMENT, location),
-      lhs_(lhs), rhs_(rhs), are_hidden_fields_ok_(false)
+      lhs_(lhs), rhs_(rhs)
   { }
 
-  // Note that it is OK for this assignment statement to set hidden
-  // fields.
-  void
-  set_hidden_fields_are_ok()
-  { this->are_hidden_fields_ok_ = true; }
-
  protected:
   int
   do_traverse(Traverse* traverse);
@@ -937,9 +911,6 @@
   Expression_list* lhs_;
   // Right hand side--a list of rvalues.
   Expression_list* rhs_;
-  // True if this statement may set hidden fields in the assignment
-  // statement.  This is used for generated method stubs.
-  bool are_hidden_fields_ok_;
 };
 
 // Traversal.
@@ -998,8 +969,6 @@
 
       Temporary_statement* temp = Statement::make_temporary((*plhs)->type(),
                                                            *prhs, loc);
-      if (this->are_hidden_fields_ok_)
-       temp->set_hidden_fields_are_ok();
       b->add_statement(temp);
       temps.push_back(temp);
 
@@ -1022,13 +991,7 @@
        continue;
 
       Expression* ref = Expression::make_temporary_reference(*ptemp, loc);
-      Statement* s = Statement::make_assignment(*plhs, ref, loc);
-      if (this->are_hidden_fields_ok_)
-       {
-         Assignment_statement* as = static_cast<Assignment_statement*>(s);
-         as->set_hidden_fields_are_ok();
-       }
-      b->add_statement(s);
+      b->add_statement(Statement::make_assignment(*plhs, ref, loc));
       ++ptemp;
     }
   go_assert(ptemp == temps.end() || saw_errors());
@@ -2736,12 +2699,7 @@
       e->determine_type(&type_context);
 
       std::string reason;
-      bool ok;
-      if (this->are_hidden_fields_ok_)
-       ok = Type::are_assignable_hidden_ok(rvtype, e->type(), &reason);
-      else
-       ok = Type::are_assignable(rvtype, e->type(), &reason);
-      if (ok)
+      if (Type::are_assignable(rvtype, e->type(), &reason))
        {
          Expression* ve = Expression::make_var_reference(rv, e->location());
          lhs->push_back(ve);
@@ -2763,28 +2721,13 @@
     ;
   else if (lhs->size() == 1)
     {
-      Statement* s = Statement::make_assignment(lhs->front(), rhs->front(),
-                                               loc);
-      if (this->are_hidden_fields_ok_)
-       {
-         Assignment_statement* as = static_cast<Assignment_statement*>(s);
-         as->set_hidden_fields_are_ok();
-       }
-      b->add_statement(s);
+      b->add_statement(Statement::make_assignment(lhs->front(), rhs->front(),
+                                                 loc));
       delete lhs;
       delete rhs;
     }
   else
-    {
-      Statement* s = Statement::make_tuple_assignment(lhs, rhs, loc);
-      if (this->are_hidden_fields_ok_)
-       {
-         Tuple_assignment_statement* tas =
-           static_cast<Tuple_assignment_statement*>(s);
-         tas->set_hidden_fields_are_ok();
-       }
-      b->add_statement(s);
-    }
+    b->add_statement(Statement::make_tuple_assignment(lhs, rhs, loc));
 
   b->add_statement(this);
 
diff -r dd6bc37fcf2d go/statements.h
--- a/go/statements.h   Mon Oct 20 12:10:55 2014 -0700
+++ b/go/statements.h   Tue Oct 21 08:34:29 2014 -0700
@@ -514,8 +514,7 @@
  public:
   Temporary_statement(Type* type, Expression* init, Location location)
     : Statement(STATEMENT_TEMPORARY, location),
-      type_(type), init_(init), bvariable_(NULL), are_hidden_fields_ok_(false),
-      is_address_taken_(false)
+      type_(type), init_(init), bvariable_(NULL), is_address_taken_(false)
   { }
 
   // Return the type of the temporary variable.
@@ -527,11 +526,6 @@
   init() const
   { return this->init_; }
 
-  // Note that it is OK for this statement to set hidden fields.
-  void
-  set_hidden_fields_are_ok()
-  { this->are_hidden_fields_ok_ = true; }
-
   // Record that something takes the address of this temporary
   // variable.
   void
@@ -569,9 +563,6 @@
   Expression* init_;
   // The backend representation of the temporary variable.
   Bvariable* bvariable_;
-  // True if this statement may set hidden fields when assigning the
-  // value to the temporary.  This is used for generated method stubs.
-  bool are_hidden_fields_ok_;
   // True if something takes the address of this temporary variable.
   bool is_address_taken_;
 };
@@ -619,7 +610,7 @@
  public:
   Return_statement(Expression_list* vals, Location location)
     : Statement(STATEMENT_RETURN, location),
-      vals_(vals), are_hidden_fields_ok_(false), is_lowered_(false)
+      vals_(vals), is_lowered_(false)
   { }
 
   // The list of values being returned.  This may be NULL.
@@ -627,12 +618,6 @@
   vals() const
   { return this->vals_; }
 
-  // Note that it is OK for this return statement to set hidden
-  // fields.
-  void
-  set_hidden_fields_are_ok()
-  { this->are_hidden_fields_ok_ = true; }
-
  protected:
   int
   do_traverse(Traverse* traverse)
@@ -657,9 +642,6 @@
  private:
   // Return values.  This may be NULL.
   Expression_list* vals_;
-  // True if this statement may pass hidden fields in the return
-  // value.  This is used for generated method stubs.
-  bool are_hidden_fields_ok_;
   // True if this statement has been lowered.
   bool is_lowered_;
 };
diff -r dd6bc37fcf2d go/types.cc
--- a/go/types.cc       Mon Oct 20 12:10:55 2014 -0700
+++ b/go/types.cc       Tue Oct 21 08:34:29 2014 -0700
@@ -594,14 +594,11 @@
 }
 
 // Return true if a value with type RHS may be assigned to a variable
-// with type LHS.  If CHECK_HIDDEN_FIELDS is true, check whether any
-// hidden fields are modified.  If REASON is not NULL, set *REASON to
-// the reason the types are not assignable.
+// with type LHS.  If REASON is not NULL, set *REASON to the reason
+// the types are not assignable.
 
 bool
-Type::are_assignable_check_hidden(const Type* lhs, const Type* rhs,
-                                 bool check_hidden_fields,
-                                 std::string* reason)
+Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
 {
   // Do some checks first.  Make sure the types are defined.
   if (rhs != NULL && !rhs->is_undefined())
@@ -621,21 +618,11 @@
        }
     }
 
-  if (lhs != NULL && !lhs->is_undefined())
-    {
-      // Any value may be assigned to the blank identifier.
-      if (lhs->is_sink_type())
-       return true;
-
-      // All fields of a struct must be exported, or the assignment
-      // must be in the same package.
-      if (check_hidden_fields && rhs != NULL && !rhs->is_undefined())
-       {
-         if (lhs->has_hidden_fields(NULL, reason)
-             || rhs->has_hidden_fields(NULL, reason))
-           return false;
-       }
-    }
+  // Any value may be assigned to the blank identifier.
+  if (lhs != NULL
+      && !lhs->is_undefined()
+      && lhs->is_sink_type())
+    return true;
 
   // Identical types are assignable.
   if (Type::are_identical(lhs, rhs, true, reason))
@@ -720,25 +707,6 @@
   return false;
 }
 
-// Return true if a value with type RHS may be assigned to a variable
-// with type LHS.  If REASON is not NULL, set *REASON to the reason
-// the types are not assignable.
-
-bool
-Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
-{
-  return Type::are_assignable_check_hidden(lhs, rhs, false, reason);
-}
-
-// Like are_assignable but don't check for hidden fields.
-
-bool
-Type::are_assignable_hidden_ok(const Type* lhs, const Type* rhs,
-                              std::string* reason)
-{
-  return Type::are_assignable_check_hidden(lhs, rhs, false, reason);
-}
-
 // Return true if a value with type RHS may be converted to type LHS.
 // If REASON is not NULL, set *REASON to the reason the types are not
 // convertible.
@@ -833,25 +801,6 @@
   return false;
 }
 
-// Return whether this type has any hidden fields.  This is only a
-// possibility for a few types.
-
-bool
-Type::has_hidden_fields(const Named_type* within, std::string* reason) const
-{
-  switch (this->forwarded()->classification_)
-    {
-    case TYPE_NAMED:
-      return this->named_type()->named_type_has_hidden_fields(reason);
-    case TYPE_STRUCT:
-      return this->struct_type()->struct_has_hidden_fields(within, reason);
-    case TYPE_ARRAY:
-      return this->array_type()->array_has_hidden_fields(within, reason);
-    default:
-      return false;
-    }
-}
-
 // Return a hash code for the type to be used for method lookup.
 
 unsigned int
@@ -4828,49 +4777,6 @@
   return true;
 }
 
-// Whether this struct type has any hidden fields.
-
-bool
-Struct_type::struct_has_hidden_fields(const Named_type* within,
-                                     std::string* reason) const
-{
-  const Struct_field_list* fields = this->fields();
-  if (fields == NULL)
-    return false;
-  const Package* within_package = (within == NULL
-                                  ? NULL
-                                  : within->named_object()->package());
-  for (Struct_field_list::const_iterator pf = fields->begin();
-       pf != fields->end();
-       ++pf)
-    {
-      if (within_package != NULL
-         && !pf->is_anonymous()
-         && Gogo::is_hidden_name(pf->field_name()))
-       {
-         if (reason != NULL)
-           {
-             std::string within_name = within->named_object()->message_name();
-             std::string name = Gogo::message_name(pf->field_name());
-             size_t bufsize = 200 + within_name.length() + name.length();
-             char* buf = new char[bufsize];
-             snprintf(buf, bufsize,
-                      _("implicit assignment of %s%s%s hidden field %s%s%s"),
-                      open_quote, within_name.c_str(), close_quote,
-                      open_quote, name.c_str(), close_quote);
-             reason->assign(buf);
-             delete[] buf;
-           }
-         return true;
-       }
-
-      if (pf->type()->has_hidden_fields(within, reason))
-       return true;
-    }
-
-  return false;
-}
-
 // Whether comparisons of this struct type are simple identity
 // comparisons.
 
@@ -8633,19 +8539,6 @@
                                       &this->pointer_interface_method_tables_);
 }
 
-// Return whether a named type has any hidden fields.
-
-bool
-Named_type::named_type_has_hidden_fields(std::string* reason) const
-{
-  if (this->seen_)
-    return false;
-  this->seen_ = true;
-  bool ret = this->type_->has_hidden_fields(this, reason);
-  this->seen_ = false;
-  return ret;
-}
-
 // Look for a use of a complete type within another type.  This is
 // used to check that we don't try to use a type within itself.
 
@@ -9772,17 +9665,8 @@
   go_assert(func != NULL);
   Call_expression* call = Expression::make_call(func, arguments, is_varargs,
                                                location);
-  call->set_hidden_fields_are_ok();
-
-  Statement* s = Statement::make_return_from_call(call, location);
-  Return_statement* retstat = s->return_statement();
-  if (retstat != NULL)
-    {
-      // We can return values with hidden fields from a stub.  This is
-      // necessary if the method is itself hidden.
-      retstat->set_hidden_fields_are_ok();
-    }
-  gogo->add_statement(s);
+
+  gogo->add_statement(Statement::make_return_from_call(call, location));
 }
 
 // Apply FIELD_INDEXES to EXPR.  The field indexes have to be applied
diff -r dd6bc37fcf2d go/types.h
--- a/go/types.h        Mon Oct 20 12:10:55 2014 -0700
+++ b/go/types.h        Tue Oct 21 08:34:29 2014 -0700
@@ -611,27 +611,12 @@
   static bool
   are_assignable(const Type* lhs, const Type* rhs, std::string* reason);
 
-  // Return true if a value with type RHS is assignable to a variable
-  // with type LHS, ignoring any assignment of hidden fields
-  // (unexported fields of a type imported from another package).
-  // This is like the are_assignable method.
-  static bool
-  are_assignable_hidden_ok(const Type* lhs, const Type* rhs,
-                          std::string* reason);
-
   // Return true if a value with type RHS may be converted to type
   // LHS.  If this returns false, and REASON is not NULL, it sets
   // *REASON.
   static bool
   are_convertible(const Type* lhs, const Type* rhs, std::string* reason);
 
-  // Whether this type has any hidden fields which are not visible in
-  // the current compilation, such as a field whose name begins with a
-  // lower case letter in a struct imported from a different package.
-  // WITHIN is not NULL if we are looking at fields in a named type.
-  bool
-  has_hidden_fields(const Named_type* within, std::string* reason) const;
-
   // Return true if values of this type can be compared using an
   // identity function which gets nothing but a pointer to the value
   // and a size.
@@ -1160,11 +1145,6 @@
            : NULL);
   }
 
-  // Support for are_assignable and are_assignable_hidden_ok.
-  static bool
-  are_assignable_check_hidden(const Type* lhs, const Type* rhs,
-                             bool check_hidden_fields, std::string* reason);
-
   // Map unnamed types to type descriptor decls.
   typedef Unordered_map_hash(const Type*, Bvariable*, Type_hash_identical,
                             Type_identical) Type_descriptor_vars;
@@ -2236,12 +2216,6 @@
   bool
   is_identical(const Struct_type* t, bool errors_are_identical) const;
 
-  // Whether this struct type has any hidden fields.  This returns
-  // true if any fields have hidden names, or if any non-pointer
-  // anonymous fields have types with hidden fields.
-  bool
-  struct_has_hidden_fields(const Named_type* within, std::string*) const;
-
   // Return whether NAME is a local field which is not exported.  This
   // is only used for better error reporting.
   bool
@@ -2403,11 +2377,6 @@
   bool
   is_identical(const Array_type* t, bool errors_are_identical) const;
 
-  // Whether this type has any hidden fields.
-  bool
-  array_has_hidden_fields(const Named_type* within, std::string* reason) const
-  { return this->element_type_->has_hidden_fields(within, reason); }
-
   // Return an expression for the pointer to the values in an array.
   Expression*
   get_value_pointer(Gogo*, Expression* array) const;
@@ -3037,10 +3006,6 @@
   Expression*
   interface_method_table(Interface_type* interface, bool is_pointer);
 
-  // Whether this type has any hidden fields.
-  bool
-  named_type_has_hidden_fields(std::string* reason) const;
-
   // Note that a type must be converted to the backend representation
   // before we convert this type.
   void
@@ -3160,10 +3125,10 @@
   bool is_circular_;
   // Whether this type has been verified.
   bool is_verified_;
-  // In a recursive operation such as has_hidden_fields, this flag is
-  // used to prevent infinite recursion when a type refers to itself.
-  // This is mutable because it is always reset to false when the
-  // function exits.
+  // In a recursive operation such as has_pointer, this flag is used
+  // to prevent infinite recursion when a type refers to itself.  This
+  // is mutable because it is always reset to false when the function
+  // exits.
   mutable bool seen_;
   // Like seen_, but used only by do_compare_is_identity.
   bool seen_in_compare_is_identity_;

Reply via email to