diff --git a/c/clang/_wrap/cursor.cpp b/c/clang/_wrap/cursor.cpp index c5c60958..45b514b8 100644 --- a/c/clang/_wrap/cursor.cpp +++ b/c/clang/_wrap/cursor.cpp @@ -31,8 +31,18 @@ void wrap_clang_getTranslationUnitCursor(CXTranslationUnit uint, CXCursor *cur) void wrap_clang_getCursorType(CXCursor *cur, CXType *typ) { *typ = clang_getCursorType(*cur); } +void wrap_clang_getPointeeType(CXType *pointerTyp, CXType *pointeeTyp) { + *pointeeTyp = clang_getPointeeType(*pointerTyp); +} + +void wrap_clang_getArrayElementType(CXType *arrayTyp, CXType *elemTyp) { + *elemTyp = clang_getArrayElementType(*arrayTyp); +} + void wrap_clang_getCursorResultType(CXCursor *cur, CXType *typ) { *typ = clang_getCursorResultType(*cur); } +void wrap_clang_getCanonicalType(CXType *typ, CXType *canonicalType) { *canonicalType = clang_getCanonicalType(*typ); } + CXString wrap_clang_getTypeSpelling(CXType *typ) { return clang_getTypeSpelling(*typ); } CXString wrap_clang_getTokenSpelling(CXTranslationUnit unit, CXToken *token) { diff --git a/c/clang/clang.go b/c/clang/clang.go index 900751bb..e06a24c1 100644 --- a/c/clang/clang.go +++ b/c/clang/clang.go @@ -1321,6 +1321,14 @@ type Cursor struct { type TypeKind c.Int +/** + * Retrieve the spelling of a given CXTypeKind. + */ +// llgo:link TypeKind.String C.clang_getTypeKindSpelling +func (TypeKind) String() (ret String) { + return +} + /** * Describes the kind of type */ @@ -1780,6 +1788,44 @@ func (t Type) String() (ret String) { return t.wrapString() } +/** + * For pointer types, returns the type of the pointee. + */ +// llgo:link (*Type).wrapPointeeType C.wrap_clang_getPointeeType +func (t *Type) wrapPointeeType(ret *Type) { return } + +func (t Type) PointeeType() (ret Type) { + t.wrapPointeeType(&ret) + return +} + +/** + * Return the element type of an array type. + * + * If a non-array type is passed in, an invalid type is returned. + */ +// llgo:link (*Type).wrapArrayElementType C.wrap_clang_getArrayElementType +func (t *Type) wrapArrayElementType(ret *Type) { return } +func (t Type) ArrayElementType() (ret Type) { + t.wrapArrayElementType(&ret) + return +} + +/** + * Return the canonical type for a CXType. + * + * Clang's type system explicitly models typedefs and all the ways + * a specific type can be represented. The canonical type is the underlying + * type with all the "sugar" removed. For example, if 'T' is a typedef + * for 'int', the canonical type for 'T' would be 'int'. + */ +// llgo:link (*Type).wrapCanonicalType C.wrap_clang_getCanonicalType +func (t *Type) wrapCanonicalType(ret *Type) { return } +func (t Type) CanonicalType() (ret Type) { + t.wrapCanonicalType(&ret) + return +} + //llgo:link File.FileName C.clang_getFileName func (File) FileName() (ret String) { return } diff --git a/chore/_xtool/castdump/castdump.go b/chore/_xtool/castdump/castdump.go index 79f82274..0cc9207b 100644 --- a/chore/_xtool/castdump/castdump.go +++ b/chore/_xtool/castdump/castdump.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "strings" "unsafe" "github.com/goplus/llgo/c" @@ -14,19 +15,22 @@ type Data struct { Unit *clang.TranslationUnit } +var accessMap = map[clang.CXXAccessSpecifier]string{ + clang.CXXInvalidAccessSpecifier: "invalid", + clang.CXXPublic: "public", + clang.CXXProtected: "protected", + clang.CXXPrivate: "private", +} + +func printIndent(depth c.Uint) { + fmt.Print(strings.Repeat(" ", int(depth))) +} + func accessToString(spec clang.CXXAccessSpecifier) string { - switch spec { - case clang.CXXInvalidAccessSpecifier: - return "invalid" - case clang.CXXPublic: - return "public" - case clang.CXXProtected: - return "protected" - case clang.CXXPrivate: - return "private" - default: - return "unkown" + if str, ok := accessMap[spec]; ok { + return str } + return "unknown" } func visit(cursor, parent clang.Cursor, ClientData c.Pointer) clang.ChildVisitResult { @@ -35,6 +39,32 @@ func visit(cursor, parent clang.Cursor, ClientData c.Pointer) clang.ChildVisitRe return clang.ChildVisit_Continue } +func printType(t clang.Type, data *Data) { + printIndent(data.Depth) + + typeSpell := t.String() + typeKind := t.Kind.String() + if t.Kind > clang.TypeFirstBuiltin && t.Kind < clang.TypeLastBuiltin { + c.Printf(c.Str(": %s\n"), typeKind.CStr(), typeSpell.CStr()) + } else if t.Kind > clang.TypeComplex { + c.Printf(c.Str(": %s\n"), typeKind.CStr(), typeSpell.CStr()) + } + + data.Depth++ + switch t.Kind { + case clang.TypePointer: + printType(t.PointeeType(), data) + case clang.TypeIncompleteArray, clang.TypeVariableArray, clang.TypeDependentSizedArray, clang.TypeConstantArray: + printType(t.ArrayElementType(), data) + case clang.TypeTypedef: + printType(t.CanonicalType(), data) + } + data.Depth-- + + typeKind.Dispose() + typeSpell.Dispose() +} + func printLocation(cursor clang.Cursor) { loc := cursor.Location() var file clang.File @@ -78,25 +108,28 @@ func printFunc(cursor clang.Cursor) { kind := cursor.Kind.String() spell := cursor.String() symbol := cursor.Mangling() + typ := cursor.Type().String() defer symbol.Dispose() defer kind.Dispose() defer spell.Dispose() + defer typ.Dispose() - c.Printf(c.Str("%s: %s (Symbol: %s)"), kind.CStr(), spell.CStr(), symbol.CStr()) + c.Printf(c.Str("%s: %s (Type: %s)(Symbol: %s)"), kind.CStr(), spell.CStr(), typ.CStr(), symbol.CStr()) } -func printDefault(cursor clang.Cursor) { +func printDefault(cursor clang.Cursor, data *Data) { kind := cursor.Kind.String() spell := cursor.String() defer kind.Dispose() defer spell.Dispose() + // node which has type if cursor.Type().Kind != clang.TypeInvalid { - typeSpell := cursor.Type().String() - c.Printf(c.Str("%s: %s (Type: %s)"), kind.CStr(), spell.CStr(), typeSpell.CStr()) - typeSpell.Dispose() - } else { c.Printf(c.Str("%s: %s"), kind.CStr(), spell.CStr()) + printLocation(cursor) + printType(cursor.Type(), data) + } else { + c.Printf(c.Str("%s: %s\n"), kind.CStr(), spell.CStr()) } } @@ -104,23 +137,22 @@ func printAST(cursor clang.Cursor, data *Data) { kind := cursor.Kind.String() spell := cursor.String() - for i := c.Uint(0); i < data.Depth; i++ { - c.Fputs(c.Str(" "), c.Stdout) - } + printIndent(data.Depth) switch cursor.Kind { case clang.CursorCXXAccessSpecifier: printAccess(cursor) + printLocation(cursor) case clang.CursorMacroDefinition: printMacro(cursor, data.Unit) + printLocation(cursor) case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor: printFunc(cursor) + printLocation(cursor) default: - printDefault(cursor) + printDefault(cursor, data) } - printLocation(cursor) - data.Depth++ clang.VisitChildren(cursor, visit, c.Pointer(data)) data.Depth--