diff --git a/.gitignore b/.gitignore index 6f6b8c23..52681010 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ *.DS_Store _temp/ +*.log # Test binary, built with `go test -c` *.test diff --git a/clang/clang.go b/clang/clang.go index 674017ff..e10e6c2f 100644 --- a/clang/clang.go +++ b/clang/clang.go @@ -31,7 +31,9 @@ type stringer interface { // String returns the Go string of a value whose String() returns a clang String. func String[T stringer](v T) string { - return clang.GoString(v.String()) + str := v.String() + defer str.Dispose() + return c.GoString(str.CStr()) } // ----------------------------------------------------------------------------- @@ -112,6 +114,11 @@ func (u TranslationUnit) Cursor() Cursor { return u.impl.Cursor() } +// Underlying returns the underlying clang TranslationUnit. +func (u TranslationUnit) Underlying() *clang.TranslationUnit { + return u.impl +} + // ----------------------------------------------------------------------------- /** @@ -134,6 +141,21 @@ func (u TranslationUnit) Cursor() Cursor { */ type Cursor = clang.Cursor +/** + * Identifies a specific source location within a translation + * unit. + * + * Use clang_getExpansionLocation() or clang_getSpellingLocation() + * to map a source location to a particular file, line, and column. + */ +type SourceLocation = clang.SourceLocation + +// PresumedFile returns the presumed file name for the given source location. +func PresumedFile(loc SourceLocation) (filename clang.String) { + loc.PresumedLocation(&filename, nil, nil) + return +} + /** * Describes how the traversal of the children of a particular * cursor should proceed after visiting a particular child cursor. diff --git a/cmd/llcppdump/cppdump.go b/cmd/llcppdump/cppdump.go index 4ee725b1..6aed0aa1 100644 --- a/cmd/llcppdump/cppdump.go +++ b/cmd/llcppdump/cppdump.go @@ -22,18 +22,33 @@ import ( "os" "strings" + "github.com/goplus/lib/c" "github.com/goplus/llcppg/clang" lc "github.com/goplus/llcppg/lib/clang" ) -func dump(c clang.Cursor, ns string) { - clang.VisitChildren(c, func(cur, parent clang.Cursor) clang.ChildVisitResult { +func dump(node clang.Cursor, ns string, presumedFile *c.Char) { + clang.VisitChildren(node, func(cur, parent clang.Cursor) clang.ChildVisitResult { + if presumedFile != nil { + loc := cur.Location() + at := clang.PresumedFile(loc) + cmpf := c.Strcmp(at.CStr(), presumedFile) + at.Dispose() + if cmpf != 0 { + return clang.Continue + } + } + kind := cur.Kind + if kind == lc.CursorCXXAccessSpecifier { + log.Println("==>", kind, "CXXAccessSpecifier", cur.CXXAccessSpecifier()) + return clang.Continue + } name := ns + clang.String(cur) - log.Println("==>", cur.Kind, clang.String(cur.Kind), name) - switch cur.Kind { + log.Println("==>", kind, clang.String(kind), name) + switch kind { case lc.CursorFunctionDecl, lc.CursorCXXMethod, lc.CursorConstructor, lc.CursorDestructor: - case lc.CursorNamespace: - dump(cur, name+"::") + case lc.CursorClassDecl, lc.CursorNamespace: + dump(cur, name+"::", presumedFile) } return clang.Continue }) @@ -57,5 +72,17 @@ func main() { u := idx.ParseTranslationUnit(0, filename, "-x", lang) defer u.Dispose() - dump(u.Cursor(), "") + usys := u.Underlying() + spelling := usys.Spelling() + defer spelling.Dispose() + log.Println("==> TranslationUnit", c.GoString(spelling.CStr())) + + file := usys.File(spelling.CStr()) + loc := usys.GetLocationForOffset(file, 2) + presumedFile := clang.PresumedFile(loc) + defer presumedFile.Dispose() + log.Println("==> PresumedFile", c.GoString(presumedFile.CStr())) + + root := u.Cursor() + dump(root, "", presumedFile.CStr()) } diff --git a/lib/clang/basic.go b/lib/clang/basic.go index 0ddee092..272104cb 100644 --- a/lib/clang/basic.go +++ b/lib/clang/basic.go @@ -57,13 +57,3 @@ type StringSet struct { */ // llgo:link (*StringSet).Dispose C.clang_disposeStringSet func (*StringSet) Dispose() {} - -// GoString returns the Go string representation of clangStr and disposes it. -func GoString(clangStr String) (str string) { - defer clangStr.Dispose() - cstr := clangStr.CStr() - if cstr != nil { - str = c.GoString(cstr) - } - return -} diff --git a/lib/clang/clang.go b/lib/clang/clang.go index d33a1707..50715d50 100644 --- a/lib/clang/clang.go +++ b/lib/clang/clang.go @@ -1284,7 +1284,7 @@ type TranslationUnit struct { * Destroy the specified CXTranslationUnit object. */ // llgo:link (*TranslationUnit).Dispose C.clang_disposeTranslationUnit -func (*TranslationUnit) Dispose() {} +func (t *TranslationUnit) Dispose() {} /** * Retrieve the cursor that represents the given translation unit. @@ -1297,6 +1297,16 @@ func (t *TranslationUnit) Cursor() (ret Cursor) { return } +// llgo:link (*TranslationUnit).File C.clang_getFile +func (t *TranslationUnit) File(filename *c.Char) (ret File) { + return +} + +// llgo:link (*TranslationUnit).Spelling C.clang_getTranslationUnitSpelling +func (t *TranslationUnit) Spelling() (ret String) { + return +} + /** * Describes the kind of entity that a cursor refers to. */ @@ -1507,6 +1517,9 @@ type Type struct { */ type File uintptr +//llgo:link File.FileName C.clang_getFileName +func (File) FileName() (ret String) { return } + /** * Identifies a specific source location within a translation * unit. @@ -2487,7 +2500,7 @@ func (c Token) Kind() (ret TokenKind) { * the text of an identifier or keyword. */ // llgo:link (*TranslationUnit).Token C.clang_getTokenSpelling -func (c *TranslationUnit) Token(token Token) (ret String) { +func (t *TranslationUnit) Token(token Token) (ret String) { return } @@ -2634,26 +2647,6 @@ func (l SourceLocation) IsInSystemHeader() (ret c.Uint) { func (l SourceLocation) SpellingLocation(file *File, line, column, offset *c.Uint) { } -func (l SourceLocation) File() (ret File) { - l.SpellingLocation(&ret, nil, nil, nil) - return -} - -func (l SourceLocation) Line() (ret c.Uint) { - l.SpellingLocation(nil, &ret, nil, nil) - return -} - -func (l SourceLocation) Column() (ret c.Uint) { - l.SpellingLocation(nil, nil, &ret, nil) - return -} - -func (l SourceLocation) Offset() (ret c.Uint) { - l.SpellingLocation(nil, nil, nil, &ret) - return -} - /** * Retrieve the file, line and column represented by the given source * location, as specified in a # line directive. @@ -2715,6 +2708,3 @@ func (r SourceRange) RangeStart() (loc SourceLocation) { func (r SourceRange) RangeEnd() (loc SourceLocation) { return } - -//llgo:link File.FileName C.clang_getFileName -func (File) FileName() (ret String) { return }