The Go language has changed to permit structs with hidden fields to be
assigned.  This patch implements that in the gccgo frontend.  Because
the change is somewhat experimental, I did not remove the old code, I
merely stopped executing it.  I will remove it later if the change
sticks.  This change meant that I had to add checks for assignments to
hidden fields in struct composite literals.  Those are still forbidden,
and were previously picked up by the check on assignment.  Bootstrapped
and ran Go testsuite on x86_64-unknown-linux-gnu.  Committed to
mainline.

Ian

Index: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 181938)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -605,7 +605,7 @@ Type::are_assignable_check_hidden(const 
 bool
 Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
 {
-  return Type::are_assignable_check_hidden(lhs, rhs, true, reason);
+  return Type::are_assignable_check_hidden(lhs, rhs, false, reason);
 }
 
 // Like are_assignable but don't check for hidden fields.
Index: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 181874)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -12817,7 +12817,22 @@ Composite_literal_expression::lower_stru
   Location location = this->location();
   Struct_type* st = type->struct_type();
   if (this->vals_ == NULL || !this->has_keys_)
-    return new Struct_construction_expression(type, this->vals_, location);
+    {
+      if (this->vals_ != NULL && !this->vals_->empty())
+	{
+	  std::string reason;
+	  if (type->has_hidden_fields(NULL, &reason))
+	    {
+	      if (reason.empty())
+		error_at(this->location(),
+			 "implicit assignment of hidden field");
+	      else
+		error_at(this->location(), "%s", reason.c_str());
+	    }
+	}
+
+      return new Struct_construction_expression(type, this->vals_, location);
+    }
 
   size_t field_count = st->field_count();
   std::vector<Expression*> vals(field_count);
@@ -12964,6 +12979,26 @@ Composite_literal_expression::lower_stru
 	  return Expression::make_error(location);
 	}
 
+      if (type->named_type() != NULL
+	  && type->named_type()->named_object()->package() != NULL
+	  && Gogo::is_hidden_name(sf->field_name()))
+	error_at(name_expr->location(),
+		 "assignment of unexported field %qs in %qs literal",
+		 Gogo::message_name(sf->field_name()).c_str(),
+		 type->named_type()->message_name().c_str());
+      else
+	{
+	  std::string reason;
+	  if (sf->type()->has_hidden_fields(NULL, &reason))
+	    {
+	      if (reason.empty())
+		error_at(name_expr->location(),
+			 "implicit assignment of hidden field");
+	      else
+		error_at(name_expr->location(), "%s", reason.c_str());
+	    }
+	}
+
       vals[index] = val;
     }
 
Index: gcc/testsuite/go.test/test/assign.go
===================================================================
--- gcc/testsuite/go.test/test/assign.go	(revision 181963)
+++ gcc/testsuite/go.test/test/assign.go	(working copy)
@@ -16,38 +16,38 @@ type T struct {
 func main() {
 	{
 		var x, y sync.Mutex
-		x = y	// ERROR "assignment.*Mutex"
+		x = y // ok
 		_ = x
 	}
 	{
 		var x, y T
-		x = y	// ERROR "assignment.*Mutex"
+		x = y // ok
 		_ = x
 	}
 	{
 		var x, y [2]sync.Mutex
-		x = y	// ERROR "assignment.*Mutex"
+		x = y // ok
 		_ = x
 	}
 	{
 		var x, y [2]T
-		x = y	// ERROR "assignment.*Mutex"
+		x = y // ok
 		_ = x
 	}
 	{
-		x := sync.Mutex{0, 0}	// ERROR "assignment.*Mutex"
+		x := sync.Mutex{0, 0} // ERROR "assignment.*Mutex"
 		_ = x
 	}
 	{
-		x := sync.Mutex{key: 0}	// ERROR "(unknown|assignment).*Mutex"
+		x := sync.Mutex{key: 0} // ERROR "(unknown|assignment).*Mutex"
 		_ = x
 	}
 	{
-		x := &sync.Mutex{}	// ok
-		var y sync.Mutex	// ok
-		y = *x	// ERROR "assignment.*Mutex"
-		*x = y	// ERROR "assignment.*Mutex"
+		x := &sync.Mutex{} // ok
+		var y sync.Mutex   // ok
+		y = *x             // ok
+		*x = y             // ok
 		_ = x
 		_ = y
-	}		
+	}
 }
