+++ /dev/null
-// Copyright 2013 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.
-
-#include "runtime.h"
-#include "cdefstest.h"
-
-struct CdefsTest test;
-struct PackedTest packed;
+++ /dev/null
-// Copyright 2013 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.
-//
-// +build ignore
-
-package cgotest
-
-/*
-// This file tests a bug found in the cgo -cdefs tool that incorrectly
-// translated Go pointer arrays generated by the cgo godefs tool back into C
-// pointer arrays.
-//
-// The comments below show how the type is translated from gcc-style C into Go
-// and back into C for both the buggy version and the correct version
-
-struct cdefsTest {
- // This was already being handled correctly
- // Correct: -> Array [20]int8 -> int8 array[20]
- char array1[20];
-
- // Buggy: -> Array [20][20]int8 -> [20]int8 array[20]
- // Correct: -> Array [20][20]int8 -> int8 array[20][20]
- char array2[20][20];
-
- // Buggy: -> Array [20]*int8 -> *int8 array[20]
- // Correct: -> Array [20]*int8 -> int8 *array[20]
- char *array3[20];
-
- // Buggy: -> Array [20][20]*int8 -> [20]*int8 array[20]
- // Correct: -> Array [20]**int8 -> int8 *array[20][20]
- char *array4[20][20];
-
- // Buggy: -> Array [20][20]**int8 -> [20]**int8 array[20]
- // Correct: -> Array [20][20]**int8 -> int8 **array[20][20]
- char **array5[20][20];
-};
-
-// Test that packed structures can be translated to C correctly too.
-// See issue 8477.
-
-struct packedTest {
- char first;
- int second;
- long long third;
-} __attribute__((packed));
-
-// Test that conflicting type definitions don't cause problems with cgo.
-// See issue 8477.
-
-typedef struct timespec {
- double bogus;
-} pid_t;
-
-*/
-import "C"
-
-type CdefsTest C.struct_cdefsTest
-
-//type PackedTest C.struct_packedTest
+++ /dev/null
-// Copyright 2013 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.
-
-#include "runtime.h"
-#include "cdefstest.h"
-
-void runtime·printf(int8*, ...);
-
-// From cdefstest.go.
-typedef struct CdefsOrig CdefsOrig;
-struct CdefsOrig {
- int8 array1[20];
- int8 array2[20][20];
- int8 *array3[20];
- int8 *array4[20][20];
- int8 **array5[20][20];
-};
-
-// Packed structs are no longer supported for -cdefs.
-/*
-typedef struct PackedOrig PackedOrig;
-#pragma pack on
-struct PackedOrig {
- int8 first;
- int32 second;
- int64 third;
-};
-#pragma pack off
-*/
-
-void
-main·test(int32 ret)
-{
- CdefsOrig o;
- CdefsTest t;
- // PackedOrig po;
- // PackedTest pt;
-
- ret = 0;
- if(sizeof(t.array1) != sizeof(o.array1) || offsetof(CdefsTest, array1[0]) != offsetof(CdefsOrig, array1[0])) {
- runtime·printf("array1: size, offset = %d, %d, want %d, %d\n", sizeof(t.array1), offsetof(CdefsTest, array1[0]), sizeof(o.array1), offsetof(CdefsOrig, array1[0]));
- ret = 1;
- }
- if(sizeof(t.array2) != sizeof(o.array2) || offsetof(CdefsTest, array2[0][0]) != offsetof(CdefsOrig, array2[0][0])) {
- runtime·printf("array2: size, offset = %d, %d, want %d, %d\n", sizeof(t.array2), offsetof(CdefsTest, array2[0][0]), sizeof(o.array2), offsetof(CdefsOrig, array2[0][0]));
- ret = 1;
- }
- if(sizeof(t.array3) != sizeof(o.array3) || offsetof(CdefsTest, array3[0]) != offsetof(CdefsOrig, array3[0])) {
- runtime·printf("array3: size, offset = %d, %d, want %d, %d\n", sizeof(t.array3), offsetof(CdefsTest, array3[0]), sizeof(o.array3), offsetof(CdefsOrig, array3[0]));
- ret = 1;
- }
- if(sizeof(t.array4) != sizeof(o.array4) || offsetof(CdefsTest, array4[0][0]) != offsetof(CdefsOrig, array4[0][0])) {
- runtime·printf("array4: size, offset = %d, %d, want %d, %d\n", sizeof(t.array4), offsetof(CdefsTest, array4[0][0]), sizeof(o.array4), offsetof(CdefsOrig, array4[0][0]));
- ret = 1;
- }
- if(sizeof(t.array5) != sizeof(o.array5) || offsetof(CdefsTest, array5[0][0]) != offsetof(CdefsOrig, array5[0][0])) {
- runtime·printf("array5: size, offset = %d, %d, want %d, %d\n", sizeof(t.array5), offsetof(CdefsTest, array5[0][0]), sizeof(o.array5), offsetof(CdefsOrig, array5[0][0]));
- ret = 1;
- }
-/*
- if(sizeof(pt.first) != sizeof(po.first) || offsetof(PackedTest, first) != offsetof(PackedOrig, first)) {
- runtime·printf("first: size, offset = %d, %d, want %d, %d\n", sizeof(pt.first), offsetof(PackedTest, first), sizeof(po.first), offsetof(PackedOrig, first));
- ret = 1;
- }
- if(sizeof(pt.second) != sizeof(po.second) || offsetof(PackedTest, second) != offsetof(PackedOrig, second)) {
- runtime·printf("second: size, offset = %d, %d, want %d, %d\n", sizeof(pt.second), offsetof(PackedTest, second), sizeof(po.second), offsetof(PackedOrig, second));
- ret = 1;
- }
- if(sizeof(pt.third) != sizeof(po.third) || offsetof(PackedTest, third) != offsetof(PackedOrig, third)) {
- runtime·printf("third: size, offset = %d, %d, want %d, %d\n", sizeof(pt.third), offsetof(PackedTest, third), sizeof(po.third), offsetof(PackedOrig, third));
- ret = 1;
- }
-*/
- FLUSH(&ret); // flush return value
-}
+++ /dev/null
-// Copyright 2013 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 main
-
-import "os"
-
-func test() int32 // in main.c
-
-func main() {
- os.Exit(int(test()))
-}
+++ /dev/null
-# Copyright 2013 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.
-
-# Just add issue file prefixes to this list if more issues come up
-FILE_PREFIXES="cdefstest"
-
-for FP in $FILE_PREFIXES
-do
- go tool cgo -cdefs ${FP}.go > ${FP}.h
-done
-
-go build . && ./testcdefs
-EXIT=$?
-rm -rf _obj testcdefs *.h
-exit $EXIT
Write out input file in Go syntax replacing C package
names with real values. Used to generate files in the
syscall package when bootstrapping a new target.
- -cdefs
- Like -godefs, but write file in C syntax.
- Used to generate files in the runtime package when
- bootstrapping a new target.
-objdir directory
Put all generated files in directory.
-gccgo
// rewriteRef rewrites all the C.xxx references in f.AST to refer to the
// Go equivalents, now that we have figured out the meaning of all
-// the xxx. In *godefs or *cdefs mode, rewriteRef replaces the names
+// the xxx. In *godefs mode, rewriteRef replaces the names
// with full definitions instead of mangled names.
func (p *Package) rewriteRef(f *File) {
// Keep a list of all the functions, to remove the ones
error_(r.Pos(), "must call C.%s", fixGo(r.Name.Go))
}
}
- if *godefs || *cdefs {
+ if *godefs {
// Substitute definition for mangled type name.
if id, ok := expr.(*ast.Ident); ok {
if t := typedef[id.Name]; t != nil {
c.goVoid = c.Ident("_Ctype_void")
// Normally cgo translates void* to unsafe.Pointer,
- // but for historical reasons -cdefs and -godefs use *byte instead.
- if *cdefs || *godefs {
+ // but for historical reasons -godefs uses *byte instead.
+ if *godefs {
c.goVoidPtr = &ast.StarExpr{X: c.byte}
} else {
c.goVoidPtr = c.Ident("unsafe.Pointer")
// If sub.Go.Name is "_Ctype_struct_foo" or "_Ctype_union_foo" or "_Ctype_class_foo",
// use that as the Go form for this typedef too, so that the typedef will be interchangeable
// with the base type.
- // In -godefs and -cdefs mode, do this for all typedefs.
- if isStructUnionClass(sub.Go) || *godefs || *cdefs {
+ // In -godefs mode, do this for all typedefs.
+ if isStructUnionClass(sub.Go) || *godefs {
t.Go = sub.Go
if isStructUnionClass(sub.Go) {
name := c.Ident("_Ctype_" + s)
tt := *t
typedef[name.Name] = &tt
- if !*godefs && !*cdefs {
+ if !*godefs {
t.Go = name
}
}
used[f.Name] = true
}
- if !*godefs && !*cdefs {
+ if !*godefs {
for cid, goid := range ident {
if token.Lookup(goid).IsKeyword() {
// Avoid keyword
name := f.Name
ft := f.Type
- // In godefs or cdefs mode, if this field is a C11
+ // In godefs mode, if this field is a C11
// anonymous union then treat the first field in the
// union as the field in the struct. This handles
// cases like the glibc <sys/resource.h> file; see
// issue 6677.
- if *godefs || *cdefs {
+ if *godefs {
if st, ok := f.Type.(*dwarf.StructType); ok && name == "" && st.Kind == "union" && len(st.Field) > 0 && !used[st.Field[0].Name] {
name = st.Field[0].Name
ident[name] = name
talign = size
}
- if talign > 0 && f.ByteOffset%talign != 0 && !*cdefs {
+ if talign > 0 && f.ByteOffset%talign != 0 {
// Drop misaligned fields, the same way we drop integer bit fields.
// The goal is to make available what can be made available.
// Otherwise one bad and unneeded field in an otherwise okay struct
// makes the whole program not compile. Much of the time these
// structs are in system headers that cannot be corrected.
- // Exception: In -cdefs mode, we use #pragma pack, so misaligned
- // fields should still work.
continue
}
n := len(fld)
buf.WriteString("}")
csyntax = buf.String()
- if *godefs || *cdefs {
+ if *godefs {
godefsFields(fld)
}
expr = &ast.StructType{Fields: &ast.FieldList{List: fld}}
n.Name = "Pad_cgo_" + strconv.Itoa(npad)
npad++
}
- if !*cdefs {
- n.Name = upper(n.Name)
- }
+ n.Name = upper(n.Name)
}
}
}
// package syscall's data structures, we drop a common prefix
// (so sec, usec, which will get turned into Sec, Usec for exporting).
func fieldPrefix(fld []*ast.Field) string {
- if *cdefs {
- return ""
- }
prefix := ""
for _, f := range fld {
for _, n := range f.Names {
return buf.String()
}
-// cdefs returns the output for -cdefs mode.
-// The easiest way to do this is to translate the godefs Go to C.
-func (p *Package) cdefs(f *File, srcfile string) string {
- godefsOutput := p.godefs(f, srcfile)
-
- lines := strings.Split(godefsOutput, "\n")
- lines[0] = "// Created by cgo -cdefs - DO NOT EDIT"
-
- for i, line := range lines {
- lines[i] = strings.TrimSpace(line)
- }
-
- var out bytes.Buffer
- printf := func(format string, args ...interface{}) { fmt.Fprintf(&out, format, args...) }
-
- didTypedef := false
- for i := 0; i < len(lines); i++ {
- line := lines[i]
-
- // Delete
- // package x
- if strings.HasPrefix(line, "package ") {
- continue
- }
-
- // Convert
- // const (
- // A = 1
- // B = 2
- // )
- //
- // to
- //
- // enum {
- // A = 1,
- // B = 2,
- // };
- if line == "const (" {
- printf("enum {\n")
- for i++; i < len(lines) && lines[i] != ")"; i++ {
- line = lines[i]
- if line != "" {
- printf("\t%s,", line)
- }
- printf("\n")
- }
- printf("};\n")
- continue
- }
-
- // Convert
- // const A = 1
- // to
- // enum { A = 1 };
- if strings.HasPrefix(line, "const ") {
- printf("enum { %s };\n", line[len("const "):])
- continue
- }
-
- // On first type definition, typedef all the structs
- // in case there are dependencies between them.
- if !didTypedef && strings.HasPrefix(line, "type ") {
- didTypedef = true
- for _, line := range lines {
- line = strings.TrimSpace(line)
- if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
- s := strings.TrimSuffix(strings.TrimPrefix(line, "type "), " struct {")
- printf("typedef struct %s %s;\n", s, s)
- }
- }
- printf("\n")
- printf("#pragma pack on\n")
- printf("\n")
- }
-
- // Convert
- // type T struct {
- // X int64
- // Y *int32
- // Z [4]byte
- // }
- //
- // to
- //
- // struct T {
- // int64 X;
- // int32 *Y;
- // byte Z[4];
- // }
- if strings.HasPrefix(line, "type ") && strings.HasSuffix(line, " struct {") {
- if len(lines) > i+1 && lines[i+1] == "}" {
- // do not output empty struct
- i++
- continue
- }
- s := line[len("type ") : len(line)-len(" struct {")]
- printf("struct %s {\n", s)
- for i++; i < len(lines) && lines[i] != "}"; i++ {
- line := lines[i]
- if line != "" {
- f := strings.Fields(line)
- if len(f) != 2 {
- fmt.Fprintf(os.Stderr, "cgo: cannot parse struct field: %s\n", line)
- nerrors++
- continue
- }
- printf("\t%s;", cdecl(f[0], f[1]))
- }
- printf("\n")
- }
- printf("};\n")
- continue
- }
-
- // Convert
- // type T int
- // to
- // typedef int T;
- if strings.HasPrefix(line, "type ") {
- f := strings.Fields(line[len("type "):])
- if len(f) != 2 {
- fmt.Fprintf(os.Stderr, "cgo: cannot parse type definition: %s\n", line)
- nerrors++
- continue
- }
- printf("typedef\t%s;\n", cdecl(f[0], f[1]))
- continue
- }
-
- printf("%s\n", line)
- }
-
- if didTypedef {
- printf("\n")
- printf("#pragma pack off\n")
- }
-
- return out.String()
-}
-
-// cdecl returns the C declaration for the given Go name and type.
-// It only handles the specific cases necessary for converting godefs output.
-func cdecl(name, typ string) string {
- // X *[0]byte -> X *void
- if strings.HasPrefix(typ, "*[0]") {
- typ = "*void"
- }
- // X [4]byte -> X[4] byte
- for strings.HasPrefix(typ, "[") {
- i := strings.Index(typ, "]") + 1
- name = name + typ[:i]
- typ = typ[i:]
- }
- // X *byte -> *X byte
- for strings.HasPrefix(typ, "*") {
- name = "*" + name
- typ = typ[1:]
- }
- // X T -> T X
- // Handle the special case: 'unsafe.Pointer' is 'void *'
- if typ == "unsafe.Pointer" {
- typ = "void"
- name = "*" + name
- }
- return typ + "\t" + name
-}
-
var gofmtBuf bytes.Buffer
// gofmt returns the gofmt-formatted string for an AST node.
var dynlinker = flag.Bool("dynlinker", false, "record dynamic linker information in -dynimport mode")
// These flags are for bootstrapping a new Go implementation,
-// to generate Go and C headers that match the data layout and
+// to generate Go types that match the data layout and
// constant values used in the host's C libraries and system calls.
var godefs = flag.Bool("godefs", false, "for bootstrap: write Go definitions for C file to standard output")
-var cdefs = flag.Bool("cdefs", false, "for bootstrap: write C definitions for C file to standard output")
var objDir = flag.String("objdir", "", "object directory")
var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
return
}
- if *godefs && *cdefs {
- fmt.Fprintf(os.Stderr, "cgo: cannot use -cdefs and -godefs together\n")
- os.Exit(2)
- }
-
- if *godefs || *cdefs {
+ if *godefs {
// Generating definitions pulled from header files,
// to be checked into Go repositories.
// Line numbers are just noise.
p.Record(f)
if *godefs {
os.Stdout.WriteString(p.godefs(f, input))
- } else if *cdefs {
- os.Stdout.WriteString(p.cdefs(f, input))
} else {
p.writeOutput(f, input)
}
}
- if !*godefs && !*cdefs {
+ if !*godefs {
p.writeDefs()
}
if nerrors > 0 {
fi
esac
-# This tests cgo -cdefs. That mode is not supported,
-# so it's okay if it doesn't work on some systems.
-# In particular, it works badly with clang on OS X.
-# It doesn't work at all now that we disallow C code
-# outside runtime. Once runtime has no C code it won't
-# even be necessary.
-# [ "$CGO_ENABLED" != 1 ] || [ "$GOOS" == darwin ] ||
-# (xcd ../misc/cgo/testcdefs
-# ./test.bash || exit 1
-# ) || exit $?
-
[ "$CGO_ENABLED" != 1 ] || [ "$GOOS" == darwin ] ||
(xcd ../misc/cgo/testgodefs
./test.bash || exit 1