-
Notifications
You must be signed in to change notification settings - Fork 11
llcppdump: support PresumedFile #699
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
| *.DS_Store | ||
|
|
||
| _temp/ | ||
| *.log | ||
|
|
||
| # Test binary, built with `go test -c` | ||
| *.test | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P3] Document PresumedFile's dispose-ownership contract
|
||
| 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. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P3] PresumedFile resolved per-node during full AST traversal For every visited child this resolves |
||
| cmpf := c.Strcmp(at.CStr(), presumedFile) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P1] strcmp on a possibly-NULL CStr is undefined behavior
|
||
| 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()) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P1] clang.String drops nil-guard on CStr(); risks nil deref
clang.Stringreplaceslib/clang.GoString, but the old helper guarded the C string before conversion:The new version calls
c.GoString(str.CStr())unconditionally.clang_getCString(CStr()) returns NULL for an invalid/defaultCXString, andc.GoStringlinks straight to the llgo string routine with no NULL guard, so a NULLCStr()scans from a nil pointer instead of yielding the previous safe empty string. Suggest restoring the guard: