]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: use type aliases for #define type macros
authorMatthew Dempsky <mdempsky@google.com>
Fri, 1 May 2020 06:05:51 +0000 (23:05 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 1 May 2020 18:01:28 +0000 (18:01 +0000)
Cgo's initial design for handling "#define foo int*" involved
rewriting "C.foo" to "*_Ctype_int" everywhere. But now that we have
type aliases, we can declare "type _Ctype_foo = *_Ctype_int" once, and
then rewrite "C.foo" to just "_Ctype_foo".

This is important for go/types's UsesCgo mode, where go/types needs to
be able to figure out a type for each C.foo identifier using only the
information written into _cgo_gotypes.go.

Fixes #38649.

Change-Id: Ia0f8c2d82df81efb1be5bc26195ea9154c0af871
Reviewed-on: https://go-review.googlesource.com/c/go/+/230037
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
misc/cgo/test/test.go
misc/cgo/testgodefs/testdata/issue38649.go [new file with mode: 0644]
misc/cgo/testgodefs/testdata/main.go
misc/cgo/testgodefs/testgodefs_test.go
src/cmd/cgo/gcc.go

index b0148995fe567cc861b8807487fe79227f02e348..b5009d43cee03a4211dc863a085db1e39308e599 100644 (file)
@@ -897,6 +897,10 @@ static uint16_t issue31093F(uint16_t v) { return v; }
 
 // issue 32579
 typedef struct S32579 { unsigned char data[1]; } S32579;
+
+// issue 38649
+// Test that #define'd type aliases work.
+#define netbsd_gid unsigned int
 */
 import "C"
 
@@ -2192,3 +2196,7 @@ func test32579(t *testing.T) {
                t.Errorf("&s[0].data[0] failed: got %d, want %d", s[0].data[0], 1)
        }
 }
+
+// issue 38649
+
+var issue38649 C.netbsd_gid = 42
diff --git a/misc/cgo/testgodefs/testdata/issue38649.go b/misc/cgo/testgodefs/testdata/issue38649.go
new file mode 100644 (file)
index 0000000..6af74d6
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2020 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.
+//
+// +build ignore
+
+package main
+
+/*
+struct Issue38649 { int x; };
+#define issue38649 struct Issue38649
+*/
+import "C"
+
+type issue38649 C.issue38649
index ef45b95e6553e34bc51385fb68c5574993885a10..2e1ad3376a1ea1f6850f0c49e350285a0bf1dc90 100644 (file)
@@ -19,5 +19,8 @@ var v6 = B{}
 // Test that S is fully defined
 var v7 = S{}
 
+// Test that #define'd type is fully defined
+var _ = issue38649{X: 0}
+
 func main() {
 }
index 438d23d65c068f0d44d5af88495cc380483f8b8e..178fff3fbc1faf9659cc548ee1dab770e382a131 100644 (file)
@@ -23,6 +23,7 @@ var filePrefixes = []string{
        "fieldtypedef",
        "issue37479",
        "issue37621",
+       "issue38649",
 }
 
 func TestGoDefs(t *testing.T) {
index e01ea081d9620fcc44987084be8b171d70abb5b0..39ab5788ec5c57f5b3c668df4a42ec43055ee605 100644 (file)
@@ -182,6 +182,9 @@ func (p *Package) Translate(f *File) {
                numTypedefs = len(p.typedefs)
                // Also ask about any typedefs we've seen so far.
                for _, info := range p.typedefList {
+                       if f.Name[info.typedef] != nil {
+                               continue
+                       }
                        n := &Name{
                                Go: info.typedef,
                                C:  info.typedef,
@@ -710,6 +713,9 @@ func (p *Package) prepareNames(f *File) {
                        }
                }
                p.mangleName(n)
+               if n.Kind == "type" && typedef[n.Mangle] == nil {
+                       typedef[n.Mangle] = n.Type
+               }
        }
 }
 
@@ -1348,6 +1354,9 @@ func (p *Package) rewriteRef(f *File) {
 
                if *godefs {
                        // Substitute definition for mangled type name.
+                       if r.Name.Type != nil {
+                               expr = r.Name.Type.Go
+                       }
                        if id, ok := expr.(*ast.Ident); ok {
                                if t := typedef[id.Name]; t != nil {
                                        expr = t.Go
@@ -1413,9 +1422,7 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
                                r.Context = ctxType
                                if r.Name.Type == nil {
                                        error_(r.Pos(), "invalid conversion to C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
-                                       break
                                }
-                               expr = r.Name.Type.Go
                                break
                        }
                        error_(r.Pos(), "call of non-function C.%s", fixGo(r.Name.Go))
@@ -1472,9 +1479,7 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
                        // Okay - might be new(T)
                        if r.Name.Type == nil {
                                error_(r.Pos(), "expression C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
-                               break
                        }
-                       expr = r.Name.Type.Go
                case "var":
                        expr = &ast.StarExpr{Star: (*r.Expr).Pos(), X: expr}
                case "macro":
@@ -1493,8 +1498,6 @@ func (p *Package) rewriteName(f *File, r *Ref) ast.Expr {
                        // Use of C.enum_x, C.struct_x or C.union_x without C definition.
                        // GCC won't raise an error when using pointers to such unknown types.
                        error_(r.Pos(), "type C.%s: undefined C type '%s'", fixGo(r.Name.Go), r.Name.C)
-               } else {
-                       expr = r.Name.Type.Go
                }
        default:
                if r.Name.Kind == "func" {