cmd/cgo: disable #cgo noescape/nocallback until Go 1.23

Go 1.21 and earlier do not understand this line, causing
"go mod vendor" of //go:build go1.22-tagged code that
uses this feature to fail.

The solution is to include the go/build change to skip over
the line in Go 1.22 (making "go mod vendor" from Go 1.22 onward
work with this change) and then wait to deploy the cgo change
until Go 1.23, at which point Go 1.21 and earlier will be unsupported.

For #56378.
Fixes #63293.

Change-Id: Ifa08b134eac5a6aa15d67dad0851f00e15e1e58b
Reviewed-on: https://go-review.googlesource.com/c/go/+/539235
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
This commit is contained in:
Russ Cox 2023-11-02 08:15:44 -04:00
parent 5622a4b205
commit 607e020150
8 changed files with 11 additions and 47 deletions

View File

@ -39,24 +39,7 @@ Do not send CLs removing the interior tags from such phrases.
<h3 id="cgo">Cgo</h3>
<p><!-- CL 497837 --> The special comment that precedes
<code>import</code> <code>"C"</code> may now include two
new <code>#cgo</code> directives.
<ul>
<li>
<code>#cgo</code> <code>noescape</code> <code>cFunctionName</code>
tells cgo that Go pointers passed to the C function
<code>cFunctionName</code> do not escape.
</li>
<li>
<code>#cgo</code> <code>nocallback</code> <code>cFunctionName</code>
tells cgo that the C function <code>cFunctionName</code> does
not call any Go functions.
</li>
</ul>
See <a href="/cmd/cgo#hdr-Optimizing_calls_of_C_code">the <code>cgo</code>
documentation</a> for more details.
</p>
<!-- CL 497837 reverted -->
<h2 id="runtime">Runtime</h2>

View File

@ -420,30 +420,6 @@ passing uninitialized C memory to Go code if the Go code is going to
store pointer values in it. Zero out the memory in C before passing it
to Go.
# Optimizing calls of C code
When passing a Go pointer to a C function the compiler normally ensures
that the Go object lives on the heap. If the C function does not keep
a copy of the Go pointer, and never passes the Go pointer back to Go code,
then this is unnecessary. The #cgo noescape directive may be used to tell
the compiler that no Go pointers escape via the named C function.
If the noescape directive is used and the C function does not handle the
pointer safely, the program may crash or see memory corruption.
For example:
// #cgo noescape cFunctionName
When a Go function calls a C function, it prepares for the C function to
call back to a Go function. the #cgo nocallback directive may be used to
tell the compiler that these preparations are not necessary.
If the nocallback directive is used and the C function does call back into
Go code, the program will panic.
For example:
// #cgo nocallback cFunctionName
# Special cases
A few special C types which would normally be represented by a pointer

View File

@ -94,8 +94,10 @@ func (f *File) ProcessCgoDirectives() {
directive := fields[1]
funcName := fields[2]
if directive == "nocallback" {
fatalf("#cgo nocallback disabled until Go 1.23")
f.NoCallbacks[funcName] = true
} else if directive == "noescape" {
fatalf("#cgo noescape disabled until Go 1.23")
f.NoEscapes[funcName] = true
}
}

View File

@ -117,7 +117,8 @@ int add(int x, int y) {
// escape vs noescape
#cgo noescape handleGoStringPointerNoescape
// TODO(#56378): enable in Go 1.23:
// #cgo noescape handleGoStringPointerNoescape
void handleGoStringPointerNoescape(void *s) {}
void handleGoStringPointerEscape(void *s) {}

View File

@ -5,7 +5,8 @@
package main
/*
// ERROR MESSAGE: #cgo noescape noMatchedCFunction: no matched C function
// TODO(#56378): change back to "#cgo noescape noMatchedCFunction: no matched C function" in Go 1.23
// ERROR MESSAGE: #cgo noescape disabled until Go 1.23
#cgo noescape noMatchedCFunction
*/
import "C"

View File

@ -754,6 +754,7 @@ func TestNeedmDeadlock(t *testing.T) {
}
func TestCgoNoCallback(t *testing.T) {
t.Skip("TODO(#56378): enable in Go 1.23")
got := runTestProg(t, "testprogcgo", "CgoNoCallback")
want := "function marked with #cgo nocallback called back into Go"
if !strings.Contains(got, want) {
@ -762,6 +763,7 @@ func TestCgoNoCallback(t *testing.T) {
}
func TestCgoNoEscape(t *testing.T) {
t.Skip("TODO(#56378): enable in Go 1.23")
got := runTestProg(t, "testprogcgo", "CgoNoEscape")
want := "OK\n"
if got != want {

View File

@ -8,8 +8,7 @@ package main
// But it do callback to go in this test, Go should crash here.
/*
#cgo nocallback runCShouldNotCallback
// TODO(#56378): #cgo nocallback runCShouldNotCallback
extern void runCShouldNotCallback();
*/
import "C"

View File

@ -13,7 +13,7 @@ package main
// 2. less than 100 new allocated heap objects after invoking withoutNoEscape 100 times.
/*
#cgo noescape runCWithNoEscape
// TODO(#56378): #cgo noescape runCWithNoEscape
void runCWithNoEscape(void *p) {
}