Skip to content

Commit 9772d3a

Browse files
ianlancetaylorgopherbot
authored andcommitted
cmd/cgo: strip top-level const qualifier from argument frame struct
Otherwise we can't assign to it. Fixes #75751 Change-Id: Iba680db672297bca1a1d1a33912b80863da66a08 Reviewed-on: https://go-review.googlesource.com/c/go/+/717342 Reviewed-by: David Chase <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Mark Freeman <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 1903782 commit 9772d3a

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

src/cmd/cgo/internal/test/test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,12 @@ typedef struct {
953953
} issue69086struct;
954954
static int issue690861(issue69086struct* p) { p->b = 1234; return p->c; }
955955
static int issue690862(unsigned long ul1, unsigned long ul2, unsigned int u, issue69086struct s) { return (int)(s.b); }
956+
957+
char issue75751v = 1;
958+
char * const issue75751p = &issue75751v;
959+
#define issue75751m issue75751p
960+
char * const volatile issue75751p2 = &issue75751v;
961+
#define issue75751m2 issue75751p2
956962
*/
957963
import "C"
958964

@@ -2396,3 +2402,8 @@ func test69086(t *testing.T) {
23962402
t.Errorf("call: got %d, want 1234", got)
23972403
}
23982404
}
2405+
2406+
// Issue 75751: no runtime test, just make sure it compiles.
2407+
func test75751() int {
2408+
return int(*C.issue75751m) + int(*C.issue75751m2)
2409+
}

src/cmd/cgo/out.go

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,36 @@ func checkImportSymName(s string) {
457457
// Also assumes that gc convention is to word-align the
458458
// input and output parameters.
459459
func (p *Package) structType(n *Name) (string, int64) {
460+
// It's possible for us to see a type with a top-level const here,
461+
// which will give us an unusable struct type. See #75751.
462+
// The top-level const will always appear as a final qualifier,
463+
// constructed by typeConv.loadType in the dwarf.QualType case.
464+
// The top-level const is meaningless here and can simply be removed.
465+
stripConst := func(s string) string {
466+
i := strings.LastIndex(s, "const")
467+
if i == -1 {
468+
return s
469+
}
470+
471+
// A top-level const can only be followed by other qualifiers.
472+
if r, ok := strings.CutSuffix(s, "const"); ok {
473+
return strings.TrimSpace(r)
474+
}
475+
476+
var nonConst []string
477+
for _, f := range strings.Fields(s[i:]) {
478+
switch f {
479+
case "const":
480+
case "restrict", "volatile":
481+
nonConst = append(nonConst, f)
482+
default:
483+
return s
484+
}
485+
}
486+
487+
return strings.TrimSpace(s[:i]) + " " + strings.Join(nonConst, " ")
488+
}
489+
460490
var buf strings.Builder
461491
fmt.Fprint(&buf, "struct {\n")
462492
off := int64(0)
@@ -468,7 +498,7 @@ func (p *Package) structType(n *Name) (string, int64) {
468498
}
469499
c := t.Typedef
470500
if c == "" {
471-
c = t.C.String()
501+
c = stripConst(t.C.String())
472502
}
473503
fmt.Fprintf(&buf, "\t\t%s p%d;\n", c, i)
474504
off += t.Size
@@ -484,7 +514,7 @@ func (p *Package) structType(n *Name) (string, int64) {
484514
fmt.Fprintf(&buf, "\t\tchar __pad%d[%d];\n", off, pad)
485515
off += pad
486516
}
487-
fmt.Fprintf(&buf, "\t\t%s r;\n", t.C)
517+
fmt.Fprintf(&buf, "\t\t%s r;\n", stripConst(t.C.String()))
488518
off += t.Size
489519
}
490520
if off%p.PtrSize != 0 {

0 commit comments

Comments
 (0)