Commit e8674549 by Ian Lance Taylor

Permit copying hidden fields when passing method receiver.

From-SVN: r171641
parent 2b80199f
...@@ -8558,9 +8558,10 @@ Call_expression::do_check_types(Gogo*) ...@@ -8558,9 +8558,10 @@ Call_expression::do_check_types(Gogo*)
if (first_arg_type->points_to() == NULL) if (first_arg_type->points_to() == NULL)
{ {
// When passing a value, we need to check that we are // 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; std::string reason;
if (!Type::are_assignable(fntype->receiver()->type(), if (!Type::are_assignable_hidden_ok(fntype->receiver()->type(),
first_arg_type, &reason)) first_arg_type, &reason))
{ {
if (reason.empty()) if (reason.empty())
......
...@@ -475,11 +475,14 @@ Type::are_compatible_for_binop(const Type* lhs, const Type* rhs) ...@@ -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 // 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 // with type LHS. If CHECK_HIDDEN_FIELDS is true, check whether any
// the types are not assignable. // hidden fields are modified. If REASON is not NULL, set *REASON to
// the reason the types are not assignable.
bool 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. // Do some checks first. Make sure the types are defined.
if (rhs != NULL if (rhs != NULL
...@@ -499,7 +502,9 @@ Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason) ...@@ -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 // All fields of a struct must be exported, or the assignment
// must be in the same package. // 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) if (lhs->has_hidden_fields(NULL, reason)
|| rhs->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) ...@@ -593,6 +598,25 @@ Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
return false; 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. // 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 // If REASON is not NULL, set *REASON to the reason the types are not
// convertible. // convertible.
......
...@@ -521,6 +521,14 @@ class Type ...@@ -521,6 +521,14 @@ class Type
static bool static bool
are_assignable(const Type* lhs, const Type* rhs, std::string* reason); 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 // 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 // LHS. If this returns false, and REASON is not NULL, it sets
// *REASON. // *REASON.
...@@ -1011,6 +1019,11 @@ class Type ...@@ -1011,6 +1019,11 @@ class Type
: NULL); : 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. // Get the hash and equality functions for a type.
void void
type_functions(const char** hash_fn, const char** equal_fn) const; type_functions(const char** hash_fn, const char** equal_fn) const;
......
...@@ -15,7 +15,7 @@ func f() { ...@@ -15,7 +15,7 @@ func f() {
_ = x.T{}; _ = x.T{};
_ = x.T{Y:2}; _ = x.T{Y:2};
ok1.M(); // ERROR "assignment.*T" ok1.M();
bad1 := *ok; // ERROR "assignment.*T" bad1 := *ok; // ERROR "assignment.*T"
bad2 := ok1; // ERROR "assignment.*T" bad2 := ok1; // ERROR "assignment.*T"
*ok4 = ok1; // ERROR "assignment.*T" *ok4 = ok1; // ERROR "assignment.*T"
......
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