Commit ac921dad authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/cgo: roll back "use C exact-width integer types to represent Go types"

Roll back CL 159258 and CL 168337. Those changes broke existing
code. I can't see any way to keep existing code working while also
producing good error messages for types like C.ulong (such as the ones
already tested for in misc/cgo/errors).

This is not an exact roll back because parts of the code have changed
since those CLs.

Updates #29878
Fixes #31093

Change-Id: I56fe76c167ff0ab381ed273b9ca4b952402e1434
Reviewed-on: https://go-review.googlesource.com/c/go/+/180357
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDmitri Shuralyov <dmitshur@golang.org>
parent 003dbc4c
...@@ -56,7 +56,6 @@ func Test25143(t *testing.T) { test25143(t) } ...@@ -56,7 +56,6 @@ func Test25143(t *testing.T) { test25143(t) }
func Test26066(t *testing.T) { test26066(t) } func Test26066(t *testing.T) { test26066(t) }
func Test27660(t *testing.T) { test27660(t) } func Test27660(t *testing.T) { test27660(t) }
func Test28896(t *testing.T) { test28896(t) } func Test28896(t *testing.T) { test28896(t) }
func Test29878(t *testing.T) { test29878(t) }
func Test30065(t *testing.T) { test30065(t) } func Test30065(t *testing.T) { test30065(t) }
func TestAlign(t *testing.T) { testAlign(t) } func TestAlign(t *testing.T) { testAlign(t) }
func TestAtol(t *testing.T) { testAtol(t) } func TestAtol(t *testing.T) { testAtol(t) }
......
...@@ -849,10 +849,6 @@ static int f29748(S29748 *p) { return 0; } ...@@ -849,10 +849,6 @@ static int f29748(S29748 *p) { return 0; }
static void issue29781F(char **p, int n) {} static void issue29781F(char **p, int n) {}
#define ISSUE29781C 0 #define ISSUE29781C 0
// issue 29878
uint64_t issue29878exported(int8_t); // prototype must match
int16_t issue29878function(uint32_t arg) { return issue29878exported(arg); }
*/ */
import "C" import "C"
...@@ -2054,14 +2050,6 @@ func issue29781G() { ...@@ -2054,14 +2050,6 @@ func issue29781G() {
X)) X))
} }
func test29878(t *testing.T) {
const arg uint32 = 123 // fits into all integer types
var ret int16 = C.issue29878function(arg) // no conversions needed
if int64(ret) != int64(arg) {
t.Errorf("return value unexpected: got %d, want %d", ret, arg)
}
}
// issue 30065 // issue 30065
func test30065(t *testing.T) { func test30065(t *testing.T) {
......
...@@ -535,8 +535,3 @@ func test20910(t *testing.T) { ...@@ -535,8 +535,3 @@ func test20910(t *testing.T) {
// issue 28772 part 2 // issue 28772 part 2
const issue28772Constant2 = C.issue28772Constant2 const issue28772Constant2 = C.issue28772Constant2
//export issue29878exported
func issue29878exported(arg int8) uint64 {
return uint64(arg)
}
...@@ -148,8 +148,6 @@ C.long, C.ulong (unsigned long), C.longlong (long long), ...@@ -148,8 +148,6 @@ C.long, C.ulong (unsigned long), C.longlong (long long),
C.ulonglong (unsigned long long), C.float, C.double, C.ulonglong (unsigned long long), C.float, C.double,
C.complexfloat (complex float), and C.complexdouble (complex double). C.complexfloat (complex float), and C.complexdouble (complex double).
The C type void* is represented by Go's unsafe.Pointer. The C type void* is represented by Go's unsafe.Pointer.
The C sized integer types (int8_t, uint8_t, …) are represented by their Go
counterparts (int8, uint8, …).
The C types __int128_t and __uint128_t are represented by [16]byte. The C types __int128_t and __uint128_t are represented by [16]byte.
A few special C types which would normally be represented by a pointer A few special C types which would normally be represented by a pointer
...@@ -298,7 +296,7 @@ Go functions can be exported for use by C code in the following way: ...@@ -298,7 +296,7 @@ Go functions can be exported for use by C code in the following way:
They will be available in the C code as: They will be available in the C code as:
extern int64_t MyFunction(int arg1, int arg2, GoString arg3); extern GoInt64 MyFunction(int arg1, int arg2, GoString arg3);
extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3); extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
found in the _cgo_export.h generated header, after any preambles found in the _cgo_export.h generated header, after any preambles
......
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
"internal/xcoff" "internal/xcoff"
"math" "math"
"os" "os"
"regexp"
"strconv" "strconv"
"strings" "strings"
"unicode" "unicode"
...@@ -2047,8 +2046,6 @@ type typeConv struct { ...@@ -2047,8 +2046,6 @@ type typeConv struct {
ptrSize int64 ptrSize int64
intSize int64 intSize int64
exactWidthIntegerTypes map[string]*Type
} }
var tagGen int var tagGen int
...@@ -2091,21 +2088,6 @@ func (c *typeConv) Init(ptrSize, intSize int64) { ...@@ -2091,21 +2088,6 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
} else { } else {
c.goVoidPtr = c.Ident("unsafe.Pointer") c.goVoidPtr = c.Ident("unsafe.Pointer")
} }
c.exactWidthIntegerTypes = make(map[string]*Type)
for _, t := range []ast.Expr{
c.int8, c.int16, c.int32, c.int64,
c.uint8, c.uint16, c.uint32, c.uint64,
} {
name := t.(*ast.Ident).Name
u := new(Type)
*u = *goTypes[name]
if u.Align > ptrSize {
u.Align = ptrSize
}
u.Go = t
c.exactWidthIntegerTypes[name] = u
}
} }
// base strips away qualifiers and typedefs to get the underlying type // base strips away qualifiers and typedefs to get the underlying type
...@@ -2477,26 +2459,6 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { ...@@ -2477,26 +2459,6 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
t.Align = c.ptrSize t.Align = c.ptrSize
break break
} }
// Exact-width integer types. These are always compatible with
// the corresponding Go types since the C standard requires
// them to have no padding bit and use the two’s complement
// representation.
if exactWidthIntegerType.MatchString(dt.Name) {
sub := c.Type(dt.Type, pos)
goname := strings.TrimPrefix(dt.Name, "__")
goname = strings.TrimSuffix(goname, "_t")
u := c.exactWidthIntegerTypes[goname]
if sub.Size != u.Size {
fatalf("%s: unexpected size: %d vs. %d – %s", lineno(pos), sub.Size, u.Size, dtype)
}
if sub.Align != u.Align {
fatalf("%s: unexpected alignment: %d vs. %d – %s", lineno(pos), sub.Align, u.Align, dtype)
}
t.Size = u.Size
t.Align = u.Align
t.Go = u.Go
break
}
name := c.Ident("_Ctype_" + dt.Name) name := c.Ident("_Ctype_" + dt.Name)
goIdent[name.Name] = name goIdent[name.Name] = name
sub := c.Type(dt.Type, pos) sub := c.Type(dt.Type, pos)
...@@ -2632,8 +2594,6 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type { ...@@ -2632,8 +2594,6 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
return t return t
} }
var exactWidthIntegerType = regexp.MustCompile(`^(__)?u?int(8|16|32|64)_t$`)
// isStructUnionClass reports whether the type described by the Go syntax x // isStructUnionClass reports whether the type described by the Go syntax x
// is a struct, union, or class with a tag. // is a struct, union, or class with a tag.
func isStructUnionClass(x ast.Expr) bool { func isStructUnionClass(x ast.Expr) bool {
......
...@@ -1367,19 +1367,19 @@ func c(repr string, args ...interface{}) *TypeRepr { ...@@ -1367,19 +1367,19 @@ func c(repr string, args ...interface{}) *TypeRepr {
// Map predeclared Go types to Type. // Map predeclared Go types to Type.
var goTypes = map[string]*Type{ var goTypes = map[string]*Type{
"bool": {Size: 1, Align: 1, C: c("uint8_t")}, "bool": {Size: 1, Align: 1, C: c("GoUint8")},
"byte": {Size: 1, Align: 1, C: c("uint8_t")}, "byte": {Size: 1, Align: 1, C: c("GoUint8")},
"int": {Size: 0, Align: 0, C: c("GoInt")}, "int": {Size: 0, Align: 0, C: c("GoInt")},
"uint": {Size: 0, Align: 0, C: c("GoUint")}, "uint": {Size: 0, Align: 0, C: c("GoUint")},
"rune": {Size: 4, Align: 4, C: c("int32_t")}, "rune": {Size: 4, Align: 4, C: c("GoInt32")},
"int8": {Size: 1, Align: 1, C: c("int8_t")}, "int8": {Size: 1, Align: 1, C: c("GoInt8")},
"uint8": {Size: 1, Align: 1, C: c("uint8_t")}, "uint8": {Size: 1, Align: 1, C: c("GoUint8")},
"int16": {Size: 2, Align: 2, C: c("int16_t")}, "int16": {Size: 2, Align: 2, C: c("GoInt16")},
"uint16": {Size: 2, Align: 2, C: c("uint16_t")}, "uint16": {Size: 2, Align: 2, C: c("GoUint16")},
"int32": {Size: 4, Align: 4, C: c("int32_t")}, "int32": {Size: 4, Align: 4, C: c("GoInt32")},
"uint32": {Size: 4, Align: 4, C: c("uint32_t")}, "uint32": {Size: 4, Align: 4, C: c("GoUint32")},
"int64": {Size: 8, Align: 8, C: c("int64_t")}, "int64": {Size: 8, Align: 8, C: c("GoInt64")},
"uint64": {Size: 8, Align: 8, C: c("uint64_t")}, "uint64": {Size: 8, Align: 8, C: c("GoUint64")},
"float32": {Size: 4, Align: 4, C: c("GoFloat32")}, "float32": {Size: 4, Align: 4, C: c("GoFloat32")},
"float64": {Size: 8, Align: 8, C: c("GoFloat64")}, "float64": {Size: 8, Align: 8, C: c("GoFloat64")},
"complex64": {Size: 8, Align: 4, C: c("GoComplex64")}, "complex64": {Size: 8, Align: 4, C: c("GoComplex64")},
...@@ -1871,10 +1871,16 @@ const gccExportHeaderProlog = ` ...@@ -1871,10 +1871,16 @@ const gccExportHeaderProlog = `
#ifndef GO_CGO_PROLOGUE_H #ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H #define GO_CGO_PROLOGUE_H
#include <stdint.h> typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef intGOINTBITS_t GoInt; typedef short GoInt16;
typedef uintGOINTBITS_t GoUint; typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoIntGOINTBITS GoInt;
typedef GoUintGOINTBITS GoUint;
typedef __SIZE_TYPE__ GoUintptr; typedef __SIZE_TYPE__ GoUintptr;
typedef float GoFloat32; typedef float GoFloat32;
typedef double GoFloat64; typedef double GoFloat64;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment