diff options
author | Ayke van Laethem <[email protected]> | 2024-11-05 08:58:40 +0100 |
---|---|---|
committer | Ron Evans <[email protected]> | 2024-11-18 18:35:20 +0100 |
commit | c4867c8743e82433526b07eff3c599d05e0b7e6e (patch) | |
tree | 0774b12c49e2fadc271f216f9cc51edc1e765d88 /cgo | |
parent | 8068419854baf06333ccff38517e8d061e6d953d (diff) | |
download | tinygo-c4867c8743e82433526b07eff3c599d05e0b7e6e.tar.gz tinygo-c4867c8743e82433526b07eff3c599d05e0b7e6e.zip |
cgo: define idents referenced only from macros
Diffstat (limited to 'cgo')
-rw-r--r-- | cgo/cgo.go | 4 | ||||
-rw-r--r-- | cgo/const.go | 22 | ||||
-rw-r--r-- | cgo/const_test.go | 2 | ||||
-rw-r--r-- | cgo/libclang.go | 2 | ||||
-rw-r--r-- | cgo/testdata/const.go | 3 | ||||
-rw-r--r-- | cgo/testdata/const.out.go | 2 |
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 |