mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +00:00
cgo: refactor Go types a little bit
Code like this is not allowed by the upstream Go CGo implementation, but
was allowed by TinyGo:
var _ int8 = C.int8_t(5)
The reason it shouldn't be allowed is a little bit complicated. While
it is true that C.int8_t is always the same underlying data type as Go
int8 (signed 8-bit integer), the C type is actually a typedef of one of
the base C types (usually unsigned char or signed char) which in turn do
_not_ map cleanly to Go types: the 'char' type is ambiguous (it may be
either signed or unsigned depending on the ABI) and types like 'int'
vary in size by ABI as well.
To make code more portable, I think it's better to match the upstream
implementation.
This commit is contained in:
+9
-19
@@ -75,19 +75,10 @@ type bitfieldInfo struct {
|
||||
}
|
||||
|
||||
// cgoAliases list type aliases between Go and C, for types that are equivalent
|
||||
// in both languages. See addTypeAliases.
|
||||
// in both languages.
|
||||
var cgoAliases = map[string]string{
|
||||
"C.int8_t": "int8",
|
||||
"C.int16_t": "int16",
|
||||
"C.int32_t": "int32",
|
||||
"C.int64_t": "int64",
|
||||
"C.uint8_t": "uint8",
|
||||
"C.uint16_t": "uint16",
|
||||
"C.uint32_t": "uint32",
|
||||
"C.uint64_t": "uint64",
|
||||
"C.uintptr_t": "uintptr",
|
||||
"C.float": "float32",
|
||||
"C.double": "float64",
|
||||
"float": "float32",
|
||||
"double": "float64",
|
||||
}
|
||||
|
||||
// builtinAliases are handled specially because they only exist on the Go side
|
||||
@@ -311,10 +302,11 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl
|
||||
// Process CGo imports for each file.
|
||||
for i, f := range files {
|
||||
cf := p.newCGoFile(f, i)
|
||||
// Float and double are aliased, meaning that C.float is the same thing
|
||||
// as float32 in Go.
|
||||
cf.names["float"] = clangCursor{}
|
||||
cf.names["double"] = clangCursor{}
|
||||
// These types are aliased with the corresponding types in C. For
|
||||
// example, float in C is always float32 in Go.
|
||||
for name := range cgoAliases {
|
||||
cf.names[name] = clangCursor{}
|
||||
}
|
||||
// Now read all the names (identifies) that C defines in the header
|
||||
// snippet.
|
||||
cf.readNames(p.cgoHeaders[i], cflagsForCGo, filepath.Base(fset.File(f.Pos()).Name()), func(names map[string]clangCursor) {
|
||||
@@ -1129,9 +1121,7 @@ func (p *cgoPackage) getUnnamedDeclName(prefix string, itf interface{}) string {
|
||||
// getASTDeclName will declare the given C AST node (if not already defined) and
|
||||
// will return its name, in the form of C.foo.
|
||||
func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) string {
|
||||
// Some types are defined in stdint.h and map directly to a particular Go
|
||||
// type.
|
||||
if alias := cgoAliases["C."+name]; alias != "" {
|
||||
if alias := cgoAliases[name]; alias != "" {
|
||||
return alias
|
||||
}
|
||||
node := f.getASTDeclNode(name, found, iscall)
|
||||
|
||||
Vendored
+8
@@ -22,8 +22,12 @@ import "C"
|
||||
// #warning another warning
|
||||
import "C"
|
||||
|
||||
// #include <stdint.h>
|
||||
import "C"
|
||||
|
||||
// Make sure that errors for the following lines won't change with future
|
||||
// additions to the CGo preamble.
|
||||
//
|
||||
//line errors.go:100
|
||||
var (
|
||||
// constant too large
|
||||
@@ -38,4 +42,8 @@ var (
|
||||
_ byte = C.SOME_CONST_3
|
||||
|
||||
_ = C.SOME_CONST_4
|
||||
|
||||
// This must result in a type error. Previously, TinyGo would allow this
|
||||
// code (which is not allowed by upstream Go).
|
||||
_ int8 = C.int8_t(5)
|
||||
)
|
||||
|
||||
Vendored
+3
@@ -11,6 +11,7 @@
|
||||
// testdata/errors.go:108: undefined: C.SOME_CONST_1
|
||||
// testdata/errors.go:110: cannot use C.SOME_CONST_3 (untyped int constant 1234) as byte value in variable declaration (overflows)
|
||||
// testdata/errors.go:112: undefined: C.SOME_CONST_4
|
||||
// testdata/errors.go:116: cannot use C.int8_t(5) (constant 5 of type C.schar) as int8 value in variable declaration
|
||||
|
||||
package main
|
||||
|
||||
@@ -58,3 +59,5 @@ type C.struct_point_t struct {
|
||||
type C.point_t = C.struct_point_t
|
||||
|
||||
const C.SOME_CONST_3 = 1234
|
||||
|
||||
type C.int8_t = C.schar
|
||||
|
||||
Vendored
-4
@@ -52,10 +52,6 @@ func main() {
|
||||
println("static headerfunc:", C.headerfunc_static(5))
|
||||
headerfunc_2()
|
||||
|
||||
// equivalent types
|
||||
var goInt8 int8 = 5
|
||||
var _ C.int8_t = goInt8
|
||||
|
||||
// more globals
|
||||
println("bool:", C.globalBool, C.globalBool2 == true)
|
||||
println("float:", C.globalFloat)
|
||||
|
||||
Reference in New Issue
Block a user