From: Ian Lance Taylor Date: Mon, 28 Mar 2011 23:54:33 +0000 (+0000) Subject: Permit copying hidden fields when passing method receiver. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e867454908aaa8192f214865b3978a104671fe45;p=gcc.git Permit copying hidden fields when passing method receiver. From-SVN: r171641 --- diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index d1de2037b9e..791ab073a44 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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")); diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 47dbc162c99..0aef9ce4cc5 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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. diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 24f425bd8b9..3255d37ff9e 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -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; diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug226.dir/y.go b/gcc/testsuite/go.test/test/fixedbugs/bug226.dir/y.go index 01e8b7b4373..c66d592b7c0 100644 --- a/gcc/testsuite/go.test/test/fixedbugs/bug226.dir/y.go +++ b/gcc/testsuite/go.test/test/fixedbugs/bug226.dir/y.go @@ -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"