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 <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Hiroshi Ioka 2017-08-31 13:49:43 +09:00 committed by Ian Lance Taylor
parent 51e92d7261
commit f74b52cf50
5 changed files with 29 additions and 36 deletions

View 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) {