aboutsummaryrefslogtreecommitdiffhomepage
path: root/cgo
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2024-11-05 08:58:40 +0100
committerRon Evans <[email protected]>2024-11-18 18:35:20 +0100
commitc4867c8743e82433526b07eff3c599d05e0b7e6e (patch)
tree0774b12c49e2fadc271f216f9cc51edc1e765d88 /cgo
parent8068419854baf06333ccff38517e8d061e6d953d (diff)
downloadtinygo-c4867c8743e82433526b07eff3c599d05e0b7e6e.tar.gz
tinygo-c4867c8743e82433526b07eff3c599d05e0b7e6e.zip
cgo: define idents referenced only from macros
Diffstat (limited to 'cgo')
-rw-r--r--cgo/cgo.go4
-rw-r--r--cgo/const.go22
-rw-r--r--cgo/const_test.go2
-rw-r--r--cgo/libclang.go2
-rw-r--r--cgo/testdata/const.go3
-rw-r--r--cgo/testdata/const.out.go2
6 files changed, 28 insertions, 7 deletions
diff --git a/cgo/cgo.go b/cgo/cgo.go
index 4a5d7efed..a90b30753 100644
--- a/cgo/cgo.go
+++ b/cgo/cgo.go
@@ -1148,7 +1148,7 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
if alias := cgoAliases["C."+name]; alias != "" {
return alias
}
- node := f.getASTDeclNode(name, found, iscall)
+ node := f.getASTDeclNode(name, found)
if node, ok := node.(*ast.FuncDecl); ok {
if !iscall {
return node.Name.Name + "$funcaddr"
@@ -1160,7 +1160,7 @@ func (f *cgoFile) getASTDeclName(name string, found clangCursor, iscall bool) st
// getASTDeclNode will declare the given C AST node (if not already defined) and
// returns it.
-func (f *cgoFile) getASTDeclNode(name string, found clangCursor, iscall bool) ast.Node {
+func (f *cgoFile) getASTDeclNode(name string, found clangCursor) ast.Node {
if node, ok := f.defined[name]; ok {
// Declaration was found in the current file, so return it immediately.
return node
diff --git a/cgo/const.go b/cgo/const.go
index f4707c80a..ab088b3c8 100644
--- a/cgo/const.go
+++ b/cgo/const.go
@@ -54,8 +54,8 @@ func init() {
}
// parseConst parses the given string as a C constant.
-func parseConst(pos token.Pos, fset *token.FileSet, value string) (ast.Expr, *scanner.Error) {
- t := newTokenizer(pos, fset, value)
+func parseConst(pos token.Pos, fset *token.FileSet, value string, f *cgoFile) (ast.Expr, *scanner.Error) {
+ t := newTokenizer(pos, fset, value, f)
expr, err := parseConstExpr(t, precedenceLowest)
t.Next()
if t.curToken != token.EOF {
@@ -96,6 +96,20 @@ func parseConstExpr(t *tokenizer, precedence int) (ast.Expr, *scanner.Error) {
}
func parseIdent(t *tokenizer) (ast.Expr, *scanner.Error) {
+ // Normally the name is something defined in the file (like another macro)
+ // which we get the declaration from using getASTDeclName.
+ // This ensures that names that are only referenced inside a macro are still
+ // getting defined.
+ if t.f != nil {
+ if cursor, ok := t.f.names[t.curValue]; ok {
+ return &ast.Ident{
+ NamePos: t.curPos,
+ Name: t.f.getASTDeclName(t.curValue, cursor, false),
+ }, nil
+ }
+ }
+
+ // t.f is nil during testing. This is a fallback.
return &ast.Ident{
NamePos: t.curPos,
Name: "C." + t.curValue,
@@ -164,6 +178,7 @@ func unexpectedToken(t *tokenizer, expected token.Token) *scanner.Error {
// tokenizer reads C source code and converts it to Go tokens.
type tokenizer struct {
+ f *cgoFile
curPos, peekPos token.Pos
fset *token.FileSet
curToken, peekToken token.Token
@@ -173,8 +188,9 @@ type tokenizer struct {
// newTokenizer initializes a new tokenizer, positioned at the first token in
// the string.
-func newTokenizer(start token.Pos, fset *token.FileSet, buf string) *tokenizer {
+func newTokenizer(start token.Pos, fset *token.FileSet, buf string, f *cgoFile) *tokenizer {
t := &tokenizer{
+ f: f,
peekPos: start,
fset: fset,
buf: buf,
diff --git a/cgo/const_test.go b/cgo/const_test.go
index d150e751f..c2f52c53c 100644
--- a/cgo/const_test.go
+++ b/cgo/const_test.go
@@ -59,7 +59,7 @@ func TestParseConst(t *testing.T) {
} {
fset := token.NewFileSet()
startPos := fset.AddFile("", -1, 1000).Pos(0)
- expr, err := parseConst(startPos, fset, tc.C)
+ expr, err := parseConst(startPos, fset, tc.C, nil)
s := "<invalid>"
if err != nil {
if !strings.HasPrefix(tc.Go, "error: ") {
diff --git a/cgo/libclang.go b/cgo/libclang.go
index 59236bad4..c66112d53 100644
--- a/cgo/libclang.go
+++ b/cgo/libclang.go
@@ -408,7 +408,7 @@ func (f *cgoFile) createASTNode(name string, c clangCursor) (ast.Node, any) {
if pos != token.NoPos {
tokenPos = pos + token.Pos(len(name))
}
- expr, scannerError := parseConst(tokenPos, f.fset, value)
+ expr, scannerError := parseConst(tokenPos, f.fset, value, f)
if scannerError != nil {
f.errors = append(f.errors, *scannerError)
return nil, nil
diff --git a/cgo/testdata/const.go b/cgo/testdata/const.go
index 43645d3ac..258942235 100644
--- a/cgo/testdata/const.go
+++ b/cgo/testdata/const.go
@@ -3,10 +3,13 @@ package main
/*
#define foo 3
#define bar foo
+#define unreferenced 4
+#define referenced unreferenced
*/
import "C"
const (
Foo = C.foo
Bar = C.bar
+ Baz = C.referenced
)
diff --git a/cgo/testdata/const.out.go b/cgo/testdata/const.out.go
index 2b48163b4..fb0bbeeba 100644
--- a/cgo/testdata/const.out.go
+++ b/cgo/testdata/const.out.go
@@ -47,3 +47,5 @@ type (
const C.foo = 3
const C.bar = C.foo
+const C.unreferenced = 4
+const C.referenced = C.unreferenced