Index: gcc/testsuite/go.test/test/fixedbugs/bug359.go
===================================================================
--- gcc/testsuite/go.test/test/fixedbugs/bug359.go	(revision 181963)
+++ gcc/testsuite/go.test/test/fixedbugs/bug359.go	(working copy)
@@ -1,26 +0,0 @@
-// errchk $G $D/$F.go
-
-// Copyright 2011 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// issue 1910
-// error on wrong line
-
-package main
-
-import "container/list"
-
-type Painting struct {
-	fragments list.List // private
-}
-
-func (p Painting) Foo() {
-	for e := p.fragments; e.Front() != nil; {  // ERROR "unexported field|hidden field"
-	}
-}
-
-// from comment 4 of issue 1910
-type Foo interface {
-	Run(a int) (a int)  // ERROR "a redeclared|redefinition|previous"
-}
Index: gcc/testsuite/go.test/test/fixedbugs/bug310.go
===================================================================
--- gcc/testsuite/go.test/test/fixedbugs/bug310.go	(revision 181963)
+++ gcc/testsuite/go.test/test/fixedbugs/bug310.go	(working copy)
@@ -1,20 +0,0 @@
-// errchk $G $D/$F.go
-
-// Copyright 2010 The Go Authors.  All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package p
-
-import (
-	"bytes"
-	"fmt"
-)
-
-type t int
-
-func main() {
-	_ = t.bar	// ERROR "no method"
-	var b bytes.Buffer
-	fmt.Print(b)	// ERROR "implicit assignment"
-}
Index: gcc/testsuite/go.test/test/fixedbugs/bug226.go
===================================================================
--- gcc/testsuite/go.test/test/fixedbugs/bug226.go	(revision 181963)
+++ gcc/testsuite/go.test/test/fixedbugs/bug226.go	(working copy)
@@ -1,7 +0,0 @@
-// $G $D/$F.dir/x.go && errchk $G $D/$F.dir/y.go
-
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-ignored
Index: gcc/testsuite/go.test/test/fixedbugs/bug226.dir/x.go
===================================================================
--- gcc/testsuite/go.test/test/fixedbugs/bug226.dir/x.go	(revision 181963)
+++ gcc/testsuite/go.test/test/fixedbugs/bug226.dir/x.go	(working copy)
@@ -1,9 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package x
-
-type T struct { x, Y int }
-
-func (t T) M()
Index: gcc/testsuite/go.test/test/fixedbugs/bug226.dir/y.go
===================================================================
--- gcc/testsuite/go.test/test/fixedbugs/bug226.dir/y.go	(revision 181963)
+++ gcc/testsuite/go.test/test/fixedbugs/bug226.dir/y.go	(working copy)
@@ -1,31 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package y
-
-import "./x"
-
-func f() {
-	ok := new(x.T);
-	var ok1 x.T;
-	ok2 := &ok1;
-	ok3 := &x.T{};
-	ok4 := &x.T{Y:2};
-	_ = x.T{};
-	_ = x.T{Y:2};
-	
-	ok1.M();
-	bad1 := *ok;	// ERROR "assignment.*T"
-	bad2 := ok1;	// ERROR "assignment.*T"
-	*ok4 = ok1;	// ERROR "assignment.*T"
-	*ok4 = *ok2;	// ERROR "assignment.*T"
-	ok1 = *ok4;	// ERROR "assignment.*T"
-	_ = bad1;
-	_ = bad2;
-	_ = ok4;
-	_ = ok3;
-	_ = ok2;
-	_ = ok1;
-	_ = ok;
-}

Reply via email to