Skip to content

Commit f74b52c

Browse files
hirochachachaianlancetaylor
authored andcommitted
cmd/cgo: support large unsigned macro again
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 51e92d7 commit f74b52c

File tree

5 files changed

+29
-36
lines changed

5 files changed

+29
-36
lines changed

misc/cgo/test/cgo_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,5 +81,6 @@ func Test18720(t *testing.T) { test18720(t) }
8181
func Test20266(t *testing.T) { test20266(t) }
8282
func Test20129(t *testing.T) { test20129(t) }
8383
func Test20910(t *testing.T) { test20910(t) }
84+
func Test21708(t *testing.T) { test21708(t) }
8485

8586
func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }

misc/cgo/test/issue21708.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Copyright 2017 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package cgotest
6+
7+
// #include <stdint.h>
8+
// #define CAST_TO_INT64 (int64_t)(-1)
9+
import "C"
10+
import "testing"
11+
12+
func test21708(t *testing.T) {
13+
if got, want := C.CAST_TO_INT64, -1; got != want {
14+
t.Errorf("C.CAST_TO_INT64 == %v, expected %v", got, want)
15+
}
16+
}

src/cmd/cgo/doc.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -419,11 +419,6 @@ identifiers C.foo, cgo generates this C program:
419419
void __cgo_f_1_4(void) { static const double __cgo_undefined__4 = (foo); }
420420
#line 1 "not-str-lit"
421421
void __cgo_f_1_5(void) { static const char __cgo_undefined__5[] = (foo); }
422-
#line 1 "not-signed-int-const"
423-
#if 0 < -(foo)
424-
#line 1 "not-signed-int-const"
425-
#error found unsigned int
426-
#endif
427422
428423
This program will not compile, but cgo can use the presence or absence
429424
of an error message on a given line to deduce the information it

src/cmd/cgo/gcc.go

