Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/cmd/cgo/internal/test/testx.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ typedef struct {
int i;
} Issue38408, *PIssue38408;

// issue 44648
typedef int issue44648T;
typedef int (*issue44648F)(void *);

extern void cfunc49633(void*); // definition is in test.go
*/
import "C"
Expand Down Expand Up @@ -575,6 +579,26 @@ func GoFunc37033(handle C.uintptr_t) {
// No runtime test; just make sure it compiles.
var _ C.PIssue38408 = &C.Issue38408{i: 1}

// issue 44648
// The C wrapper for an exported Go function failed to compile if a
// parameter had the same name as a C type used by the function.
// No runtime test; just make sure it compiles.

//export Issue44648A
func Issue44648A(issue44648F C.issue44648F, data unsafe.Pointer) C.int {
return 0
}

//export Issue44648B
func Issue44648B(issue44648T C.issue44648T) (C.issue44648T, C.issue44648T) {
return issue44648T, issue44648T
}

//export Issue44648C
func Issue44648C(r C.int) (a, b C.int) {
return r, r
}

// issue 49633, example use of cgo.Handle with void*

type data49633 struct {
Expand Down
53 changes: 33 additions & 20 deletions src/cmd/cgo/out.go
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,12 @@ func (p *Package) packedAttribute() string {
return s + "))"
}

// genParamName returns the generated name for the parameter at the given
// position in the C wrapper that cgo writes for an exported function.
func genParamName(param string, position int) string {
return fmt.Sprintf("p%d", position)
}

// exportParamName returns the value of param as it should be
// displayed in a c header file. If param contains any non-ASCII
// characters, this function will return the character p followed by
Expand Down Expand Up @@ -1047,37 +1053,44 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
}

// Build the wrapper function compiled by gcc.
var s strings.Builder
fmt.Fprintf(&s, "%s %s(", gccResult, exp.ExpName)
if fn.Recv != nil {
s.WriteString(p.cgoType(fn.Recv.List[0].Type).C.String())
s.WriteString(" recv")
}
// The declaration in the header uses the Go parameter
// names, but the definition uses generated names so
// that a parameter cannot shadow a C type or variable
// used in the body of the wrapper (issue 44648).
cdecl := func(paramName func(aname string, i int) string) string {
var s strings.Builder
fmt.Fprintf(&s, "%s %s(", gccResult, exp.ExpName)
if fn.Recv != nil {
s.WriteString(p.cgoType(fn.Recv.List[0].Type).C.String())
s.WriteString(" recv")
}

if len(fntype.Params.List) > 0 {
forFieldList(fntype.Params,
func(i int, aname string, atype ast.Expr) {
if i > 0 || fn.Recv != nil {
s.WriteString(", ")
}
fmt.Fprintf(&s, "%s %s", p.cgoType(atype).C, exportParamName(aname, i))
})
} else {
s.WriteString("void")
if len(fntype.Params.List) > 0 {
forFieldList(fntype.Params,
func(i int, aname string, atype ast.Expr) {
if i > 0 || fn.Recv != nil {
s.WriteString(", ")
}
fmt.Fprintf(&s, "%s %s", p.cgoType(atype).C, paramName(aname, i))
})
} else {
s.WriteString("void")
}
s.WriteByte(')')
return s.String()
}
s.WriteByte(')')

if len(exp.Doc) > 0 {
fmt.Fprintf(fgcch, "\n%s", exp.Doc)
if !strings.HasSuffix(exp.Doc, "\n") {
fmt.Fprint(fgcch, "\n")
}
}
fmt.Fprintf(fgcch, "extern %s;\n", s.String())
fmt.Fprintf(fgcch, "extern %s;\n", cdecl(exportParamName))

fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *);\n", cPrefix, exp.ExpName)
fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD")
fmt.Fprintf(fgcc, "\n%s\n", s.String())
fmt.Fprintf(fgcc, "\n%s\n", cdecl(genParamName))
fmt.Fprintf(fgcc, "{\n")
fmt.Fprintf(fgcc, "\tsize_t _cgo_ctxt = _cgo_wait_runtime_init_done();\n")
// The results part of the argument structure must be
Expand All @@ -1104,7 +1117,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
}
forFieldList(fntype.Params,
func(i int, aname string, atype ast.Expr) {
fmt.Fprintf(fgcc, "\t_cgo_a.p%d = %s;\n", i, exportParamName(aname, i))
fmt.Fprintf(fgcc, "\t_cgo_a.p%d = %s;\n", i, genParamName(aname, i))
})
fmt.Fprintf(fgcc, "\t_cgo_tsan_release();\n")
fmt.Fprintf(fgcc, "\tcrosscall2(_cgoexp%s_%s, &_cgo_a, %d, _cgo_ctxt);\n", cPrefix, exp.ExpName, off)
Expand Down
Loading