Commits

Anonymous committed 50af094

adding machinery for cursor-visitor

  • Participants
  • Parent commits d773036

Comments (0)

Files changed (7)

pkg/clang/clang.go

 package clang
 
 // #include <stdlib.h>
-// #cgo LDFLAGS: -L/opt/local/libexec/llvm-3.0/lib -lclang
-// #include "/opt/local/libexec/llvm-3.0/include/clang-c/Index.h"
+// #cgo LDFLAGS: -L/opt/local/libexec/llvm-3.0/lib -L/usr/lib/llvm -lclang
+// #cgo CFLAGS: -I/opt/local/libexec/llvm-3.0/include
+// #include "clang-c/Index.h"
 import "C"
 import (
+	"time"
 	"unsafe"
 )
 
 	c C.CXIndex
 }
 
-/**
- * CreateIndex provides a shared context for creating
- * translation units. It provides two options:
- *
- * - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local"
- * declarations (when loading any new translation units). A "local" declaration
- * is one that belongs in the translation unit itself and not in a precompiled
- * header that was used by the translation unit. If zero, all declarations
- * will be enumerated.
- *
- * Here is an example:
- *
- *   // excludeDeclsFromPCH = 1, displayDiagnostics=1
- *   Idx = clang_createIndex(1, 1);
- *
- *   // IndexTest.pch was produced with the following command:
- *   // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch"
- *   TU = clang_createTranslationUnit(Idx, "IndexTest.pch");
- *
- *   // This will load all the symbols from 'IndexTest.pch'
- *   clang_visitChildren(clang_getTranslationUnitCursor(TU),
- *                       TranslationUnitVisitor, 0);
- *   clang_disposeTranslationUnit(TU);
- *
- *   // This will load all the symbols from 'IndexTest.c', excluding symbols
- *   // from 'IndexTest.pch'.
- *   char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" };
- *   TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args,
- *                                                  0, 0);
- *   clang_visitChildren(clang_getTranslationUnitCursor(TU),
- *                       TranslationUnitVisitor, 0);
- *   clang_disposeTranslationUnit(TU);
- *
- * This process of creating the 'pch', loading it separately, and using it (via
- * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
- * (which gives the indexer the same performance benefit as the compiler).
- */
+
+// NewIndex provides a shared context for creating
+// translation units. It provides two options:
+//
+// - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local"
+// declarations (when loading any new translation units). A "local" declaration
+// is one that belongs in the translation unit itself and not in a precompiled
+// header that was used by the translation unit. If zero, all declarations
+// will be enumerated.
+//
+// Here is an example:
+//
+//   // excludeDeclsFromPCH = 1, displayDiagnostics=1
+//   Idx = clang_createIndex(1, 1);
+//
+//   // IndexTest.pch was produced with the following command:
+//   // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch"
+//   TU = clang_createTranslationUnit(Idx, "IndexTest.pch");
+//
+//   // This will load all the symbols from 'IndexTest.pch'
+//   clang_visitChildren(clang_getTranslationUnitCursor(TU),
+//                       TranslationUnitVisitor, 0);
+//   clang_disposeTranslationUnit(TU);
+//
+//   // This will load all the symbols from 'IndexTest.c', excluding symbols
+//   // from 'IndexTest.pch'.
+//   char *args[] = { "-Xclang", "-include-pch=IndexTest.pch" };
+//   TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args,
+//                                                  0, 0);
+//   clang_visitChildren(clang_getTranslationUnitCursor(TU),
+//                       TranslationUnitVisitor, 0);
+//   clang_disposeTranslationUnit(TU);
+//
+// This process of creating the 'pch', loading it separately, and using it (via
+// -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks
+// (which gives the indexer the same performance benefit as the compiler).
 func NewIndex(excludeDeclarationsFromPCH, displayDiagnostics int) Index {
 	idx := C.clang_createIndex(C.int(excludeDeclarationsFromPCH),
 		C.int(displayDiagnostics))
 	return Index{idx}
 }
 
-/**
- * Destroy the given index.
- *
- * The index must not be destroyed until all of the translation units created
- * within that index have been destroyed.
- */
+// Dispose destroys the given index.
+//
+// The index must not be destroyed until all of the translation units created
+// within that index have been destroyed.
 func (idx Index) Dispose() {
 	C.clang_disposeIndex(idx.c)
 }
 
+/**
+ * \brief Create a translation unit from an AST file (-emit-ast).
+ */
+func (idx Index) CreateTranslationUnit(fname string) TranslationUnit {
+	cstr := C.CString(fname)
+	defer C.free(unsafe.Pointer(cstr))
+	o := C.clang_createTranslationUnit(idx.c, cstr)
+	return TranslationUnit{o}
+}
+
 // A single translation unit, which resides in an index
 type TranslationUnit struct {
 	c C.CXTranslationUnit
 	return File{f}
 }
 
-/**
- * \brief Determine whether the given header is guarded against
- * multiple inclusions, either with the conventional
- * #ifndef/#define/#endif macro guards or with #pragma once.
- */
+// IsFileMultipleIncludeGuarded determines whether the given header is guarded
+// against multiple inclusions, either with the conventional
+// #ifndef/#define/#endif macro guards or with #pragma once.
 func (tu TranslationUnit) IsFileMultipleIncludeGuarded(file File) bool {
 	o := C.clang_isFileMultipleIncludeGuarded(tu.c, file.c)
 	if o != C.uint(0) {
 }
 
 /**
- * \brief Map a source location to the cursor that describes the entity at that
- * location in the source code.
- *
- * clang_getCursor() maps an arbitrary source location within a translation
- * unit down to the most specific cursor that describes the entity at that
- * location. For example, given an expression \c x + y, invoking
- * clang_getCursor() with a source location pointing to "x" will return the
- * cursor for "x"; similarly for "y". If the cursor points anywhere between
- * "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor()
- * will return a cursor referring to the "+" expression.
- *
- * \returns a cursor representing the entity at the given source location, or
- * a NULL cursor if no such entity can be found.
+ * \brief Get the original translation unit source file name.
  */
+func (tu TranslationUnit) Spelling() string {
+	cstr := cxstring{C.clang_getTranslationUnitSpelling(tu.c)}
+	defer cstr.Dispose()
+	return cstr.String()
+}
+
+// CursorOf maps a source location to the cursor that describes the entity at that
+// location in the source code.
+//
+// clang_getCursor() maps an arbitrary source location within a translation
+// unit down to the most specific cursor that describes the entity at that
+// location. For example, given an expression \c x + y, invoking
+// clang_getCursor() with a source location pointing to "x" will return the
+// cursor for "x"; similarly for "y". If the cursor points anywhere between
+// "x" or "y" (e.g., on the + or the whitespace around it), clang_getCursor()
+// will return a cursor referring to the "+" expression.
+//
+// Returns a cursor representing the entity at the given source location, or
+// a NULL cursor if no such entity can be found.
 func (tu TranslationUnit) Cursor(loc SourceLocation) Cursor {
 	o := C.clang_getCursor(tu.c, loc.c)
 	return Cursor{o}
 }
 
+/**
+ * \brief Saves a translation unit into a serialized representation of
+ * that translation unit on disk.
+ *
+ * Any translation unit that was parsed without error can be saved
+ * into a file. The translation unit can then be deserialized into a
+ * new \c CXTranslationUnit with \c clang_createTranslationUnit() or,
+ * if it is an incomplete translation unit that corresponds to a
+ * header, used as a precompiled header when parsing other translation
+ * units.
+ *
+ * \param TU The translation unit to save.
+ *
+ * \param FileName The file to which the translation unit will be saved.
+ *
+ * \param options A bitmask of options that affects how the translation unit
+ * is saved. This should be a bitwise OR of the
+ * CXSaveTranslationUnit_XXX flags.
+ *
+ * \returns A value that will match one of the enumerators of the CXSaveError
+ * enumeration. Zero (CXSaveError_None) indicates that the translation unit was 
+ * saved successfully, while a non-zero value indicates that a problem occurred.
+ */
+func (tu TranslationUnit) Save(fname string, options uint) uint32 {
+	cstr := C.CString(fname)
+	defer C.free(unsafe.Pointer(cstr))
+	o := C.clang_saveTranslationUnit(tu.c, cstr, C.uint(options))
+	// FIXME: should be a SaveError type...
+	return uint32(o)
+}
+
+/**
+ * \brief Destroy the specified CXTranslationUnit object.
+ */
+func (tu TranslationUnit) Dispose() {
+	C.clang_disposeTranslationUnit(tu.c)
+}
+
 // A particular source file that is part of a translation unit.
 type File struct {
 	c C.CXFile
 }
 
-// FIXME
-// /**
-//  * \brief Retrieve the complete file and path name of the given file.
-//  */
-// CINDEX_LINKAGE CXString clang_getFileName(CXFile SFile);
+// Name retrieves the complete file and path name of the given file.
+func (c File) Name() string {
+	cstr := cxstring{C.clang_getFileName(c.c)}
+	defer cstr.Dispose()
+	return cstr.String()
+}
 
-// /**
-//  * \brief Retrieve the last modification time of the given file.
-//  */
-// CINDEX_LINKAGE time_t clang_getFileTime(CXFile SFile);
+// ModTime retrieves the last modification time of the given file.
+func (c File) ModTime() time.Time {
+	// time_t is in seconds since epoch
+	sec := C.clang_getFileTime(c.c)
+	const nsec = 0
+	return time.Unix(int64(sec), nsec)
+}
 
 
 
-/**
- * \brief 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.
- */
+// SourceLocation 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 struct {
 	c C.CXSourceLocation
 }
 
