diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go index a6de999752..b0afb07633 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -76,5 +76,6 @@ func TestThreadLock(t *testing.T) { testThreadLockFunc(t) } func TestCheckConst(t *testing.T) { testCheckConst(t) } func Test17537(t *testing.T) { test17537(t) } func Test18126(t *testing.T) { test18126(t) } +func Test20369(t *testing.T) { test20369(t) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } diff --git a/misc/cgo/test/issue20369.go b/misc/cgo/test/issue20369.go new file mode 100644 index 0000000000..37b4b78dfe --- /dev/null +++ b/misc/cgo/test/issue20369.go @@ -0,0 +1,20 @@ +// 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 + +/* +#define UINT64_MAX 18446744073709551615ULL +*/ +import "C" +import ( + "math" + "testing" +) + +func test20369(t *testing.T) { + if C.UINT64_MAX != math.MaxUint64 { + t.Fatalf("got %v, want %v", uint64(C.UINT64_MAX), uint64(math.MaxUint64)) + } +} diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 3b6d4580de..2e570bb5b0 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -305,12 +305,18 @@ func (p *Package) guessKinds(f *File) []*Name { // void __cgo_f_xxx_4(void) { static const double x = (name); } // #line xxx "not-str-lit" // void __cgo_f_xxx_5(void) { static const char x[] = (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. @@ -329,12 +335,19 @@ func (p *Package) guessKinds(f *File) []*Name { "#line %d \"not-num-const\"\n"+ "void __cgo_f_%d_4(void) { static const double x = (%s); }\n"+ "#line %d \"not-str-lit\"\n"+ - "void __cgo_f_%d_5(void) { static const char s[] = (%s); }\n", + "void __cgo_f_%d_5(void) { static const char s[] = (%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", 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, i+1, n.C, + i+1, n.C, i+1, + ) } fmt.Fprintf(&b, "#line 1 \"completed\"\n"+ "int __cgo__1 = __cgo__2;\n") @@ -352,6 +365,7 @@ func (p *Package) guessKinds(f *File) []*Name { notNumConst notStrLiteral notDeclared + notSignedIntConst ) for _, line := range strings.Split(stderr, "\n") { if !strings.Contains(line, ": error:") { @@ -395,6 +409,8 @@ 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 } } @@ -403,11 +419,15 @@ func (p *Package) guessKinds(f *File) []*Name { } for i, n := range names { - switch sniff[i] { + switch sniff[i] &^ notSignedIntConst { default: error_(token.NoPos, "could not determine kind of name for C.%s", fixGo(n.Go)) case notStrLiteral | notType: - n.Kind = "iconst" + if sniff[i]¬SignedIntConst != 0 { + n.Kind = "uconst" + } else { + n.Kind = "iconst" + } case notIntConst | notStrLiteral | notType: n.Kind = "fconst" case notIntConst | notNumConst | notType: @@ -452,7 +472,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" { + if n.Kind == "iconst" || n.Kind == "uconst" { fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C) } } @@ -461,7 +481,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" { + if n.Kind == "iconst" || n.Kind == "uconst" { fmt.Fprintf(&b, "\t%s,\n", n.C) } else { fmt.Fprintf(&b, "\t0,\n") @@ -564,6 +584,10 @@ func (p *Package) loadDWARF(f *File, names []*Name) { 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])) + } case "fconst": if i < len(floats) { n.Const = fmt.Sprintf("%f", floats[i]) diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index 4a60ac5f6e..3dc3d141b7 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -88,7 +88,7 @@ type Name struct { Mangle string // name used in generated Go C string // name used in C Define string // #define expansion - Kind string // "iconst", "fconst", "sconst", "type", "var", "fpvar", "func", "not-type" + Kind string // "iconst", "uconst", "fconst", "sconst", "type", "var", "fpvar", "func", "not-type" Type *Type // the type of xxx FuncType *FuncType AddError bool @@ -100,9 +100,9 @@ func (n *Name) IsVar() bool { return n.Kind == "var" || n.Kind == "fpvar" } -// IsConst reports whether Kind is either "iconst", "fconst" or "sconst" +// IsConst reports whether Kind is either "iconst", "uconst", "fconst" or "sconst" func (n *Name) IsConst() bool { - return n.Kind == "iconst" || n.Kind == "fconst" || n.Kind == "sconst" + return strings.HasSuffix(n.Kind, "const") } // A ExpFunc is an exported function, callable from C.