]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cgo: support large unsigned macro again
authorHiroshi Ioka <hirochachacha@gmail.com>
Thu, 31 Aug 2017 04:49:43 +0000 (13:49 +0900)
committerIan Lance Taylor <iant@golang.org>
Fri, 1 Sep 2017 00:42:21 +0000 (00:42 +0000)
The approach of https://golang.org/cl/43476 turned out incorrect.
The problem is that the sniff introduced by the CL only work for simple
expression. And when it fails it fallback to uint64, not int64, which
breaks backward compatibility.
In this CL, we use DWARF for guessing kind instead. That should be more
reliable than previous approach. And importanly, it fallbacks to int64 even
if it fails to guess kind.

Fixes #21708

Change-Id: I39a18cb2efbe4faa9becdcf53d5ac68dba180d46
Reviewed-on: https://go-review.googlesource.com/60510
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
misc/cgo/test/cgo_test.go
misc/cgo/test/issue21708.go [new file with mode: 0644]
src/cmd/cgo/doc.go
src/cmd/cgo/gcc.go
src/cmd/cgo/main.go

index a44eff27b856549827ee8ad2f5f2bd6a78ec5b14..f6cf86befc1408f2ae36900f685334a460b8aff6 100644 (file)
@@ -81,5 +81,6 @@ func Test18720(t *testing.T)                 { test18720(t) }
 func Test20266(t *testing.T)                 { test20266(t) }
 func Test20129(t *testing.T)                 { test20129(t) }
 func Test20910(t *testing.T)                 { test20910(t) }
+func Test21708(t *testing.T)                 { test21708(t) }
 
 func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
diff --git a/misc/cgo/test/issue21708.go b/misc/cgo/test/issue21708.go
new file mode 100644 (file)
index 0000000..d413e3c
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2017 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 cgotest
+
+// #include <stdint.h>
+// #define CAST_TO_INT64 (int64_t)(-1)
+import "C"
+import "testing"
+
+func test21708(t *testing.T) {
+       if got, want := C.CAST_TO_INT64, -1; got != want {
+               t.Errorf("C.CAST_TO_INT64 == %v, expected %v", got, want)
+       }
+}
index cfd09246af0e674c47135016d9b1894a27205a61..9cd2a42988f96d7dcea8b50963f2265c8c5b90f8 100644 (file)
@@ -419,11 +419,6 @@ identifiers C.foo, cgo generates this C program:
        void __cgo_f_1_4(void) { static const double __cgo_undefined__4 = (foo); }
        #line 1 "not-str-lit"
        void __cgo_f_1_5(void) { static const char __cgo_undefined__5[] = (foo); }
-       #line 1 "not-signed-int-const"
-       #if 0 < -(foo)
-       #line 1 "not-signed-int-const"
-       #error found unsigned int
-       #endif
 
 This program will not compile, but cgo can use the presence or absence
 of an error message on a given line to deduce the information it
index 6cfd83f8358ed9a90312bd5d91cc0ab812014d4a..774786405c0e9ea0a70b3110a4e7777538fe5a85 100644 (file)
@@ -301,18 +301,12 @@ func (p *Package) guessKinds(f *File) []*Name {
        //      void __cgo_f_xxx_4(void) { static const double __cgo_undefined__4 = (name); }
        //      #line xxx "not-str-lit"
        //      void __cgo_f_xxx_5(void) { static const char __cgo_undefined__5[] = (name); }
-       //      #line xxx "not-signed-int-const"
-       //      #if 0 < -(name)
-       //      #line xxx "not-signed-int-const"
-       //      #error found unsigned int
-       //      #endif
        //
        // If we see an error at not-declared:xxx, the corresponding name is not declared.
        // If we see an error at not-type:xxx, the corresponding name is a type.
        // If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
        // If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
        // If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
-       // If we see an error at not-signed-int-const:xxx, the corresponding name is not a signed integer literal.
        //
        // The specific input forms are chosen so that they are valid C syntax regardless of
        // whether name denotes a type or an expression.
@@ -331,18 +325,12 @@ func (p *Package) guessKinds(f *File) []*Name {
                        "#line %d \"not-num-const\"\n"+
                        "void __cgo_f_%d_4(void) { static const double __cgo_undefined__4 = (%s); }\n"+
                        "#line %d \"not-str-lit\"\n"+
-                       "void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n"+
-                       "#line %d \"not-signed-int-const\"\n"+
-                       "#if 0 < (%s)\n"+
-                       "#line %d \"not-signed-int-const\"\n"+
-                       "#error found unsigned int\n"+
-                       "#endif\n",
+                       "void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n",
                        i+1, i+1, n.C,
                        i+1, i+1, n.C,
                        i+1, i+1, n.C,
                        i+1, i+1, n.C,
                        i+1, i+1, n.C,
-                       i+1, n.C, i+1,
                )
        }
        fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