-/**
- * \brief Identifies a half-open character range in the source code.
- *
- * Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
- * starting and end locations from a source range, respectively.
- */
+// SourceRange identifies a half-open character range in the source code.
+//
+// Use clang_getRangeStart() and clang_getRangeEnd() to retrieve the
+// starting and end locations from a source range, respectively.
 type SourceRange struct {
 	c C.CXSourceRange
 }
 
-/**
- * \brief Retrieve a NULL (invalid) source location.
- */
+// NewNullLocation creates a NULL (invalid) source location.
 func NewNullLocation() SourceLocation {
 	return SourceLocation{C.clang_getNullLocation()}
 }
 
-/**
- * \determine Determine whether two source locations, which must refer into
- * the same translation unit, refer to exactly the same point in the source
- * code.
- *
- * \returns non-zero if the source locations refer to the same location, zero
- * if they refer to different locations.
- */
+// EqualLocations determines whether two source locations, which must refer into
+// the same translation unit, refer to exactly the same point in the source
+// code.
+// Returns non-zero if the source locations refer to the same location, zero
+// if they refer to different locations.
 func EqualLocations(loc1, loc2 SourceLocation) bool {
 	o := C.clang_equalLocations(loc1.c, loc2.c)
 	if o != C.uint(0) {
 	return false
 }
 
-/**
- * \brief Retrieves the source location associated with a given file/line/column
- * in a particular translation unit.
- */
+// Location returns the source location associated with a given file/line/column
+// in a particular translation unit.
 func (tu TranslationUnit) Location(f File, line, column uint) SourceLocation {
 	loc := C.clang_getLocation(tu.c, f.c, C.uint(line), C.uint(column))
 	return SourceLocation{loc}
 }
 
-/**
- * \brief Retrieves the source location associated with a given character offset
- * in a particular translation unit.
- */
+// LocationForOffset returns the source location associated with a given
+// character offset in a particular translation unit.
 func (tu TranslationUnit) LocationForOffset(f File, offset uint) SourceLocation {
 	loc := C.clang_getLocationForOffset(tu.c, f.c, C.uint(offset))
 	return SourceLocation{loc}
 }
 
-/**
- * \brief Retrieve a NULL (invalid) source range.
- */
+// NewNullRange creates a NULL (invalid) source range.
 func NewNullRange() SourceRange {
 	return SourceRange{C.clang_getNullRange()}
 }
 
-/**
- * \brief Retrieve a source range given the beginning and ending source
- * locations.
- */
+
+// NewRange creates a source range given the beginning and ending source
+// locations.
 func NewRange(beg, end SourceLocation) SourceRange {
 	o := C.clang_getRange(beg.c, end.c)
 	return SourceRange{o}
 }
 
-/**
- * \brief Determine whether two ranges are equivalent.
- *
- * \returns non-zero if the ranges are the same, zero if they differ.
- */
+
+// EqualRanges determines whether two ranges are equivalent.
 func EqualRanges(r1, r2 SourceRange) bool {
 	o := C.clang_equalRanges(r1.c, r2.c)
 	if o != C.uint(0) {
 	return false
 }
 
-/**
- * \brief Returns non-zero if \arg range is null.
- */
+// IsNull checks if the underlying source range is null.
 func (r SourceRange) IsNull() bool {
 	o := C.clang_Range_isNull(r.c)
 	if o != C.int(0) {
 	return false
 }
 
+
+// ExpansionLocation returns the file, line, column, and offset represented by
+// the given source location.
+// 
+// If the location refers into a macro expansion, retrieves the
+// location of the macro expansion.
+//
+// file: if non-NULL, will be set to the file to which the given
+// source location points.
+// 
+// line: if non-NULL, will be set to the line to which the given
+// source location points.
+// 
+// column: if non-NULL, will be set to the column to which the given
+// source location points.
+//
+// offset: if non-NULL, will be set to the offset into the
+// buffer to which the given source location points.
+func (l SourceLocation) ExpansionLocation() (f File, line, column, offset uint) {
+	cline := C.uint(0)
+	ccol  := C.uint(0)
+	coff  := C.uint(0)
+	// FIXME: undefined reference to `clang_getExpansionLocation'
+	C.clang_getInstantiationLocation(l.c, &f.c, &cline, &ccol, &coff)
+	line  = uint(cline)
+	column = uint(ccol)
+	offset = uint(coff)
+
+	return
+}
+
+/**
+ * \brief Retrieve the file, line, column, and offset represented by
+ * the given source location, as specified in a # line directive.
+ *
+ * Example: given the following source code in a file somefile.c
+ *
+ * #123 "dummy.c" 1
+ *
+ * static int func(void)
+ * {
+ *     return 0;
+ * }
+ *
+ * the location information returned by this function would be
+ *
+ * File: dummy.c Line: 124 Column: 12
+ *
+ * whereas clang_getExpansionLocation would have returned
+ *
+ * File: somefile.c Line: 3 Column: 12
+ *
+ * \param location the location within a source file that will be decomposed
+ * into its parts.
+ *
+ * \param filename [out] if non-NULL, will be set to the filename of the
+ * source location. Note that filenames returned will be for "virtual" files,
+ * which don't necessarily exist on the machine running clang - e.g. when
+ * parsing preprocessed output obtained from a different environment. If
+ * a non-NULL value is passed in, remember to dispose of the returned value
+ * using \c clang_disposeString() once you've finished with it. For an invalid
+ * source location, an empty string is returned.
+ *
+ * \param line [out] if non-NULL, will be set to the line number of the
+ * source location. For an invalid source location, zero is returned.
+ *
+ * \param column [out] if non-NULL, will be set to the column number of the
+ * source location. For an invalid source location, zero is returned.
+ */
+func (l SourceLocation) PresumedLocation() (fname string, line, column uint) {
+
+	cname := cxstring{}
+	defer cname.Dispose()
+	cline := C.uint(0)
+	ccol  := C.uint(0)
+	C.clang_getPresumedLocation(l.c, &cname.c, &cline, &ccol)
+	fname = cname.String()
+	line  = uint(cline)
+	column = uint(ccol)
+	return
+}
+
+/**
+ * \brief Legacy API to retrieve the file, line, column, and offset represented
+ * by the given source location.
+ *
+ * This interface has been replaced by the newer interface
+ * \see clang_getExpansionLocation(). See that interface's documentation for
+ * details.
+ */
+func (l SourceLocation) InstantiationLocation() (file File, line, column, offset uint) {
+	
+	cline := C.uint(0)
+	ccol  := C.uint(0)
+	coff  := C.uint(0)
+	C.clang_getInstantiationLocation(l.c,
+                 &file.c,
+                 &cline,
+                 &ccol,
+                 &coff)
+	line  = uint(cline)
+	column = uint(ccol)
+	offset = uint(coff)
+	return
+}
+
 /**
  * \brief Retrieve the file, line, column, and offset represented by
  * the given source location.
  *
- * If the location refers into a macro expansion, retrieves the
- * location of the macro expansion.
+ * If the location refers into a macro instantiation, return where the
+ * location was originally spelled in the source file.
  *
  * \param location the location within a source file that will be decomposed
  * into its parts.
  * \param offset [out] if non-NULL, will be set to the offset into the
  * buffer to which the given source location points.
  */
-func (l SourceLocation) GetExpansionLocation() (f File, line, column, offset uint) {
+func (l SourceLocation) SpellingLocation() (file File, line, column, offset uint) {
+	
 	cline := C.uint(0)
 	ccol  := C.uint(0)
 	coff  := C.uint(0)
-	// FIXME
-	// C.clang_getExpansionLocation(l.c,
-        //         unsafe.Pointer(&f.c),
-        //         unsafe.Pointer(&cline),
-        //         unsafe.Pointer(&ccol),
-        //         unsafe.Pointer(&coff))
+	C.clang_getSpellingLocation(l.c,
+                 &file.c,
+                 &cline,
+                 &ccol,
+                 &coff)
 	line  = uint(cline)
 	column = uint(ccol)
 	offset = uint(coff)
-
 	return
 }
 
+/**
+ * \brief Retrieve a source location representing the first character within a
+ * source range.
+ */
+func (s SourceRange) Start() SourceLocation {
+	o := C.clang_getRangeStart(s.c)
+	return SourceLocation{o}
+}
+
+/**
+ * \brief Retrieve a source location representing the last character within a
+ * source range.
+ */
+func (s SourceRange) End() SourceLocation {
+	o := C.clang_getRangeEnd(s.c)
+	return SourceLocation{o}
+}
+
+
 // EOF

pkg/clang/cursor.go

 package clang
 
 // #include <stdlib.h>
-// #cgo LDFLAGS: -L/opt/local/libexec/llvm-3.0/lib -lclang
-// #include "/opt/local/libexec/llvm-3.0/include/clang-c/Index.h"
+// #cgo LDFLAGS: -L/opt/local/libexec/llvm-3.0/lib -L/usr/lib/llvm -lclang
+// #cgo CFLAGS: -I/opt/local/libexec/llvm-3.0/include -I.
+// #include "clang-c/Index.h"
+// #include "go-clang.h"
 // inline static
 // CXCursor _go_clang_ocursor_at(CXCursor *c, int idx) {
 //   return c[idx];
 //
 import "C"
 import (
-	//"unsafe"
-)
-
-/**
- * \brief Describes the kind of entity that a cursor refers to.
- */
-type CursorKind uint32 //FIXME: use uint32? int64?
-const (
-  /**
-   * \brief A declaration whose specific kind is not exposed via this
-   * interface.
-   *
-   * Unexposed declarations have the same operations as any other kind
-   * of declaration; one can extract their location information,
-   * spelling, find their definitions, etc. However, the specific kind
-   * of the declaration is not reported.
-   */
-	CK_UnexposedDecl CursorKind = C.CXCursor_UnexposedDecl
-
-	// A C or C++ struct.
-	CK_StructDecl = C.CXCursor_StructDecl
+//"unsafe"
 )
 
 /**
 	}
 	return false
 }
-  
+
 /***
  * \brief Determine whether the given cursor represents a currently
  *  unexposed piece of the AST (e.g., CXCursor_UnexposedStmt).
  * \brief Describe the linkage of the entity referred to by a cursor.
  */
 type LinkageKind uint32
+
 const (
 	/** \brief This value indicates that no linkage information is available
 	 * for a provided CXCursor. */
 
 // LanguageKind describes the "language" of the entity referred to by a cursor.
 type LanguageKind uint32
+
 const (
-	LanguageInvalid LanguageKind = C.CXLanguage_Invalid
-	LanguageC  = C.CXLanguage_C
-	LanguageObjC  = C.CXLanguage_ObjC
-	LanguageCPlusPlus = C.CXLanguage_CPlusPlus
+	LanguageInvalid   LanguageKind = C.CXLanguage_Invalid
+	LanguageC                      = C.CXLanguage_C
+	LanguageObjC                   = C.CXLanguage_ObjC
+	LanguageCPlusPlus              = C.CXLanguage_CPlusPlus
 )
 
 // Language returns the "language" of the entity referred to by a cursor.
 	return TranslationUnit{o}
 }
 
+// DeclObjCTypeEncoding returns the Objective-C type encoding for the
+// specified declaration.
+func (c Cursor) DeclObjCTypeEncoding() string {
+	o := C.clang_getDeclObjCTypeEncoding(c.c)
+	cstr := cxstring{o}
+	defer cstr.Dispose()
+	return cstr.String()
+}
+
 // CursorSet is a fast container representing a set of Cursors.
 type CursorSet struct {
 	c C.CXCursorSet
  * cursor with kind CX_CXXBaseSpecifier.
  */
 type AccessSpecifier uint32
+
 const (
-	AS_Invalid AccessSpecifier = C.CX_CXXInvalidAccessSpecifier
-	AS_Public = C.CX_CXXPublic
-	AS_Protected = C.CX_CXXProtected
-	AS_Private = C.CX_CXXPrivate
+	AS_Invalid   AccessSpecifier = C.CX_CXXInvalidAccessSpecifier
+	AS_Public                    = C.CX_CXXPublic
+	AS_Protected                 = C.CX_CXXProtected
+	AS_Private                   = C.CX_CXXPrivate
 )
 
 /**
 	CVR_Recurse = C.CXChildVisit_Recurse
 )
 
+/**
+ * \brief Visitor invoked for each cursor found by a traversal.
+ *
+ * This visitor function will be invoked for each cursor found by
+ * clang_visitCursorChildren(). Its first argument is the cursor being
+ * visited, its second argument is the parent visitor for that cursor,
+ * and its third argument is the client data provided to
+ * clang_visitCursorChildren().
+ *
+ * The visitor should return one of the \c CXChildVisitResult values
+ * to direct clang_visitCursorChildren().
+ */
+type CursorVisitor func(cursor, parent Cursor) (status ChildVisitResult)
+
+/**
+ * \brief Visit the children of a particular cursor.
+ *
+ * This function visits all the direct children of the given cursor,
+ * invoking the given \p visitor function with the cursors of each
+ * visited child. The traversal may be recursive, if the visitor returns
+ * \c CXChildVisit_Recurse. The traversal may also be ended prematurely, if
+ * the visitor returns \c CXChildVisit_Break.
+ *
+ * \param parent the cursor whose child may be visited. All kinds of
+ * cursors can be visited, including invalid cursors (which, by
+ * definition, have no children).
+ *
+ * \param visitor the visitor function that will be invoked for each
+ * child of \p parent.
+ *
+ * \param client_data pointer data supplied by the client, which will
+ * be passed to the visitor each time it is invoked.
+ *
+ * \returns a non-zero value if the traversal was terminated
+ * prematurely by the visitor returning \c CXChildVisit_Break.
+ */
+func (c Cursor) Visit(visitor CursorVisitor) bool {
+	g_visitor = visitor
+	o := C._go_clang_visit_children(c.c)
+	if o != C.uint(0) {
+		return false
+	}
+	return true
+}
+
+var g_visitor CursorVisitor
+
+//export GoClangCursorVisitor
+func GoClangCursorVisitor(cursor, parent C.CXCursor) (status ChildVisitResult) {
+	o := g_visitor(Cursor{cursor}, Cursor{parent})
+	return o
+}
+
+/**
+ * \brief Retrieve a Unified Symbol Resolution (USR) for the entity referenced
+ * by the given cursor.
+ *
+ * A Unified Symbol Resolution (USR) is a string that identifies a particular
+ * entity (function, class, variable, etc.) within a program. USRs can be
+ * compared across translation units to determine, e.g., when references in
+ * one translation refer to an entity defined in another translation unit.
+ */
+func (c Cursor) USR() string {
+	cstr := cxstring{C.clang_getCursorUSR(c.c)}
+	defer cstr.Dispose()
+	return cstr.String()
+}
+
+//FIXME
+// /**
+//  * \brief Construct a USR for a specified Objective-C class.
+//  */
+// CINDEX_LINKAGE CXString clang_constructUSR_ObjCClass(const char *class_name);
+
+// /**
+//  * \brief Construct a USR for a specified Objective-C category.
+//  */
+// CINDEX_LINKAGE CXString
+//   clang_constructUSR_ObjCCategory(const char *class_name,
+//                                  const char *category_name);
+
+// /**
+//  * \brief Construct a USR for a specified Objective-C protocol.
+//  */
+// CINDEX_LINKAGE CXString
+//   clang_constructUSR_ObjCProtocol(const char *protocol_name);
+
 // EOF

pkg/clang/cursorkind.go

+package clang
+
+// #include <stdlib.h>
+// #cgo LDFLAGS: -L/opt/local/libexec/llvm-3.0/lib -L/usr/lib/llvm -lclang
+// #cgo CFLAGS: -I/opt/local/libexec/llvm-3.0/include
+// #include "clang-c/Index.h"
+// inline static
+// CXCursor _go_clang_ocursor_at(CXCursor *c, int idx) {
+//   return c[idx];
+// }
+//
+import "C"
+import (
+//"unsafe"
+)
+
+/**
+ * \brief Describes the kind of entity that a cursor refers to.
+ */
+type CursorKind uint32 //FIXME: use uint32? int64?
+const (
+	/**
+	 * \brief A declaration whose specific kind is not exposed via this
+	 * interface.
+	 *
+	 * Unexposed declarations have the same operations as any other kind
+	 * of declaration; one can extract their location information,
+	 * spelling, find their definitions, etc. However, the specific kind
+	 * of the declaration is not reported.
+	 */
+	CK_UnexposedDecl CursorKind = C.CXCursor_UnexposedDecl
+
+	// A C or C++ struct.
+	CK_StructDecl = C.CXCursor_StructDecl
+	// A C or C++ union
+	CK_UnionDecl = C.CXCursor_UnionDecl
+	// A C++ class
+	CK_ClassDecl = C.CXCursor_ClassDecl
+	// An enumeration
+	CK_EnumDecl = C.CXCursor_EnumDecl
+	// A field (in C) or non-static data member (in C++) in a
+	// struct, union, or C++ class.
+	CK_FieldDecl = C.CXCursor_FieldDecl
+	/** \brief An enumerator constant. */
+	CK_EnumConstantDecl = C.CXCursor_EnumConstantDecl
+	/** \brief A function. */
+	CK_FunctionDecl = C.CXCursor_FunctionDecl
+	/** \brief A variable. */
+	CK_VarDecl = C.CXCursor_VarDecl
+	/** \brief A function or method parameter. */
+	CK_ParmDecl = C.CXCursor_ParmDecl
+	/** \brief An Objective-C @interface. */
+	CK_ObjCInterfaceDecl = C.CXCursor_ObjCInterfaceDecl
+	/** \brief An Objective-C @interface for a category. */
+	CK_ObjCCategoryDecl = C.CXCursor_ObjCCategoryDecl
+	/** \brief An Objective-C @protocol declaration. */
+	CK_ObjCProtocolDecl = C.CXCursor_ObjCProtocolDecl
+	/** \brief An Objective-C @property declaration. */
+	CK_ObjCPropertyDecl = C.CXCursor_ObjCPropertyDecl
+	/** \brief An Objective-C instance variable. */
+	CK_ObjCIvarDecl = C.CXCursor_ObjCIvarDecl
+	/** \brief An Objective-C instance method. */
+	CK_ObjCInstanceMethodDecl = C.CXCursor_ObjCInstanceMethodDecl
+	/** \brief An Objective-C class method. */
+	CK_ObjCClassMethodDecl = C.CXCursor_ObjCClassMethodDecl
+	/** \brief An Objective-C @implementation. */
+	CK_ObjCImplementationDecl = C.CXCursor_ObjCImplementationDecl
+	/** \brief An Objective-C @implementation for a category. */
+	CK_ObjCCategoryImplDecl = C.CXCursor_ObjCCategoryImplDecl
+	/** \brief A typedef */
+	CK_TypedefDecl = C.CXCursor_TypedefDecl
+	/** \brief A C++ class method. */
+	CK_CXXMethod = C.CXCursor_CXXMethod
+	/** \brief A C++ namespace. */
+	CK_Namespace = C.CXCursor_Namespace
+	/** \brief A linkage specification, e.g. 'extern "C"'. */
+	CK_LinkageSpec = C.CXCursor_LinkageSpec
+	/** \brief A C++ constructor. */
+	CK_Constructor = C.CXCursor_Constructor
+	/** \brief A C++ destructor. */
+	CK_Destructor = C.CXCursor_Destructor
+	/** \brief A C++ conversion function. */
+	CK_ConversionFunction = C.CXCursor_ConversionFunction
+	/** \brief A C++ template type parameter. */
+	CK_TemplateTypeParameter = C.CXCursor_TemplateTypeParameter
+	/** \brief A C++ non-type template parameter. */
+	CK_NonTypeTemplateParameter = C.CXCursor_NonTypeTemplateParameter
+	/** \brief A C++ template template parameter. */
+	CK_TemplateTemplateParameter = C.CXCursor_TemplateTemplateParameter
+	/** \brief A C++ function template. */
+	CK_FunctionTemplate = C.CXCursor_FunctionTemplate
+	/** \brief A C++ class template. */
+	CK_ClassTemplate = C.CXCursor_ClassTemplate
+	/** \brief A C++ class template partial specialization. */
+	CK_ClassTemplatePartialSpecialization = C.CXCursor_ClassTemplatePartialSpecialization
+	/** \brief A C++ namespace alias declaration. */
+	CK_NamespaceAlias = C.CXCursor_NamespaceAlias
+	/** \brief A C++ using directive. */
+	CK_UsingDirective = C.CXCursor_UsingDirective
+	/** \brief A C++ using declaration. */
+	CK_UsingDeclaration = C.CXCursor_UsingDeclaration
+	/** \brief A C++ alias declaration */
+	CK_TypeAliasDecl = C.CXCursor_TypeAliasDecl
+	/** \brief An Objective-C @synthesize definition. */
+	CK_ObjCSynthesizeDecl = C.CXCursor_ObjCSynthesizeDecl
+	/** \brief An Objective-C @dynamic definition. */
+	CK_ObjCDynamicDecl = C.CXCursor_ObjCDynamicDecl
+	/** \brief An access specifier. */
+	CK_CXXAccessSpecifier = C.CXCursor_CXXAccessSpecifier
+
+	CK_FirstDecl = C.CXCursor_FirstDecl
+	CK_LastDecl  = C.CXCursor_LastDecl
+
+	/* References */
+	CK_FirstRef          = C.CXCursor_FirstRef
+	CK_ObjCSuperClassRef = C.CXCursor_ObjCSuperClassRef
+	CK_ObjCProtocolRef   = C.CXCursor_ObjCProtocolRef
+	CK_ObjCClassRef      = C.CXCursor_ObjCClassRef
+	/**
+	 * \brief A reference to a type declaration.
+	 *
+	 * A type reference occurs anywhere where a type is named but not
+	 * declared. For example, given:
+	 *
+	 * \code
+	 * typedef unsigned size_type;
+	 * size_type size;
+	 * \endcode
+	 *
+	 * The typedef is a declaration of size_type (CXCursor_TypedefDecl),
+	 * while the type of the variable "size" is referenced. The cursor
+	 * referenced by the type of size is the typedef for size_type.
+	 */
+	CK_TypeRef          = C.CXCursor_TypeRef
+	CK_CXXBaseSpecifier = C.CXCursor_CXXBaseSpecifier
+	/** 
+	 * \brief A reference to a class template, function template, template
+	 * template parameter, or class template partial specialization.
+	 */
+	CK_TemplateRef = C.CXCursor_TemplateRef
+	/**
+	 * \brief A reference to a namespace or namespace alias.
+	 */
+	CK_NamespaceRef = C.CXCursor_NamespaceRef
+	/**
+	 * \brief A reference to a member of a struct, union, or class that occurs in 
+	 * some non-expression context, e.g., a designated initializer.
+	 */
+	CK_MemberRef = C.CXCursor_MemberRef
+	/**
+	 * \brief A reference to a labeled statement.
+	 *
+	 * This cursor kind is used to describe the jump to "start_over" in the 
+	 * goto statement in the following example:
+	 *
+	 * \code
+	 *   start_over:
+	 *     ++counter;
+	 *
+	 *     goto start_over;
+	 * \endcode
+	 *
+	 * A label reference cursor refers to a label statement.
+	 */
+	CK_LabelRef = C.CXCursor_LabelRef
+
+	/**
+	 * \brief A reference to a set of overloaded functions or function templates
+	 * that has not yet been resolved to a specific function or function template.
+	 *
+	 * An overloaded declaration reference cursor occurs in C++ templates where
+	 * a dependent name refers to a function. For example:
+	 *
+	 * \code
+	 * template<typename T> void swap(T&, T&);
+	 *
+	 * struct X { ... };
+	 * void swap(X&, X&);
+	 *
+	 * template<typename T>
+	 * void reverse(T* first, T* last) {
+	 *   while (first < last - 1) {
+	 *     swap(*first, *--last);
+	 *     ++first;
+	 *   }
+	 * }
+	 *
+	 * struct Y { };
+	 * void swap(Y&, Y&);
+	 * \endcode
+	 *
+	 * Here, the identifier "swap" is associated with an overloaded declaration
+	 * reference. In the template definition, "swap" refers to either of the two
+	 * "swap" functions declared above, so both results will be available. At
+	 * instantiation time, "swap" may also refer to other functions found via
+	 * argument-dependent lookup (e.g., the "swap" function at the end of the
+	 * example).
+	 *
+	 * The functions \c clang_getNumOverloadedDecls() and 
+	 * \c clang_getOverloadedDecl() can be used to retrieve the definitions
+	 * referenced by this cursor.
+	 */
+	CK_OverloadedDeclRef = C.CXCursor_OverloadedDeclRef
+
+	CK_LastRef = C.CXCursor_LastRef
+
+	/* Error conditions */
+	CK_FirstInvalid   = C.CXCursor_FirstInvalid
+	CK_InvalidFile    = C.CXCursor_InvalidFile
+	CK_NoDeclFound    = C.CXCursor_NoDeclFound
+	CK_NotImplemented = C.CXCursor_NotImplemented
+	CK_InvalidCode    = C.CXCursor_InvalidCode
+	CK_LastInvalid    = C.CXCursor_LastInvalid
+
+	/* Expressions */
+	CK_FirstExpr = C.CXCursor_FirstExpr
+
+	/**
+	 * \brief An expression whose specific kind is not exposed via this
+	 * interface.
+	 *
+	 * Unexposed expressions have the same operations as any other kind
+	 * of expression; one can extract their location information,
+	 * spelling, children, etc. However, the specific kind of the
+	 * expression is not reported.
+	 */
+	CK_UnexposedExpr = C.CXCursor_UnexposedExpr
+
+	/**
+	 * \brief An expression that refers to some value declaration, such
+	 * as a function, varible, or enumerator.
+	 */
+	CK_DeclRefExpr = C.CXCursor_DeclRefExpr
+
+	/**
+	 * \brief An expression that refers to a member of a struct, union,
+	 * class, Objective-C class, etc.
+	 */
+	CK_MemberRefExpr = C.CXCursor_MemberRefExpr
+
+	/** \brief An expression that calls a function. */
+	CK_CallExpr = C.CXCursor_CallExpr
+
+	/** \brief An expression that sends a message to an Objective-C
+	  object or class. */
+	CK_ObjCMessageExpr = C.CXCursor_ObjCMessageExpr
+
+	/** \brief An expression that represents a block literal. */
+	CK_BlockExpr = C.CXCursor_BlockExpr
+
+	/** \brief An integer literal.
+	 */
+	CK_IntegerLiteral = C.CXCursor_IntegerLiteral
+
+	/** \brief A floating point number literal.
+	 */
+	CK_FloatingLiteral = C.CXCursor_FloatingLiteral
+
+	/** \brief An imaginary number literal.
+	 */
+	CK_ImaginaryLiteral = C.CXCursor_ImaginaryLiteral
+
+	/** \brief A string literal.
+	 */
+	CK_StringLiteral = C.CXCursor_StringLiteral
+
+	/** \brief A character literal.
+	 */
+	CK_CharacterLiteral = C.CXCursor_CharacterLiteral
+
+	/** \brief A parenthesized expression, e.g. "(1)".
+	 *
+	 * This AST node is only formed if full location information is requested.
+	 */
+	CK_ParenExpr = C.CXCursor_ParenExpr
+
+	/** \brief This represents the unary-expression's (except sizeof and
+	 * alignof).
+	 */
+	CK_UnaryOperator = C.CXCursor_UnaryOperator
+
+	/** \brief [C99 6.5.2.1] Array Subscripting.
+	 */
+	CK_ArraySubscriptExpr = C.CXCursor_ArraySubscriptExpr
+
+	/** \brief A builtin binary operation expression such as "x + y" or
+	 * "x <= y".
+	 */
+	CK_BinaryOperator = C.CXCursor_BinaryOperator
+
+	/** \brief Compound assignment such as "+=".
+	 */
+	CK_CompoundAssignOperator = C.CXCursor_CompoundAssignOperator
+
+	/** \brief The ?: ternary operator.
+	 */
+	CK_ConditionalOperator = C.CXCursor_ConditionalOperator
+
+	/** \brief An explicit cast in C (C99 6.5.4) or a C-style cast in C++
+	 * (C++ [expr.cast]), which uses the syntax (Type)expr.
+	 *
+	 * For example: (int)f.
+	 */
+	CK_CStyleCastExpr = C.CXCursor_CStyleCastExpr
+
+	/** \brief [C99 6.5.2.5]
+	 */
+	CK_CompoundLiteralExpr = C.CXCursor_CompoundLiteralExpr
+
+	/** \brief Describes an C or C++ initializer list.
+	 */
+	CK_InitListExpr = C.CXCursor_InitListExpr
+
+	/** \brief The GNU address of label extension, representing &&label.
+	 */
+	CK_AddrLabelExpr = C.CXCursor_AddrLabelExpr
+
+	/** \brief This is the GNU Statement Expression extension: ({int X=4; X;})
+	 */
+	CK_StmtExpr = C.CXCursor_StmtExpr
+
+	/** \brief Represents a C1X generic selection.
+	 */
+	CK_GenericSelectionExpr = C.CXCursor_GenericSelectionExpr
+
+	/** \brief Implements the GNU __null extension, which is a name for a null
+	 * pointer constant that has integral type (e.g., int or long) and is the same
+	 * size and alignment as a pointer.
+	 *
+	 * The __null extension is typically only used by system headers, which define
+	 * NULL as __null in C++ rather than using 0 (which is an integer that may not
+	 * match the size of a pointer).
+	 */
+	CK_GNUNullExpr = C.CXCursor_GNUNullExpr
+
+	/** \brief C++'s static_cast<> expression.
+	 */
+	CK_CXXStaticCastExpr = C.CXCursor_CXXStaticCastExpr
+
+	/** \brief C++'s dynamic_cast<> expression.
+	 */
+	CK_CXXDynamicCastExpr = C.CXCursor_CXXDynamicCastExpr
+
+	/** \brief C++'s reinterpret_cast<> expression.
+	 */
+	CK_CXXReinterpretCastExpr = C.CXCursor_CXXReinterpretCastExpr
+
+	/** \brief C++'s const_cast<> expression.
+	 */
+	CK_CXXConstCastExpr = C.CXCursor_CXXConstCastExpr
+
+	/** \brief Represents an explicit C++ type conversion that uses "functional"
+	 * notion (C++ [expr.type.conv]).
+	 *
+	 * Example:
+	 * \code
+	 *   x = int(0.5);
+	 * \endcode
+	 */
+	CK_CXXFunctionalCastExpr = C.CXCursor_CXXFunctionalCastExpr
+
+	/** \brief A C++ typeid expression (C++ [expr.typeid]).
+	 */
+	CK_CXXTypeidExpr = C.CXCursor_CXXTypeidExpr
+
+	/** \brief [C++ 2.13.5] C++ Boolean Literal.
+	 */
+	CK_CXXBoolLiteralExpr = C.CXCursor_CXXBoolLiteralExpr
+
+	/** \brief [C++0x 2.14.7] C++ Pointer Literal.
+	 */
+	CK_CXXNullPtrLiteralExpr = C.CXCursor_CXXNullPtrLiteralExpr
+
+	/** \brief Represents the "this" expression in C++
+	 */
+	CK_CXXThisExpr = C.CXCursor_CXXThisExpr
+
+	/** \brief [C++ 15] C++ Throw Expression.
+	 *
+	 * This handles 'throw' and 'throw' assignment-expression. When
+	 * assignment-expression isn't present, Op will be null.
+	 */
+	CK_CXXThrowExpr = C.CXCursor_CXXThrowExpr
+
+	/** \brief A new expression for memory allocation and constructor calls, e.g:
+	 * "new CXXNewExpr(foo)".
+	 */
+	CK_CXXNewExpr = C.CXCursor_CXXNewExpr
+
+	/** \brief A delete expression for memory deallocation and destructor calls,
+	 * e.g. "delete[] pArray".
+	 */
+	CK_CXXDeleteExpr = C.CXCursor_CXXDeleteExpr
+
+	/** \brief A unary expression.
+	 */
+	CK_UnaryExpr = C.CXCursor_UnaryExpr
+
+	/** \brief ObjCStringLiteral, used for Objective-C string literals i.e. "foo".
+	 */
+	CK_ObjCStringLiteral = C.CXCursor_ObjCStringLiteral
+
+	/** \brief ObjCEncodeExpr, used for in Objective-C.
+	 */
+	CK_ObjCEncodeExpr = C.CXCursor_ObjCEncodeExpr
+
+	/** \brief ObjCSelectorExpr used for in Objective-C.
+	 */
+	CK_ObjCSelectorExpr = C.CXCursor_ObjCSelectorExpr
+
+	/** \brief Objective-C's protocol expression.
+	 */
+	CK_ObjCProtocolExpr = C.CXCursor_ObjCProtocolExpr
+
+	/** \brief An Objective-C "bridged" cast expression, which casts between
+	 * Objective-C pointers and C pointers, transferring ownership in the process.
+	 *
+	 * \code
+	 *   NSString *str = (__bridge_transfer NSString *)CFCreateString();
+	 * \endcode
+	 */
+	CK_ObjCBridgedCastExpr = C.CXCursor_ObjCBridgedCastExpr
+
+	/** \brief Represents a C++0x pack expansion that produces a sequence of
+	 * expressions.
+	 *
+	 * A pack expansion expression contains a pattern (which itself is an
+	 * expression) followed by an ellipsis. For example:
+	 *
+	 * \code
+	 * template<typename F, typename ...Types>
+	 * void forward(F f, Types &&...args) {
+	 *  f(static_cast<Types&&>(args)...);
+	 * }
+	 * \endcode
+	 */
+	CK_PackExpansionExpr = C.CXCursor_PackExpansionExpr
+
+	/** \brief Represents an expression that computes the length of a parameter
+	 * pack.
+	 *
+	 * \code
+	 * template<typename ...Types>
+	 * struct count {
+	 *   static const unsigned value = sizeof...(Types);
+	 * };
+	 * \endcode
+	 */
+	CK_SizeOfPackExpr = C.CXCursor_SizeOfPackExpr
+
+	CK_LastExpr = C.CXCursor_LastExpr
+
+	/* Statements */
+	CK_FirstStmt = C.CXCursor_FirstStmt
+	/**
+	 * \brief A statement whose specific kind is not exposed via this
+	 * interface.
+	 *
+	 * Unexposed statements have the same operations as any other kind of
+	 * statement; one can extract their location information, spelling,
+	 * children, etc. However, the specific kind of the statement is not
+	 * reported.
+	 */
+	CK_UnexposedStmt = C.CXCursor_UnexposedStmt
+
+	/** \brief A labelled statement in a function. 
+	 *
+	 * This cursor kind is used to describe the "start_over:" label statement in 
+	 * the following example:
+	 *
+	 * \code
+	 *   start_over:
+	 *     ++counter;
+	 * \endcode
+	 *
+	 */
+	CK_LabelStmt = C.CXCursor_LabelStmt
+
+	/** \brief A group of statements like { stmt stmt }.
+	 *
+	 * This cursor kind is used to describe compound statements, e.g. function
+	 * bodies.
+	 */
+	CK_CompoundStmt = C.CXCursor_CompoundStmt
+
+	/** \brief A case statment.
+	 */
+	CK_CaseStmt = C.CXCursor_CaseStmt
+
+	/** \brief A default statement.
+	 */
+	CK_DefaultStmt = C.CXCursor_DefaultStmt
+
+	/** \brief An if statement
+	 */
+	CK_IfStmt = C.CXCursor_IfStmt
+
+	/** \brief A switch statement.
+	 */
+	CK_SwitchStmt = C.CXCursor_SwitchStmt
+
+	/** \brief A while statement.
+	 */
+	CK_WhileStmt = C.CXCursor_WhileStmt
+
+	/** \brief A do statement.
+	 */
+	CK_DoStmt = C.CXCursor_DoStmt
+
+	/** \brief A for statement.
+	 */
+	CK_ForStmt = C.CXCursor_ForStmt
+
+	/** \brief A goto statement.
+	 */
+	CK_GotoStmt = C.CXCursor_GotoStmt
+
+	/** \brief An indirect goto statement.
+	 */
+	CK_IndirectGotoStmt = C.CXCursor_IndirectGotoStmt
+
+	/** \brief A continue statement.
+	 */
+	CK_ContinueStmt = C.CXCursor_ContinueStmt
+
+	/** \brief A break statement.
+	 */
+	CK_BreakStmt = C.CXCursor_BreakStmt
+
+	/** \brief A return statement.
+	 */
+	CK_ReturnStmt = C.CXCursor_ReturnStmt
+
+	/** \brief A GNU inline assembly statement extension.
+	 */
+	CK_AsmStmt = C.CXCursor_AsmStmt
+
+	/** \brief Objective-C's overall @try-@catc-@finall statement.
+	 */
+	CK_ObjCAtTryStmt = C.CXCursor_ObjCAtTryStmt
+
+	/** \brief Objective-C's @catch statement.
+	 */
+	CK_ObjCAtCatchStmt = C.CXCursor_ObjCAtCatchStmt
+
+	/** \brief Objective-C's @finally statement.
+	 */
+	CK_ObjCAtFinallyStmt = C.CXCursor_ObjCAtFinallyStmt
+
+	/** \brief Objective-C's @throw statement.
+	 */
+	CK_ObjCAtThrowStmt = C.CXCursor_ObjCAtThrowStmt
+
+	/** \brief Objective-C's @synchronized statement.
+	 */
+	CK_ObjCAtSynchronizedStmt = C.CXCursor_ObjCAtSynchronizedStmt
+
+	/** \brief Objective-C's autorelease pool statement.
+	 */
+	CK_ObjCAutoreleasePoolStmt = C.CXCursor_ObjCAutoreleasePoolStmt
+
+	/** \brief Objective-C's collection statement.
+	 */
+	CK_ObjCForCollectionStmt = C.CXCursor_ObjCForCollectionStmt
+
+	/** \brief C++'s catch statement.
+	 */
+	CK_CXXCatchStmt = C.CXCursor_CXXCatchStmt
+
+	/** \brief C++'s try statement.
+	 */
+	CK_CXXTryStmt = C.CXCursor_CXXTryStmt
+
+	/** \brief C++'s for (* : *) statement.
+	 */
+	CK_CXXForRangeStmt = C.CXCursor_CXXForRangeStmt
+
+	/** \brief Windows Structured Exception Handling's try statement.
+	 */
+	CK_SEHTryStmt = C.CXCursor_SEHTryStmt
+
+	/** \brief Windows Structured Exception Handling's except statement.
+	 */
+	CK_SEHExceptStmt = C.CXCursor_SEHExceptStmt
+
+	/** \brief Windows Structured Exception Handling's finally statement.
+	 */
+	CK_SEHFinallyStmt = C.CXCursor_SEHFinallyStmt
+
+	/** \brief The null satement ";": C99 6.8.3p3.
+	 *
+	 * This cursor kind is used to describe the null statement.
+	 */
+	CK_NullStmt = C.CXCursor_NullStmt
+
+	/** \brief Adaptor class for mixing declarations with statements and
+	 * expressions.
+	 */
+	CK_DeclStmt = C.CXCursor_DeclStmt
+
+	CK_LastStmt = C.CXCursor_LastStmt
+
+	/**
+	 * \brief Cursor that represents the translation unit itself.
+	 *
+	 * The translation unit cursor exists primarily to act as the root
+	 * cursor for traversing the contents of a translation unit.
+	 */
+	CK_TranslationUnit = C.CXCursor_TranslationUnit
+
+	/* Attributes */
+	CK_FirstAttr = C.CXCursor_FirstAttr
+	/**
+	 * \brief An attribute whose specific kind is not exposed via this
+	 * interface.
+	 */
+	CK_UnexposedAttr = C.CXCursor_UnexposedAttr
+
+	CK_IBActionAttr           = C.CXCursor_IBActionAttr
+	CK_IBOutletAttr           = C.CXCursor_IBOutletAttr
+	CK_IBOutletCollectionAttr = C.CXCursor_IBOutletCollectionAttr
+	CK_CXXFinalAttr           = C.CXCursor_CXXFinalAttr
+	CK_CXXOverrideAttr        = C.CXCursor_CXXOverrideAttr
+	CK_AnnotateAttr           = C.CXCursor_AnnotateAttr
+	CK_LastAttr               = C.CXCursor_LastAttr
+
+	/* Preprocessing */
+	CK_PreprocessingDirective = C.CXCursor_PreprocessingDirective
+	CK_MacroDefinition        = C.CXCursor_MacroDefinition
+	CK_MacroExpansion         = C.CXCursor_MacroExpansion
+	CK_MacroInstantiation     = C.CXCursor_MacroInstantiation
+	CK_InclusionDirective     = C.CXCursor_InclusionDirective
+	CK_FirstPreprocessing     = C.CXCursor_FirstPreprocessing
+	CK_LastPreprocessing      = C.CXCursor_LastPreprocessing
+)
+
+func (c CursorKind) to_c() uint32 {
+	return uint32(c)
+}
+
+/* for debug/testing */
+func (c CursorKind) Spelling() string {
+	cstr := cxstring{C.clang_getCursorKindSpelling(c.to_c())}
+	defer cstr.Dispose()
+	return cstr.String()
+}
+
+// EOF

pkg/clang/cxstring.go

+package clang
+
+// #include <stdlib.h>
+// #cgo LDFLAGS: -L/opt/local/libexec/llvm-3.0/lib -L/usr/lib/llvm -lclang
+// #cgo CFLAGS: -I/opt/local/libexec/llvm-3.0/include
+// #include "clang-c/Index.h"
+import "C"
+import (
+	//"unsafe"
+)
+
+// cxstring is a character string.
+//
+// The cxstring type is used to return strings from the interface when the
+// ownership of that string might different from one call to the next.
+type cxstring struct {
+	c C.CXString
+}
+
+func (c cxstring) String() string {
+	cstr := C.clang_getCString(c.c)
+	return C.GoString(cstr)
+}
+
+func (c cxstring) Dispose() {
+	C.clang_disposeString(c.c)
+}
+
+// EOF

pkg/clang/go-clang.h

+#ifndef _GO_CLANG
+#define _GO_CLANG 1
+
+unsigned _go_clang_visit_children(CXCursor c);
+
+#endif /* !_GO_CLANG */

pkg/clang/type.go

 package clang
 
 // #include <stdlib.h>
-// #cgo LDFLAGS: -L/opt/local/libexec/llvm-3.0/lib -lclang
-// #include "/opt/local/libexec/llvm-3.0/include/clang-c/Index.h"
+// #cgo LDFLAGS: -L/opt/local/libexec/llvm-3.0/lib -L/usr/lib/llvm -lclang
+// #cgo CFLAGS: -I/opt/local/libexec/llvm-3.0/include
+// #include "clang-c/Index.h"
 // inline static
 // CXCursor _go_clang_ocursor_at(CXCursor *c, int idx) {
 //   return c[idx];
 //
 import "C"
 import (
-	//"unsafe"
+//"unsafe"
 )
 
 // TypeKind describes the kind of a type
 
 	// A type whose specific kind is not exposed via this interface.
 	TK_Unexposed = C.CXType_Unexposed
-	
-	//FIXME
+
+	TK_Void       = C.CXType_Void
+	TK_Bool       = C.CXType_Bool
+	TK_Char_U     = C.CXType_Char_U
+	TK_UChar      = C.CXType_UChar
+	TK_Char16     = C.CXType_Char16
+	TK_Char32     = C.CXType_Char32
+	TK_UShort     = C.CXType_UShort
+	TK_UInt       = C.CXType_UInt
+	TK_ULong      = C.CXType_ULong
+	TK_ULongLong  = C.CXType_ULongLong
+	TK_UInt128    = C.CXType_UInt128
+	TK_Char_S     = C.CXType_Char_S
+	TK_SChar      = C.CXType_SChar
+	TK_WChar      = C.CXType_WChar
+	TK_Short      = C.CXType_Short
+	TK_Int        = C.CXType_Int
+	TK_Long       = C.CXType_Long
+	TK_LongLong   = C.CXType_LongLong
+	TK_Int128     = C.CXType_Int128
+	TK_Float      = C.CXType_Float
+	TK_Double     = C.CXType_Double
+	TK_LongDouble = C.CXType_LongDouble
+	TK_NullPtr    = C.CXType_NullPtr
+	TK_Overload   = C.CXType_Overload
+	TK_Dependent  = C.CXType_Dependent
+	TK_ObjCId     = C.CXType_ObjCId
+	TK_ObjCClass  = C.CXType_ObjCClass
+	TK_ObjCSel    = C.CXType_ObjCSel
+
+	TK_FirstBuiltin = C.CXType_FirstBuiltin
+	TK_LastBuiltin  = C.CXType_LastBuiltin
+
+	TK_Complex           = C.CXType_Complex
+	TK_Pointer           = C.CXType_Pointer
+	TK_BlockPointer      = C.CXType_BlockPointer
+	TK_LValueReference   = C.CXType_LValueReference
+	TK_RValueReference   = C.CXType_RValueReference
+	TK_Record            = C.CXType_Record
+	TK_Enum              = C.CXType_Enum
+	TK_Typedef           = C.CXType_Typedef
+	TK_ObjCInterface     = C.CXType_ObjCInterface
+	TK_ObjCObjectPointer = C.CXType_ObjCObjectPointer
+	TK_FunctionNoProto   = C.CXType_FunctionNoProto
+	TK_FunctionProto     = C.CXType_FunctionProto
+	TK_ConstantArray     = C.CXType_ConstantArray
 )
 
+func (t TypeKind) to_c() uint32 {
+	return uint32(t)
+}
+
 // Type represents the type of an element in the abstract syntax tree.
 type Type struct {
 	c C.CXType
 }
 
+// Spelling returns the spelling of a given TypeKind.
+func (t TypeKind) Spelling() string {
+	cstr := cxstring{C.clang_getTypeKindSpelling(t.to_c())}
+	defer cstr.Dispose()
+	return cstr.String()
+}
+
 // EqualTypes determines whether two Types represent the same type.
 func EqualTypes(t1, t2 Type) bool {
 	o := C.clang_equalTypes(t1.c, t2.c)
 	return false
 }
 
-/**
- * \brief 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'.
- */
+// CanonicalType returns the canonical type for a Type.
+//
+// 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'.
 func (t Type) CanonicalType() Type {
 	o := C.clang_getCanonicalType(t.c)
 	return Type{o}
 }
 
-/**
- *  \determine Determine whether a CXType has the "const" qualifier set, 
- *  without looking through typedefs that may have added "const" at a different level.
- */
+// IsConstQualified determines whether a Type has the "const" qualifier set, 
+// without looking through typedefs that may have added "const" at a
+// different level.
 func (t Type) IsConstQualified() bool {
 	o := C.clang_isConstQualifiedType(t.c)
 	if o != C.uint(0) {
 	return false
 }
 
-/**
- *  \determine Determine whether a CXType has the "volatile" qualifier set,
- *  without looking through typedefs that may have added "volatile" at a different level.
- */
+// IsVolatileQualified determines whether a Type has the "volatile" qualifier 
+// set, without looking through typedefs that may have added "volatile" at a
+// different level.
 func (t Type) IsVolatileQualified() bool {
 	o := C.clang_isVolatileQualifiedType(t.c)
 	if o != C.uint(0) {
 	return false
 }
 
-/**
- *  \determine Determine whether a CXType has the "restrict" qualifier set,
- *  without looking through typedefs that may have added "restrict" at a different level.
- */
+// IsRestrictQualified determines whether a Type has the "restrict" qualifier
+// set, without looking through typedefs that may have added "restrict" at a
+// different level.
 func (t Type) IsRestrictQualified() bool {
 	o := C.clang_isRestrictQualifiedType(t.c)
 	if o != C.uint(0) {
 	return false
 }
 
-/**
- * \brief For pointer types, returns the type of the pointee.
- *
- */
+// PointeeType (for pointer types), returns the type of the pointee.
 func (t Type) PointeeType() Type {
 	o := C.clang_getPointeeType(t.c)
 	return Type{o}
 }
 
-/**
- * \brief Return the cursor for the declaration of the given type.
- */
+// Declaration returns the cursor for the declaration of the given type.
 func (t Type) Declaration() Cursor {
 	o := C.clang_getTypeDeclaration(t.c)
 	return Cursor{o}
 }
 
 /**
- * Returns the Objective-C type encoding for the specified declaration.
- */
-//FIXME
-//CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C);
-
-/**
- * \brief Retrieve the spelling of a given CXTypeKind.
- */
-//FIXME
-//CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K);
-
-/**
  * \brief Retrieve the result type associated with a function type.
  */
 func (t Type) ResultType() Type {
 	return int64(o)
 }
 
-
-
-
 // EOF

pkg/clang/visitorwrap.c

+/* helper functions to visit cursors
+ */
+
+#include "_cgo_export.h"
+#include "clang-c/Index.h"
+#include "go-clang.h"
+
+unsigned
+_go_clang_visit_children(CXCursor c)
+{
+  return clang_visitChildren(c, (CXCursorVisitor)&GoClangCursorVisitor, NULL);
+}
+
+/* EOF */