Lines changed: 10 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -301,18 +301,12 @@ func (p *Package) guessKinds(f *File) []*Name {
301301
// void __cgo_f_xxx_4(void) { static const double __cgo_undefined__4 = (name); }
302302
// #line xxx "not-str-lit"
303303
// void __cgo_f_xxx_5(void) { static const char __cgo_undefined__5[] = (name); }
304-
// #line xxx "not-signed-int-const"
305-
// #if 0 < -(name)
306-
// #line xxx "not-signed-int-const"
307-
// #error found unsigned int
308-
// #endif
309304
//
310305
// If we see an error at not-declared:xxx, the corresponding name is not declared.
311306
// If we see an error at not-type:xxx, the corresponding name is a type.
312307
// If we see an error at not-int-const:xxx, the corresponding name is not an integer constant.
313308
// If we see an error at not-num-const:xxx, the corresponding name is not a number constant.
314309
// If we see an error at not-str-lit:xxx, the corresponding name is not a string literal.
315-
// If we see an error at not-signed-int-const:xxx, the corresponding name is not a signed integer literal.
316310
//
317311
// The specific input forms are chosen so that they are valid C syntax regardless of
318312
// whether name denotes a type or an expression.
@@ -331,18 +325,12 @@ func (p *Package) guessKinds(f *File) []*Name {
331325
"#line %d \"not-num-const\"\n"+
332326
"void __cgo_f_%d_4(void) { static const double __cgo_undefined__4 = (%s); }\n"+
333327
"#line %d \"not-str-lit\"\n"+
334-
"void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n"+
335-
"#line %d \"not-signed-int-const\"\n"+
336-
"#if 0 < (%s)\n"+
337-
"#line %d \"not-signed-int-const\"\n"+
338-
"#error found unsigned int\n"+
339-
"#endif\n",
328+
"void __cgo_f_%d_5(void) { static const char __cgo_undefined__5[] = (%s); }\n",
340329
i+1, i+1, n.C,
341330
i+1, i+1, n.C,
342331
i+1, i+1, n.C,
343332
i+1, i+1, n.C,
344333
i+1, i+1, n.C,
345-
i+1, n.C, i+1,
346334
)
347335
}
348336
fmt.Fprintf(&b, "#line 1 \"completed\"\n"+
@@ -361,7 +349,6 @@ func (p *Package) guessKinds(f *File) []*Name {
361349
notNumConst
362350
notStrLiteral
363351
notDeclared
364-
notSignedIntConst
365352
)
366353
sawUnmatchedErrors := false
367354
for _, line := range strings.Split(stderr, "\n") {
@@ -415,8 +402,6 @@ func (p *Package) guessKinds(f *File) []*Name {
415402
sniff[i] |= notNumConst
416403
case "not-str-lit":
417404
sniff[i] |= notStrLiteral
418-
case "not-signed-int-const":
419-
sniff[i] |= notSignedIntConst
420405
default:
421406
if isError {
422407
sawUnmatchedErrors = true
@@ -432,15 +417,11 @@ func (p *Package) guessKinds(f *File) []*Name {
432417
}
433418

434419
for i, n := range names {
435-
switch sniff[i] &^ notSignedIntConst {
420+
switch sniff[i] {
436421
default:
437422
error_(f.NamePos[n], "could not determine kind of name for C.%s", fixGo(n.Go))
438423
case notStrLiteral | notType:
439-
if sniff[i]&notSignedIntConst != 0 {
440-
n.Kind = "uconst"
441-
} else {
442-
n.Kind = "iconst"
443-
}
424+
n.Kind = "iconst"
444425
case notIntConst | notStrLiteral | notType:
445426
n.Kind = "fconst"
446427
case notIntConst | notNumConst | notType:
@@ -485,7 +466,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
485466
b.WriteString("#line 1 \"cgo-dwarf-inference\"\n")
486467
for i, n := range names {
487468
fmt.Fprintf(&b, "__typeof__(%s) *__cgo__%d;\n", n.C, i)
488-
if n.Kind == "iconst" || n.Kind == "uconst" {
469+
if n.Kind == "iconst" {
489470
fmt.Fprintf(&b, "enum { __cgo_enum__%d = %s };\n", i, n.C)
490471
}
491472
}
@@ -494,7 +475,7 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
494475
// so we can read them out of the object file.
495476
fmt.Fprintf(&b, "long long __cgodebug_ints[] = {\n")
496477
for _, n := range names {
497-
if n.Kind == "iconst" || n.Kind == "uconst" {
478+
if n.Kind == "iconst" {
498479
fmt.Fprintf(&b, "\t%s,\n", n.C)
499480
} else {
500481
fmt.Fprintf(&b, "\t0,\n")
@@ -592,11 +573,11 @@ func (p *Package) loadDWARF(f *File, names []*Name) {
592573
switch n.Kind {
593574
case "iconst":
594575
if i < len(ints) {
595-
n.Const = fmt.Sprintf("%#x", ints[i])
596-
}
597-
case "uconst":
598-
if i < len(ints) {
599-
n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
576+
if _, ok := types[i].(*dwarf.UintType); ok {
577+
n.Const = fmt.Sprintf("%#x", uint64(ints[i]))
578+
} else {
579+
n.Const = fmt.Sprintf("%#x", ints[i])
580+
}
600581
}
601582
case "fconst":
602583
if i < len(floats) {

src/cmd/cgo/main.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ type Name struct {
8989
Mangle string // name used in generated Go
9090
C string // name used in C
9191
Define string // #define expansion
92-
Kind string // "iconst", "uconst", "fconst", "sconst", "type", "var", "fpvar", "func", "macro", "not-type"
92+
Kind string // "iconst", "fconst", "sconst", "type", "var", "fpvar", "func", "macro", "not-type"
9393
Type *Type // the type of xxx
9494
FuncType *FuncType
9595
AddError bool
@@ -101,7 +101,7 @@ func (n *Name) IsVar() bool {
101101
return n.Kind == "var" || n.Kind == "fpvar"
102102
}
103103

104-
// IsConst reports whether Kind is either "iconst", "uconst", "fconst" or "sconst"
104+
// IsConst reports whether Kind is either "iconst", "fconst" or "sconst"
105105
func (n *Name) IsConst() bool {
106106
return strings.HasSuffix(n.Kind, "const")
107107
}

0 commit comments

Comments
 (0)