Permit copying hidden fields when passing method receiver.
From-SVN: r171641
This commit is contained in:
parent
2b80199f41
commit
e867454908
4 changed files with 46 additions and 8 deletions
|
@ -8558,10 +8558,11 @@ Call_expression::do_check_types(Gogo*)
|
|||
if (first_arg_type->points_to() == NULL)
|
||||
{
|
||||
// When passing a value, we need to check that we are
|
||||
// permitted to copy it.
|
||||
// permitted to copy it. The language permits copying
|
||||
// hidden fields for a method receiver.
|
||||
std::string reason;
|
||||
if (!Type::are_assignable(fntype->receiver()->type(),
|
||||
first_arg_type, &reason))
|
||||
if (!Type::are_assignable_hidden_ok(fntype->receiver()->type(),
|
||||
first_arg_type, &reason))
|
||||
{
|
||||
if (reason.empty())
|
||||
this->report_error(_("incompatible type for receiver"));
|
||||
|
|
|
@ -475,11 +475,14 @@ Type::are_compatible_for_binop(const Type* lhs, const Type* rhs)
|
|||
}
|
||||
|
||||
// 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.
|
||||
// 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.
|
||||
|
||||
bool
|
||||
Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
|
||||
Type::are_assignable_check_hidden(const Type* lhs, const Type* rhs,
|
||||
bool check_hidden_fields,
|
||||
std::string* reason)
|
||||
{
|
||||
// Do some checks first. Make sure the types are defined.
|
||||
if (rhs != NULL
|
||||
|
@ -499,7 +502,9 @@ Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
|
|||
|
||||
// All fields of a struct must be exported, or the assignment
|
||||
// must be in the same package.
|
||||
if (rhs != NULL && rhs->forwarded()->forward_declaration_type() == NULL)
|
||||
if (check_hidden_fields
|
||||
&& rhs != NULL
|
||||
&& rhs->forwarded()->forward_declaration_type() == NULL)
|
||||
{
|
||||
if (lhs->has_hidden_fields(NULL, reason)
|
||||
|| rhs->has_hidden_fields(NULL, reason))
|
||||
|
@ -593,6 +598,25 @@ Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
|
|||
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, true, 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.
|
||||
|
|
|
@ -521,6 +521,14 @@ 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.
|
||||
|
@ -1011,6 +1019,11 @@ 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);
|
||||
|
||||
// Get the hash and equality functions for a type.
|
||||
void
|
||||
type_functions(const char** hash_fn, const char** equal_fn) const;
|
||||
|
|
|
@ -15,7 +15,7 @@ func f() {
|
|||
_ = x.T{};
|
||||
_ = x.T{Y:2};
|
||||
|
||||
ok1.M(); // ERROR "assignment.*T"
|
||||
ok1.M();
|
||||
bad1 := *ok; // ERROR "assignment.*T"
|
||||
bad2 := ok1; // ERROR "assignment.*T"
|
||||
*ok4 = ok1; // ERROR "assignment.*T"
|
||||
|
|
Loading…
Add table
Reference in a new issue