From patchwork Tue Sep 10 20:26:20 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 1160555 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-508800-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=golang.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="JL0GZuql"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=golang-org.20150623.gappssmtp.com header.i=@golang-org.20150623.gappssmtp.com header.b="bd91qZow"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46Sc521cLVz9sDB for ; Wed, 11 Sep 2019 06:26:44 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=Yqnsytb8m5YzBewjo4YJR2RPoH2SPRmReMetxzFtVHFRIr DPf6utA3O4YikyVrT1SW3CAsxUwn6GFSHTRu4eX3LOj+iDLd+UnDHay7Uwa1buux qp7w3Xl7kjMViws5beOtUyyukc8uRI9UybvQKdfiUJC9WfOAXXm9LzndAiKcM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=720jfhW8KumdgImETJF7qSu1t9g=; b=JL0GZuqlKt1ZKUkEObja YGRvll0ap96R4WeHMu8QLQmF4kaMS5XvPjSFovlWF479Rg/KnHnyFJUcug/Ocejk 7dreug+WHoVqqtv+NSld/zU1cDwq9mrN/kYY7gxg3Ni7E8BPi0OwrBGs5fkRkqvZ owxOqxm55Oq2zgZ9hIMFiac= Received: (qmail 53943 invoked by alias); 10 Sep 2019 20:26:37 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 53795 invoked by uid 89); 10 Sep 2019 20:26:36 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-13.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=6447, UD:T, Method X-HELO: mail-ed1-f41.google.com Received: from mail-ed1-f41.google.com (HELO mail-ed1-f41.google.com) (209.85.208.41) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 10 Sep 2019 20:26:34 +0000 Received: by mail-ed1-f41.google.com with SMTP id i8so18427789edn.13 for ; Tue, 10 Sep 2019 13:26:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=golang-org.20150623.gappssmtp.com; s=20150623; h=mime-version:from:date:message-id:subject:to; bh=lNFloQJ4Yq+uCF25EAx6u08U9qs00+JGqmDso4eQy1w=; b=bd91qZowQWpZtsuLMPhJwCULH4fP49LVwgPjOab+IKfENgkY0fdLAF6BHlG3DEnB6O jkKXDnj6gLnSqtzA+2p99KI5JsIlzbab+wrr5Emq4dB7aK/OI1u5QlZjPxqO1zE1kl+2 9uQnnulOENNHrECXyKzivKCGEnR+JAFqKWK/pkuRiTfBTtplRFf4QEVqepDBIblgRCUS qQwMjU62mlWvicDI1TUhUjHzRq/zllX6HQMQHNeWAuT4kcDz0yrjzhrPyUJw2gY7ndfZ DhGtqOd21P+oS0fR+aDINkCaJxDIbtvEiGEgwvSItWCKSxbdVRlNKwIs5mF2vzMZh9bQ zzRg== MIME-Version: 1.0 From: Ian Lance Taylor Date: Tue, 10 Sep 2019 13:26:20 -0700 Message-ID: Subject: libgo patch committed: gccgoimporter support embedded field in pointer loop To: gcc-patches , gofrontend-dev This libgo patch fixes the go/internal/gccgoimporter package to support an embedded field in a pointer loop. This is a backport of https://golang.org/cl/194440 in the master repository. Original description: If an embedded field refers to a type via a pointer, the parser needs to know the name of the embedded field. It is possible that the pointer type is not yet resolved. This CL fixes the parser to handle that case by setting the pointer element type to the unresolved named type while the pointer is being resolved. This is https://golang.org/issue/34182. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline and GCC 9 branch. Ian Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 275594) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -68038b4fdf1456482af986cb05dcf3121bd43ffc +556451586b10584e4778694c84b03d0ecbbab150 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: libgo/go/go/internal/gccgoimporter/importer_test.go =================================================================== --- libgo/go/go/internal/gccgoimporter/importer_test.go (revision 275594) +++ libgo/go/go/internal/gccgoimporter/importer_test.go (working copy) @@ -96,6 +96,7 @@ var importerTests = [...]importerTest{ {pkgpath: "issue29198", name: "FooServer", gccgoVersion: 7, want: "type FooServer struct{FooServer *FooServer; user string; ctx context.Context}"}, {pkgpath: "issue30628", name: "Apple", want: "type Apple struct{hey sync.RWMutex; x int; RQ [517]struct{Count uintptr; NumBytes uintptr; Last uintptr}}"}, {pkgpath: "issue31540", name: "S", gccgoVersion: 7, want: "type S struct{b int; map[Y]Z}"}, + {pkgpath: "issue34182", name: "T1", want: "type T1 struct{f *T2}"}, } func TestGoxImporter(t *testing.T) { Index: libgo/go/go/internal/gccgoimporter/parser.go =================================================================== --- libgo/go/go/internal/gccgoimporter/parser.go (revision 275594) +++ libgo/go/go/internal/gccgoimporter/parser.go (working copy) @@ -254,7 +254,7 @@ func (p *parser) parseField(pkg *types.P case *types.Named: name = typ.Obj().Name() default: - p.error("anonymous field expected") + p.error("embedded field expected") } } } @@ -469,8 +469,12 @@ func (p *parser) reserve(n int) { } } -// update sets the type map entries for the given type numbers nlist to t. -func (p *parser) update(t types.Type, nlist []int) { +// update sets the type map entries for the entries in nlist to t. +// An entry in nlist can be a type number in p.typeList, +// used to resolve named types, or it can be a *types.Pointer, +// used to resolve pointers to named types in case they are referenced +// by embedded fields. +func (p *parser) update(t types.Type, nlist []interface{}) { if len(nlist) != 0 { if t == reserved { p.errorf("internal error: update(%v) invoked on reserved", nlist) @@ -480,20 +484,34 @@ func (p *parser) update(t types.Type, nl } } for _, n := range nlist { - if p.typeList[n] == t { - continue - } - if p.typeList[n] != reserved { - p.errorf("internal error: update(%v): %d not reserved", nlist, n) + switch n := n.(type) { + case int: + if p.typeList[n] == t { + continue + } + if p.typeList[n] != reserved { + p.errorf("internal error: update(%v): %d not reserved", nlist, n) + } + p.typeList[n] = t + case *types.Pointer: + if *n != (types.Pointer{}) { + elem := n.Elem() + if elem == t { + continue + } + p.errorf("internal error: update: pointer already set to %v, expected %v", elem, t) + } + *n = *types.NewPointer(t) + default: + p.errorf("internal error: %T on nlist", n) } - p.typeList[n] = t } } // NamedType = TypeName [ "=" ] Type { Method } . // TypeName = ExportedName . // Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" . -func (p *parser) parseNamedType(nlist []int) types.Type { +func (p *parser) parseNamedType(nlist []interface{}) types.Type { pkg, name := p.parseExportedName() scope := pkg.Scope() obj := scope.Lookup(name) @@ -504,7 +522,7 @@ func (p *parser) parseNamedType(nlist [] // type alias if p.tok == '=' { p.next() - p.aliases[nlist[len(nlist)-1]] = name + p.aliases[nlist[len(nlist)-1].(int)] = name if obj != nil { // use the previously imported (canonical) type t := obj.Type() @@ -603,7 +621,7 @@ func (p *parser) parseInt() int { } // ArrayOrSliceType = "[" [ int ] "]" Type . -func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []int) types.Type { +func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []interface{}) types.Type { p.expect('[') if p.tok == ']' { p.next() @@ -626,7 +644,7 @@ func (p *parser) parseArrayOrSliceType(p } // MapType = "map" "[" Type "]" Type . -func (p *parser) parseMapType(pkg *types.Package, nlist []int) types.Type { +func (p *parser) parseMapType(pkg *types.Package, nlist []interface{}) types.Type { p.expectKeyword("map") t := new(types.Map) @@ -642,7 +660,7 @@ func (p *parser) parseMapType(pkg *types } // ChanType = "chan" ["<-" | "-<"] Type . -func (p *parser) parseChanType(pkg *types.Package, nlist []int) types.Type { +func (p *parser) parseChanType(pkg *types.Package, nlist []interface{}) types.Type { p.expectKeyword("chan") t := new(types.Chan) @@ -669,7 +687,7 @@ func (p *parser) parseChanType(pkg *type } // StructType = "struct" "{" { Field } "}" . -func (p *parser) parseStructType(pkg *types.Package, nlist []int) types.Type { +func (p *parser) parseStructType(pkg *types.Package, nlist []interface{}) types.Type { p.expectKeyword("struct") t := new(types.Struct) @@ -736,7 +754,7 @@ func (p *parser) parseResultList(pkg *ty } // FunctionType = ParamList ResultList . -func (p *parser) parseFunctionType(pkg *types.Package, nlist []int) *types.Signature { +func (p *parser) parseFunctionType(pkg *types.Package, nlist []interface{}) *types.Signature { t := new(types.Signature) p.update(t, nlist) @@ -776,7 +794,7 @@ func (p *parser) parseFunc(pkg *types.Pa } // InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" . -func (p *parser) parseInterfaceType(pkg *types.Package, nlist []int) types.Type { +func (p *parser) parseInterfaceType(pkg *types.Package, nlist []interface{}) types.Type { p.expectKeyword("interface") t := new(types.Interface) @@ -805,7 +823,7 @@ func (p *parser) parseInterfaceType(pkg } // PointerType = "*" ("any" | Type) . -func (p *parser) parsePointerType(pkg *types.Package, nlist []int) types.Type { +func (p *parser) parsePointerType(pkg *types.Package, nlist []interface{}) types.Type { p.expect('*') if p.tok == scanner.Ident { p.expectKeyword("any") @@ -817,13 +835,13 @@ func (p *parser) parsePointerType(pkg *t t := new(types.Pointer) p.update(t, nlist) - *t = *types.NewPointer(p.parseType(pkg)) + *t = *types.NewPointer(p.parseType(pkg, t)) return t } // TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType . -func (p *parser) parseTypeSpec(pkg *types.Package, nlist []int) types.Type { +func (p *parser) parseTypeSpec(pkg *types.Package, nlist []interface{}) types.Type { switch p.tok { case scanner.String: return p.parseNamedType(nlist) @@ -912,14 +930,14 @@ func lookupBuiltinType(typ int) types.Ty // // parseType updates the type map to t for all type numbers n. // -func (p *parser) parseType(pkg *types.Package, n ...int) types.Type { +func (p *parser) parseType(pkg *types.Package, n ...interface{}) types.Type { p.expect('<') t, _ := p.parseTypeAfterAngle(pkg, n...) return t } // (*parser).Type after reading the "<". -func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type, n1 int) { +func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...interface{}) (t types.Type, n1 int) { p.expectKeyword("type") n1 = 0 @@ -962,7 +980,7 @@ func (p *parser) parseTypeAfterAngle(pkg // parseTypeExtended is identical to parseType, but if the type in // question is a saved type, returns the index as well as the type // pointer (index returned is zero if we parsed a builtin). -func (p *parser) parseTypeExtended(pkg *types.Package, n ...int) (t types.Type, n1 int) { +func (p *parser) parseTypeExtended(pkg *types.Package, n ...interface{}) (t types.Type, n1 int) { p.expect('<') t, n1 = p.parseTypeAfterAngle(pkg, n...) return @@ -1044,12 +1062,12 @@ func (p *parser) parseTypes(pkg *types.P } for i := 1; i < int(exportedp1); i++ { - p.parseSavedType(pkg, i, []int{}) + p.parseSavedType(pkg, i, nil) } } // parseSavedType parses one saved type definition. -func (p *parser) parseSavedType(pkg *types.Package, i int, nlist []int) { +func (p *parser) parseSavedType(pkg *types.Package, i int, nlist []interface{}) { defer func(s *scanner.Scanner, tok rune, lit string) { p.scanner = s p.tok = tok Index: libgo/go/go/internal/gccgoimporter/testdata/issue34182.go =================================================================== --- libgo/go/go/internal/gccgoimporter/testdata/issue34182.go (nonexistent) +++ libgo/go/go/internal/gccgoimporter/testdata/issue34182.go (working copy) @@ -0,0 +1,17 @@ +// Copyright 2019 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 issue34182 + +type T1 struct { + f *T2 +} + +type T2 struct { + f T3 +} + +type T3 struct { + *T2 +} Index: libgo/go/go/internal/gccgoimporter/testdata/issue34182.gox =================================================================== --- libgo/go/go/internal/gccgoimporter/testdata/issue34182.gox (nonexistent) +++ libgo/go/go/internal/gccgoimporter/testdata/issue34182.gox (working copy) @@ -0,0 +1,13 @@ +v3; +package issue34182 +pkgpath issue34182 +init issue34182 ~go.issue34182 +types 8 4 21 21 21 17 30 45 45 +type 1 "T1" +type 2 "T2" +type 3 "T3" +type 4 * +type 5 struct { ? ; } +type 6 struct { .go.issue34182.f ; } +type 7 struct { .go.issue34182.f ; } +checksum FF02C49BAF44B06C087ED4E573F7CC880C79C208