@@ -361,7 +349,6 @@ func (p *Package) guessKinds(f *File) []*Name {
                notNumConst
                notStrLiteral
                notDeclared
-               notSignedIntConst
        )
        sawUnmatchedErrors := false
        for _, line := range strings.Split(stderr, "\n") {
@@ -415,8 +402,6 @@ func (p *Package) guessKinds(f *File) []*Name {
                        sniff[i] |= notNumConst
                case "not-str-lit":
                        sniff[i] |= notStrLiteral
-               case "not-signed-int-const":
-                       sniff[i] |= notSignedIntConst
                default:
                        if isError {
                                sawUnmatchedErrors = true
@@ -432,15 +417,11 @@ func (p *Package) guessKinds(f *File) []*Name {
        }
 
        for i, n := range names {
-               switch sniff[i] &^ notSignedIntConst {
+               switch sniff[i] {
                default:
                        error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go))
                case notStrLiteral | notType:
-                       if sniff[i]&notSignedIntConst != 0 {
-                               n.Kind = "uconst"
-                       } else {
-                               n.Kind = "iconst"
-                       }
+                       n.Kind = "iconst"
                case notIntConst | notStrLiteral | notType:
                        n.Kind = "fconst"
                case notIntConst | notNumConst | notType:
@@ -485,7 +466,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
        b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
        for i, n := range names {
                fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
-               if n.Kind == "iconst" || n.Kind == "uconst" {
+               if n.Kind == "iconst" {
                        fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
                }
        }
@@ -494,7 +475,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
        // so we can read them out of the object file.
        fmt.Fprintf(&b, "long long __cgodebug_ints[] = {\n")
        for _, n := range names {
-               if n.Kind == "iconst" || n.Kind == "uconst" {
+               if n.Kind == "iconst" {
                        fmt.Fprintf(&b, "\t%s,\n", n.C)
                } else {
                        fmt.Fprintf(&b, "\t0,\n")
@@ -592,11 +573,11 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
                        switch n.Kind {
                        case "iconst":
                                if i < len(ints) {
-                                       n.Const = fmt.Sprintf("%#x", ints[i])
-                               }
-                       case "uconst":
-                               if i < len(ints) {
-                                       n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
+                                       if _, ok := types[i].(*dwarf.UintType); ok {
+                                               n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
+                                       } else {
+                                               n.Const = fmt.Sprintf("%#x", ints[i])
+                                       }
                                }
                        case "fconst":
                                if i < len(floats) {
index c43985d1bf1ba88e2f508ffed1453baec9a10548..2820fc1bfbbc763dc4c0da045553226c360b50c9 100644 (file)
@@ -89,7 +89,7 @@ type Name struct {
        Mangle   string // name used in generated Go
        C        string // name used in C
        Define   string // #define expansion
-       Kind     string // "iconst", "uconst", "fconst", "sconst", "type", "var", "fpvar", "func", "macro", "not-type"
+       Kind     string // "iconst", "fconst", "sconst", "type", "var", "fpvar", "func", "macro", "not-type"
        Type     *Type  // the type of xxx
        FuncType *FuncType
        AddError bool
@@ -101,7 +101,7 @@ func (n *Name) IsVar() bool {
        return n.Kind == "var" || n.Kind == "fpvar"
 }
 
-// IsConst reports whether Kind is either "iconst", "uconst", "fconst" or "sconst"
+// IsConst reports whether Kind is either "iconst", "fconst" or "sconst"
 func (n *Name) IsConst() bool {
        return strings.HasSuffix(n.Kind, "const")
 }