Commit 5900d755 by Ian Lance Taylor

compiler: Remove obsolete hidden_fields_are_ok code.

The language used to forbid assigning structs with hidden
fields, but that was changed before the Go 1 release.  At the
time the change was experimental, so I left the old code in
the compiler.  At this point it's clearly not experimental, so
this removes the unused code.

From-SVN: r216519
parent dd637013
......@@ -9305,13 +9305,7 @@ Call_expression::check_argument_type(int i, const Type* parameter_type,
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 @@ Call_expression::do_check_types(Gogo*)
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"));
......
......@@ -1617,8 +1617,8 @@ class Call_expression : public Expression
: 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 @@ class Call_expression : public Expression
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 @@ class Call_expression : public Expression
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.
......
......@@ -409,13 +409,7 @@ Temporary_statement::do_check_types(Gogo*)
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 @@ class Assignment_statement : public Statement
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 @@ class Assignment_statement : public Statement
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 @@ Assignment_statement::do_check_types(Gogo*)
}
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 @@ class Tuple_assignment_statement : public Statement
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 @@ class Tuple_assignment_statement : public Statement
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 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
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 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
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 @@ Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
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 @@ Return_statement::do_lower(Gogo*, Named_object* function, Block* enclosing,
;
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);
......
......@@ -514,8 +514,7 @@ class Temporary_statement : public Statement
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 @@ class Temporary_statement : public Statement
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 @@ class Temporary_statement : public Statement
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 @@ class Return_statement : public Statement
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 @@ class Return_statement : public Statement
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 @@ class Return_statement : public Statement
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_;
};
......
......@@ -594,14 +594,11 @@ Type::are_compatible_for_comparison(bool is_equality_op, const Type *t1,
}
// 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 @@ Type::are_assignable_check_hidden(const Type* lhs, const Type* rhs,
}
}
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 @@ Type::are_assignable_check_hidden(const Type* lhs, const Type* rhs,
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 @@ Type::are_convertible(const Type* lhs, const Type* rhs, std::string* reason)
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 @@ Struct_type::is_identical(const Struct_type* t,
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 @@ Named_type::interface_method_table(Interface_type* interface, bool is_pointer)
&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 @@ Type::build_one_stub_method(Gogo* gogo, Method* method,
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
......
......@@ -611,27 +611,12 @@ class Type
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 @@ class Type
: 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 @@ class Struct_type : public Type
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 @@ class Array_type : public Type
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 @@ class Named_type : public Type
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 @@ class Named_type : public Type
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_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment