diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,32 @@
+Copyright (c) Chetan Taralekar 2010, 2011, 2014
+Copyright (c) Seth Fowler 2013, 2014
+Each patch is attributed to its author, usually by email address.
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * The names of the contributors may not be used to endorse or promote
+    products derived from this software without specific prior written
+    permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/LibClang.cabal b/LibClang.cabal
new file mode 100644
--- /dev/null
+++ b/LibClang.cabal
@@ -0,0 +1,75 @@
+Name: LibClang
+Cabal-version: >= 1.18
+Version: 3.8.0
+Author: Chetan Taralekar <chetant@gmail.com>
+Maintainer: Chetan Taralekar <chetant@gmail.com>, Seth Fowler <mark.seth.fowler@gmail.com>
+Homepage: https://github.com/chetant/LibClang
+License: BSD3
+License-file: LICENSE
+Synopsis: Haskell bindings for libclang (a C++ parsing library)
+Description:
+  LibClang package provides bindings to libclang.
+  .
+  This should be enough for parsing C/C++ code, walking the AST and querying nodes and completion queries.
+  .
+  * NOTE: This version is set to build against llvm 3.8.0
+  .
+  Please use <https://github.com/chetant/LibClang/issues> to report bugs
+
+Category: Language
+Tested-With: GHC == 7.8.4
+           , GHC == 7.10.3
+           , GHC == 8.0.2
+Build-type: Custom
+Extra-Source-Files: cbits/utils.h, cbits/visitors.h, cbits/wrappers.h,
+                    test/*.hs, test/*.c, test/runTest.sh, test/Makefile
+Source-Repository head
+  type: git
+  location: git://github.com/chetant/LibClang.git
+
+Library
+  ghc-options:     -Wall -funbox-strict-fields
+  build-tools:     c2hs >= 0.28.1
+  build-depends:   base >= 4.6 && < 5,
+                   bytestring >= 0.10 && < 0.11,
+                   filepath >= 1.3 && < 1.5,
+                   hashable >= 1.2 && < 1.3,
+                   mtl >= 2.1 && < 2.3,
+                   resourcet >= 1.1 && < 1.2,
+                   text >= 1.1 && < 1.3,
+                   time >= 1.4 && < 1.7,
+                   transformers >= 0.3 && < 0.6,
+                   transformers-base >= 0.4,
+                   vector >= 0.10 && < 0.12
+  hs-source-dirs:  src
+  c-sources:       cbits/utils.c,
+                   cbits/visitors.c,
+                   cbits/wrappers.c
+  include-dirs:    cbits
+  exposed-modules: Clang,
+                   Clang.Comment,
+                   Clang.Completion,
+                   Clang.Cursor,
+                   Clang.Debug,
+                   Clang.Diagnostic,
+                   Clang.File,
+                   Clang.Location,
+                   Clang.Index,
+                   Clang.Module,
+                   Clang.Range,
+                   Clang.Remapping,
+                   Clang.String,
+                   Clang.Token,
+                   Clang.TranslationUnit,
+                   Clang.Type,
+                   Clang.UnsavedFile,
+                   Clang.USR,
+                   Clang.Version
+  other-modules: Clang.Internal.BitFlags,
+                 Clang.Internal.Comment,
+                 Clang.Internal.Monad,
+                 Clang.Internal.FFI,
+                 Clang.Internal.FFIConstants
+  default-language: Haskell2010
+  pkgconfig-depends: ncurses
+  extra-libraries: clang-3.8
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,78 @@
+{-# LANGUAGE CPP #-}
+import Distribution.Simple
+import Distribution.PackageDescription
+import Data.Version
+import Data.List
+import Data.Char(isSpace)
+import Data.Maybe
+import System.Directory(getCurrentDirectory, removeFile)
+import System.IO(IOMode(..), openFile, hPutStr, hFlush, hClose)
+import System.IO.Error(catchIOError)
+import System.Process(readProcess)
+import System.Environment(lookupEnv, getEnv, setEnv)
+import System.FilePath.Posix((</>))
+import Control.Applicative((<$>))
+import Control.Exception(bracket)
+
+rtrim :: String -> String
+rtrim = f . f
+  where f = reverse . dropWhile isSpace
+
+getLLVMDetails llvmConfigPath = do
+  version <- rtrim <$> readProcess llvmConfigPath ["--version"] []
+  libPath <- rtrim <$> readProcess llvmConfigPath ["--libdir"] []
+  includePath <- rtrim <$> readProcess llvmConfigPath ["--includedir"] []
+  return (version,libPath,includePath)
+
+setupLLVMPkgConfig tmpPCPath outf = do
+  let tryElse act failAct = catchIOError act (const failAct)
+  (version,libPath,includePath) <- getLLVMDetails "llvm-config-3.8" `tryElse`
+                                   getLLVMDetails "llvm-config" `tryElse`
+                                   (getEnv "LLVM_CONFIG" >>= getLLVMDetails) `tryElse`
+                                   (error "ERROR: cannot find llvm-config, please setup environment variable LLVM_CONFIG with location of llvm-config and try again")
+  let pc = unlines $ ["Name: LLVM"
+                     ,"Description: Low-level Virtual Machine compiler framework"
+                     ,"Version: " ++ version
+                     ,"URL: http://www.llvm.org/"
+                     ,"Requires:"
+                     ,"Conflicts:"
+                     ,"Libs: -L" ++ libPath ++ " -lLLVM-" ++ version
+                     ,"Cflags: -I" ++ includePath]
+      pkgConfigPath = "PKG_CONFIG_PATH"
+  hPutStr outf pc
+  hFlush outf
+  mpc <- lookupEnv pkgConfigPath
+  let pkgConfigPathVal = case mpc of
+        Just pc -> pc ++ ":" ++ tmpPCPath
+        Nothing -> tmpPCPath
+  -- putStrLn $ pkgConfigPath ++ "=" ++ pkgConfigPathVal
+  setEnv pkgConfigPath pkgConfigPathVal
+
+withTmpPC runM = do
+  cwd <- getCurrentDirectory
+  let llvmPCFname = cwd </> "llvm.pc"
+  bracket
+    (openFile llvmPCFname WriteMode)
+    (\outf -> hClose outf >> removeFile llvmPCFname)
+    (runM cwd)
+
+pcHook = simpleUserHooks { confHook = confHookM }
+  where confHookM (gpd, hbi) cf = do
+          let cdt = fromJust $ condLibrary gpd
+              lib = condTreeData cdt
+              lbi = libBuildInfo lib
+              vRange = withinVersion $ makeVersion [3,8]
+              lbi' = lbi { pkgconfigDepends = pkgconfigDepends lbi ++
+                                              [Dependency (PackageName "llvm") vRange] }
+              lib' = lib { libBuildInfo = lbi' }
+              gpd' = gpd { condLibrary = Just (cdt { condTreeData = lib' }) }
+          (confHook simpleUserHooks) (gpd', hbi) cf
+
+#if __GLASGOW_HASKELL__ < 710
+makeVersion xs = Version xs []
+#endif
+
+main =
+  withTmpPC $ \cwd outf -> do
+    setupLLVMPkgConfig cwd outf
+    defaultMainWithHooks pcHook
diff --git a/cbits/utils.c b/cbits/utils.c
new file mode 100644
--- /dev/null
+++ b/cbits/utils.c
@@ -0,0 +1,24 @@
+#include "utils.h"
+
+unsigned codeCompleteGetNumResults(CXCodeCompleteResults* results)
+{
+  return results ? results->NumResults
+                 : 0;
+}
+
+// We don't perform any null or bounds checks here because this is an internal function
+// with only one caller, but if we exposed this API publicly we'd have to do so.
+enum CXCursorKind codeCompleteGetResult(CXCodeCompleteResults* results,
+                                        unsigned index,
+                                        CXCompletionString* stringOut)
+{
+  *stringOut = results->Results[index].CompletionString;
+  return results->Results[index].CursorKind;
+}
+
+void freeClangString(void* data, unsigned flags) {
+  CXString str;
+  str.data = data;
+  str.private_flags = flags;
+  clang_disposeString(str);
+}
diff --git a/cbits/utils.h b/cbits/utils.h
new file mode 100644
--- /dev/null
+++ b/cbits/utils.h
@@ -0,0 +1,12 @@
+#include <clang-c/Index.h>
+
+// This file contains utility functions that make implementing the Haskell FFI
+// code easier.
+
+unsigned codeCompleteGetNumResults(CXCodeCompleteResults* results);
+
+enum CXCursorKind codeCompleteGetResult(CXCodeCompleteResults* results,
+                                        unsigned index,
+                                        CXCompletionString* stringOut);
+
+void freeClangString(void* data, unsigned flags);
diff --git a/cbits/visitors.c b/cbits/visitors.c
new file mode 100644
--- /dev/null
+++ b/cbits/visitors.c
@@ -0,0 +1,333 @@
+#include <stdlib.h>
+
+#include "visitors.h"
+
+#define INITIAL_LIST_CAPACITY 16
+#define LIST_GROWTH_RATE 4
+
+typedef struct
+{
+  CXCursor* items;
+  unsigned  count;
+  size_t    capacity;
+} CursorList;
+
+void freeCursorList(CXCursor* cursors)
+{
+  free(cursors);
+}
+
+#define LIST_INIT(_type) {                         \
+    malloc(INITIAL_LIST_CAPACITY * sizeof(_type)), \
+    0,                                             \
+    INITIAL_LIST_CAPACITY                          \
+  }
+
+#define LIST_APPEND(_type, _list, _item)                       \
+  do {                                                         \
+    if (_list->count >= _list->capacity) {                     \
+      size_t newCapacity = LIST_GROWTH_RATE * _list->capacity; \
+      _list->items =                                           \
+        realloc(_list->items, newCapacity * sizeof(_type));    \
+      _list->capacity = newCapacity;                           \
+    }                                                          \
+                                                               \
+    _list->items[_list->count++] = _item;                      \
+  } while(0)                                                   \
+
+enum CXChildVisitResult childListBuilder(CXCursor cursor, CXCursor parent,
+                                         CXClientData clientData)
+{
+  CursorList* childList = (CursorList*) clientData;
+  LIST_APPEND(CXCursor, childList, cursor);
+  return CXChildVisit_Continue;
+}
+
+void getChildren(CXCursor parent, CXCursor** childrenOut, unsigned* countOut)
+{
+  CursorList childList = LIST_INIT(CXCursor);
+  clang_visitChildren(parent, childListBuilder, &childList);
+  *childrenOut = childList.items;
+  *countOut = childList.count;
+}
+
+enum CXChildVisitResult descendantListBuilder(CXCursor cursor, CXCursor parent,
+                                              CXClientData clientData)
+{
+  CursorList* childList = (CursorList*) clientData;
+  LIST_APPEND(CXCursor, childList, cursor);
+  return CXChildVisit_Recurse;
+}
+
+void getDescendants(CXCursor parent, CXCursor** childrenOut, unsigned* countOut)
+{
+  CursorList childList = LIST_INIT(CXCursor);
+  clang_visitChildren(parent, descendantListBuilder, &childList);
+  *childrenOut = childList.items;
+  *countOut = childList.count;
+}
+
+enum CXChildVisitResult declarationListBuilder(CXCursor cursor, CXCursor parent,
+                                               CXClientData clientData)
+{
+  if (clang_isDeclaration(clang_getCursorKind(cursor))) {
+    CursorList* childList = (CursorList*) clientData;
+    LIST_APPEND(CXCursor, childList, cursor);
+  }
+  return CXChildVisit_Recurse;
+}
+
+void getDeclarations(CXTranslationUnit tu, CXCursor** childrenOut, unsigned* countOut)
+{
+  CursorList childList = LIST_INIT(CXCursor);
+  CXCursor parent = clang_getTranslationUnitCursor(tu);
+  clang_visitChildren(parent, declarationListBuilder, &childList);
+  *childrenOut = childList.items;
+  *countOut = childList.count;
+}
+
+enum CXChildVisitResult referenceListBuilder(CXCursor cursor, CXCursor parent,
+                                              CXClientData clientData)
+{
+  if (clang_isReference(clang_getCursorKind(cursor))) {
+    CursorList* childList = (CursorList*) clientData;
+    LIST_APPEND(CXCursor, childList, cursor);
+  }
+  return CXChildVisit_Recurse;
+}
+
+void getReferences(CXTranslationUnit tu, CXCursor** childrenOut, unsigned* countOut)
+{
+  CursorList childList = LIST_INIT(CXCursor);
+  CXCursor parent = clang_getTranslationUnitCursor(tu);
+  clang_visitChildren(parent, referenceListBuilder, &childList);
+  *childrenOut = childList.items;
+  *countOut = childList.count;
+}
+
+typedef struct
+{
+  CursorList decls;
+  CursorList refs;
+} CursorListPair;
+
+enum CXChildVisitResult declAndRefListBuilder(CXCursor cursor, CXCursor parent,
+                                              CXClientData clientData)
+{
+  CursorListPair* declsAndRefs = (CursorListPair*) clientData;
+
+  if (clang_isDeclaration(clang_getCursorKind(cursor))) {
+    CursorList* decls = &declsAndRefs->decls;
+    LIST_APPEND(CXCursor, decls, cursor);
+  }
+
+  if (clang_isReference(clang_getCursorKind(cursor))) {
+    CursorList* refs = &declsAndRefs->refs;
+    LIST_APPEND(CXCursor, refs, cursor);
+  }
+  
+  return CXChildVisit_Recurse;
+}
+
+void getDeclarationsAndReferences(CXTranslationUnit tu,
+                                  CXCursor** declsOut,
+                                  unsigned* declCountOut,
+                                  CXCursor** refsOut,
+                                  unsigned* refCountOut)
+{
+  CursorListPair declsAndRefs = {
+    LIST_INIT(CXCursor),
+    LIST_INIT(CXCursor)
+  };
+
+  CXCursor parent = clang_getTranslationUnitCursor(tu);
+  clang_visitChildren(parent, declAndRefListBuilder, &declsAndRefs);
+
+  *declsOut = declsAndRefs.decls.items;
+  *declCountOut = declsAndRefs.decls.count;
+  *refsOut = declsAndRefs.refs.items;
+  *refCountOut = declsAndRefs.refs.count;
+}
+
+typedef struct
+{
+  ParentedCursor* items;
+  unsigned        count;
+  size_t          capacity;
+} ParentedCursorList;
+
+void freeParentedCursorList(ParentedCursor* parentedCursors)
+{
+  free(parentedCursors);
+}
+
+enum CXChildVisitResult parentedDescendantListBuilder(CXCursor cursor, CXCursor parent,
+                                                      CXClientData clientData)
+{
+  ParentedCursorList* descendantList = (ParentedCursorList*) clientData;
+
+  ParentedCursor newEntry = {
+    parent,
+    cursor
+  };
+
+  LIST_APPEND(ParentedCursor, descendantList, newEntry);
+
+  return CXChildVisit_Recurse;
+}
+
+void getParentedDescendants(CXCursor parent, ParentedCursor** descendantsOut,
+                            unsigned* countOut)
+{
+  ParentedCursorList descendantList = LIST_INIT(ParentedCursor);
+  clang_visitChildren(parent, parentedDescendantListBuilder, &descendantList);
+  *descendantsOut = descendantList.items;
+  *countOut = descendantList.count;
+}
+
+enum CXChildVisitResult parentedDeclarationListBuilder(CXCursor cursor, CXCursor parent,
+                                                      CXClientData clientData)
+{
+  ParentedCursorList* declarationList = (ParentedCursorList*) clientData;
+
+  if (clang_isDeclaration(clang_getCursorKind(cursor))) {
+    ParentedCursor newEntry = {
+      parent,
+      cursor
+    };
+
+    LIST_APPEND(ParentedCursor, declarationList, newEntry);
+  }
+
+  return CXChildVisit_Recurse;
+}
+
+void getParentedDeclarations(CXTranslationUnit tu, ParentedCursor** declarationsOut,
+                             unsigned* countOut)
+{
+  ParentedCursorList declarationList = LIST_INIT(ParentedCursor);
+  CXCursor parent = clang_getTranslationUnitCursor(tu);
+  clang_visitChildren(parent, parentedDeclarationListBuilder, &declarationList);
+  *declarationsOut = declarationList.items;
+  *countOut = declarationList.count;
+}
+
+enum CXChildVisitResult parentedReferenceListBuilder(CXCursor cursor, CXCursor parent,
+                                                      CXClientData clientData)
+{
+  ParentedCursorList* referenceList = (ParentedCursorList*) clientData;
+
+  if (clang_isReference(clang_getCursorKind(cursor))) {
+    ParentedCursor newEntry = {
+      parent,
+      cursor
+    };
+
+    LIST_APPEND(ParentedCursor, referenceList, newEntry);
+  }
+
+  return CXChildVisit_Recurse;
+}
+
+void getParentedReferences(CXTranslationUnit tu, ParentedCursor** referencesOut,
+                           unsigned* countOut)
+{
+  ParentedCursorList referenceList = LIST_INIT(ParentedCursor);
+  CXCursor parent = clang_getTranslationUnitCursor(tu);
+  clang_visitChildren(parent, parentedReferenceListBuilder, &referenceList);
+  *referencesOut = referenceList.items;
+  *countOut = referenceList.count;
+}
+
+typedef struct
+{
+  ParentedCursorList decls;
+  ParentedCursorList refs;
+} ParentedCursorListPair;
+
+enum CXChildVisitResult parentedDeclAndRefListBuilder(CXCursor cursor,
+                                                      CXCursor parent,
+                                                      CXClientData clientData)
+{
+  ParentedCursorListPair* declsAndRefs = (ParentedCursorListPair*) clientData;
+
+  if (clang_isDeclaration(clang_getCursorKind(cursor))) {
+    ParentedCursor newEntry = {
+      parent,
+      cursor
+    };
+
+    ParentedCursorList* decls = &declsAndRefs->decls;
+    LIST_APPEND(ParentedCursor, decls, newEntry);
+  }
+
+  if (clang_isReference(clang_getCursorKind(cursor))) {
+    ParentedCursor newEntry = {
+      parent,
+      cursor
+    };
+
+    ParentedCursorList* refs = &declsAndRefs->refs;
+    LIST_APPEND(ParentedCursor, refs, newEntry);
+  }
+
+  return CXChildVisit_Recurse;
+}
+
+void getParentedDeclarationsAndReferences(CXTranslationUnit tu,
+                                          ParentedCursor** declsOut,
+                                          unsigned* declCountOut,
+                                          ParentedCursor** refsOut,
+                                          unsigned* refCountOut)
+{
+  ParentedCursorListPair declsAndRefs = {
+    LIST_INIT(ParentedCursor),
+    LIST_INIT(ParentedCursor)
+  };
+ 
+  CXCursor parent = clang_getTranslationUnitCursor(tu);
+  clang_visitChildren(parent, parentedDeclAndRefListBuilder, &declsAndRefs);
+  *declsOut = declsAndRefs.decls.items;
+  *declCountOut = declsAndRefs.decls.count;
+  *refsOut = declsAndRefs.refs.items;
+  *refCountOut = declsAndRefs.refs.count;
+}
+
+typedef struct
+{
+  Inclusion* items;
+  unsigned   count;
+  size_t     capacity;
+} InclusionList;
+
+void freeInclusionList(Inclusion* inclusions)
+{
+  free(inclusions);
+}
+
+void inclusionListBuilder(CXFile includedFile, CXSourceLocation* inclusionStack,
+                          unsigned stackLen, CXClientData clientData)
+{
+  // Skip the initial file.
+  if (stackLen == 0)
+    return;
+  
+  InclusionList* inclusionList = (InclusionList*) clientData;
+
+  Inclusion newEntry = {
+    includedFile,
+    inclusionStack[0],
+    stackLen == 1  // It's a direct inclusion if there's only one stack entry.
+  };
+
+  LIST_APPEND(Inclusion, inclusionList, newEntry);
+}
+
+void getInclusions(CXTranslationUnit tu, Inclusion** inclusionsOut,
+                   unsigned* countOut)
+{
+  InclusionList inclusionList = LIST_INIT(Inclusion);
+  clang_getInclusions(tu, inclusionListBuilder, &inclusionList);
+  *inclusionsOut = inclusionList.items;
+  *countOut = inclusionList.count;
+}
diff --git a/cbits/visitors.h b/cbits/visitors.h
new file mode 100644
--- /dev/null
+++ b/cbits/visitors.h
@@ -0,0 +1,54 @@
+#ifndef LIBCLANG_VISITORS_H
+#define LIBCLANG_VISITORS_H
+
+#include "clang-c/Index.h"
+
+void freeCursorList(CXCursor* cursors);
+
+typedef struct
+{
+  CXCursor parent;
+  CXCursor cursor;
+} ParentedCursor;
+
+void freeParentedCursorList(ParentedCursor* parentedCursors);
+
+// Wrappers for libclang traversals.
+void getChildren(CXCursor parent, CXCursor** childrenOut, unsigned* countOut);
+void getDescendants(CXCursor parent, CXCursor** childrenOut, unsigned* countOut);
+void getDeclarations(CXTranslationUnit tu, CXCursor** declsOut, unsigned* declCountOut);
+void getReferences(CXTranslationUnit tu, CXCursor** refsOut, unsigned* refCountOut);
+void getDeclarationsAndReferences(CXTranslationUnit tu,
+                                  CXCursor** declsOut, unsigned* declCountOut,
+                                  CXCursor** refsOut, unsigned* refCountOut);
+
+// Variants that include the parent of each cursor.
+void getParentedDescendants(CXCursor parent,
+                            ParentedCursor** descendantsOut,
+                            unsigned* countOut);
+void getParentedDeclarations(CXTranslationUnit tu,
+                             ParentedCursor** declsOut,
+                             unsigned* declCountOut);
+void getParentedReferences(CXTranslationUnit tu,
+                           ParentedCursor** refsOut,
+                           unsigned* refCountOut);
+void getParentedDeclarationsAndReferences(CXTranslationUnit tu,
+                                          ParentedCursor** declsOut,
+                                          unsigned* declCountOut,
+                                          ParentedCursor** refsOut,
+                                          unsigned* refCountOut);
+
+// Wrappers for clang_getInclusions.
+typedef struct
+{
+  CXFile           inclusion;
+  CXSourceLocation location;
+  unsigned char    isDirect;
+} Inclusion;
+
+void freeInclusionList(Inclusion* inclusions);
+
+void getInclusions(CXTranslationUnit tu, Inclusion** inclusionsOut,
+                   unsigned* countOut);
+
+#endif
diff --git a/cbits/wrappers.c b/cbits/wrappers.c
new file mode 100644
--- /dev/null
+++ b/cbits/wrappers.c
@@ -0,0 +1,129 @@
+#include "wrappers.h"
+#include <stdlib.h>
+
+WRAPPED_IMPL(CXSourceLocation, clang_getNullLocation, (), ());
+WRAPPED_IMPL(CXSourceLocation, clang_getLocation, (CXTranslationUnit tu,
+                                                   CXFile file,
+                                                   unsigned line,
+                                                   unsigned column), (tu,
+                                                                      file,
+                                                                      line,
+                                                                      column));
+WRAPPED_IMPL(CXSourceLocation, clang_getLocationForOffset, (CXTranslationUnit tu,
+                                                            CXFile file,
+                                                            unsigned offset), (tu,
+                                                                               file,
+                                                                               offset));
+WRAPPED_IMPL(CXSourceLocation, clang_getRangeStart, (CXSourceRange range), (range));
+WRAPPED_IMPL(CXSourceLocation, clang_getRangeEnd, (CXSourceRange range), (range));
+WRAPPED_IMPL(CXSourceLocation, clang_getDiagnosticLocation, (CXDiagnostic d), (d));
+WRAPPED_IMPL(CXSourceLocation, clang_getCursorLocation, (CXCursor c), (c));
+WRAPPED_IMPL(CXSourceLocation, clang_getTokenLocation, (CXTranslationUnit tu,
+                                                        CXToken token), (tu,
+                                                                         token));
+
+WRAPPED_IMPL(CXSourceRange,clang_getNullRange, (), ());
+WRAPPED_IMPL(CXSourceRange,clang_getRange,(CXSourceLocation begin,
+                                           CXSourceLocation end),(begin,
+                                                                  end));
+WRAPPED_IMPL(CXSourceRange,clang_getDiagnosticRange, (CXDiagnostic Diagnostic,
+                                                      unsigned Range),(Diagnostic,
+                                                                       Range));
+WRAPPED_IMPL(CXSourceRange,clang_getCursorExtent,(CXCursor c), (c));
+WRAPPED_IMPL(CXSourceRange,clang_Cursor_getSpellingNameRange, (CXCursor c,
+                                                               unsigned pieceIndex,
+                                                               unsigned options),(c,
+                                                                                  pieceIndex,
+                                                                                  options));
+WRAPPED_IMPL(CXSourceRange,clang_Cursor_getCommentRange, (CXCursor C), (C));
+WRAPPED_IMPL(CXSourceRange,clang_getCursorReferenceNameRange, (CXCursor C,
+                                                               unsigned NameFlags,
+                                                               unsigned PieceIndex),(C,
+                                                                                     NameFlags,
+                                                                                     PieceIndex));
+WRAPPED_IMPL(CXSourceRange,clang_getTokenExtent, (CXTranslationUnit tu, CXToken token), (tu, token));
+
+WRAPPED_IMPL(CXCursor,clang_getNullCursor,(),());
+WRAPPED_IMPL(CXCursor,clang_getTranslationUnitCursor,(CXTranslationUnit tu),(tu));
+WRAPPED_IMPL(CXCursor,clang_getCursorSemanticParent,(CXCursor cursor),(cursor));
+WRAPPED_IMPL(CXCursor,clang_getCursorLexicalParent,(CXCursor cursor),(cursor));
+WRAPPED_IMPL(CXCursor,clang_getCursor,(CXTranslationUnit tu, CXSourceLocation sl),(tu, sl));
+WRAPPED_IMPL(CXCursor,clang_Cursor_getArgument,(CXCursor C, unsigned i),(C, i));
+WRAPPED_IMPL(CXCursor,clang_getTypeDeclaration,(CXType T),(T));
+WRAPPED_IMPL(CXCursor,clang_getOverloadedDecl,(CXCursor cursor,
+                                                unsigned index),(cursor, index));
+WRAPPED_IMPL(CXCursor,clang_getCursorReferenced,(CXCursor c),(c));
+WRAPPED_IMPL(CXCursor,clang_getCursorDefinition,(CXCursor c),(c));
+WRAPPED_IMPL(CXCursor,clang_getCanonicalCursor,(CXCursor c),(c));
+WRAPPED_IMPL(CXCursor,clang_getSpecializedCursorTemplate,(CXCursor C),(C));
+
+WRAPPED_IMPL(CXComment,clang_Cursor_getParsedComment,(CXCursor C),(C));
+
+WRAPPED_IMPL(CXType,clang_getCursorType,(CXCursor C),(C));
+WRAPPED_IMPL(CXType,clang_getTypedefDeclUnderlyingType,(CXCursor C),(C));
+WRAPPED_IMPL(CXType,clang_getEnumDeclIntegerType,(CXCursor C),(C));
+WRAPPED_IMPL(CXType,clang_getCanonicalType,(CXType T),(T));
+WRAPPED_IMPL(CXType,clang_getPointeeType,(CXType T),(T));
+WRAPPED_IMPL(CXType,clang_getResultType,(CXType T),(T));
+WRAPPED_IMPL(CXType,clang_getArgType,(CXType T, unsigned i),(T, i));
+WRAPPED_IMPL(CXType,clang_getCursorResultType,(CXCursor C),(C));
+WRAPPED_IMPL(CXType,clang_getElementType,(CXType T),(T));
+WRAPPED_IMPL(CXType,clang_getArrayElementType,(CXType T),(T));
+WRAPPED_IMPL(CXType,clang_Type_getClassType,(CXType T),(T));
+WRAPPED_IMPL(CXType,clang_getIBOutletCollectionType,(CXCursor c),(c));
+WRAPPED_IMPL(CXType,clang_Cursor_getReceiverType,(CXCursor C),(C));
+
+WRAPPED_IMPL(CXString,clang_getFileName,(CXFile SFile),(SFile));
+WRAPPED_IMPL(CXString,clang_formatDiagnostic,(CXDiagnostic Diagnostic,
+                                               unsigned Options),(Diagnostic,
+                                               Options));
+WRAPPED_IMPL(CXString,clang_getDiagnosticSpelling,(CXDiagnostic d),(d));
+WRAPPED_IMPL(CXString,clang_getDiagnosticOption,(CXDiagnostic Diag,
+                                                  CXString *Disable),(Diag,
+                                                  Disable));
+WRAPPED_IMPL(CXString,clang_getDiagnosticCategoryText,(CXDiagnostic d),(d));
+WRAPPED_IMPL(CXString,clang_getDiagnosticFixIt,(CXDiagnostic Diagnostic,
+                                                 unsigned FixIt,
+                                               CXSourceRange *ReplacementRange),(Diagnostic,
+                                                 FixIt,
+                                               ReplacementRange));
+WRAPPED_IMPL(CXString,clang_getTranslationUnitSpelling,(CXTranslationUnit CTUnit),(CTUnit));;
+WRAPPED_IMPL(CXString,clang_getTypeSpelling,(CXType CT),(CT));
+WRAPPED_IMPL(CXString,clang_getDeclObjCTypeEncoding,(CXCursor C),(C));
+WRAPPED_IMPL(CXString,clang_getTypeKindSpelling,(enum CXTypeKind K),(K));
+WRAPPED_IMPL(CXString,clang_getCursorUSR,(CXCursor c),(c));
+WRAPPED_IMPL(CXString,clang_constructUSR_ObjCClass,(const char *class_name),(class_name));
+WRAPPED_IMPL(CXString,clang_constructUSR_ObjCCategory,(const char *class_name,
+                                 const char *category_name),(class_name,
+                                 category_name));;
+WRAPPED_IMPL(CXString,clang_constructUSR_ObjCProtocol,(const char *protocol_name),(protocol_name));;
+WRAPPED_IMPL(CXString,clang_constructUSR_ObjCIvar,(const char *name,
+                                                    CXString classUSR),(name,
+                                                    classUSR));
+WRAPPED_IMPL(CXString,clang_constructUSR_ObjCMethod,(const char *name,
+                                                      unsigned isInstanceMethod,
+                                                      CXString classUSR),(name,
+                                                      isInstanceMethod,
+                                                      classUSR));
+WRAPPED_IMPL(CXString,clang_constructUSR_ObjCProperty,(const char *property,
+                                                        CXString classUSR),(property,
+                                                        classUSR));
+WRAPPED_IMPL(CXString,clang_getCursorSpelling,(CXCursor c),(c));
+WRAPPED_IMPL(CXString,clang_getCursorDisplayName,(CXCursor c),(c));
+WRAPPED_IMPL(CXString,clang_Cursor_getRawCommentText,(CXCursor C),(C));
+WRAPPED_IMPL(CXString,clang_Cursor_getBriefCommentText,(CXCursor C),(C));
+WRAPPED_IMPL(CXString,clang_Module_getName,(CXModule Module),(Module));
+WRAPPED_IMPL(CXString,clang_Module_getFullName,(CXModule Module),(Module));
+WRAPPED_IMPL(CXString,clang_TextComment_getText,(CXComment Comment),(Comment));
+WRAPPED_IMPL(CXString,clang_HTMLTagComment_getTagName,(CXComment Comment),(Comment));
+WRAPPED_IMPL(CXString,clang_VerbatimLineComment_getText,(CXComment Comment),(Comment));
+WRAPPED_IMPL(CXString,clang_HTMLTagComment_getAsString,(CXComment Comment),(Comment));
+WRAPPED_IMPL(CXString,clang_FullComment_getAsHTML,(CXComment Comment),(Comment));
+WRAPPED_IMPL(CXString,clang_FullComment_getAsXML,(CXComment Comment),(Comment));
+WRAPPED_IMPL(CXString,clang_getTokenSpelling,(CXTranslationUnit tu, CXToken token),(tu, token));
+WRAPPED_IMPL(CXString,clang_getCursorKindSpelling,(enum CXCursorKind Kind),(Kind));
+WRAPPED_IMPL(CXString,clang_getCompletionChunkText,(CXCompletionString completion_string, unsigned chunk_number),(completion_string, chunk_number));;
+WRAPPED_IMPL(CXString,clang_getCompletionAnnotation,(CXCompletionString completion_string, unsigned annotation_number),(completion_string, annotation_number));;
+WRAPPED_IMPL(CXString,clang_getCompletionParent,(CXCompletionString completion_string, enum CXCursorKind *kind),(completion_string, kind));;
+WRAPPED_IMPL(CXString,clang_getCompletionBriefComment,(CXCompletionString completion_string),(completion_string));;
+WRAPPED_IMPL(CXString,clang_getClangVersion,(),());
diff --git a/cbits/wrappers.h b/cbits/wrappers.h
new file mode 100644
--- /dev/null
+++ b/cbits/wrappers.h
@@ -0,0 +1,125 @@
+#include <clang-c/Index.h>
+#include <clang-c/Documentation.h>
+
+// This file contains wrappers around clang_* functions that return
+// bare structs. Since bare structs are not supported by the Haskell
+// FFI these functions
+// 1. call the clang_* function
+// 2. copy the returned struct to the heap
+// 3. hand the caller a pointer to that location.
+
+#define WRAPPED_HEADER(RETURN_TYPE, CLANG_FUNCTION, CLANG_FUNCTION_ARGS) \
+  RETURN_TYPE* wrapped_##CLANG_FUNCTION CLANG_FUNCTION_ARGS
+#define WRAPPED_IMPL(RETURN_TYPE, CLANG_FUNCTION, CLANG_FUNCTION_ARGS, CLANG_FUNCTION_CALL_ARGS) \
+  RETURN_TYPE* wrapped_##CLANG_FUNCTION CLANG_FUNCTION_ARGS \
+  {                                                         \
+    RETURN_TYPE* ret = (void*) malloc(sizeof(RETURN_TYPE)); \
+    *ret = CLANG_FUNCTION CLANG_FUNCTION_CALL_ARGS;         \
+    return ret;                                             \
+  };                                                        \
+
+WRAPPED_HEADER(CXSourceLocation, clang_getNullLocation, (void));
+WRAPPED_HEADER(CXSourceLocation, clang_getLocation, (CXTranslationUnit tu,
+                                                  CXFile file,
+                                                  unsigned line,
+                                                     unsigned column));
+WRAPPED_HEADER(CXSourceLocation, clang_getLocationForOffset, (CXTranslationUnit tu,
+                                                           CXFile file,
+                                                              unsigned offset));
+WRAPPED_HEADER(CXSourceLocation, clang_getRangeStart, (CXSourceRange range));
+WRAPPED_HEADER(CXSourceLocation, clang_getRangeEnd, (CXSourceRange range));
+WRAPPED_HEADER(CXSourceLocation, clang_getDiagnosticLocation, (CXDiagnostic d));
+WRAPPED_HEADER(CXSourceLocation, clang_getCursorLocation, (CXCursor c));
+WRAPPED_HEADER(CXSourceLocation, clang_getTokenLocation, (CXTranslationUnit tu,
+                                                          CXToken token));
+
+WRAPPED_HEADER(CXSourceRange,clang_getNullRange, (void));
+WRAPPED_HEADER(CXSourceRange,clang_getRange,(CXSourceLocation begin,
+                                             CXSourceLocation end));
+WRAPPED_HEADER(CXSourceRange,clang_getDiagnosticRange,(CXDiagnostic Diagnostic,
+                                                      unsigned Range));
+WRAPPED_HEADER(CXSourceRange,clang_getCursorExtent,(CXCursor));
+WRAPPED_HEADER(CXSourceRange,clang_Cursor_getSpellingNameRange,(CXCursor,
+                                                               unsigned pieceIndex,
+                                                               unsigned options));
+WRAPPED_HEADER(CXSourceRange,clang_Cursor_getCommentRange,(CXCursor C));
+WRAPPED_HEADER(CXSourceRange,clang_getCursorReferenceNameRange,(CXCursor C,
+                                                               unsigned NameFlags,
+                                                               unsigned PieceIndex));
+WRAPPED_HEADER(CXSourceRange,clang_getTokenExtent,(CXTranslationUnit, CXToken));
+
+WRAPPED_HEADER(CXCursor,clang_getNullCursor,(void));
+WRAPPED_HEADER(CXCursor,clang_getTranslationUnitCursor,(CXTranslationUnit));
+WRAPPED_HEADER(CXCursor,clang_getCursorSemanticParent,(CXCursor cursor));
+WRAPPED_HEADER(CXCursor,clang_getCursorLexicalParent,(CXCursor cursor));
+WRAPPED_HEADER(CXCursor,clang_getCursor,(CXTranslationUnit, CXSourceLocation));
+WRAPPED_HEADER(CXCursor,clang_Cursor_getArgument,(CXCursor C, unsigned i));
+WRAPPED_HEADER(CXCursor,clang_getTypeDeclaration,(CXType T));
+WRAPPED_HEADER(CXCursor,clang_getOverloadedDecl,(CXCursor cursor,
+                                                unsigned index));
+WRAPPED_HEADER(CXCursor,clang_getCursorReferenced,(CXCursor));
+WRAPPED_HEADER(CXCursor,clang_getCursorDefinition,(CXCursor));
+WRAPPED_HEADER(CXCursor,clang_getCanonicalCursor,(CXCursor));
+WRAPPED_HEADER(CXCursor,clang_getSpecializedCursorTemplate,(CXCursor C));
+
+WRAPPED_HEADER(CXComment,clang_Cursor_getParsedComment,(CXCursor C));
+
+WRAPPED_HEADER(CXType,clang_getCursorType,(CXCursor C));
+WRAPPED_HEADER(CXType,clang_getTypedefDeclUnderlyingType,(CXCursor C));
+WRAPPED_HEADER(CXType,clang_getEnumDeclIntegerType,(CXCursor C));
+WRAPPED_HEADER(CXType,clang_getCanonicalType,(CXType T));
+WRAPPED_HEADER(CXType,clang_getPointeeType,(CXType T));
+WRAPPED_HEADER(CXType,clang_getResultType,(CXType T));
+WRAPPED_HEADER(CXType,clang_getArgType,(CXType T, unsigned i));
+WRAPPED_HEADER(CXType,clang_getCursorResultType,(CXCursor C));
+WRAPPED_HEADER(CXType,clang_getElementType,(CXType T));
+WRAPPED_HEADER(CXType,clang_getArrayElementType,(CXType T));
+WRAPPED_HEADER(CXType,clang_Type_getClassType,(CXType T));
+WRAPPED_HEADER(CXType,clang_getIBOutletCollectionType,(CXCursor));
+WRAPPED_HEADER(CXType,clang_Cursor_getReceiverType,(CXCursor C));
+
+WRAPPED_HEADER(CXString,clang_getFileName,(CXFile SFile));
+WRAPPED_HEADER(CXString,clang_formatDiagnostic,(CXDiagnostic Diagnostic,
+                                               unsigned Options));
+WRAPPED_HEADER(CXString,clang_getDiagnosticSpelling,(CXDiagnostic d));
+WRAPPED_HEADER(CXString,clang_getDiagnosticOption,(CXDiagnostic Diag,
+                                                  CXString *Disable));
+WRAPPED_HEADER(CXString,clang_getDiagnosticCategoryText,(CXDiagnostic d));
+WRAPPED_HEADER(CXString,clang_getDiagnosticFixIt,(CXDiagnostic Diagnostic,
+                                                 unsigned FixIt,
+                                               CXSourceRange *ReplacementRange));
+WRAPPED_HEADER(CXString,clang_getTranslationUnitSpelling,(CXTranslationUnit CTUnit));;
+WRAPPED_HEADER(CXString,clang_getTypeSpelling,(CXType CT));
+WRAPPED_HEADER(CXString,clang_getDeclObjCTypeEncoding,(CXCursor C));
+WRAPPED_HEADER(CXString,clang_getTypeKindSpelling,(enum CXTypeKind K));
+WRAPPED_HEADER(CXString,clang_getCursorUSR,(CXCursor c));
+WRAPPED_HEADER(CXString,clang_constructUSR_ObjCClass,(const char *class_name));
+WRAPPED_HEADER(CXString,clang_constructUSR_ObjCCategory,(const char *class_name,
+                                 const char *category_name));;
+WRAPPED_HEADER(CXString,clang_constructUSR_ObjCProtocol,(const char *protocol_name));;
+WRAPPED_HEADER(CXString,clang_constructUSR_ObjCIvar,(const char *name,
+                                                    CXString classUSR));
+WRAPPED_HEADER(CXString,clang_constructUSR_ObjCMethod,(const char *name,
+                                                      unsigned isInstanceMethod,
+                                                      CXString classUSR));
+WRAPPED_HEADER(CXString,clang_constructUSR_ObjCProperty,(const char *property,
+                                                        CXString classUSR));
+WRAPPED_HEADER(CXString,clang_getCursorSpelling,(CXCursor c));
+WRAPPED_HEADER(CXString,clang_getCursorDisplayName,(CXCursor c));
+WRAPPED_HEADER(CXString,clang_Cursor_getRawCommentText,(CXCursor C));
+WRAPPED_HEADER(CXString,clang_Cursor_getBriefCommentText,(CXCursor C));
+WRAPPED_HEADER(CXString,clang_Module_getName,(CXModule Module));
+WRAPPED_HEADER(CXString,clang_Module_getFullName,(CXModule Module));
+WRAPPED_HEADER(CXString,clang_TextComment_getText,(CXComment Comment));
+WRAPPED_HEADER(CXString,clang_HTMLTagComment_getTagName,(CXComment Comment));
+WRAPPED_HEADER(CXString,clang_VerbatimLineComment_getText,(CXComment Comment));
+WRAPPED_HEADER(CXString,clang_HTMLTagComment_getAsString,(CXComment Comment));
+WRAPPED_HEADER(CXString,clang_FullComment_getAsHTML,(CXComment Comment));
+WRAPPED_HEADER(CXString,clang_FullComment_getAsXML,(CXComment Comment));
+WRAPPED_HEADER(CXString,clang_getTokenSpelling,(CXTranslationUnit tu, CXToken token));
+WRAPPED_HEADER(CXString,clang_getCursorKindSpelling,(enum CXCursorKind Kind));
+WRAPPED_HEADER(CXString,clang_getCompletionChunkText,(CXCompletionString completion_string, unsigned chunk_number));;
+WRAPPED_HEADER(CXString,clang_getCompletionAnnotation,(CXCompletionString completion_string, unsigned annotation_number));;
+WRAPPED_HEADER(CXString,clang_getCompletionParent,(CXCompletionString completion_string, enum CXCursorKind *kind));;
+WRAPPED_HEADER(CXString,clang_getCompletionBriefComment,(CXCompletionString completion_string));;
+WRAPPED_HEADER(CXString,clang_getClangVersion,());
diff --git a/src/Clang.hs b/src/Clang.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang.hs
@@ -0,0 +1,167 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ImpredicativeTypes #-}
+{-# LANGUAGE RankNTypes #-}
+
+-- | LibClang is a Haskell binding to the libclang library, a compiler
+-- front-end for C-family languages. It allows you to produce and walk
+-- an AST, get a list of diagnostic warnings and errors, perform code
+-- completion, and more.
+--
+-- Your starting point for using LibClang should be this module, which
+-- exports the 'ClangT' monad and the functions you'll need to start
+-- analyzing source code. The other modules in this library, such as
+-- "Clang.Cursor" and "Clang.Type", are meant to be imported
+-- qualified, and provide the functions you'll need to get more
+-- detailed information about the AST.
+module Clang (
+-- * Parsing
+  parseSourceFile
+
+-- * Traversing the AST
+, FFI.CursorList
+, getChildren
+, getDescendants
+, getDeclarations
+, getReferences
+, getDeclarationsAndReferences
+
+, FFI.ParentedCursorList
+, getParentedDescendants
+, getParentedDeclarations
+, getParentedReferences
+, getParentedDeclarationsAndReferences
+
+-- * Traversing inclusions
+, FFI.Inclusion(..)
+, FFI.InclusionList
+, getInclusions
+
+-- * The ClangT monad
+, ClangT
+, Clang
+, ClangBase
+, ClangValue(..)
+, ClangValueList(..)
+, clangScope
+
+-- * Clang AST types
+, FFI.AvailabilityKind(..)
+, FFI.CursorKind(..)
+, FFI.LinkageKind(..)
+, FFI.LanguageKind(..)
+, FFI.Cursor
+, FFI.CursorSet
+, FFI.ParentedCursor(..)
+, FFI.ObjCPropertyAttrKind(..)
+, FFI.ObjCDeclQualifierKind(..)
+, FFI.NameRefFlags(..)
+, FFI.Version(..)
+, FFI.PlatformAvailability(..)
+, FFI.PlatformAvailabilityInfo(..)
+, FFI.Diagnostic
+, FFI.DiagnosticSet
+, FFI.File
+, FFI.Remapping
+, FFI.SourceLocation
+, FFI.SourceRange
+, FFI.ClangString
+, FFI.Token
+, FFI.TokenKind(..)
+, FFI.Index
+, FFI.TranslationUnit
+, FFI.UnsavedFile
+, FFI.Module (..)
+, FFI.Type
+, FFI.TypeKind(..)
+, FFI.CallingConv(..)
+, FFI.CXXAccessSpecifier(..)
+, FFI.TypeLayoutError(..)
+, FFI.RefQualifierKind(..)
+) where
+
+import qualified Data.Vector as DV
+
+import qualified Clang.Internal.FFI as FFI
+import qualified Clang.Index as Index
+import Clang.Internal.Monad
+import qualified Clang.TranslationUnit as TU
+
+-- | Parses a source file using libclang and allows you to analyze the
+-- resulting AST using a callback.
+--
+-- More flexible alternatives to 'parseSourceFile' are available in
+-- "Clang.Index" and "Clang.TranslationUnit".
+parseSourceFile :: ClangBase m
+                => FilePath  -- ^ Source filename
+                -> [String]  -- ^ Clang-compatible compilation arguments
+                -> (forall s. FFI.TranslationUnit s -> ClangT s m a)  -- ^ Callback
+                -> m (Maybe a)
+parseSourceFile path args f =
+  Index.withNew False False $ \index ->
+    TU.withParsed index (Just path) args DV.empty [] f
+
+-- | Gets an 'FFI.CursorList' of the children of this 'FFI.Cursor'.
+getChildren :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.CursorList s)
+getChildren = FFI.getChildren
+
+-- | Gets an 'FFI.CursorList' of all descendants of this
+-- 'FFI.Cursor'. If you are planning on visiting all the descendants
+-- anyway, this is often more efficient than calling 'getChildren'
+-- repeatedly. The descendants are listed according to a preorder
+-- traversal of the AST.
+getDescendants :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.CursorList s)
+getDescendants = FFI.getDescendants
+
+-- | Like 'getDescendants', but each descendant is annotated with its
+-- parent AST node. This provides enough information to replicate the
+-- preorder traversal of the AST, but maintains the performance
+-- benefits relative to 'getChildren'.
+getParentedDescendants :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.ParentedCursorList s)
+getParentedDescendants = FFI.getParentedDescendants
+
+-- | Gets an 'FFI.CursorList' of all declarations in this 'FFI.TranslationUnit'.
+getDeclarations :: ClangBase m => FFI.TranslationUnit s' -> ClangT s m (FFI.CursorList s)
+getDeclarations = FFI.getDeclarations
+
+-- | Like 'getDeclarations', but each declaration is annotated with
+-- its parent AST node.
+getParentedDeclarations :: ClangBase m => FFI.TranslationUnit s'
+                        -> ClangT s m (FFI.ParentedCursorList s)
+getParentedDeclarations = FFI.getParentedDeclarations
+
+-- | Gets an 'FFI.CursorList' of all references in this 'FFI.TranslationUnit'.
+getReferences :: ClangBase m => FFI.TranslationUnit s' -> ClangT s m (FFI.CursorList s)
+getReferences = FFI.getReferences
+
+-- | Like 'getReferences', but each reference is annotated with
+-- its parent AST node.
+getParentedReferences :: ClangBase m => FFI.TranslationUnit s'
+                      -> ClangT s m (FFI.ParentedCursorList s)
+getParentedReferences = FFI.getParentedReferences
+
+-- | Gets two 'FFI.CursorList's, one containing all declarations in
+-- this 'FFI.TranslationUnit', and another containing all
+-- references. If you need both lists, this is more efficient than
+-- calling 'getDeclarations' and 'getReferences' individually, as it
+-- only traverses the AST once.
+getDeclarationsAndReferences :: ClangBase m => FFI.TranslationUnit s'
+                             -> ClangT s m (FFI.CursorList s, FFI.CursorList s)
+getDeclarationsAndReferences = FFI.getDeclarationsAndReferences
+
+-- | Like 'getDeclarationsAndReferences', but each reference is annotated with
+-- its parent AST node.
+getParentedDeclarationsAndReferences :: ClangBase m => FFI.TranslationUnit s'
+                                     -> ClangT s m (FFI.ParentedCursorList s,
+                                                    FFI.ParentedCursorList s)
+getParentedDeclarationsAndReferences = FFI.getParentedDeclarationsAndReferences
+
+-- | Gets all inclusions in this 'FFI.TranslationUnit'.
+getInclusions :: ClangBase m => FFI.TranslationUnit s' -> ClangT s m (FFI.InclusionList s)
+getInclusions = FFI.getInclusions
+
+-- | 'Clang' is a specialization of the 'ClangT' monad to 'IO',
+-- provided as a convenience. If you have a more complicated monad
+-- stack, you may find it useful to define your own 'Clang'-like
+-- type synonym.
+type Clang s a = ClangT s IO a
diff --git a/src/Clang/Comment.hs b/src/Clang/Comment.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Comment.hs
@@ -0,0 +1,113 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for traversing the comment AST and analyzing the nodes it contains.
+--
+-- To start traversing the comment AST, use 'Clang.Cursor.getParsedComment' to
+-- retrieve the comment from an AST node that may be associated with one (for
+-- example, any kind of declaration). You can access child nodes in the AST using
+-- 'getChildren'. Most of the important information about comment AST nodes is
+-- contained in the fields of the 'ParsedComment' type.
+--
+-- This module is intended to be imported qualified.
+module Clang.Comment
+(
+-- * Navigating the comment AST
+  getChildren
+
+-- * Predicates and transformations
+, isWhitespace
+, hasTrailingNewline
+, getTagCommentAsString
+, getFullCommentAsHTML
+, getFullCommentAsXML
+
+-- * Comment AST nodes
+, ParsedComment(..)
+, ParamPassDirection(..)
+, FFI.ParamPassDirectionKind (..)
+, FFI.InlineCommandRenderStyle (..)
+) where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.IO.Class
+import Data.Maybe
+
+import Clang.Internal.Comment
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Returns the children nodes of the given comment in the comment AST.
+getChildren :: ClangBase m => ParsedComment s' -> ClangT s m [ParsedComment s]
+getChildren pc = do
+  let c = getFFIComment pc
+  numC <- liftIO $ FFI.comment_getNumChildren c
+  mayCs <- forM [0..(numC - 1)] $ \i ->
+    parseComment =<< liftIO (FFI.comment_getChild mkProxy c i)
+  return $ catMaybes mayCs
+
+-- | Returns 'True' if the provided comment is a 'TextComment' which is empty or contains
+-- only whitespace, or if it is a 'ParagraphComment' which contains only whitespace
+-- 'TextComment' nodes.
+isWhitespace :: ClangBase m => ParsedComment s' -> ClangT s m Bool
+isWhitespace c = liftIO $ FFI.comment_isWhitespace (getFFIComment c)
+
+-- | Returns 'True' if the provided comment is inline content and has a newline immediately
+-- following it in the comment text. Newlines between paragraphs do not count.
+hasTrailingNewline :: ClangBase m => ParsedComment s' -> ClangT s m Bool
+hasTrailingNewline c = liftIO $ FFI.inlineContentComment_hasTrailingNewline (getFFIComment c)
+
+-- | Returns a string representation of an 'HTMLStartTagComment' or 'HTMLEndTagComment'.
+-- For other kinds of comments, returns 'Nothing'.
+getTagCommentAsString :: ClangBase m => ParsedComment s' -> ClangT s m (Maybe (FFI.ClangString s))
+getTagCommentAsString (HTMLStartTagComment c _ _ _) = Just <$> FFI.hTMLTagComment_getAsString c
+getTagCommentAsString (HTMLEndTagComment c _)       = Just <$> FFI.hTMLTagComment_getAsString c
+getTagCommentAsString _                             = return Nothing
+
+-- | Converts the given 'FullComment' to an HTML fragment.
+--
+-- Specific details of HTML layout are subject to change.  Don't try to parse
+-- this HTML back into an AST; use other APIs instead.
+--
+-- Currently the following CSS classes are used:
+--
+-- * \"para-brief\" for \'brief\' paragraph and equivalent commands;
+--
+-- * \"para-returns\" for \'returns\' paragraph and equivalent commands;
+--
+-- * \"word-returns\" for the \"Returns\" word in a \'returns\' paragraph.
+--
+-- Function argument documentation is rendered as a \<dl\> list with arguments
+-- sorted in function prototype order. The following CSS classes are used:
+--
+-- * \"param-name-index-NUMBER\" for parameter name (\<dt\>);
+--
+-- * \"param-descr-index-NUMBER\" for parameter description (\<dd\>);
+--
+-- * \"param-name-index-invalid\" and \"param-descr-index-invalid\" are used if
+--   parameter index is invalid.
+--
+-- Template parameter documentation is rendered as a \<dl\> list with
+-- parameters sorted in template parameter list order. The following CSS classes are used:
+--
+-- * \"tparam-name-index-NUMBER\" for parameter name (\<dt\>);
+--
+-- * \"tparam-descr-index-NUMBER\" for parameter description (\<dd\>);
+--
+-- * \"tparam-name-index-other\" and \"tparam-descr-index-other\" are used for
+--   names inside template template parameters;
+--
+-- * \"tparam-name-index-invalid\" and \"tparam-descr-index-invalid\" are used if
+--   parameter position is invalid.
+getFullCommentAsHTML :: ClangBase m => ParsedComment s' -> ClangT s m (Maybe (FFI.ClangString s))
+getFullCommentAsHTML (FullComment c) = Just <$> FFI.fullComment_getAsHTML c
+getFullCommentAsHTML _               = return Nothing
+
+-- | Converts the given 'FullComment' to an XML document.
+--
+-- A Relax NG schema for the XML is distributed in the \"comment-xml-schema.rng\" file
+-- inside the libclang source tree.
+getFullCommentAsXML :: ClangBase m => ParsedComment s' -> ClangT s m (Maybe (FFI.ClangString s))
+getFullCommentAsXML (FullComment c) = Just <$> FFI.fullComment_getAsXML c
+getFullCommentAsXML _               = return Nothing
diff --git a/src/Clang/Completion.hs b/src/Clang/Completion.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Completion.hs
@@ -0,0 +1,225 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for performing code completion.
+--
+-- To get started with code completion, it's enough to parse a file with
+-- 'Clang.parseSourceFile' and pass the 'FFI.TranslationUnit' to 'codeCompleteAt'.
+-- This will return a 'FFI.CodeCompleteResults' value, from which you can
+-- retrieve a list of completion strings using 'getResults'. Each completion
+-- string in turn consists of a series of chunks, which you can retrieve using
+-- 'getChunks'.
+--
+-- This module is intended to be imported qualified.
+module Clang.Completion
+(
+-- * Code completion
+  codeCompleteAt
+, FFI.CodeCompleteFlags(..)
+, FFI.CodeCompleteResults
+
+-- * Completion results
+, getResults
+, FFI.CompletionString
+, sortResults
+, getDiagnostics
+, getContexts
+, FFI.CompletionContext(..)
+, getContainerKind
+, getContainerUSR
+, getObjCSelector
+
+-- * Completion strings
+, getChunks
+, Chunk(..)
+, FFI.ChunkKind(..)
+, getPriority
+, getAvailability
+, getAnnotations
+, getParent
+, getBriefComment
+) where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.IO.Class
+import Data.Typeable
+import qualified Data.Vector as DV
+
+import Clang.Internal.BitFlags
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Perform code completion at a given location in a translation unit.
+--
+-- This function performs code completion at a particular file, line, and
+-- column within source code, providing results that suggest potential
+-- code snippets based on the context of the completion. The basic model
+-- for code completion is that Clang will parse a complete source file,
+-- performing syntax checking up to the location where code completion has
+-- been requested. At that point, a special code completion token is passed
+-- to the parser, which recognizes this token and determines, based on the
+-- current location in the C \/ Objective-C \/ C++ grammar and the state of
+-- semantic analysis, what completions to provide. These completions are
+-- returned via a 'FFI.CodeCompleteResults' value.
+--
+-- Code completion itself is meant to be triggered by the client when the
+-- user types punctuation characters or whitespace, at which point the
+-- code completion location will coincide with the cursor. For example, if \'p\'
+-- is a pointer, code completion might be triggered after the \'-\' and then
+-- after the \'>\' in \'p->\'. When the code completion location is after the \'>\',
+-- the completion results will provide, e.g., the members of the struct that
+-- \'p\' points to. The client is responsible for placing the cursor at the
+-- beginning of the token currently being typed, then filtering the results
+-- based on the contents of the token. For example, when code-completing for
+-- the expression \'p->get\', the client should provide the location just after
+-- the \'>\' (e.g., pointing at the \'g\') to this code completion hook. Then, the
+-- client can filter the results based on the current token text (\'get\'), only
+-- showing those results that start with \'get\'. The intent of this interface
+-- is to separate the relatively high-latency acquisition of code completion
+-- results from the filtering of results on a per-character basis, which must
+-- have a lower latency.
+codeCompleteAt ::
+      ClangBase m
+   => FFI.TranslationUnit s'  -- ^ The translation unit in which code completion should occur.
+                              -- The source files for this translation unit need not be
+                              -- completely up-to-date (and the contents of those source files
+                              -- may be overridden via the 'FFI.UnsavedFile' vector). Cursors
+                              -- referring into the translation unit may be invalidated by
+                              -- this invocation.
+  -> FilePath  -- ^ The name of the source file where code
+               -- completion should be performed. This filename may be any file
+               -- included in the translation unit.
+  -> Int  -- ^ The line at which code completion should occur.
+  -> Int  -- ^ The column at which code completion should occur.
+          -- Note that the column should point just after the syntactic construct that
+          -- initiated code completion, and not in the middle of a lexical token.
+  -> DV.Vector FFI.UnsavedFile  -- ^ Files that have not yet been saved to disk
+                                -- but may be required for parsing or code completion, including
+                                -- the contents of those files.  The contents and name of these
+                                -- files (as specified by 'FFI.UnsavedFile') are copied when
+                                -- necessary, so the client only needs to guarantee their
+                                -- validity until the call to this function returns.
+  -> Maybe [FFI.CodeCompleteFlags]  -- ^ Extra options that control the behavior of code
+                                    -- completion, or 'Nothing' to use the default set.
+  -> ClangT s m (FFI.CodeCompleteResults s)
+codeCompleteAt t fname l c ufs mayOpts = do
+  opts <- case mayOpts of
+    Just os -> return os
+    Nothing -> unFlags <$> liftIO FFI.defaultCodeCompleteOptions
+  FFI.codeCompleteAt t fname l c ufs (orFlags opts)
+
+-- | Retrieves a list of code completion results.
+--
+-- The first element of each tuple is the completion string, which describes how to insert
+-- this result into the editing buffer. Use 'getChunks' to analyze it further.
+--
+-- The second element of each tuple is the kind of entity that this completion refers to.
+-- It will be a macro, keyword, or declaration describing the entity that the completion
+-- is referring to.
+getResults :: ClangBase m => FFI.CodeCompleteResults s'
+           -> ClangT s m [(FFI.CompletionString s, FFI.CursorKind)]
+getResults rs = do
+  numS <- liftIO $ FFI.codeCompleteGetNumResults rs
+  forM [0..(numS - 1)] $ \i ->
+    FFI.codeCompleteGetResult rs i
+
+-- | Sort the provided code completion results in case-insensitive alphabetical order.
+sortResults :: ClangBase m => FFI.CodeCompleteResults s' -> ClangT s m ()
+sortResults c = liftIO $ FFI.sortCodeCompletionResults c
+
+-- | Retrieves the diagnostics associated with the given code completion.
+getDiagnostics :: ClangBase m => FFI.CodeCompleteResults s' -> ClangT s m [FFI.Diagnostic s]
+getDiagnostics c = do
+  numD <- liftIO $ FFI.codeCompleteGetNumDiagnostics c
+  mapM (FFI.codeCompleteGetDiagnostic c) [0..(numD - 1)]
+
+-- | Determines which kinds of completions are appropriate for the context
+-- of the given code completion.
+getContexts :: ClangBase m => FFI.CodeCompleteResults s' -> ClangT s m [FFI.CompletionContext]
+getContexts rs = unFlags <$> liftIO (FFI.codeCompleteGetContexts rs)
+
+-- | Returns a cursor kind for the container associated with the given code
+-- completion. Only contexts like member accesses and Objective-C message sends
+-- have containers; for other kinds of contexts, a cursor kind of
+-- 'FFI.InvalidCodeCursor' is returned.
+--
+-- The second element of the result tuple is a boolean indicating whether libclang
+-- has incomplete information about the container. A 'True' value indicates that
+-- information about the container is incomplete.
+getContainerKind :: ClangBase m => FFI.CodeCompleteResults s'
+                 -> ClangT s m (FFI.CursorKind, Bool)
+getContainerKind rs = liftIO $ FFI.codeCompleteGetContainerKind rs
+
+-- | Given a code completion context, returns a "Clang.USR" for the appropriate
+-- container. Only contexts like member accesses and Objective-C message sends
+-- have containers; for other kinds of contexts, the empty string is returned.
+getContainerUSR :: ClangBase m => FFI.CodeCompleteResults s' -> ClangT s m (FFI.ClangString s)
+getContainerUSR = FFI.codeCompleteGetContainerUSR
+
+-- | Returns the currently-entered selector for an Objective-C message
+-- send, formatted like \"initWithFoo:bar:\". This function is only guaranteed
+-- to return a non-empty string if the completion context is an Objective-C
+-- instance message or class message send, which you can check with 'getContexts'.
+getObjCSelector :: ClangBase m => FFI.CodeCompleteResults s' -> ClangT s m (FFI.ClangString s)
+getObjCSelector = FFI.codeCompleteGetObjCSelector
+
+-- | The completion string is a template that describes not only the completion itself,
+-- but also information about how it should be presented to the user. It is divided into
+-- a list of chunks, with each kind of chunk playing a different role in the template.
+data Chunk s
+  = TextChunk FFI.ChunkKind (FFI.ClangString s)
+  | OptionalChunk (FFI.CompletionString s)
+    deriving (Eq, Ord, Typeable)
+
+-- | Retrieves the chunks within a completion string.
+--
+-- Each \"chunk\" contains either a piece of text with a specific \"kind\"
+-- that describes how that text should be interpreted by the client, or
+-- another completion string.
+getChunks :: ClangBase m => FFI.CompletionString s' -> ClangT s m [Chunk s]
+getChunks cs = do
+  numC <- liftIO $ FFI.getNumCompletionChunks cs
+  forM [0..(numC - 1)] $ \i -> do
+    kind <- liftIO $ FFI.getCompletionChunkKind cs i
+    case kind of
+      FFI.OptionalChunkKind ->
+        OptionalChunk <$> (liftIO $ FFI.getCompletionChunkCompletionString cs i)
+      _ ->
+        TextChunk kind <$> FFI.getCompletionChunkText cs i
+
+-- | Determines the priority of this code completion string.
+--
+-- The priority of a code completion indicates how likely it is that this
+-- particular completion is the completion that the user will select. The
+-- priority is selected by various internal heuristics. Smaller values
+-- indicate more likely completions.
+getPriority :: ClangBase m => FFI.CompletionString s' -> ClangT s m Int
+getPriority cs = liftIO $ FFI.getCompletionPriority cs
+
+-- | Determines the availability of the entity that this code completion
+-- string refers to.
+getAvailability :: ClangBase m => FFI.CompletionString s' -> ClangT s m FFI.AvailabilityKind
+getAvailability cs = liftIO $ FFI.getCompletionAvailability cs
+
+-- | Retrieves the annotations associated with the given completion string.
+getAnnotations :: ClangBase m => FFI.CompletionString s' -> ClangT s m [FFI.ClangString s]
+getAnnotations cs = do
+  numA <- liftIO $ FFI.getCompletionNumAnnotations cs
+  mapM (FFI.getCompletionAnnotation cs) [0..(numA - 1)]
+
+-- | Retrieves the parent context of the given completion string.
+--
+-- The parent context of a completion string is the semantic parent of
+-- the declaration (if any) that the code completion represents. For example,
+-- a code completion for an Objective-C method would have the method's class
+-- or protocol as its context. A completion string representing a method on
+-- the NSObject class might have a parent context of \"NSObject\".
+getParent :: ClangBase m => FFI.CompletionString s' -> ClangT s m (FFI.ClangString s)
+getParent = FFI.getCompletionParent
+
+-- | Retrieves the brief documentation comment attached to the declaration
+-- that corresponds to the given completion string.
+getBriefComment :: ClangBase m => FFI.CompletionString s' -> ClangT s m (FFI.ClangString s)
+getBriefComment = FFI.getCompletionBriefComment
diff --git a/src/Clang/Cursor.hs b/src/Clang/Cursor.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Cursor.hs
@@ -0,0 +1,329 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+{-|
+  The Cursor is an easy way to reference something in code and query its properties and relationships
+  This is the primary way of traversing and querying code
+-}
+module Clang.Cursor
+( isNullCursor
+, nullCursor
+, getHash
+, getKind
+, getLinkage
+, getAvailability
+, getLanguage
+, getTranslationUnit
+, getSemanticParent
+, getLexicalParent
+, getOverriddenCursors
+, getIncludedFile
+, getLocation
+, getSpellingLocation
+, getExtent
+, getType
+, getResultType
+, getDeclObjCTypeEncoding
+, getSpelling
+, getSpellingNameRange
+, getDisplayName
+, getReferenced
+, getDefinition
+, getCanonicalCursor
+, getObjCSelectorIndex
+, getReceiverType
+, getObjCPropertyAttributes
+, getObjCDeclQualifiers
+, isObjCOptional
+, isVariadic
+, getTemplateKind
+, getTemplateForSpecialization
+, getReferenceNameRange
+, getTypeDeclaration
+, getNumArguments
+, getArgument
+, getUSR
+
+-- attribute function
+, getIBOutletCollectionType
+
+, isDefinition
+, isDeclaration
+, isReference
+, isExpression
+, isStatement
+, isAttribute
+, isInvalid
+, isTranslationUnit
+, isPreprocessing
+, isUnexposed
+, isBitField
+, isVirtualBase
+, isPureVirtualCppMethod
+, isStaticCppMethod
+, isVirtualCppMethod
+, isDynamicCall
+, getCommentRange
+, getRawCommentText
+, getBriefCommentText
+, getParsedComment
+, getModule
+, getCXXAccessSpecifier
+, getOverloadedDecls
+
+-- CursorSet functions
+, createSet
+, setContains
+, setInsert
+
+-- CursorKind functions
+, getCursorKindSpelling
+
+-- Platform availability
+, getCursorPlatformAvailability
+
+, getCompletionString
+) where
+
+import Control.Applicative
+import Control.Monad.IO.Class
+import GHC.Word
+
+import Clang.Internal.BitFlags
+import Clang.Internal.Comment
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+isNullCursor :: FFI.Cursor s -> Bool
+isNullCursor = FFI.cursor_isNull
+{-# INLINE isNullCursor #-}
+
+nullCursor :: ClangBase m => ClangT s m (FFI.Cursor s)
+nullCursor = FFI.getNullCursor
+{-# INLINE nullCursor #-}
+
+getHash :: ClangBase m => FFI.Cursor s' -> ClangT s m GHC.Word.Word32
+getHash c = liftIO $ FFI.hashCursor c
+
+getKind :: FFI.Cursor s -> FFI.CursorKind
+getKind = FFI.getCursorKind
+{-# INLINE getKind #-}
+
+getLinkage :: ClangBase m => FFI.Cursor s' -> ClangT s m FFI.LinkageKind
+getLinkage c = liftIO $ FFI.getCursorLinkage c
+
+getAvailability  :: ClangBase m => FFI.Cursor s' -> ClangT s m FFI.AvailabilityKind
+getAvailability c = liftIO $ FFI.getCursorAvailability c
+
+getLanguage :: ClangBase m => FFI.Cursor s' -> ClangT s m FFI.LanguageKind
+getLanguage c = liftIO $ FFI.getCursorLanguage c
+
+getTranslationUnit :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.TranslationUnit s)
+getTranslationUnit = FFI.cursor_getTranslationUnit
+
+getSemanticParent :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Cursor s)
+getSemanticParent c = liftIO $ FFI.getCursorSemanticParent mkProxy c
+
+getLexicalParent :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Cursor s)
+getLexicalParent c = liftIO $ FFI.getCursorLexicalParent mkProxy c
+
+getOverriddenCursors :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.CursorList s)
+getOverriddenCursors = FFI.getOverriddenCursors
+
+getIncludedFile :: ClangBase m => FFI.Cursor s' -> ClangT s m (Maybe (FFI.File s))
+getIncludedFile c = liftIO $ FFI.getIncludedFile mkProxy c
+
+getLocation :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.SourceLocation s)
+getLocation c = liftIO $ FFI.getCursorLocation mkProxy c
+
+getSpellingLocation :: ClangBase m => FFI.Cursor s'
+                    -> ClangT s m (Maybe (FFI.File s), Int, Int, Int)
+getSpellingLocation l = liftIO $ FFI.getCursorSpellingLocation mkProxy l
+
+getExtent :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.SourceRange s)
+getExtent c = liftIO $ FFI.getCursorExtent mkProxy c
+
+getType :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Type s)
+getType c = liftIO $ FFI.getCursorType mkProxy c
+
+getResultType :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Type s)
+getResultType c = liftIO $ FFI.getCursorResultType mkProxy c
+
+getDeclObjCTypeEncoding :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.ClangString s)
+getDeclObjCTypeEncoding = FFI.getDeclObjCTypeEncoding
+
+getSpelling :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.ClangString s)
+getSpelling = FFI.getCursorSpelling
+
+getSpellingNameRange :: ClangBase m => FFI.Cursor s' -> Int -> ClangT s m (FFI.SourceRange s)
+getSpellingNameRange c idx = liftIO $ FFI.cursor_getSpellingNameRange mkProxy c idx
+
+getDisplayName :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.ClangString s)
+getDisplayName = FFI.getCursorDisplayName
+
+getReferenced :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Cursor s)
+getReferenced c = liftIO $ FFI.getCursorReferenced mkProxy c
+
+getDefinition :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Cursor s)
+getDefinition c = liftIO $ FFI.getCursorDefinition mkProxy c
+
+getCanonicalCursor :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Cursor s)
+getCanonicalCursor c = liftIO $ FFI.getCanonicalCursor mkProxy c
+
+getObjCSelectorIndex :: ClangBase m => FFI.Cursor s' -> ClangT s m Int
+getObjCSelectorIndex c = liftIO $ FFI.cursor_getObjCSelectorIndex c
+
+getReceiverType :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Type s)
+getReceiverType c = liftIO $ FFI.cursor_getReceiverType mkProxy c
+
+getObjCPropertyAttributes :: ClangBase m => FFI.Cursor s'
+                          -> ClangT s m [FFI.ObjCPropertyAttrKind]
+getObjCPropertyAttributes c = unFlags <$> liftIO (FFI.cursor_getObjCPropertyAttributes c)
+
+getObjCDeclQualifiers :: ClangBase m => FFI.Cursor s' -> ClangT s m [FFI.ObjCDeclQualifierKind]
+getObjCDeclQualifiers c = unFlags <$> liftIO (FFI.cursor_getObjCDeclQualifiers c)
+
+isObjCOptional :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isObjCOptional c = liftIO $ FFI.cursor_isObjCOptional c
+
+isVariadic :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isVariadic c = liftIO $ FFI.cursor_isVariadic c
+
+getTemplateKind :: ClangBase m => FFI.Cursor s' -> ClangT s m FFI.CursorKind
+getTemplateKind c = liftIO $ FFI.getTemplateCursorKind c
+
+getTemplateForSpecialization :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Cursor s)
+getTemplateForSpecialization c = liftIO $ FFI.getSpecializedCursorTemplate mkProxy c
+
+getReferenceNameRange :: ClangBase m => FFI.Cursor s' -> [FFI.NameRefFlags] -> Int
+                      -> ClangT s m (FFI.SourceRange s)
+getReferenceNameRange c fs p = liftIO $ FFI.getCursorReferenceNameRange mkProxy c (orFlags fs) p
+
+getTypeDeclaration :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Cursor s)
+getTypeDeclaration t = liftIO $ FFI.getTypeDeclaration mkProxy t
+
+getNumArguments :: ClangBase m => FFI.Cursor s' -> ClangT s m Int
+getNumArguments c = liftIO $ FFI.cursor_getNumArguments c
+
+getArgument :: ClangBase m => FFI.Cursor s' -> Int -> ClangT s m (FFI.Cursor s)
+getArgument c i = liftIO $ FFI.cursor_getArgument mkProxy c i
+
+getUSR :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.ClangString s)
+getUSR = FFI.getCursorUSR
+
+-- attribute function
+
+getIBOutletCollectionType :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Type s)
+getIBOutletCollectionType c = liftIO $ FFI.getIBOutletCollectionType mkProxy c
+
+isDefinition :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isDefinition c = liftIO $ FFI.isCursorDefinition c
+
+isDeclaration :: FFI.CursorKind -> Bool
+isDeclaration = FFI.isDeclaration
+{-# INLINE isDeclaration #-}
+
+isReference :: FFI.CursorKind -> Bool
+isReference = FFI.isReference
+{-# INLINE isReference #-}
+
+isExpression :: FFI.CursorKind -> Bool
+isExpression = FFI.isExpression
+{-# INLINE isExpression #-}
+
+isStatement :: FFI.CursorKind -> Bool
+isStatement = FFI.isStatement
+{-# INLINE isStatement #-}
+
+isAttribute :: FFI.CursorKind -> Bool
+isAttribute = FFI.isAttribute
+{-# INLINE isAttribute #-}
+
+isInvalid :: FFI.CursorKind -> Bool
+isInvalid = FFI.isInvalid
+{-# INLINE isInvalid #-}
+
+isTranslationUnit :: FFI.CursorKind -> Bool
+isTranslationUnit = FFI.isTranslationUnit
+{-# INLINE isTranslationUnit #-}
+
+isPreprocessing :: FFI.CursorKind -> Bool
+isPreprocessing = FFI.isPreprocessing
+{-# INLINE isPreprocessing #-}
+
+isUnexposed :: FFI.CursorKind -> Bool
+isUnexposed = FFI.isUnexposed
+{-# INLINE isUnexposed #-}
+
+isBitField :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isBitField c = liftIO $ FFI.isBitField c
+
+isVirtualBase :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isVirtualBase c = liftIO $ FFI.isVirtualBase c
+
+isPureVirtualCppMethod :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isPureVirtualCppMethod c = liftIO $ FFI.cXXMethod_isPureVirtual c
+
+isStaticCppMethod :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isStaticCppMethod c = liftIO $ FFI.cXXMethod_isStatic c
+
+isVirtualCppMethod :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isVirtualCppMethod c = liftIO $ FFI.cXXMethod_isVirtual c
+
+isDynamicCall :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isDynamicCall c = liftIO $ FFI.cursor_isDynamicCall c
+
+getCommentRange :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.SourceRange s)
+getCommentRange c = liftIO $ FFI.cursor_getCommentRange mkProxy c
+
+getRawCommentText :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.ClangString s)
+getRawCommentText = FFI.cursor_getRawCommentText
+
+getBriefCommentText :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.ClangString s)
+getBriefCommentText = FFI.cursor_getBriefCommentText
+
+getParsedComment :: ClangBase m => FFI.Cursor s' -> ClangT s m (Maybe (ParsedComment s))
+getParsedComment c = do
+  comment <- liftIO $ FFI.cursor_getParsedComment mkProxy c
+  parseComment comment
+
+getModule :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Module s)
+getModule c = liftIO $ FFI.cursor_getModule mkProxy c
+
+getCXXAccessSpecifier :: ClangBase m => FFI.Cursor s' -> ClangT s m FFI.CXXAccessSpecifier
+getCXXAccessSpecifier c = liftIO $ FFI.getCXXAccessSpecifier c
+
+getOverloadedDecls :: ClangBase m => FFI.Cursor s' -> ClangT s m [FFI.Cursor s]
+getOverloadedDecls c = liftIO $ do
+  numDecls <- FFI.getNumOverloadedDecls c
+  mapM (FFI.getOverloadedDecl mkProxy c) [0..(numDecls - 1)]
+
+-- CursorSet functions
+
+createSet :: ClangBase m => ClangT s m (FFI.CursorSet s)
+createSet = FFI.createCXCursorSet
+
+setContains :: ClangBase m => FFI.CursorSet s' -> FFI.Cursor s'' -> ClangT s m Bool
+setContains s c = liftIO $ FFI.cXCursorSet_contains s c
+
+setInsert :: ClangBase m => FFI.CursorSet s' -> FFI.Cursor s'' -> ClangT s m Bool
+setInsert s c = liftIO $ FFI.cXCursorSet_insert s c
+
+
+-- CursorKind functions
+
+getCursorKindSpelling :: ClangBase m => FFI.CursorKind -> ClangT s m (FFI.ClangString s)
+getCursorKindSpelling = FFI.getCursorKindSpelling
+
+-- Platform availability
+
+getCursorPlatformAvailability :: ClangBase m => FFI.Cursor s'
+                              -> ClangT s m (FFI.PlatformAvailabilityInfo s)
+getCursorPlatformAvailability = FFI.getCursorPlatformAvailability
+
+-- | Retrieve a completion string for an arbitrary declaration or macro
+-- definition cursor.
+--
+-- Completion strings can be manipulated using the functions in "Clang.Completion".
+getCompletionString :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.CompletionString s)
+getCompletionString = FFI.getCursorCompletionString
diff --git a/src/Clang/Debug.hs b/src/Clang/Debug.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Debug.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | This module contains debug-related functionality.
+module Clang.Debug
+( setCrashRecoveryEnabled
+, enableStackTraces
+) where
+
+import Control.Monad.IO.Class
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Enable or disable crash recovery.
+setCrashRecoveryEnabled :: ClangBase m
+                        => Bool -- ^ Whether crash recovery should be enabled.
+                        -> ClangT s m ()
+setCrashRecoveryEnabled enable = liftIO $ FFI.toggleCrashRecovery enable
+
+-- | Enable stack traces when crashes occur.
+enableStackTraces :: ClangBase m => ClangT s m ()
+enableStackTraces = liftIO FFI.enableStackTraces
diff --git a/src/Clang/Diagnostic.hs b/src/Clang/Diagnostic.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Diagnostic.hs
@@ -0,0 +1,151 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for manipulating 'FFI.Diagnostic's, which represent
+-- diagnostics - warnings, errors, and the like - produced by libclang.
+--
+-- 'FFI.Diagnostic's are grouped into 'FFI.DiagnosticSet's. You
+-- usually obtain a 'FFI.DiagnosticSet' from a 'FFI.TranslationUnit'
+-- using 'Clang.TranslationUnit.getDiagnosticSet', and then analyze it
+-- using the functions in this module.
+--
+-- This module is intended to be imported qualified.
+module Clang.Diagnostic
+(
+-- * Diagnostic sets
+  getElements
+
+-- * Diagnostics
+, getChildren
+, getSeverity
+, FFI.Severity(..)
+, getSpelling
+, getOptions
+, getCategoryName
+, getCategoryId
+, getRanges
+, getFixIts
+
+-- * Rendering diagnostics
+, format
+, FFI.DisplayOptions(..)
+
+-- * Deserializing diagnostics
+, load
+, FFI.LoadError(..)
+) where
+
+import Control.Monad.IO.Class
+
+import Clang.Internal.BitFlags
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+
+-- | Retrieve the diagnostics contained in the given 'FFI.DiagnosticSet'.
+--
+-- You can obtain a 'FFI.DiagnosticSet' from a 'FFI.TranslationUnit'
+-- using 'Clang.TranslationUnit.getDiagnosticSet', or by deserializing
+-- it from a file using 'load'.
+getElements :: ClangBase m => FFI.DiagnosticSet s' -> ClangT s m [FFI.Diagnostic s]
+getElements ds = do
+  numDiags <- liftIO $ FFI.getNumDiagnosticsInSet ds
+  mapM (FFI.getDiagnosticInSet ds) [0..(numDiags - 1)]
+
+-- | Get the child diagnostics of the given diagnostic.
+getChildren :: ClangBase m => FFI.Diagnostic s' -> ClangT s m (FFI.DiagnosticSet s)
+getChildren = FFI.getChildDiagnostics
+
+-- | Determine the severity of the given diagnostic.
+getSeverity :: ClangBase m => FFI.Diagnostic s' -> ClangT s m FFI.Severity
+getSeverity d = liftIO $ FFI.getDiagnosticSeverity d
+
+-- | Retrieve the text of the given diagnostic.
+getSpelling :: ClangBase m => FFI.Diagnostic s' -> ClangT s m (FFI.ClangString s)
+getSpelling = FFI.getDiagnosticSpelling
+
+-- | Retrieve the name of the command-line option that enabled this diagnostic.
+getOptions :: ClangBase m
+           => FFI.Diagnostic s'  -- ^ The diagnostic in question.
+           -> ClangT s m (FFI.ClangString s, FFI.ClangString s)  -- ^ The options controlling
+                                                                 --   this diagnostic. The
+                                                                 --   first member of the pair
+                                                                 --   is the option to enable
+                                                                 --   this diagnostic. The
+                                                                 --   second member is the
+                                                                 --   option to disable it.
+getOptions = FFI.getDiagnosticOption
+
+-- | Get the name of the diagnostic category for the given diagnostic.
+--
+-- Diagnostics are categorized into groups along with other,
+-- related diagnostics (e.g., diagnostics under the same warning
+-- flag).
+getCategoryName :: ClangBase m => FFI.Diagnostic s' -> ClangT s m (FFI.ClangString s)
+getCategoryName = FFI.getDiagnosticCategoryText
+
+-- | Retrieve the category id for this diagnostic.
+--
+-- For display to the user, use 'getCategoryName'.
+getCategoryId :: ClangBase m => FFI.Diagnostic s' -> ClangT s m Int
+getCategoryId d = liftIO $ FFI.getDiagnosticCategory d
+
+-- | Retrieve the source ranges associated with this diagnostic.
+--
+-- A diagnostic's source ranges highlight important elements in the
+-- source code. On the command line, Clang displays source ranges by
+-- underlining them with '~' characters.
+getRanges :: ClangBase m => FFI.Diagnostic s' -> ClangT s m [FFI.SourceRange s]
+getRanges d = liftIO $ do
+                numRanges <- FFI.getDiagnosticNumRanges d
+                mapM (FFI.getDiagnosticRange d) [0..(numRanges - 1)]
+
+-- | Retrieve the fix-it hints associated with the given diagnostic.
+--
+-- Fix-its are described in terms of a source range whose contents
+-- should be replaced by a string. This approach generalizes over
+-- three kinds of operations: removal of source code (the range covers
+-- the code to be removed and the replacement string is empty),
+-- replacement of source code (the range covers the code to be
+-- replaced and the replacement string provides the new code), and
+-- insertion (both the start and end of the range point at the
+-- insertion location, and the replacement string provides the text to
+-- insert).
+getFixIts :: ClangBase m
+          => FFI.Diagnostic s'  -- ^ The diagnostic in question.
+          -> ClangT s m [(FFI.SourceRange s, FFI.ClangString s)]  -- ^ A list of replacement
+                                                                  --   ranges and strings. Note
+                                                                  --   that source ranges are
+                                                                  --   half-open ranges '[a, b)'
+                                                                  --   so the source code should
+                                                                  --   be replaced from 'a' up
+                                                                  --   to (but not including)
+                                                                  --   'b'.
+getFixIts d = do
+  numFixes <- liftIO $ FFI.getDiagnosticNumFixIts d
+  mapM (FFI.getDiagnosticFixIt d) [0..(numFixes - 1)]
+
+-- | Format the given diagnostic in a manner that is suitable for
+-- display.
+format :: ClangBase m
+       => Maybe [FFI.DisplayOptions]     -- ^ An optional list of options
+                                         --   for rendering the diagnostic.
+                                         --   If 'Nothing' is given, default
+                                         --   options are used that mimic the
+                                         --   behavior of the Clang compiler
+                                         --   as closely as possible.
+       -> FFI.Diagnostic s'              -- ^ The diagnostic to format.
+       -> ClangT s m (FFI.ClangString s) -- ^ A formatted rendering of the
+                                         --   given diagnostic.
+format Nothing diag     = FFI.formatDiagnostic diag =<<
+                          liftIO FFI.defaultDiagnosticDisplayOptions
+format (Just opts) diag = FFI.formatDiagnostic diag (orFlags opts)
+
+-- | Deserialize a set of diagnostics from a Clang diagnostics bitcode file.
+--
+-- If an error is encountered, a 'FFI.LoadError' and a textual error
+-- message suitable for display to the user are returned.
+load :: ClangBase m
+     => FilePath
+     -> ClangT s m (Either (FFI.LoadError, FFI.ClangString s) (FFI.DiagnosticSet s))
+load = FFI.loadDiagnostics
diff --git a/src/Clang/File.hs b/src/Clang/File.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/File.hs
@@ -0,0 +1,60 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for manipulating 'FFI.File's, which represent
+-- references to files in the libclang AST.
+--
+-- This module is intended to be imported qualified.
+module Clang.File
+(
+-- * Creating files
+  createFromPath
+
+-- * File properties
+, getName
+, isMultipleIncludeGuarded
+, getMTime
+, getPosixMTime
+
+-- * Unique IDs
+, getUniqueId
+, FFI.UniqueId
+) where
+
+import Control.Applicative
+import Control.Monad.IO.Class
+import Data.Time.Clock.POSIX (POSIXTime, posixSecondsToUTCTime)
+import Data.Time.Clock (UTCTime)
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Create a new 'FFI.File' value from the provided path.
+createFromPath :: ClangBase m => FFI.TranslationUnit s' -> FilePath -> ClangT s m (FFI.File s)
+createFromPath t f = liftIO $ FFI.getFile mkProxy t f
+
+-- | Retrieve the filename of the given file.
+getName :: ClangBase m => FFI.File s' -> ClangT s m (FFI.ClangString s)
+getName = FFI.getFileName
+
+-- | Determines whether the given file is guarded against multiple
+-- inclusions, either with the conventional '#ifdef' / '#define' / '#endif'
+-- macro guards or with '#pragma once'.
+isMultipleIncludeGuarded :: ClangBase m => FFI.TranslationUnit s' -> FFI.File s''
+                         -> ClangT s m Bool
+isMultipleIncludeGuarded t f = liftIO $ FFI.isFileMultipleIncludeGuarded t f
+
+-- | Returns the last modification time of the given file, represented
+-- as a 'UTCTime'.
+getMTime :: ClangBase m => FFI.File s' -> ClangT s m UTCTime
+getMTime f = liftIO $ posixSecondsToUTCTime . realToFrac <$> FFI.getFileTime f
+
+-- | Returns the last modification time of the given file, represented
+-- as a 'POSIXTime'.
+getPosixMTime :: ClangBase m => FFI.File s' -> ClangT s m POSIXTime
+getPosixMTime f = liftIO $ realToFrac <$> FFI.getFileTime f
+
+-- | Retrieves a unique ID for the given file. If no unique ID can be
+-- generated, returns 'Nothing'.
+getUniqueId :: ClangBase m => FFI.File s' -> ClangT s m (Maybe FFI.UniqueId)
+getUniqueId f = liftIO $ FFI.getFileUniqueID f
diff --git a/src/Clang/Index.hs b/src/Clang/Index.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Index.hs
@@ -0,0 +1,45 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes #-}
+
+-- | Functions for manipulating indexes.
+--
+-- An index is a container that holds a set of translation units. Generally
+-- you'll create an index using 'withNew' and then use that index with functions
+-- from "Clang.TranslationUnit" to create and work with translation units.
+--
+-- This module is intended to be imported qualified.
+module Clang.Index
+(
+-- * Creating an index
+  withNew
+
+-- * Index options
+, getGlobalOptions
+, setGlobalOptions
+, FFI.GlobalIndexOptions(..)
+, FFI.threadBackgroundPriorityForAll
+) where
+
+import Control.Applicative
+import Control.Monad.IO.Class
+
+import Clang.Internal.BitFlags
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Creates an index.
+withNew :: ClangBase m
+        => Bool  -- ^ Whether to exclude declarations coming from pre-compiled headers.
+        -> Bool  -- ^ Whether to automatically display diagnostic messages.
+        -> (forall s. FFI.Index s -> ClangT s m a)  -- ^ The function which will use the index.
+        -> m a
+withNew i1 i2 f = runClangT (FFI.createIndex i1 i2 >>= f)
+
+-- | Retrieves the global options for this index.
+getGlobalOptions :: ClangBase m => FFI.Index s' -> ClangT s m [FFI.GlobalIndexOptions]
+getGlobalOptions i = unFlags <$> liftIO (FFI.cXIndex_getGlobalOptions i)
+
+-- | Sets the global options for this index.
+setGlobalOptions :: ClangBase m => FFI.Index s' -> [FFI.GlobalIndexOptions] -> ClangT s m ()
+setGlobalOptions i opts = liftIO $ FFI.cXIndex_setGlobalOptions i (orFlags opts)
diff --git a/src/Clang/Internal/BitFlags.hs b/src/Clang/Internal/BitFlags.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Internal/BitFlags.hs
@@ -0,0 +1,33 @@
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module Clang.Internal.BitFlags
+( BitFlags (..)
+, orFlags
+, andFlags
+, unFlags
+) where
+
+import Data.Bits
+import Data.List
+
+class (Bits (FlagInt a), Num (FlagInt a)) => BitFlags a where
+  type FlagInt a :: *
+  type FlagInt a = Int
+
+  toBit :: a -> FlagInt a
+
+orFlags :: BitFlags a => [a] -> FlagInt a
+orFlags [] = 0
+orFlags fs = foldl1' (.|.) $ map toBit fs
+
+andFlags :: BitFlags a => [a] -> FlagInt a
+andFlags [] = 0
+andFlags fs = foldl1' (.&.) $ map toBit fs
+
+unFlags :: forall a. (BitFlags a, Bounded a, Enum a) => FlagInt a -> [a]
+unFlags v = filter (checkFlag v) allFlags
+  where
+    checkFlag i f = (i .&. toBit f) /= 0
+    allFlags = enumFrom (minBound :: a)
diff --git a/src/Clang/Internal/Comment.hs b/src/Clang/Internal/Comment.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Internal/Comment.hs
@@ -0,0 +1,189 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+module Clang.Internal.Comment
+( ParsedComment(..)
+, ParamPassDirection(..)
+, parseComment
+, getFFIComment
+) where
+
+import Control.Applicative
+import Control.Monad
+import Control.Monad.IO.Class
+import Data.Typeable
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | A node in the comment AST.
+--
+-- Every constructor contains an opaque 'FFI.Comment' value, which represents the AST node
+-- itself. The other fields are the user-visible metadata for that node type.
+data ParsedComment s
+  -- | Plain text. Inline content.
+  = TextComment (FFI.Comment s) (FFI.ClangString s)
+
+  -- | A command with word-like arguments that is considered inline content.
+  | InlineCommandComment (FFI.Comment s) (FFI.ClangString s) FFI.InlineCommandRenderStyle [FFI.ClangString s]
+
+  -- | An HTML start tag with attributes (represented as name/value pairs). Considered inline content.
+  -- The final argument of the constructor is 'True' if the tag is self-closing.
+  | HTMLStartTagComment (FFI.Comment s) (FFI.ClangString s) [(FFI.ClangString s, FFI.ClangString s)] Bool
+
+  -- | An HTML end tag. Considered inline content.
+  | HTMLEndTagComment (FFI.Comment s) (FFI.ClangString s)
+
+  -- | A paragraph, which contains inline content. The paragraph itself is block content.
+  | ParagraphComment (FFI.Comment s)
+
+  -- | A command which has zero or more word-like arguments and a paragraph argument. Block content.
+  -- The paragraph argument (of type 'ParsedComment') is also a child of the 'BlockCommandComment'.
+  --
+  -- As an example, a \'\\brief\' comment creates a 'BlockCommandComment' AST node with no word-like
+  -- arguments and a paragraph argument.
+  | BlockCommandComment (FFI.Comment s) (FFI.ClangString s) [FFI.ClangString s] (Maybe (ParsedComment s))
+
+  -- | A \'\\param\' or \'\\arg\' command that describes a function parameter. The parameter name,
+  -- index in the parameter list (or 'Nothing' if the index is invalid), and parameter passing
+  -- direction are provided as constructor fields. The description is provided as a child node.
+  | ParamCommandComment (FFI.Comment s) (FFI.ClangString s) (Maybe Int) ParamPassDirection
+
+
+  -- | A \'\\tparam\' command that describes a template parameter. The parameter name and position
+  -- are provided as constructor fields, while the description is provided as a child node.
+  --
+  -- Since template parameters can be nested, the position is a list with a left-to-right position
+  -- at each nesting depth. For example, for the following declaration:
+  --
+  -- > template<typename C, template<typename T> class TT>
+  -- > void test(TT<int> aaa);
+  --
+  -- The resulting position would be [0] for \'C\', [1] for \'TT\', and [1, 0] for \'T\'.
+  | TypeParamCommandComment (FFI.Comment s) (FFI.ClangString s) (Maybe [Int])
+
+  -- | A verbatim block command (e.g. preformatted code). A verbatim block has an opening
+  -- and a closing command and contains multiple lines of text, represented as
+  -- 'VerbatimBlockLineComment' nodes.
+  | VerbatimBlockCommandComment (FFI.Comment s) (Maybe (ParsedComment s))
+
+  -- | A line of text that is contained within a 'VerbatimBlockCommandComment' node.
+  | VerbatimBlockLineComment (FFI.Comment s) (FFI.ClangString s)
+
+  -- | A verbatim line command. A verbatim line has an opening command, a single line
+  -- of text (up to the newline after the opening command), and has no closing command.
+  | VerbatimLineComment (FFI.Comment s) (FFI.ClangString s)
+
+  -- | A full comment attached to a declaration. Contains block content.
+  | FullComment (FFI.Comment s)
+    deriving (Eq, Ord, Typeable)
+
+-- | A parameter passing direction, either explicitly provided in the comment text or
+-- inferred.
+data ParamPassDirection
+  = ExplicitParamPassDirection FFI.ParamPassDirectionKind
+  | InferredParamPassDirection FFI.ParamPassDirectionKind
+    deriving (Eq, Ord, Read, Show, Typeable)
+
+parseComment :: ClangBase m => FFI.Comment s -> ClangT s m (Maybe (ParsedComment s))
+parseComment c = do
+  kind <- liftIO $ FFI.comment_getKind c
+  case kind of
+    FFI.NullComment                 -> pure Nothing
+    FFI.TextComment                 -> Just . TextComment c <$> FFI.textComment_getText c
+    FFI.InlineCommandComment        -> do v <- InlineCommandComment c <$> FFI.inlineCommandComment_getCommandName c
+                                                                     <*> inlineCommandComment_getRenderKind c
+                                                                     <*> inlineCommandComment_getArgs c
+                                          return $ Just v
+    FFI.HTMLStartTagComment         -> do v <- HTMLStartTagComment c <$> FFI.hTMLTagComment_getTagName c
+                                                                     <*> htmlStartTagComment_getAttrs c
+                                                                     <*> htmlStartTagComment_isSelfClosing c
+                                          return $ Just v
+    FFI.HTMLEndTagComment           -> Just . HTMLEndTagComment c <$> FFI.hTMLTagComment_getTagName c
+    FFI.ParagraphComment            -> pure $ Just (ParagraphComment c)
+    FFI.BlockCommandComment         -> do v <- BlockCommandComment c <$> FFI.blockCommandComment_getCommandName c
+                                                                     <*> blockCommandComment_getArgs c
+                                                                     <*> blockCommandComment_getParagraph c
+                                          return $ Just v
+    FFI.ParamCommandComment         -> do v <- ParamCommandComment c <$> FFI.paramCommandComment_getParamName c
+                                                                     <*> paramCommandComment_getParamIndex c
+                                                                     <*> paramCommandComment_getDirection c
+                                          return $ Just v
+    FFI.TParamCommandComment        -> do v <- TypeParamCommandComment c
+                                                 <$> FFI.tParamCommandComment_getParamName c
+                                                 <*> tParamCommandComment_getPosition c
+                                          return $ Just v
+    FFI.VerbatimBlockCommandComment -> Just . VerbatimBlockCommandComment c <$> blockCommandComment_getParagraph c
+    FFI.VerbatimBlockLineComment    -> Just . VerbatimBlockLineComment c <$> FFI.verbatimBlockLineComment_getText c
+    FFI.VerbatimLineComment         -> Just . VerbatimLineComment c <$> FFI.verbatimLineComment_getText c
+    FFI.FullComment                 -> pure $ Just (FullComment c)
+
+getFFIComment :: ParsedComment s ->  FFI.Comment s
+getFFIComment (TextComment c _) = c
+getFFIComment (InlineCommandComment c _ _ _) = c
+getFFIComment (HTMLStartTagComment c _ _ _) = c
+getFFIComment (HTMLEndTagComment c _) = c
+getFFIComment (ParagraphComment c) = c
+getFFIComment (BlockCommandComment c _ _ _) = c
+getFFIComment (ParamCommandComment c _ _ _) = c
+getFFIComment (TypeParamCommandComment c _ _) = c
+getFFIComment (VerbatimBlockCommandComment c _) = c
+getFFIComment (VerbatimBlockLineComment c _) = c
+getFFIComment (VerbatimLineComment c _) = c
+getFFIComment (FullComment c) = c
+
+inlineCommandComment_getRenderKind :: ClangBase m => FFI.Comment s'
+                                   -> ClangT s m FFI.InlineCommandRenderStyle
+inlineCommandComment_getRenderKind c = liftIO $ FFI.inlineCommandComment_getRenderKind c
+
+inlineCommandComment_getArgs :: ClangBase m => FFI.Comment s' -> ClangT s m [FFI.ClangString s]
+inlineCommandComment_getArgs c = do
+  numArgs <- liftIO $ FFI.inlineCommandComment_getNumArgs c
+  mapM (FFI.inlineCommandComment_getArgText c) [0..(numArgs - 1)]
+
+htmlStartTagComment_getAttrs :: ClangBase m => FFI.Comment s'
+                             -> ClangT s m [(FFI.ClangString s, FFI.ClangString s)]
+htmlStartTagComment_getAttrs c = do
+  numAttrs <- liftIO $ FFI.hTMLStartTag_getNumAttrs c
+  forM [0..numAttrs] $ \attr -> do
+    attrName <- FFI.hTMLStartTag_getAttrName c attr
+    attrValue <- FFI.hTMLStartTag_getAttrValue c attr
+    return (attrName, attrValue)
+
+htmlStartTagComment_isSelfClosing :: ClangBase m => FFI.Comment s' -> ClangT s m Bool
+htmlStartTagComment_isSelfClosing c = liftIO $ FFI.hTMLStartTagComment_isSelfClosing c
+
+blockCommandComment_getArgs :: ClangBase m => FFI.Comment s' -> ClangT s m [FFI.ClangString s]
+blockCommandComment_getArgs c = do
+  numArgs <- liftIO $ FFI.blockCommandComment_getNumArgs c
+  mapM (FFI.blockCommandComment_getArgText c) [0..(numArgs - 1)]
+
+blockCommandComment_getParagraph :: ClangBase m => FFI.Comment s' -> ClangT s m (Maybe (ParsedComment s))
+blockCommandComment_getParagraph c =
+  parseComment =<< liftIO (FFI.blockCommandComment_getParagraph mkProxy c)
+
+paramCommandComment_getParamIndex :: ClangBase m => FFI.Comment s' -> ClangT s m (Maybe Int)
+paramCommandComment_getParamIndex c = do
+  valid <- liftIO $ FFI.paramCommandComment_isParamIndexValid c
+  if valid
+    then Just <$> (liftIO $ FFI.paramCommandComment_getParamIndex c)
+    else return Nothing
+
+paramCommandComment_getDirection :: ClangBase m => FFI.Comment s' -> ClangT s m ParamPassDirection
+paramCommandComment_getDirection c = do
+  dir <- liftIO $ FFI.paramCommandComment_getDirection c
+  explicit <- liftIO $ FFI.paramCommandComment_isDirectionExplicit c
+  return $ if explicit
+             then ExplicitParamPassDirection dir
+             else InferredParamPassDirection dir
+
+tParamCommandComment_getPosition :: ClangBase m => FFI.Comment s' -> ClangT s m (Maybe [Int])
+tParamCommandComment_getPosition c = do
+  valid <- liftIO $ FFI.tParamCommandComment_isParamPositionValid c
+  if valid
+     then do depth <- liftIO $ FFI.tParamCommandComment_getDepth c
+             indices <- forM [0..depth] $ \d ->
+                          liftIO $ FFI.tParamCommandComment_getIndex c d
+             return $ Just indices
+     else return Nothing
diff --git a/src/Clang/Internal/FFI.chs b/src/Clang/Internal/FFI.chs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Internal/FFI.chs
@@ -0,0 +1,5068 @@
+{-# OPTIONS_GHC -fno-warn-unused-binds -fno-warn-unused-matches #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE ForeignFunctionInterface #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TupleSections #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE CPP #-}
+
+module Clang.Internal.FFI
+( versionMajor
+, versionMinor
+, encodedVersion
+, Index
+, createIndex
+, GlobalIndexOptions(..)
+, threadBackgroundPriorityForAll
+, cXIndex_setGlobalOptions
+, cXIndex_getGlobalOptions
+, TranslationUnit
+, UnsavedFile
+, unsavedFilename
+, unsavedContents
+, newUnsavedFile
+, updateUnsavedContents
+, AvailabilityKind(..)
+, Version(..)
+, ClangString
+, getString
+, getByteString
+, unsafeGetByteString
+, File(..)
+, getFileName
+, getFileTime
+, UniqueId(..)
+, getFileUniqueID
+, isFileMultipleIncludeGuarded
+, getFile
+, SourceLocation
+, getNullLocation
+, equalLocations
+, getLocation
+, getLocationForOffset
+, location_isInSystemHeader
+, location_isFromMainFile
+, SourceRange
+, getNullRange
+, getRange
+, equalRanges
+, range_isNull
+, getExpansionLocation
+, getPresumedLocation
+, getSpellingLocation
+, getFileLocation
+, getRangeStart
+, getRangeEnd
+, Severity(..)
+, Diagnostic
+, DiagnosticSet
+, getNumDiagnosticsInSet
+, getDiagnosticInSet
+, LoadError(..)
+, loadDiagnostics
+, getChildDiagnostics
+, getNumDiagnostics
+, getDiagnostic
+, getDiagnosticSetFromTU
+, DisplayOptions(..)
+, formatDiagnostic
+, defaultDiagnosticDisplayOptions
+, getDiagnosticSeverity
+, getDiagnosticLocation
+, getDiagnosticSpelling
+, getDiagnosticOption
+, getDiagnosticCategory
+, getDiagnosticCategoryText
+, getDiagnosticNumRanges
+, getDiagnosticRange
+, getDiagnosticNumFixIts
+, getDiagnosticFixIt
+, getTranslationUnitSpelling
+, createTranslationUnitFromSourceFile
+, createTranslationUnit
+, TranslationUnitFlags(..)
+, defaultEditingTranslationUnitOptions
+, parseTranslationUnit
+, SaveTranslationUnitFlags(..)
+, defaultSaveOptions
+, saveTranslationUnit
+, ReparseFlags(..)
+, defaultReparseOptions
+, reparseTranslationUnit
+, CursorKind(..)
+, firstDeclCursor
+, lastDeclCursor
+, firstRefCursor
+, lastRefCursor
+, firstInvalidCursor
+, lastInvalidCursor
+, firstExprCursor
+, lastExprCursor
+, firstStmtCursor
+, lastStmtCursor
+, firstAttrCursor
+, lastAttrCursor
+, firstPreprocessingCursor
+, lastPreprocessingCursor
+, firstExtraDeclCursor
+, lastExtraDeclCursor
+, gccAsmStmtCursor
+, macroInstantiationCursor
+, Comment(..)
+, Cursor
+, getNullCursor
+, getTranslationUnitCursor
+, cursor_isNull
+, hashCursor
+, getCursorKind
+, isDeclaration
+, isReference
+, isExpression
+, isStatement
+, isAttribute
+, isInvalid
+, isTranslationUnit
+, isPreprocessing
+, isUnexposed
+, LinkageKind(..)
+, getCursorLinkage
+, getCursorAvailability
+, PlatformAvailability(..)
+, PlatformAvailabilityInfo(..)
+, getCursorPlatformAvailability
+, LanguageKind(..)
+, getCursorLanguage
+, cursor_getTranslationUnit
+, CursorSet
+, createCXCursorSet
+, cXCursorSet_contains
+, cXCursorSet_insert
+, getCursorSemanticParent
+, getCursorLexicalParent
+, getOverriddenCursors
+, getIncludedFile
+, getCursor
+, getCursorLocation
+, getCursorSpellingLocation
+, getCursorExtent
+, TypeKind(..)
+, type_FirstBuiltin
+, type_LastBuiltin
+, CallingConv(..)
+, Type
+, getTypeKind
+, getCursorType
+, getTypeSpelling
+, getTypedefDeclUnderlyingType
+, getEnumDeclIntegerType
+, getEnumConstantDeclValue
+, getEnumConstantDeclUnsignedValue
+, getFieldDeclBitWidth
+, cursor_getNumArguments
+, cursor_getArgument
+, equalTypes
+, getCanonicalType
+, isConstQualifiedType
+, isVolatileQualifiedType
+, isRestrictQualifiedType
+, getPointeeType
+, getTypeDeclaration
+, getDeclObjCTypeEncoding
+, getTypeKindSpelling
+, getFunctionTypeCallingConv
+, getResultType
+, getNumArgTypes
+, getArgType
+, isFunctionTypeVariadic
+, getCursorResultType
+, isPODType
+, getElementType
+, getNumElements
+, getArrayElementType
+, getArraySize
+, TypeLayoutError(..)
+, type_getAlignOf
+, type_getClassType
+, type_getSizeOf
+, type_getOffsetOf
+, RefQualifierKind(..)
+, type_getCXXRefQualifier
+, isBitField
+, isVirtualBase
+, CXXAccessSpecifier(..)
+, getCXXAccessSpecifier
+, getNumOverloadedDecls
+, getOverloadedDecl
+, getIBOutletCollectionType
+, CursorList
+, getChildren
+, getDescendants
+, getDeclarations
+, getReferences
+, getDeclarationsAndReferences
+, ParentedCursor(..)
+, ParentedCursorList
+, getParentedDescendants
+, getParentedDeclarations
+, getParentedReferences
+, getParentedDeclarationsAndReferences
+, getCursorUSR
+, constructUSR_ObjCClass
+, constructUSR_ObjCCategory
+, constructUSR_ObjCProtocol
+, constructUSR_ObjCIvar
+, constructUSR_ObjCMethod
+, constructUSR_ObjCProperty
+, getCursorSpelling
+, cursor_getSpellingNameRange
+, getCursorDisplayName
+, getCursorReferenced
+, getCursorDefinition
+, isCursorDefinition
+, cursor_isDynamicCall
+, getCanonicalCursor
+, cursor_getObjCSelectorIndex
+, cursor_getReceiverType
+, ObjCPropertyAttrKind(..)
+, cursor_getObjCPropertyAttributes
+, ObjCDeclQualifierKind(..)
+, cursor_getObjCDeclQualifiers
+, cursor_isObjCOptional
+, cursor_isVariadic
+, cursor_getCommentRange
+, cursor_getRawCommentText
+, cursor_getBriefCommentText
+, cursor_getParsedComment
+, Module(..)
+, cursor_getModule
+, module_getASTFile
+, module_getParent
+, module_getName
+, module_getFullName
+, module_getNumTopLevelHeaders
+, module_getTopLevelHeader
+, cXXMethod_isPureVirtual
+, cXXMethod_isStatic
+, cXXMethod_isVirtual
+, getTemplateCursorKind
+, getSpecializedCursorTemplate
+, getCursorReferenceNameRange
+, NameRefFlags(..)
+, CommentKind(..)
+, InlineCommandRenderStyle(..)
+, ParamPassDirectionKind(..)
+, comment_getKind
+, comment_getNumChildren
+, comment_getChild
+, comment_isWhitespace
+, inlineContentComment_hasTrailingNewline
+, textComment_getText
+, inlineCommandComment_getCommandName
+, inlineCommandComment_getRenderKind
+, inlineCommandComment_getNumArgs
+, inlineCommandComment_getArgText
+, hTMLTagComment_getTagName
+, hTMLStartTagComment_isSelfClosing
+, hTMLStartTag_getNumAttrs
+, hTMLStartTag_getAttrName
+, hTMLStartTag_getAttrValue
+, blockCommandComment_getCommandName
+, blockCommandComment_getNumArgs
+, blockCommandComment_getArgText
+, blockCommandComment_getParagraph
+, paramCommandComment_getParamName
+, paramCommandComment_isParamIndexValid
+, paramCommandComment_getParamIndex
+, paramCommandComment_isDirectionExplicit
+, paramCommandComment_getDirection
+, tParamCommandComment_getParamName
+, tParamCommandComment_isParamPositionValid
+, tParamCommandComment_getDepth
+, tParamCommandComment_getIndex
+, verbatimBlockLineComment_getText
+, verbatimLineComment_getText
+, hTMLTagComment_getAsString
+, fullComment_getAsHTML
+, fullComment_getAsXML
+, TokenKind(..)
+, Token
+, TokenList
+, getTokenKind
+, getTokenSpelling
+, getTokenLocation
+, getTokenExtent
+, tokenize
+, annotateTokens
+, getCursorKindSpelling
+, enableStackTraces
+, CompletionString
+, CompletionResult
+, ChunkKind(..)
+, getCompletionChunkKind
+, getCompletionChunkText
+, getCompletionChunkCompletionString
+, getNumCompletionChunks
+, getCompletionPriority
+, getCompletionAvailability
+, getCompletionNumAnnotations
+, getCompletionAnnotation
+, getCompletionParent
+, getCompletionBriefComment
+, getCursorCompletionString
+, CodeCompleteFlags(..)
+, defaultCodeCompleteOptions
+, CodeCompleteResults
+, codeCompleteAt
+, codeCompleteGetNumResults
+, codeCompleteGetResult
+, sortCodeCompletionResults
+, codeCompleteGetNumDiagnostics
+, codeCompleteGetDiagnostic
+, CompletionContext(..)
+, codeCompleteGetContexts
+, codeCompleteGetContainerKind
+, codeCompleteGetContainerUSR
+, codeCompleteGetObjCSelector
+, getClangVersion
+, toggleCrashRecovery
+, Inclusion(..)
+, InclusionList
+, getInclusions
+, Remapping
+, getRemappings
+, getRemappingsFromFileList
+, remap_getNumFiles
+, remap_getFilenames
+) where
+
+import Control.Applicative
+import Control.Monad (forM_)
+import Control.Monad.Trans
+import qualified Data.ByteString as B
+import qualified Data.ByteString.Unsafe as BU
+import Data.Hashable
+import Data.Typeable (Typeable)
+import qualified Data.Vector as DV
+import qualified Data.Vector.Storable as DVS
+import qualified Data.Vector.Storable.Mutable as DVSM
+import Data.Word
+import Foreign.C
+import Foreign
+import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
+import Unsafe.Coerce (unsafeCoerce)  -- With GHC 7.8 we can use the safer 'coerce'.
+import System.IO.Unsafe(unsafePerformIO)
+
+import Clang.Internal.BitFlags
+import Clang.Internal.FFIConstants
+import Clang.Internal.Monad
+
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <clang-c/Index.h>
+#include <stdio.h>
+#include "utils.h"
+#include "visitors.h"
+#include "wrappers.h"
+
+{-
+LibClang uses two strategies to create safe, deterministic
+bindings.
+
+First, all types that either represent resources managed on the C side
+(for example, TranslationUnit and ClangString) or contain pointers into
+those resources (for example, Cursor) are tagged with an ST-like
+universally quantified phantom type parameter. This prevents them from
+being used outside of the scope in which they were allocated. This is
+particularly important for libclang, which uses an arena allocator to
+store much of its data; preventing resources from leaking outside
+their proper scope is critical to making this safe.
+
+Second, all operations that allocate a resource that later
+needs to be freed are wrapped in a type-specific 'register'
+function. An example is registerClangString. This function registers a
+cleanup action with the underlying ClangT monad, which is essentially
+just ResourceT in disguise. This not only provides safety, but it also
+enforces prompt finalization of resources which can significantly
+increase performance by keeping the working set of user programs down.
+
+There are a few different patterns for the FFI code, depending on what
+kind of value the libclang function we want to wrap returns.
+
+If it returns a pure value (say an Int), then we don't need to do
+anything special. The greencard-generated function will have a return
+type of IO Int, and the user-facing wrapper function will use liftIO
+to call it.
+
+If it returns a value that doesn't represent a newly allocated
+resource, but does need the phantom type parameter (because it
+contains a pointer into some other resource, generally), then we
+generally pass a Proxy value with a type parameter that we'll use to
+tag the return type. This has no runtime cost. The user-facing wrapper
+function still needs to call liftIO.
+
+For values that DO represent a newly allocated resource, we need to
+call the appropriate 'register' function. This function will return a
+value in the ClangT monad, so user-facing wrapper functions don't need
+to use liftIO or Proxy in this case. It's the convention to use '()' for the
+phantom type parameter returned from the greencard-generated function,
+and allow the 'register' function to coerce the value to the correct
+type. This way we can distinguish values that need to be registered
+from other values: if a value's phantom type parameter is '()', it
+needs to be registered, and it won't typecheck as the return value of
+a user-facing wrapper function.
+
+It's important to keep in mind that it should be legal to use values
+from enclosing scopes in an inner scope created by clangScope. In
+practice, this means that the phantom type parameters used by each
+argument to a function should be distinct, and they should all be
+distinct from the phantom type parameter used in the return value.
+Of course, this doesn't apply to the Proxy parameter, which must
+always have the same phantom type parameter as the return value.
+-}
+
+-- Marshalling utility functions.
+fromCInt :: Num b => CInt -> b
+fromCInt = fromIntegral
+
+toCInt :: Integral a => a -> CInt
+toCInt = fromIntegral
+
+-- Version information.
+versionMajor :: Int
+versionMajor   = {# const CINDEX_VERSION_MAJOR #}
+versionMinor :: Int
+versionMinor   = {# const CINDEX_VERSION_MINOR #}
+encodedVersion :: Int
+encodedVersion = {# const CINDEX_VERSION #}
+
+-- typedef void *CXIndex;
+newtype Index s = Index { unIndex :: Ptr () }
+                  deriving (Eq, Ord, Typeable)
+
+instance ClangValue Index
+
+mkIndex :: Ptr () -> Index ()
+mkIndex = Index
+
+-- CXIndex clang_createIndex(int excludeDeclarationsFromPCH, int displayDiagnostics);
+{# fun clang_createIndex { `CInt', `CInt' } -> `Ptr ()' #}
+unsafe_createIndex :: Bool -> Bool -> IO (Index ())
+unsafe_createIndex a b = clang_createIndex (fromBool a) (fromBool b) >>= return . mkIndex
+
+createIndex :: ClangBase m => Bool -> Bool -> ClangT s m (Index s)
+createIndex = (registerIndex .) . unsafe_createIndex
+
+
+-- void clang_disposeIndex(CXIndex index);
+{# fun clang_disposeIndex { `Ptr ()' } -> `()' #}
+disposeIndex :: Index s -> IO ()
+disposeIndex index = clang_disposeIndex (unIndex index)
+
+registerIndex :: ClangBase m => IO (Index ()) -> ClangT s m (Index s)
+registerIndex action = do
+  (_, idx) <- clangAllocate (action >>= return . unsafeCoerce)
+                            (\i -> disposeIndex i)
+  return idx
+{-# INLINEABLE registerIndex #-}
+
+-- typedef enum {
+--   CXGlobalOpt_None = 0x0,
+--   CXGlobalOpt_ThreadBackgroundPriorityForIndexing = 0x1,
+--   CXGlobalOpt_ThreadBackgroundPriorityForEditing = 0x2,
+--   CXGlobalOpt_ThreadBackgroundPriorityForAll =
+--       CXGlobalOpt_ThreadBackgroundPriorityForIndexing |
+--       CXGlobalOpt_ThreadBackgroundPriorityForEditing
+--
+-- } CXGlobalOptFlags;
+
+-- | Options that apply globally to every translation unit within an index.
+#c
+enum GlobalIndexOptions
+   { DefaultGlobalIndexOptions = CXGlobalOpt_None
+   , ThreadBackgroundPriorityForIndexing = CXGlobalOpt_ThreadBackgroundPriorityForIndexing
+   , ThreadBackgroundPriorityForEditing = CXGlobalOpt_ThreadBackgroundPriorityForEditing
+   };
+#endc
+{# enum GlobalIndexOptions{} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags GlobalIndexOptions where
+  toBit DefaultGlobalIndexOptions           = 0x0
+  toBit ThreadBackgroundPriorityForIndexing = 0x1
+  toBit ThreadBackgroundPriorityForEditing  = 0x2
+
+-- | A set of global index options that requests background priority for all threads.
+threadBackgroundPriorityForAll :: [GlobalIndexOptions]
+threadBackgroundPriorityForAll = [ThreadBackgroundPriorityForEditing,
+                                  ThreadBackgroundPriorityForIndexing]
+
+-- void clang_CXIndex_setGlobalOptions(CXIndex, unsigned options);
+{# fun clang_CXIndex_setGlobalOptions { `Ptr ()', `Int' } -> `()' #}
+cXIndex_setGlobalOptions :: Index s -> Int -> IO ()
+cXIndex_setGlobalOptions index options = clang_CXIndex_setGlobalOptions (unIndex index) options
+
+-- unsigned clang_CXIndex_getGlobalOptions(CXIndex);
+{# fun clang_CXIndex_getGlobalOptions { `Ptr ()' } -> `Int' #}
+cXIndex_getGlobalOptions :: Index s -> IO Int
+cXIndex_getGlobalOptions index = clang_CXIndex_getGlobalOptions (unIndex index)
+
+-- typedef struct CXTranslationUnitImpl *CXTranslationUnit;
+newtype TranslationUnit s = TranslationUnit { unTranslationUnit :: (Ptr ()) }
+                            deriving (Eq, Ord, Typeable)
+
+instance ClangValue TranslationUnit
+
+mkTranslationUnit :: Ptr () -> TranslationUnit ()
+mkTranslationUnit = TranslationUnit
+
+-- void clang_disposeTranslationUnit(CXTranslationUnit);
+{# fun clang_disposeTranslationUnit { `Ptr ()' } -> `()' #}
+disposeTranslationUnit :: TranslationUnit s -> IO ()
+disposeTranslationUnit t = clang_disposeTranslationUnit (unTranslationUnit t)
+
+registerTranslationUnit :: ClangBase m => IO (TranslationUnit ())
+                        -> ClangT s m (TranslationUnit s)
+registerTranslationUnit action = do
+  (_, tu) <- clangAllocate (action >>= return . unsafeCoerce)
+                           (\t -> disposeTranslationUnit t)
+  return tu
+{-# INLINEABLE registerTranslationUnit #-}
+
+-- struct CXUnsavedFile {
+--   const char* Filename;
+--   const char* Contents;
+--   unsigned long Length;
+-- };
+
+-- | A representation of an unsaved file and its contents.
+data UnsavedFile = UnsavedFile
+  { _unsavedFilename :: !B.ByteString
+  , _unsavedContents :: !B.ByteString
+  } deriving (Eq, Show, Typeable)
+
+-- We maintain the invariant that _unsavedFilename is always
+-- null-terminated. That's why we don't directly expose the record fields.
+unsavedFilename :: UnsavedFile -> B.ByteString
+unsavedFilename = _unsavedFilename
+
+unsavedContents :: UnsavedFile -> B.ByteString
+unsavedContents = _unsavedContents
+
+newUnsavedFile :: B.ByteString -> B.ByteString -> UnsavedFile
+newUnsavedFile f c = UnsavedFile (nullTerminate f) c
+
+updateUnsavedContents :: UnsavedFile -> B.ByteString -> UnsavedFile
+updateUnsavedContents uf c = UnsavedFile (unsavedFilename uf) c
+
+-- TODO: Use BU.unsafeLast when we can use newer B.ByteString.
+nullTerminate :: B.ByteString -> B.ByteString
+nullTerminate bs
+  | B.null bs      = B.singleton 0
+  | B.last bs == 0 = bs
+  | otherwise      = B.snoc bs 0
+
+-- Functions which take a Vector UnsavedFile argument are implemented
+-- internally in terms of this function, which temporarily allocates a
+-- Vector CUnsavedFile holding the same data. (But does not copy the
+-- string data itself.)
+withUnsavedFiles :: DV.Vector UnsavedFile -> (Ptr CUnsavedFile -> Int -> IO a) -> IO a
+withUnsavedFiles ufs f =
+  withCUnsavedFiles ufs $ \cufs ->
+    DVS.unsafeWith cufs $ \ptr ->
+      f ptr (DVS.length cufs)
+
+data CUnsavedFile = CUnsavedFile
+  { cUnsavedFilename    :: CString
+  , cUnsavedContents    :: CString
+  , cUnsavedContentsLen :: CULong
+  }
+
+instance Storable CUnsavedFile where
+    sizeOf _ = sizeOfCXUnsavedFile
+    {-# INLINE sizeOf #-}
+
+    alignment _ = alignOfCXUnsavedFile
+    {-# INLINE alignment #-}
+
+    peek p = do
+      filename    <- peekByteOff p offsetCXUnsavedFileFilename
+      contents    <- peekByteOff p offsetCXUnsavedFileContents
+      contentsLen <- peekByteOff p offsetCXUnsavedFileContentsLen
+      return $! CUnsavedFile filename contents contentsLen
+    {-# INLINE peek #-}
+
+    poke p (CUnsavedFile filename contents contentsLen) = do
+      pokeByteOff p offsetCXUnsavedFileFilename filename
+      pokeByteOff p offsetCXUnsavedFileContents contents
+      pokeByteOff p offsetCXUnsavedFileContentsLen contentsLen
+    {-# INLINE poke #-}
+
+
+withCUnsavedFiles :: DV.Vector UnsavedFile -> (DVS.Vector CUnsavedFile -> IO a) -> IO a
+withCUnsavedFiles ufs f = do
+    let len = DV.length ufs
+    v <- DVSM.new len
+    go v 0 len
+  where
+    go v i len
+      | i == len  = f =<< DVS.unsafeFreeze v
+      | otherwise = do let uf = DV.unsafeIndex ufs i
+                           ufFilename = unsavedFilename uf
+                           ufContents = unsavedContents uf
+                       BU.unsafeUseAsCString ufFilename $ \cufFilename ->
+                         BU.unsafeUseAsCString ufContents $ \cufContents -> do
+                           let contentsLen = fromIntegral $ B.length ufContents
+                               cuf = CUnsavedFile cufFilename cufContents contentsLen
+                           DVSM.write v i cuf
+                           go v (i + 1) len
+
+#c
+enum AvailabilityKind {
+  Availability_Available = CXAvailability_Available,
+  Availability_Deprecated = CXAvailability_Deprecated,
+  Availability_NotAvailable = CXAvailability_NotAvailable,
+  Availability_NotAccessible = CXAvailability_NotAccessible
+};
+#endc
+{# enum AvailabilityKind{} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+data Version = Version
+  { majorVersion    :: !Int
+  , minorVersion    :: !Int
+  , subminorVersion :: !Int
+  } deriving (Eq, Ord, Show, Typeable)
+
+instance Storable Version where
+  sizeOf _ = sizeOfCXVersion
+  {-# INLINE sizeOf #-}
+
+  alignment _ = alignOfCXVersion
+  {-# INLINE alignment #-}
+
+  peek p = do
+    major <- fromCInt <$> peekByteOff p offsetCXVersionMajor
+    minor <- fromCInt <$> peekByteOff p offsetCXVersionMinor
+    subminor <- fromCInt <$> peekByteOff p offsetCXVersionSubminor
+    return $! Version major minor subminor
+  {-# INLINE peek #-}
+
+  poke p (Version major minor subminor) = do
+    pokeByteOff p offsetCXVersionMajor major
+    pokeByteOff p offsetCXVersionMinor minor
+    pokeByteOff p offsetCXVersionSubminor subminor
+  {-# INLINE poke #-}
+
+-- typedef struct {
+--   const void *data;
+--   unsigned private_flags;
+-- } CXString;
+data ClangString s = ClangString !(Ptr ()) !Word32
+                     deriving (Eq, Ord, Typeable)
+
+instance ClangValue ClangString
+
+instance Storable (ClangString s) where
+  sizeOf _ = {# sizeof CXString #} -- sizeOfCXString
+  {-# INLINE sizeOf #-}
+
+  alignment _ = {# alignof CXString #} -- alignOfCXString
+  {-# INLINE alignment #-}
+
+  peek p = do
+    strData <- {#get CXString->data #} p
+    strFlags <- {#get CXString->private_flags #} p
+    return $! ClangString strData (fromIntegral strFlags)
+  {-# INLINE peek #-}
+
+  poke p (ClangString d f) = do
+    {#set CXString->data #} p d
+    {#set CXString->private_flags #} p (fromIntegral f)
+  {-# INLINE poke #-}
+
+instance Hashable (ClangString s) where
+  hashWithSalt salt (ClangString p f) = (`hashWithSalt` f)
+                                      . (`hashWithSalt` pInt)
+                                      $ salt
+    where
+      pInt = (fromIntegral $ ptrToWordPtr p) :: Int
+
+registerClangString :: ClangBase m => IO (ClangString ()) -> ClangT s m (ClangString s)
+registerClangString action = do
+  (_, str) <- clangAllocate (action >>= return . unsafeCoerce)
+                            (\(ClangString d f) -> freeClangString d f)
+  return str
+{-# INLINEABLE registerClangString #-}
+
+{#fun freeClangString { id `Ptr ()', `Word32' } -> `()' #}
+
+unmarshall_clangString :: Ptr () -> Word32 -> IO (ClangString ())
+unmarshall_clangString d f = return $ ClangString d f
+
+getString :: ClangBase m => ClangString s' -> ClangT s m String
+getString (ClangString d f) = liftIO $ getCStringPtr d f >>= peekCString
+
+getByteString :: ClangBase m => ClangString s' -> ClangT s m B.ByteString
+getByteString (ClangString d f) = liftIO $ getCStringPtr d f >>= B.packCString
+
+unsafeGetByteString :: ClangBase m => ClangString s' -> ClangT s m B.ByteString
+unsafeGetByteString (ClangString d f) = liftIO $ getCStringPtr d f >>= BU.unsafePackCString
+
+-- const char *clang_getCString(ClangString string);
+{# fun clang_getCString {withVoided* %`ClangString a' } -> `CString' id #}
+getCStringPtr :: Ptr () -> Word32 -> IO CString
+getCStringPtr d f = clang_getCString (ClangString d f)
+
+-- typedef void *CXFile;
+newtype File s = File { unFile :: Ptr () }
+                 deriving (Eq, Ord, Typeable)
+
+instance ClangValue File
+
+instance Hashable (File s) where
+  hashWithSalt salt (File p) = let !pInt = (fromIntegral $ ptrToWordPtr p) :: Int
+                               in  hashWithSalt salt pInt
+
+maybeFile :: File s' -> Maybe (File s)
+maybeFile (File p) | p == nullPtr = Nothing
+maybeFile f                       = Just (unsafeCoerce f)
+
+unMaybeFile :: Maybe (File s') -> File s
+unMaybeFile (Just f) = unsafeCoerce f
+unMaybeFile Nothing  = File nullPtr
+
+
+-- CXString clang_getFileName(CXFile SFile);
+{# fun wrapped_clang_getFileName as clang_getFileName { `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getFileName :: File s -> IO (ClangString ())
+unsafe_getFileName x = clang_getFileName (unFile x) >>= peek
+
+getFileName :: ClangBase m => File s' -> ClangT s m (ClangString s)
+getFileName = registerClangString . unsafe_getFileName
+
+-- time_t clang_getFileTime(CXFile SFile);
+foreign import ccall unsafe "clang-c/Index.h clang_getFileTime" clang_getFileTime :: Ptr () -> IO CTime
+
+getFileTime :: File s -> IO CTime
+getFileTime (File ptr) = clang_getFileTime ptr
+
+-- | A unique identifier that can be used to distinguish 'File's.
+data UniqueId = UniqueId !Word64 !Word64 !Word64
+                deriving (Eq, Ord, Show, Typeable)
+
+instance Hashable UniqueId where
+    hashWithSalt salt (UniqueId a b c) = (`hashWithSalt` a)
+                                       . (`hashWithSalt` b)
+                                       . (`hashWithSalt` c)
+                                       $ salt
+    {-# INLINE hashWithSalt #-}
+
+maybeFileUniqueID :: (Int, Word64, Word64, Word64) -> Maybe UniqueId
+maybeFileUniqueID (v, d1, d2, d3) | v /= 0    = Nothing
+                                  | otherwise = Just $ UniqueId d1 d2 d3
+
+-- int clang_getFileUniqueID(CXFile file, CXFileUniqueID *outID);
+{# fun clang_getFileUniqueID { `Ptr ()', `Ptr ()' } -> `CInt' id #}
+getFileUniqueID :: File s -> IO (Maybe UniqueId)
+getFileUniqueID f =
+  allocaArray 3 (ptrToFileUniqueId f)
+  where
+    ptrToFileUniqueId :: File s -> Ptr Word64 -> IO (Maybe UniqueId)
+    ptrToFileUniqueId f' ptr = do
+       res' <- clang_getFileUniqueID (unFile f') (castPtr ptr)
+       ds' <- peekArray 3 ptr
+       return (maybeFileUniqueID (fromIntegral res', ds' !! 0, ds' !! 1, ds' !! 2))
+
+-- -- unsigned clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file);
+{# fun clang_isFileMultipleIncludeGuarded { `Ptr ()', `Ptr ()' } -> `CInt' #}
+isFileMultipleIncludeGuarded :: TranslationUnit s -> File s' -> IO Bool
+isFileMultipleIncludeGuarded t f = clang_isFileMultipleIncludeGuarded (unTranslationUnit t) (unFile f) >>= return . (toBool :: Int -> Bool) . fromIntegral
+
+-- CXFile clang_getFile(CXTranslationUnit tu, const char *file_name);
+{# fun clang_getFile { `Ptr ()', `CString' } -> `Ptr ()' #}
+getFile:: Proxy s -> TranslationUnit s' -> String -> IO (File s)
+getFile _ t s = withCString s (\cs -> clang_getFile (unTranslationUnit t) cs >>= return . File)
+
+-- typedef struct {
+--   void *ptr_data[2];
+--   unsigned int_data;
+-- } CXSourceLocation;
+
+data SourceLocation s = SourceLocation !(Ptr ()) !(Ptr ()) !Int
+                        deriving (Ord, Typeable)
+
+instance ClangValue SourceLocation
+
+instance Eq (SourceLocation s) where
+  a == b = unsafePerformIO $ equalLocations a b
+
+instance Storable (SourceLocation s) where
+    sizeOf _ = sizeOfCXSourceLocation
+    {-# INLINE sizeOf #-}
+
+    alignment _ = alignOfCXSourceLocation
+    {-# INLINE alignment #-}
+
+    peek p = do
+      ptrArray <- {#get CXSourceLocation->ptr_data #} p >>= peekArray 2
+      intData <- {#get CXSourceLocation->int_data #} p
+      return $! SourceLocation (ptrArray !! 0) (ptrArray !! 1) (fromIntegral intData)
+    {-# INLINE peek #-}
+
+    poke p (SourceLocation p0 p1 i )= do
+      ptrsArray <- mallocArray 2
+      pokeArray ptrsArray [p0,p1]
+      {#set CXSourceLocation->ptr_data #} p (castPtr ptrsArray)
+      {#set CXSourceLocation->int_data #} p (fromIntegral i)
+    {-# INLINE poke #-}
+
+-- typedef struct {
+--   void *ptr_data[2];
+--   unsigned begin_int_data;
+--   unsigned end_int_data;
+-- } CXSourceRange;
+data SourceRange s = SourceRange !(Ptr ()) !(Ptr ()) !Int !Int
+                     deriving (Ord, Typeable)
+
+instance ClangValue SourceRange
+
+instance Eq (SourceRange s) where
+  a == b = unsafePerformIO $ equalRanges a b
+
+instance Storable (SourceRange s) where
+    sizeOf _ = sizeOfCXSourceRange
+    {-# INLINE sizeOf #-}
+
+    alignment _ = alignOfCXSourceRange
+    {-# INLINE alignment #-}
+
+    peek p = do
+      ptrArray <- {#get CXSourceRange->ptr_data #} p >>= peekArray 2
+      beginIntData <- {#get CXSourceRange->begin_int_data #} p
+      endIntData <- {#get CXSourceRange->end_int_data #} p
+      return $! SourceRange (ptrArray !! 0) (ptrArray !! 1) (fromIntegral beginIntData) (fromIntegral endIntData)
+    {-# INLINE peek #-}
+
+    poke p (SourceRange p0 p1 begin end)= do
+      ptrsArray <- mallocArray 2
+      pokeArray ptrsArray [p0,p1]
+      {#set CXSourceRange->ptr_data #} p (castPtr ptrsArray)
+      {#set CXSourceRange->begin_int_data #} p (fromIntegral begin)
+      {#set CXSourceRange->end_int_data #} p (fromIntegral end)
+    {-# INLINE poke #-}
+
+-- CXSourceLocation wrapped_clang_getNullLocation();
+{# fun wrapped_clang_getNullLocation as clang_getNullLocation { } -> `Ptr (SourceLocation s)' castPtr #}
+getNullLocation :: Proxy s -> IO (SourceLocation s)
+getNullLocation _ = clang_getNullLocation >>= peek
+
+withVoided :: Storable a => a -> (Ptr () -> IO c) -> IO c
+withVoided a f= with a (\aPtr -> f (castPtr aPtr))
+
+-- unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2);
+{# fun clang_equalLocations {withVoided* %`SourceLocation a' , withVoided* %`SourceLocation b' } -> `Bool' toBool #}
+equalLocations :: SourceLocation s -> SourceLocation s' -> IO Bool
+equalLocations s1 s2 = clang_equalLocations s1 s2
+
+-- CXSourceLocation clang_getLocation(CXTranslationUnit tu,
+--                                                   CXFile file,
+--                                                   unsigned line,
+--                                                   unsigned column);
+{# fun wrapped_clang_getLocation as clang_getLocation { `Ptr ()' , `Ptr ()', `Int', `Int' } -> `Ptr (SourceLocation s)' castPtr #}
+getLocation :: Proxy s -> TranslationUnit s' -> File s'' -> Int -> Int -> IO (SourceLocation s)
+getLocation _ t f i j = clang_getLocation (unTranslationUnit t) (unFile f) i j >>= peek
+
+-- CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu,
+--                                                            CXFile file,
+--                                                            unsigned offset);
+{# fun wrapped_clang_getLocationForOffset as clang_getLocationForOffset { `Ptr ()', `Ptr ()', `Int' } -> `Ptr (SourceLocation s)' castPtr #}
+getLocationForOffset :: Proxy s -> TranslationUnit s' -> File s'' -> Int -> IO (SourceLocation s)
+getLocationForOffset _ t f i = clang_getLocationForOffset (unTranslationUnit t) (unFile f) i >>= peek
+
+-- int clang_Location_isInSystemHeader(CXSourceLocation location);
+{# fun clang_Location_isInSystemHeader { withVoided* %`SourceLocation a' } -> `Bool' toBool #}
+location_isInSystemHeader :: SourceLocation s -> IO Bool
+location_isInSystemHeader s = clang_Location_isInSystemHeader s
+
+-- int clang_Location_isFromMainFile(CXSourceLocation location);
+{# fun clang_Location_isFromMainFile { withVoided* %`SourceLocation a' } -> `Bool' toBool #}
+location_isFromMainFile :: SourceLocation s -> IO Bool
+location_isFromMainFile s = clang_Location_isFromMainFile s
+
+-- CXSourceRange clang_getNullRange();
+{# fun wrapped_clang_getNullRange as clang_getNullRange { } -> `Ptr (SourceRange s)' castPtr #}
+getNullRange :: Proxy s -> IO (SourceRange s)
+getNullRange _ = clang_getNullRange >>= peek
+
+-- CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end);
+{# fun wrapped_clang_getRange as clang_getRange { withVoided* %`SourceLocation a', withVoided* %`SourceLocation b' } -> `Ptr (SourceRange s)' castPtr #}
+getRange :: Proxy s -> SourceLocation s' -> SourceLocation s'' -> IO (SourceRange s)
+getRange _ sl1 sl2 = clang_getRange sl1 sl2 >>= peek
+
+-- unsigned clang_equalRanges(CXSourceRange range1, CXSourceRange range2);
+{# fun clang_equalRanges {withVoided* %`SourceRange a', withVoided* %`SourceRange b' } -> `Bool' toBool #}
+equalRanges :: SourceRange s' -> SourceRange s'' -> IO Bool
+equalRanges sr1 sr2 = clang_equalRanges sr1 sr2
+
+-- int clang_Range_isNull(CXSourceRange range);
+{# fun clang_Range_isNull {withVoided* %`SourceRange a ' } -> `Bool' toBool #}
+range_isNull :: SourceRange s -> IO Bool
+range_isNull s = clang_Range_isNull s
+
+#c
+typedef CXFile** PtrPtrCXFile;
+#endc
+
+-- void clang_getExpansionLocation(CXSourceLocation location,
+--                                 CXFile *file,
+--                                 unsigned *line,
+--                                 unsigned *column,
+--                                 unsigned *offset);
+{# fun clang_getExpansionLocation { withVoided* %`SourceLocation a', id `Ptr (Ptr ())', id `Ptr CUInt', id `Ptr CUInt', id `Ptr CUInt' } -> `()' #}
+getExpansionLocation :: Proxy s -> SourceLocation s' -> IO (Maybe (File s), Int, Int, Int)
+getExpansionLocation _ s =
+  allocaBytes {#sizeof PtrPtrCXFile #} (\ptrToFilePtr ->
+  alloca (\(linePtr :: (Ptr CUInt)) ->
+  alloca (\(columnPtr :: (Ptr CUInt)) ->
+  alloca (\(offsetPtr :: (Ptr CUInt)) -> do
+    clang_getExpansionLocation s (castPtr ptrToFilePtr) (castPtr linePtr) (castPtr columnPtr) (castPtr offsetPtr)
+    filePtr <- {#get *CXFile #} ptrToFilePtr
+    let _maybeFile = maybeFile (File filePtr)
+    line <- peek linePtr
+    column <- peek columnPtr
+    offset <- peek offsetPtr
+    return (_maybeFile, fromIntegral line, fromIntegral column, fromIntegral offset)))))
+
+-- void clang_getPresumedLocation(CXSourceLocation location,
+--                                CXString *filename,
+--                                unsigned *line,
+--                                unsigned *column);
+
+{# fun clang_getPresumedLocation { withVoided* %`SourceLocation a', id `Ptr ()', alloca- `CUInt' peek*, alloca- `CUInt' peek* } -> `()' #}
+unsafe_getPresumedLocation :: SourceLocation s' -> IO (ClangString (), Int, Int)
+unsafe_getPresumedLocation s =
+  alloca (\(stringPtr :: (Ptr (ClangString ()))) -> do
+    (line, column) <- clang_getPresumedLocation s (castPtr stringPtr)
+    clangString <- peek stringPtr
+    return (clangString, fromIntegral line, fromIntegral column))
+
+getPresumedLocation :: ClangBase m => SourceLocation s' -> ClangT s m (ClangString s, Int, Int)
+getPresumedLocation l = do
+  (f, ln, c) <- liftIO $ unsafe_getPresumedLocation l
+  (,,) <$> registerClangString (return f) <*> return ln <*> return c
+
+-- void clang_getSpellingLocation(CXSourceLocation location,
+--                                CXFile *file,
+--                                unsigned *line,
+--                                unsigned *column,
+--                                unsigned *offset);
+{# fun clang_getSpellingLocation { withVoided* %`SourceLocation a', id `Ptr (Ptr ())', id `Ptr CUInt', id `Ptr CUInt', id `Ptr CUInt' } -> `()' #}
+getSpellingLocation :: Proxy s -> SourceLocation s' -> IO (Maybe (File s), Int, Int, Int)
+getSpellingLocation _ s =
+  allocaBytes {# sizeof PtrPtrCXFile #} (\ptrToFilePtr ->
+  alloca (\(linePtr :: (Ptr CUInt)) ->
+  alloca (\(columnPtr :: (Ptr CUInt)) ->
+  alloca (\(offsetPtr :: (Ptr CUInt)) -> do
+    clang_getSpellingLocation s (castPtr ptrToFilePtr) linePtr columnPtr offsetPtr
+    filePtr <- {#get *CXFile #} ptrToFilePtr
+    let _maybeFile = maybeFile (File filePtr)
+    line <- peek linePtr
+    column <- peek columnPtr
+    offset <- peek offsetPtr
+    return (_maybeFile, fromIntegral line, fromIntegral column, fromIntegral offset)))))
+
+-- void clang_getFileLocation(CXSourceLocation location,
+--                            CXFile *file,
+--                            unsigned *line,
+--                            unsigned *column,
+--                            unsigned *offset);
+{# fun clang_getFileLocation { withVoided* %`SourceLocation a', id `Ptr (Ptr ())', id `Ptr CUInt', id `Ptr CUInt', id `Ptr CUInt' } -> `()' #}
+getFileLocation :: Proxy s -> SourceLocation s' -> IO (Maybe (File s), Int, Int, Int)
+getFileLocation _ s =
+  allocaBytes {#sizeof PtrPtrCXFile #} (\ptrToFilePtr ->
+  alloca (\(linePtr :: (Ptr CUInt)) ->
+  alloca (\(columnPtr :: (Ptr CUInt)) ->
+  alloca (\(offsetPtr :: (Ptr CUInt)) -> do
+    clang_getFileLocation s ptrToFilePtr (castPtr linePtr) (castPtr columnPtr) (castPtr offsetPtr)
+    filePtr <- {#get *CXFile #} ptrToFilePtr
+    let _maybeFile = maybeFile (File filePtr)
+    line <- peek linePtr
+    column <- peek columnPtr
+    offset <- peek offsetPtr
+    return (_maybeFile, fromIntegral line, fromIntegral column, fromIntegral offset)))))
+
+-- CXSourceLocation clang_getRangeStart(CXSourceRange range);
+{# fun wrapped_clang_getRangeStart as clang_getRangeStart {withVoided* %`SourceRange a' } -> `Ptr (SourceLocation s)' castPtr #}
+getRangeStart :: Proxy s -> SourceRange s' -> IO (SourceLocation s)
+getRangeStart _ sr = clang_getRangeStart sr >>= peek
+
+-- CXSourceLocation clang_getRangeEnd(CXSourceRange range);
+{# fun wrapped_clang_getRangeEnd as clang_getRangeEnd {withVoided* %`SourceRange a' } -> `Ptr (SourceLocation s)' castPtr #}
+getRangeEnd :: Proxy s -> SourceRange s' -> IO (SourceLocation s)
+getRangeEnd _ sr = clang_getRangeEnd sr >>= peek
+
+-- enum CXDiagnosticSeverity {
+--   CXDiagnostic_Ignored = 0,
+--   CXDiagnostic_Note    = 1,
+--   CXDiagnostic_Warning = 2,
+--   CXDiagnostic_Error   = 3,
+--   CXDiagnostic_Fatal   = 4
+-- };
+
+-- | The severity of a diagnostic.
+#c
+enum Severity
+ { SeverityIgnored = CXDiagnostic_Ignored
+ , SeverityNote    = CXDiagnostic_Note
+ , SeverityWarning = CXDiagnostic_Warning
+ , SeverityError   = CXDiagnostic_Error
+ , SeverityFatal   = CXDiagnostic_Fatal
+ };
+#endc
+{# enum Severity {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- typedef void* CXDiagnostic;
+newtype Diagnostic s = Diagnostic { unDiagnostic :: Ptr () }
+                       deriving (Eq, Ord, Typeable)
+
+instance ClangValue Diagnostic
+
+mkDiagnostic :: Ptr () -> Diagnostic ()
+mkDiagnostic = Diagnostic
+
+-- void clang_disposeDiagnostic(CXDiagnostic);
+{# fun clang_disposeDiagnostic { id `Ptr ()' } -> `()' #}
+disposeDiagnostic:: Diagnostic s -> IO ()
+disposeDiagnostic d = clang_disposeDiagnostic (unDiagnostic d)
+
+registerDiagnostic :: ClangBase m => IO (Diagnostic ()) -> ClangT s m (Diagnostic s)
+registerDiagnostic action = do
+  (_, idx) <- clangAllocate (action >>= return . unsafeCoerce)
+                            (\i -> disposeDiagnostic i)
+  return idx
+{-# INLINEABLE registerDiagnostic #-}
+
+-- typedef void* CXDiagnosticSet;
+newtype DiagnosticSet s = DiagnosticSet { unDiagnosticSet :: Ptr () }
+                          deriving (Eq, Ord, Typeable)
+
+instance ClangValue DiagnosticSet
+
+mkDiagnosticSet :: Ptr () -> DiagnosticSet ()
+mkDiagnosticSet = DiagnosticSet
+
+-- void clang_disposeDiagnosticSet(CXDiagnosticSet);
+{# fun clang_disposeDiagnosticSet { id `Ptr ()' } -> `()' #}
+disposeDiagnosticSet :: DiagnosticSet s -> IO ()
+disposeDiagnosticSet s = clang_disposeDiagnosticSet (unDiagnosticSet s)
+
+registerDiagnosticSet :: ClangBase m => IO (DiagnosticSet ()) -> ClangT s m (DiagnosticSet s)
+registerDiagnosticSet action = do
+  (_, idx) <- clangAllocate (action >>= return . unsafeCoerce)
+                            (\i -> disposeDiagnosticSet i)
+  return idx
+{-# INLINEABLE registerDiagnosticSet #-}
+
+-- unsigned clang_getNumDiagnosticsInSet(CXDiagnosticSet Diags);
+{# fun clang_getNumDiagnosticsInSet { id `Ptr ()' } -> `Int' #}
+getNumDiagnosticsInSet :: DiagnosticSet s -> IO Int
+getNumDiagnosticsInSet s = clang_getNumDiagnosticsInSet (unDiagnosticSet s)
+
+-- CXDiagnostic clang_getDiagnosticInSet(CXDiagnosticSet Diags, unsigned Index);
+{# fun clang_getDiagnosticInSet { id `Ptr ()', `Int' } -> `Ptr ()' id #}
+unsafe_getDiagnosticInSet :: DiagnosticSet s -> Int -> IO (Diagnostic ())
+unsafe_getDiagnosticInSet s i = clang_getDiagnosticInSet (unDiagnosticSet s) i >>= return . mkDiagnostic
+
+getDiagnosticInSet :: ClangBase m => DiagnosticSet s' -> Int -> ClangT s m (Diagnostic s)
+getDiagnosticInSet = (registerDiagnostic .) . unsafe_getDiagnosticInSet
+
+-- enum CXLoadDiag_Error {
+--   CXLoadDiag_None = 0,
+--   CXLoadDiag_Unknown = 1,
+--   CXLoadDiag_CannotLoad = 2,
+--   CXLoadDiag_InvalidFile = 3
+-- };
+
+-- | An error encountered while loading a serialized diagnostics bitcode file.
+#c
+enum LoadError
+ { LoadSuccessful   = CXLoadDiag_None
+ , LoadUnknownError = CXLoadDiag_Unknown
+ , LoadCannotOpen   = CXLoadDiag_CannotLoad
+ , LoadInvalidFile  = CXLoadDiag_InvalidFile
+ };
+#endc
+{# enum LoadError {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+data LoadDiagsResult =
+  LoadDiagsResult LoadError (ClangString ()) (DiagnosticSet ())
+
+-- CXDiagnosticSet clang_loadDiagnostics(const char *file,
+--                                       enum CXLoadDiag_Error *error,
+--                                       CXString *errorString);
+{# fun clang_loadDiagnostics {`CString', alloca- `CInt' peek*, `Ptr ()' } -> `Ptr ()' id #}
+unsafe_loadDiagnostics :: FilePath -> IO LoadDiagsResult
+unsafe_loadDiagnostics file = withCString file (\cString -> alloca (go cString))
+  where
+    go :: CString -> Ptr (ClangString ()) -> IO LoadDiagsResult
+    go str ptr = do
+       (diagnosticSetPtr, err) <- clang_loadDiagnostics str (castPtr ptr)
+       errString <- peek (castPtr ptr)
+       return (LoadDiagsResult (toEnum (fromIntegral err)) errString (DiagnosticSet diagnosticSetPtr))
+
+loadDiagnostics :: ClangBase m => FilePath
+                -> ClangT s m (Either (LoadError, ClangString s) (DiagnosticSet s))
+loadDiagnostics path = do
+  result <- liftIO $ unsafe_loadDiagnostics path
+  case result of
+    (LoadDiagsResult err errStr ds@(DiagnosticSet p))
+      | p == nullPtr -> Left . (err,) <$> registerClangString (return errStr)
+      | otherwise    -> Right <$> registerDiagnosticSet (return ds)
+
+-- CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D);
+{# fun clang_getChildDiagnostics { `Ptr ()' } -> `Ptr ()' id #}
+unsafe_getChildDiagnostics :: Diagnostic s' -> IO (DiagnosticSet ())
+unsafe_getChildDiagnostics d = clang_getChildDiagnostics (unDiagnostic d) >>= return . mkDiagnosticSet
+
+-- Note that as a special case, the DiagnosticSet returned by this
+-- function does not need to be freed, so we intentionally don't
+-- register it.
+getChildDiagnostics :: ClangBase m => Diagnostic s' -> ClangT s m (DiagnosticSet s)
+getChildDiagnostics = unsafeCoerce <$> unsafe_getChildDiagnostics
+
+-- unsigned clang_getNumDiagnostics(CXTranslationUnit Unit);
+{# fun clang_getNumDiagnostics { `Ptr ()' } -> `CUInt' id#}
+getNumDiagnostics :: TranslationUnit s -> IO Int
+getNumDiagnostics t = clang_getNumDiagnostics (unTranslationUnit t) >>= return . fromIntegral
+
+-- CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index);
+{# fun clang_getDiagnostic { `Ptr ()', `CUInt' } -> `Ptr ()' id #}
+unsafe_getDiagnostic :: TranslationUnit s -> Int -> IO (Diagnostic ())
+unsafe_getDiagnostic t i = clang_getDiagnostic (unTranslationUnit t) (fromIntegral i) >>= return . mkDiagnostic
+
+getDiagnostic :: ClangBase m => TranslationUnit s' -> Int -> ClangT s m (Diagnostic s)
+getDiagnostic = (registerDiagnostic .) . unsafe_getDiagnostic
+
+-- CXDiagnosticSet clang_getDiagnosticSetFromTU(CXTranslationUnit Unit);
+{# fun clang_getDiagnosticSetFromTU { `Ptr ()' } -> `Ptr ()' id #}
+unsafe_getDiagnosticSetFromTU :: TranslationUnit s -> IO (DiagnosticSet ())
+unsafe_getDiagnosticSetFromTU t = do
+  set <- clang_getDiagnosticSetFromTU (unTranslationUnit t)
+  return (mkDiagnosticSet set)
+
+getDiagnosticSetFromTU :: ClangBase m => TranslationUnit s' -> ClangT s m (DiagnosticSet s)
+getDiagnosticSetFromTU = registerDiagnosticSet . unsafe_getDiagnosticSetFromTU
+
+-- enum CXDiagnosticDisplayOptions {
+--   CXDiagnostic_DisplaySourceLocation = 0x01,
+--   CXDiagnostic_DisplayColumn = 0x02,
+--   CXDiagnostic_DisplaySourceRanges = 0x04,
+--   CXDiagnostic_DisplayOption = 0x08,
+--   CXDiagnostic_DisplayCategoryId = 0x10,
+--   CXDiagnostic_DisplayCategoryName = 0x20
+-- };
+
+-- | Options for rendering of 'Diagnostic' values.
+#c
+enum DisplayOptions
+ { DisplaySourceLocation = CXDiagnostic_DisplaySourceLocation
+ , DisplayColumn         = CXDiagnostic_DisplayColumn
+ , DisplaySourceRanges   = CXDiagnostic_DisplaySourceRanges
+ , DisplayOption         = CXDiagnostic_DisplayOption
+ , DisplayCategoryId     = CXDiagnostic_DisplayCategoryId
+ , DisplayCategoryName   = CXDiagnostic_DisplayCategoryName
+ };
+#endc
+{#enum DisplayOptions {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags DisplayOptions where
+  toBit DisplaySourceLocation = 0x1
+  toBit DisplayColumn         = 0x2
+  toBit DisplaySourceRanges   = 0x4
+  toBit DisplayOption         = 0x8
+  toBit DisplayCategoryId     = 0x10
+  toBit DisplayCategoryName   = 0x20
+
+-- CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options);
+{# fun wrapped_clang_formatDiagnostic as clang_formatDiagnostic { `Ptr ()' , `Int' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_formatDiagnostic :: Diagnostic s -> Int -> IO (ClangString ())
+unsafe_formatDiagnostic d i = clang_formatDiagnostic (unDiagnostic d) (fromIntegral i) >>= peek
+
+formatDiagnostic :: ClangBase m => Diagnostic s' -> Int -> ClangT s m (ClangString s)
+formatDiagnostic = (registerClangString .) . unsafe_formatDiagnostic
+
+-- unsigned clang_defaultDiagnosticDisplayOptions(void);
+{# fun clang_defaultDiagnosticDisplayOptions { } -> `CUInt' #}
+defaultDiagnosticDisplayOptions :: IO Int
+defaultDiagnosticDisplayOptions = clang_defaultDiagnosticDisplayOptions >>= return . fromIntegral
+
+-- clang_getDiagnosticSeverity(CXDiagnostic);
+{# fun clang_getDiagnosticSeverity {id `Ptr ()' } -> `CInt' #}
+getDiagnosticSeverity :: Diagnostic s -> IO Severity
+getDiagnosticSeverity d = clang_getDiagnosticSeverity (unDiagnostic d) >>= return . toEnum . fromIntegral
+
+-- CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic);
+{# fun wrapped_clang_getDiagnosticLocation as clang_getDiagnosticLocation {id `Ptr ()' } -> `Ptr (SourceLocation s)' castPtr #}
+getDiagnosticLocation :: Proxy s -> Diagnostic s' -> IO (SourceLocation s)
+getDiagnosticLocation _ d = clang_getDiagnosticLocation (unDiagnostic d) >>= peek
+
+-- CXString clang_getDiagnosticSpelling(CXDiagnostic);
+{# fun wrapped_clang_getDiagnosticSpelling as clang_getDiagnosticSpelling  { id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getDiagnosticSpelling :: Diagnostic s -> IO (ClangString ())
+unsafe_getDiagnosticSpelling d = clang_getDiagnosticSpelling (unDiagnostic d) >>= peek
+
+getDiagnosticSpelling :: ClangBase m => Diagnostic s' -> ClangT s m (ClangString s)
+getDiagnosticSpelling = registerClangString . unsafe_getDiagnosticSpelling
+
+-- CXString clang_getDiagnosticOption(CXDiagnostic Diag,
+--                                                   CXString *Disable);
+{# fun wrapped_clang_getDiagnosticOption as clang_getDiagnosticOption { id `Ptr ()', id `Ptr ()' } -> `Ptr ()' id #}
+unsafe_getDiagnosticOption :: Diagnostic s -> IO (ClangString (), ClangString ())
+unsafe_getDiagnosticOption d =
+  alloca (\(disableCXStringPtr :: (Ptr (ClangString ()))) -> do
+    diagnosticOptionPtr <- clang_getDiagnosticOption (unDiagnostic d) (castPtr disableCXStringPtr)
+    disableCXString <- peek disableCXStringPtr
+    diagnosticOption <- peek (castPtr diagnosticOptionPtr)
+    return (diagnosticOption, disableCXString))
+
+getDiagnosticOption :: ClangBase m => Diagnostic s' -> ClangT s m (ClangString s, ClangString s)
+getDiagnosticOption d = do
+  (a, b) <- liftIO $ unsafe_getDiagnosticOption d
+  (,) <$> registerClangString (return a) <*> registerClangString (return b)
+
+-- unsigned clang_getDiagnosticCategory(CXDiagnostic);
+{# fun clang_getDiagnosticCategory { id `Ptr ()' } -> `Int' #}
+getDiagnosticCategory :: Diagnostic s -> IO Int
+getDiagnosticCategory d = clang_getDiagnosticCategory (unDiagnostic d)
+
+-- CXString clang_getDiagnosticCategoryText(CXDiagnostic);
+{# fun wrapped_clang_getDiagnosticCategoryText as clang_getDiagnosticCategoryText { id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getDiagnosticCategoryText :: Diagnostic s -> IO (ClangString ())
+unsafe_getDiagnosticCategoryText d = clang_getDiagnosticCategoryText (unDiagnostic d) >>= peek
+
+getDiagnosticCategoryText :: ClangBase m => Diagnostic s' -> ClangT s m (ClangString s)
+getDiagnosticCategoryText = registerClangString . unsafe_getDiagnosticCategoryText
+
+-- unsigned clang_getDiagnosticNumRanges(CXDiagnostic);
+{# fun clang_getDiagnosticNumRanges { id `Ptr ()' } -> `Int' #}
+getDiagnosticNumRanges :: Diagnostic s -> IO Int
+getDiagnosticNumRanges d = clang_getDiagnosticNumRanges (unDiagnostic d)
+
+-- CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diagnostic,
+--                                                       unsigned Range);
+{# fun wrapped_clang_getDiagnosticRange as clang_getDiagnosticRange { id `Ptr ()', `Int' } -> `Ptr (SourceRange s)' castPtr #}
+getDiagnosticRange :: Diagnostic s' -> Int -> IO (SourceRange s)
+getDiagnosticRange d i = clang_getDiagnosticRange (unDiagnostic d) i >>= peek
+
+-- unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diagnostic);
+{# fun clang_getDiagnosticNumFixIts { id `Ptr ()' } -> `Int' #}
+getDiagnosticNumFixIts :: Diagnostic s -> IO Int
+getDiagnosticNumFixIts d = clang_getDiagnosticNumFixIts (unDiagnostic d)
+
+-- CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic,
+--                                                  unsigned FixIt,
+--                                                CXSourceRange *ReplacementRange);
+{# fun wrapped_clang_getDiagnosticFixIt as clang_getDiagnosticFixIt { id `Ptr ()', `Int', id `Ptr ()' } -> `Ptr (ClangString())' castPtr #}
+unsafe_getDiagnosticFixIt :: Diagnostic s' -> Int -> IO (SourceRange s, ClangString ())
+unsafe_getDiagnosticFixIt d i =
+  alloca (\(replacementRangePtr :: (Ptr (SourceRange s))) -> do
+     clangStringPtr <- clang_getDiagnosticFixIt (unDiagnostic d) i (castPtr replacementRangePtr)
+     clangString <- peek clangStringPtr
+     replacementRange <- peek replacementRangePtr
+     return (replacementRange, clangString))
+
+getDiagnosticFixIt :: ClangBase m => Diagnostic s' -> Int
+                   -> ClangT s m (SourceRange s, ClangString s)
+getDiagnosticFixIt d i = do
+  (r, s) <- liftIO $ unsafe_getDiagnosticFixIt d i
+  (r,) <$> registerClangString (return s)
+
+-- CXString
+-- clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit);
+{# fun wrapped_clang_getTranslationUnitSpelling as clang_getTranslationUnitSpelling { id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getTranslationUnitSpelling :: TranslationUnit s -> IO (ClangString ())
+unsafe_getTranslationUnitSpelling t = clang_getTranslationUnitSpelling (unTranslationUnit t) >>= peek
+
+getTranslationUnitSpelling :: ClangBase m => TranslationUnit s' -> ClangT s m (ClangString s)
+getTranslationUnitSpelling = registerClangString . unsafe_getTranslationUnitSpelling
+
+-- CXTranslationUnit clang_createTranslationUnitFromSourceFile(
+--                                          CXIndex CIdx,
+--                                          const char *source_filename,
+--                                          int num_clang_command_line_args,
+--                                    const char * const *clang_command_line_args,
+--                                          unsigned num_unsaved_files,
+--                                          struct CXUnsavedFile *unsaved_files);
+{# fun clang_createTranslationUnitFromSourceFile { id `Ptr ()' , `CString' , `Int' , id `Ptr CString' , `Int' , id `Ptr ()' }  -> `Ptr ()' id #}
+unsafe_createTranslationUnitFromSourceFile :: Index s -> String -> Int -> Ptr CString -> Int -> Ptr CUnsavedFile -> IO (TranslationUnit ())
+unsafe_createTranslationUnitFromSourceFile i s nas as nufs ufs =
+  withCString s (\sPtr -> do
+     rPtr <- clang_createTranslationUnitFromSourceFile (unIndex i) sPtr nas as nufs (castPtr ufs)
+     return (mkTranslationUnit rPtr))
+
+createTranslationUnitFromSourceFile :: ClangBase m => Index s' -> String -> [String]
+                                    -> DV.Vector UnsavedFile -> ClangT s m (TranslationUnit s)
+createTranslationUnitFromSourceFile idx sf as ufs =
+  registerTranslationUnit $
+    withStringList as $ \asPtr asLen ->
+      withUnsavedFiles ufs $ \ufsPtr ufsLen ->
+        unsafe_createTranslationUnitFromSourceFile idx sf asLen asPtr ufsLen ufsPtr
+
+-- CXTranslationUnit clang_createTranslationUnit(CXIndex,
+--                                              const char *ast_filename);
+{# fun clang_createTranslationUnit { id `Ptr ()', `CString' } -> `Ptr ()' #}
+unsafe_createTranslationUnit :: Index s -> String -> IO (TranslationUnit ())
+unsafe_createTranslationUnit i s =
+  withCString s (\strPtr -> do
+   trPtr <- clang_createTranslationUnit (unIndex i) strPtr
+   return (mkTranslationUnit trPtr))
+
+createTranslationUnit :: ClangBase m => Index s' -> String -> ClangT s m (TranslationUnit s)
+createTranslationUnit = (registerTranslationUnit .) . unsafe_createTranslationUnit
+
+-- enum CXTranslationUnit_Flags {
+--   CXTranslationUnit_None = 0x0,
+--   CXTranslationUnit_DetailedPreprocessingRecord = 0x01,
+--   CXTranslationUnit_Incomplete = 0x02,
+--   CXTranslationUnit_PrecompiledPreamble = 0x04,
+--   CXTranslationUnit_CacheCompletionResults = 0x08,
+--   CXTranslationUnit_ForSerialization = 0x10,
+--   CXTranslationUnit_CXXChainedPCH = 0x20,
+--   CXTranslationUnit_SkipFunctionBodies = 0x40,
+--   CXTranslationUnit_IncludeBriefCommentsInCodeCompletion = 0x80
+-- };
+
+-- | Flags that control how a translation unit is parsed.
+--
+-- * 'DetailedPreprocessingRecordFlag': Used to indicate that the parser should construct a
+--   "detailed" preprocessing record, including all macro definitions and instantiations.
+--   Constructing a detailed preprocessing record requires more memory and time to parse,
+--   since the information contained in the record is usually not retained. However, it can be
+--   useful for applications that require more detailed information about the behavior of the
+--   preprocessor.
+--
+-- * 'IncompleteFlag': Used to indicate that the translation unit is incomplete.
+--   When a translation unit is considered "incomplete", semantic analysis that is typically
+--   performed at the end of the translation unit will be suppressed. For example, this
+--   suppresses the completion of tentative declarations in C and of instantiation of
+--   implicitly-instantiation function templates in C++. This option is typically used when
+--   parsing a header with the intent of producing a precompiled header.
+--
+-- * 'PrecompiledPreambleFlag': Used to indicate that the translation unit should be built
+--   with an implicit precompiled header for the preamble. An implicit precompiled header is
+--   used as an optimization when a particular translation unit is likely to be reparsed many
+--   times when the sources aren't changing that often. In this case, an implicit precompiled
+--   header will be built containing all of the initial includes at the top of the main file
+--   (what we refer to as the "preamble" of the file). In subsequent parses, if the preamble
+--   or the files in it have not changed, 'Clang.TranslationUnit.reparse' will re-use the
+--   implicit precompiled header to improve parsing performance.
+--
+-- * 'CacheCompletionResultsFlag': Used to indicate that the translation unit should cache
+--   some code-completion results with each reparse of the source file.
+--   Caching of code-completion results is a performance optimization that introduces some
+--   overhead to reparsing but improves the performance of code-completion operations.
+--
+-- * 'ForSerializationFlag': Used to indicate that the translation unit will be serialized
+--   'Clang.TranslationUnit.save'. This option is typically used when parsing a header with
+--   the intent of producing a precompiled header.
+--
+-- * 'CXXChainedPCHFlag': DEPRECATED: Enabled chained precompiled preambles in C++. Note:
+--   this is a *temporary* option that is available only while we are testing C++ precompiled
+--   preamble support. It is deprecated.
+--
+-- * 'SkipFunctionBodiesFlag': Used to indicate that function/method bodies should be skipped
+--   while parsing. This option can be used to search for declarations/definitions while
+--   ignoring the usages.
+--
+-- * 'IncludeBriefCommentsInCodeCompletionFlag': Used to indicate that brief documentation
+--   comments should be included into the set of code completions returned from this
+--   translation unit.
+#c
+enum TranslationUnitFlags
+  { DefaultTranslationUnitFlags              = CXTranslationUnit_None
+  , DetailedPreprocessingRecordFlag          = CXTranslationUnit_DetailedPreprocessingRecord
+  , IncompleteFlag                           = CXTranslationUnit_Incomplete
+  , PrecompiledPreambleFlag                  = CXTranslationUnit_PrecompiledPreamble
+  , CacheCompletionResultsFlag               = CXTranslationUnit_CacheCompletionResults
+  , ForSerializationFlag                     = CXTranslationUnit_ForSerialization
+  , ChainedPCHFlag                           = CXTranslationUnit_CXXChainedPCH
+  , SkipFunctionBodiesFlag                   = CXTranslationUnit_SkipFunctionBodies
+  , IncludeBriefCommentsInCodeCompletionFlag = CXTranslationUnit_IncludeBriefCommentsInCodeCompletion
+ };
+#endc
+{# enum TranslationUnitFlags {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags TranslationUnitFlags where
+  toBit DefaultTranslationUnitFlags              = 0x0
+  toBit DetailedPreprocessingRecordFlag          = 0x01
+  toBit IncompleteFlag                           = 0x02
+  toBit PrecompiledPreambleFlag                  = 0x04
+  toBit CacheCompletionResultsFlag               = 0x08
+  toBit ForSerializationFlag                     = 0x10
+  toBit ChainedPCHFlag                           = 0x20
+  toBit SkipFunctionBodiesFlag                   = 0x40
+  toBit IncludeBriefCommentsInCodeCompletionFlag = 0x80
+
+-- unsigned clang_defaultEditingTranslationUnitOptions(void);
+{# fun clang_defaultEditingTranslationUnitOptions as defaultEditingTranslationUnitOptions {} -> `Int' #}
+
+maybeTranslationUnit :: TranslationUnit s' -> Maybe (TranslationUnit s)
+maybeTranslationUnit (TranslationUnit p) | p == nullPtr = Nothing
+maybeTranslationUnit f                         = Just (unsafeCoerce f)
+
+-- CXTranslationUnit clang_parseTranslationUnit(CXIndex CIdx,
+--                                                     const char *source_filename,
+--                                          const char * const *command_line_args,
+--                                                       int num_command_line_args,
+--                                             struct CXUnsavedFile *unsaved_files,
+--                                                      unsigned num_unsaved_files,
+--                                                             unsigned options);
+{# fun clang_parseTranslationUnit { id `Ptr ()', `CString' , id `Ptr CString', `Int', id `Ptr ()', `Int', `Int'}  -> `Ptr ()' id #}
+unsafe_parseTranslationUnit :: Index s -> CString -> Ptr CString -> Int -> Ptr CUnsavedFile -> Int -> Int -> IO (Maybe (TranslationUnit ()))
+unsafe_parseTranslationUnit i s as nas ufs nufs o =
+  clang_parseTranslationUnit (unIndex i) s as nas (castPtr ufs) nufs o >>= return . maybeTranslationUnit . mkTranslationUnit
+
+parseTranslationUnit :: ClangBase m => Index s' -> Maybe String -> [String]
+                     -> DV.Vector UnsavedFile -> Int -> ClangT s m (Maybe (TranslationUnit s))
+parseTranslationUnit idx maySF as ufs opts = do
+    mayTU <- liftIO $
+      withMaybeCString maySF $ \cSF ->
+        withStringList as $ \asPtr asLen ->
+          withUnsavedFiles ufs $ \ufsPtr ufsLen ->
+            unsafe_parseTranslationUnit idx cSF asPtr asLen ufsPtr ufsLen opts
+    case mayTU of
+      Just tu -> Just <$> registerTranslationUnit (return tu)
+      Nothing -> return Nothing
+
+withMaybeCString :: Maybe String -> (CString -> IO a) -> IO a
+withMaybeCString (Just s) f = withCString s f
+withMaybeCString Nothing  f = f nullPtr
+
+withStringList :: [String] -> (Ptr CString -> Int -> IO a) -> IO a
+withStringList [] f = f nullPtr 0
+withStringList strs f = do
+    let len = length strs
+    allocaArray len $ \arr -> go arr len arr strs
+  where
+    go arr len _ [] = f arr len
+    go arr len ptr (s : ss) = withCString s $ \cs -> do
+      poke ptr cs
+      go arr len (advancePtr ptr 1) ss
+
+-- enum CXSaveTranslationUnit_Flags {
+--   CXSaveTranslationUnit_None = 0x0
+-- };
+
+-- | Flags that control how a translation unit is saved.
+#c
+enum SaveTranslationUnitFlags
+  {DefaultSaveTranslationUnitFlags = CXSaveTranslationUnit_None};
+#endc
+{# enum SaveTranslationUnitFlags {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+instance BitFlags SaveTranslationUnitFlags where
+  toBit DefaultSaveTranslationUnitFlags = 0x0
+
+-- unsigned clang_defaultSaveOptions(CXTranslationUnit TU);
+{# fun clang_defaultSaveOptions { id `Ptr ()' } -> `Int' #}
+defaultSaveOptions :: TranslationUnit s -> IO Int
+defaultSaveOptions t = clang_defaultSaveOptions (unTranslationUnit t)
+
+
+-- int clang_saveTranslationUnit(CXTranslationUnit TU,
+--                                              const char *FileName,
+--                                              unsigned options);
+{# fun clang_saveTranslationUnit { id `Ptr ()' , `CString', `Int' } -> `Int' #}
+saveTranslationUnit :: TranslationUnit s -> String -> Int -> IO Bool
+saveTranslationUnit t s i =
+ withCString s (\sPtr -> do
+   r <- clang_saveTranslationUnit (unTranslationUnit t) sPtr i
+   return (toBool ((if (r /= 0) then 0 else 1) :: Int)))
+
+-- enum CXReparse_Flags {
+--   CXReparse_None = 0x0
+-- };
+
+-- | Flags that control how a translation unit is reparsed.
+#c
+enum ReparseFlags {
+  DefaultReparseFlags = CXReparse_None
+};
+#endc
+{# enum ReparseFlags {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags ReparseFlags where
+  toBit DefaultReparseFlags = 0x0
+
+-- unsigned clang_defaultReparseOptions(CXTranslationUnit TU);
+{# fun clang_defaultReparseOptions { id `Ptr ()' } -> `CUInt' #}
+defaultReparseOptions :: TranslationUnit s -> IO Int
+defaultReparseOptions t = clang_defaultReparseOptions (unTranslationUnit t) >>= return . fromIntegral
+
+-- int clang_reparseTranslationUnit(CXTranslationUnit TU,
+--                                                 unsigned num_unsaved_files,
+--                                           struct CXUnsavedFile *unsaved_files,
+--                                                 unsigned options);
+{# fun clang_reparseTranslationUnit { id `Ptr ()', `Int' , id `Ptr ()' , `Int' } -> `Bool' toBool #}
+unsafe_reparseTranslationUnit :: TranslationUnit s -> Ptr CUnsavedFile -> Int -> Int -> IO Bool
+unsafe_reparseTranslationUnit t ufs nufs i =
+  clang_reparseTranslationUnit (unTranslationUnit t) nufs (castPtr ufs) i
+
+reparseTranslationUnit :: ClangBase m => TranslationUnit s' -> DV.Vector UnsavedFile -> Int
+                       -> ClangT s m Bool
+reparseTranslationUnit tu ufs opts = liftIO $
+  withUnsavedFiles ufs $ \ufsPtr ufsLen ->
+    unsafe_reparseTranslationUnit tu ufsPtr ufsLen opts
+
+
+-- enum CXCursorKind {
+--   /* Declarations */
+--   /**
+--    * \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.
+--    */
+--   CXCursor_UnexposedDecl                 = 1,
+--   /** \brief A C or C++ struct. */
+--   CXCursor_StructDecl                    = 2,
+--   /** \brief A C or C++ union. */
+--   CXCursor_UnionDecl                     = 3,
+--   /** \brief A C++ class. */
+--   CXCursor_ClassDecl                     = 4,
+--   /** \brief An enumeration. */
+--   CXCursor_EnumDecl                      = 5,
+--   /**
+--    * \brief A field (in C) or non-static data member (in C++) in a
+--    * struct, union, or C++ class.
+--    */
+--   CXCursor_FieldDecl                     = 6,
+--   /** \brief An enumerator constant. */
+--   CXCursor_EnumConstantDecl              = 7,
+--   /** \brief A function. */
+--   CXCursor_FunctionDecl                  = 8,
+--   /** \brief A variable. */
+--   CXCursor_VarDecl                       = 9,
+--   /** \brief A function or method parameter. */
+--   CXCursor_ParmDecl                      = 10,
+--   /** \brief An Objective-C @interface. */
+--   CXCursor_ObjCInterfaceDecl             = 11,
+--   /** \brief An Objective-C @interface for a category. */
+--   CXCursor_ObjCCategoryDecl              = 12,
+--   /** \brief An Objective-C @protocol declaration. */
+--   CXCursor_ObjCProtocolDecl              = 13,
+--   /** \brief An Objective-C @property declaration. */
+--   CXCursor_ObjCPropertyDecl              = 14,
+--   /** \brief An Objective-C instance variable. */
+--   CXCursor_ObjCIvarDecl                  = 15,
+--   /** \brief An Objective-C instance method. */
+--   CXCursor_ObjCInstanceMethodDecl        = 16,
+--   /** \brief An Objective-C class method. */
+--   CXCursor_ObjCClassMethodDecl           = 17,
+--   /** \brief An Objective-C @implementation. */
+--   CXCursor_ObjCImplementationDecl        = 18,
+--   /** \brief An Objective-C @implementation for a category. */
+--   CXCursor_ObjCCategoryImplDecl          = 19,
+--   /** \brief A typedef */
+--   CXCursor_TypedefDecl                   = 20,
+--   /** \brief A C++ class method. */
+--   CXCursor_CXXMethod                     = 21,
+--   /** \brief A C++ namespace. */
+--   CXCursor_Namespace                     = 22,
+--   /** \brief A linkage specification, e.g. 'extern "C"'. */
+--   CXCursor_LinkageSpec                   = 23,
+--   /** \brief A C++ constructor. */
+--   CXCursor_Constructor                   = 24,
+--   /** \brief A C++ destructor. */
+--   CXCursor_Destructor                    = 25,
+--   /** \brief A C++ conversion function. */
+--   CXCursor_ConversionFunction            = 26,
+--   /** \brief A C++ template type parameter. */
+--   CXCursor_TemplateTypeParameter         = 27,
+--   /** \brief A C++ non-type template parameter. */
+--   CXCursor_NonTypeTemplateParameter      = 28,
+--   /** \brief A C++ template template parameter. */
+--   CXCursor_TemplateTemplateParameter     = 29,
+--   /** \brief A C++ function template. */
+--   CXCursor_FunctionTemplate              = 30,
+--   /** \brief A C++ class template. */
+--   CXCursor_ClassTemplate                 = 31,
+--   /** \brief A C++ class template partial specialization. */
+--   CXCursor_ClassTemplatePartialSpecialization = 32,
+--   /** \brief A C++ namespace alias declaration. */
+--   CXCursor_NamespaceAlias                = 33,
+--   /** \brief A C++ using directive. */
+--   CXCursor_UsingDirective                = 34,
+--   /** \brief A C++ using declaration. */
+--   CXCursor_UsingDeclaration              = 35,
+--   /** \brief A C++ alias declaration */
+--   CXCursor_TypeAliasDecl                 = 36,
+--   /** \brief An Objective-C @synthesize definition. */
+--   CXCursor_ObjCSynthesizeDecl            = 37,
+--   /** \brief An Objective-C @dynamic definition. */
+--   CXCursor_ObjCDynamicDecl               = 38,
+--   /** \brief An access specifier. */
+--   CXCursor_CXXAccessSpecifier            = 39,
+
+--   CXCursor_FirstDecl                     = CXCursor_UnexposedDecl,
+--   CXCursor_LastDecl                      = CXCursor_CXXAccessSpecifier,
+
+--   /* References */
+--   CXCursor_FirstRef                      = 40, /* Decl references */
+--   CXCursor_ObjCSuperClassRef             = 40,
+--   CXCursor_ObjCProtocolRef               = 41,
+--   CXCursor_ObjCClassRef                  = 42,
+--   /**
+--    * \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.
+--    */
+--   CXCursor_TypeRef                       = 43,
+--   CXCursor_CXXBaseSpecifier              = 44,
+--   /**
+--    * \brief A reference to a class template, function template, template
+--    * template parameter, or class template partial specialization.
+--    */
+--   CXCursor_TemplateRef                   = 45,
+--   /**
+--    * \brief A reference to a namespace or namespace alias.
+--    */
+--   CXCursor_NamespaceRef                  = 46,
+--   /**
+--    * \brief A reference to a member of a struct, union, or class that occurs in
+--    * some non-expression context, e.g., a designated initializer.
+--    */
+--   CXCursor_MemberRef                     = 47,
+--   /**
+--    * \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.
+--    */
+--   CXCursor_LabelRef                      = 48,
+
+--   /**
+--    * \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.
+--    */
+--   CXCursor_OverloadedDeclRef             = 49,
+
+--   /*
+--    * \brief A reference to a variable that occurs in some non-expression
+--    * context, e.g., a C++ lambda capture list.
+--    */
+--   CXCursor_VariableRef                   = 50,
+
+--   CXCursor_LastRef                       = CXCursor_VariableRef,
+
+--   /* Error conditions */
+--   CXCursor_FirstInvalid                  = 70,
+--   CXCursor_InvalidFile                   = 70,
+--   CXCursor_NoDeclFound                   = 71,
+--   CXCursor_NotImplemented                = 72,
+--   CXCursor_InvalidCode                   = 73,
+--   CXCursor_LastInvalid                   = CXCursor_InvalidCode,
+
+--   /* Expressions */
+--   CXCursor_FirstExpr                     = 100,
+
+--   /**
+--    * \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.
+--    */
+--   CXCursor_UnexposedExpr                 = 100,
+
+--   /**
+--    * \brief An expression that refers to some value declaration, such
+--    * as a function, varible, or enumerator.
+--    */
+--   CXCursor_DeclRefExpr                   = 101,
+
+--   /**
+--    * \brief An expression that refers to a member of a struct, union,
+--    * class, Objective-C class, etc.
+--    */
+--   CXCursor_MemberRefExpr                 = 102,
+
+--   /** \brief An expression that calls a function. */
+--   CXCursor_CallExpr                      = 103,
+
+--   /** \brief An expression that sends a message to an Objective-C
+--    object or class. */
+--   CXCursor_ObjCMessageExpr               = 104,
+
+--   /** \brief An expression that represents a block literal. */
+--   CXCursor_BlockExpr                     = 105,
+
+--   /** \brief An integer literal.
+--    */
+--   CXCursor_IntegerLiteral                = 106,
+
+--   /** \brief A floating point number literal.
+--    */
+--   CXCursor_FloatingLiteral               = 107,
+
+--   /** \brief An imaginary number literal.
+--    */
+--   CXCursor_ImaginaryLiteral              = 108,
+
+--   /** \brief A string literal.
+--    */
+--   CXCursor_StringLiteral                 = 109,
+
+--   /** \brief A character literal.
+--    */
+--   CXCursor_CharacterLiteral              = 110,
+
+--   /** \brief A parenthesized expression, e.g. "(1)".
+--    *
+--    * This AST node is only formed if full location information is requested.
+--    */
+--   CXCursor_ParenExpr                     = 111,
+
+--   /** \brief This represents the unary-expression's (except sizeof and
+--    * alignof).
+--    */
+--   CXCursor_UnaryOperator                 = 112,
+
+--   /** \brief [C99 6.5.2.1] Array Subscripting.
+--    */
+--   CXCursor_ArraySubscriptExpr            = 113,
+
+--   /** \brief A builtin binary operation expression such as "x + y" or
+--    * "x <= y".
+--    */
+--   CXCursor_BinaryOperator                = 114,
+
+--   /** \brief Compound assignment such as "+=".
+--    */
+--   CXCursor_CompoundAssignOperator        = 115,
+
+--   /** \brief The ?: ternary operator.
+--    */
+--   CXCursor_ConditionalOperator           = 116,
+
+--   /** \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.
+--    */
+--   CXCursor_CStyleCastExpr                = 117,
+
+--   /** \brief [C99 6.5.2.5]
+--    */
+--   CXCursor_CompoundLiteralExpr           = 118,
+
+--   /** \brief Describes an C or C++ initializer list.
+--    */
+--   CXCursor_InitListExpr                  = 119,
+
+--   /** \brief The GNU address of label extension, representing &&label.
+--    */
+--   CXCursor_AddrLabelExpr                 = 120,
+
+--   /** \brief This is the GNU Statement Expression extension: ({int X=4; X;})
+--    */
+--   CXCursor_StmtExpr                      = 121,
+
+--   /** \brief Represents a C1X generic selection.
+--    */
+--   CXCursor_GenericSelectionExpr          = 122,
+
+--   /** \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).
+--    */
+--   CXCursor_GNUNullExpr                   = 123,
+
+--   /** \brief C++'s static_cast<> expression.
+--    */
+--   CXCursor_CXXStaticCastExpr             = 124,
+
+--   /** \brief C++'s dynamic_cast<> expression.
+--    */
+--   CXCursor_CXXDynamicCastExpr            = 125,
+
+--   /** \brief C++'s reinterpret_cast<> expression.
+--    */
+--   CXCursor_CXXReinterpretCastExpr        = 126,
+
+--   /** \brief C++'s const_cast<> expression.
+--    */
+--   CXCursor_CXXConstCastExpr              = 127,
+
+--   /** \brief Represents an explicit C++ type conversion that uses "functional"
+--    * notion (C++ [expr.type.conv]).
+--    *
+--    * Example:
+--    * \code
+--    *   x = int(0.5);
+--    * \endcode
+--    */
+--   CXCursor_CXXFunctionalCastExpr         = 128,
+
+--   /** \brief A C++ typeid expression (C++ [expr.typeid]).
+--    */
+--   CXCursor_CXXTypeidExpr                 = 129,
+
+--   /** \brief [C++ 2.13.5] C++ Boolean Literal.
+--    */
+--   CXCursor_CXXBoolLiteralExpr            = 130,
+
+--   /** \brief [C++0x 2.14.7] C++ Pointer Literal.
+--    */
+--   CXCursor_CXXNullPtrLiteralExpr         = 131,
+
+--   /** \brief Represents the "this" expression in C++
+--    */
+--   CXCursor_CXXThisExpr                   = 132,
+
+--   /** \brief [C++ 15] C++ Throw Expression.
+--    *
+--    * This handles 'throw' and 'throw' assignment-expression. When
+--    * assignment-expression isn't present, Op will be null.
+--    */
+--   CXCursor_CXXThrowExpr                  = 133,
+
+--   /** \brief A new expression for memory allocation and constructor calls, e.g:
+--    * "new CXXNewExpr(foo)".
+--    */
+--   CXCursor_CXXNewExpr                    = 134,
+
+--   /** \brief A delete expression for memory deallocation and destructor calls,
+--    * e.g. "delete[] pArray".
+--    */
+--   CXCursor_CXXDeleteExpr                 = 135,
+
+--   /** \brief A unary expression.
+--    */
+--   CXCursor_UnaryExpr                     = 136,
+
+--   /** \brief ObjCStringLiteral, used for Objective-C string literals i.e. "foo".
+--    */
+--   CXCursor_ObjCStringLiteral             = 137,
+
+--   /** \brief ObjCEncodeExpr, used for in Objective-C.
+--    */
+--   CXCursor_ObjCEncodeExpr                = 138,
+
+--   /** \brief ObjCSelectorExpr used for in Objective-C.
+--    */
+--   CXCursor_ObjCSelectorExpr              = 139,
+
+--   /** \brief Objective-C's protocol expression.
+--    */
+--   CXCursor_ObjCProtocolExpr              = 140,
+
+--   /** \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
+--    */
+--   CXCursor_ObjCBridgedCastExpr           = 141,
+
+--   /** \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
+--    */
+--   CXCursor_PackExpansionExpr             = 142,
+
+--   /** \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
+--    */
+--   CXCursor_SizeOfPackExpr                = 143,
+
+--   /* \brief Represents a C++ lambda expression that produces a local function
+--    * object.
+--    *
+--    * \code
+--    * void abssort(float *x, unsigned N) {
+--    *   std::sort(x, x + N,
+--    *             [](float a, float b) {
+--    *               return std::abs(a) < std::abs(b);
+--    *             });
+--    * }
+--    * \endcode
+--    */
+--   CXCursor_LambdaExpr                    = 144,
+
+--   /** \brief Objective-c Boolean Literal.
+--    */
+--   CXCursor_ObjCBoolLiteralExpr           = 145,
+
+--   /** \brief Represents the "self" expression in a ObjC method.
+--    */
+--   CXCursor_ObjCSelfExpr                  = 146,
+
+--   CXCursor_LastExpr                      = CXCursor_ObjCSelfExpr,
+
+--   /* Statements */
+--   CXCursor_FirstStmt                     = 200,
+--   /**
+--    * \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.
+--    */
+--   CXCursor_UnexposedStmt                 = 200,
+
+--   /** \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
+--    *
+--    */
+--   CXCursor_LabelStmt                     = 201,
+
+--   /** \brief A group of statements like { stmt stmt }.
+--    *
+--    * This cursor kind is used to describe compound statements, e.g. function
+--    * bodies.
+--    */
+--   CXCursor_CompoundStmt                  = 202,
+
+--   /** \brief A case statment.
+--    */
+--   CXCursor_CaseStmt                      = 203,
+
+--   /** \brief A default statement.
+--    */
+--   CXCursor_DefaultStmt                   = 204,
+
+--   /** \brief An if statement
+--    */
+--   CXCursor_IfStmt                        = 205,
+
+--   /** \brief A switch statement.
+--    */
+--   CXCursor_SwitchStmt                    = 206,
+
+--   /** \brief A while statement.
+--    */
+--   CXCursor_WhileStmt                     = 207,
+
+--   /** \brief A do statement.
+--    */
+--   CXCursor_DoStmt                        = 208,
+
+--   /** \brief A for statement.
+--    */
+--   CXCursor_ForStmt                       = 209,
+
+--   /** \brief A goto statement.
+--    */
+--   CXCursor_GotoStmt                      = 210,
+
+--   /** \brief An indirect goto statement.
+--    */
+--   CXCursor_IndirectGotoStmt              = 211,
+
+--   /** \brief A continue statement.
+--    */
+--   CXCursor_ContinueStmt                  = 212,
+
+--   /** \brief A break statement.
+--    */
+--   CXCursor_BreakStmt                     = 213,
+
+--   /** \brief A return statement.
+--    */
+--   CXCursor_ReturnStmt                    = 214,
+
+--   /** \brief A GNU inline assembly statement extension.
+--    */
+--   CXCursor_GCCAsmStmt                    = 215,
+--   CXCursor_AsmStmt                       = CXCursor_GCCAsmStmt,
+
+--   /** \brief Objective-C's overall @try-@catc-@finall statement.
+--    */
+--   CXCursor_ObjCAtTryStmt                 = 216,
+
+--   /** \brief Objective-C's @catch statement.
+--    */
+--   CXCursor_ObjCAtCatchStmt               = 217,
+
+--   /** \brief Objective-C's @finally statement.
+--    */
+--   CXCursor_ObjCAtFinallyStmt             = 218,
+
+--   /** \brief Objective-C's @throw statement.
+--    */
+--   CXCursor_ObjCAtThrowStmt               = 219,
+
+--   /** \brief Objective-C's @synchronized statement.
+--    */
+--   CXCursor_ObjCAtSynchronizedStmt        = 220,
+
+--   /** \brief Objective-C's autorelease pool statement.
+--    */
+--   CXCursor_ObjCAutoreleasePoolStmt       = 221,
+
+--   /** \brief Objective-C's collection statement.
+--    */
+--   CXCursor_ObjCForCollectionStmt         = 222,
+
+--   /** \brief C++'s catch statement.
+--    */
+--   CXCursor_CXXCatchStmt                  = 223,
+
+--   /** \brief C++'s try statement.
+--    */
+--   CXCursor_CXXTryStmt                    = 224,
+
+--   /** \brief C++'s for (* : *) statement.
+--    */
+--   CXCursor_CXXForRangeStmt               = 225,
+
+--   /** \brief Windows Structured Exception Handling's try statement.
+--    */
+--   CXCursor_SEHTryStmt                    = 226,
+
+--   /** \brief Windows Structured Exception Handling's except statement.
+--    */
+--   CXCursor_SEHExceptStmt                 = 227,
+
+--   /** \brief Windows Structured Exception Handling's finally statement.
+--    */
+--   CXCursor_SEHFinallyStmt                = 228,
+
+--   /** \brief A MS inline assembly statement extension.
+--    */
+--   CXCursor_MSAsmStmt                     = 229,
+
+--   /** \brief The null satement ";": C99 6.8.3p3.
+--    *
+--    * This cursor kind is used to describe the null statement.
+--    */
+--   CXCursor_NullStmt                      = 230,
+
+--   /** \brief Adaptor class for mixing declarations with statements and
+--    * expressions.
+--    */
+--   CXCursor_DeclStmt                      = 231,
+
+--   /** \brief OpenMP parallel directive.
+--    */
+--   CXCursor_OMPParallelDirective          = 232,
+
+--   CXCursor_LastStmt                      = CXCursor_OMPParallelDirective,
+
+--   /**
+--    * \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.
+--    */
+--   CXCursor_TranslationUnit               = 300,
+
+--   /* Attributes */
+--   CXCursor_FirstAttr                     = 400,
+--   /**
+--    * \brief An attribute whose specific kind is not exposed via this
+--    * interface.
+--    */
+--   CXCursor_UnexposedAttr                 = 400,
+
+--   CXCursor_IBActionAttr                  = 401,
+--   CXCursor_IBOutletAttr                  = 402,
+--   CXCursor_IBOutletCollectionAttr        = 403,
+--   CXCursor_CXXFinalAttr                  = 404,
+--   CXCursor_CXXOverrideAttr               = 405,
+--   CXCursor_AnnotateAttr                  = 406,
+--   CXCursor_AsmLabelAttr                  = 407,
+--   CXCursor_PackedAttr                    = 408,
+--   CXCursor_LastAttr                      = CXCursor_PackedAttr,
+
+--   /* Preprocessing */
+--   CXCursor_PreprocessingDirective        = 500,
+--   CXCursor_MacroDefinition               = 501,
+--   CXCursor_MacroExpansion                = 502,
+--   CXCursor_MacroInstantiation            = CXCursor_MacroExpansion,
+--   CXCursor_InclusionDirective            = 503,
+--   CXCursor_FirstPreprocessing            = CXCursor_PreprocessingDirective,
+--   CXCursor_LastPreprocessing             = CXCursor_InclusionDirective
+
+--   /* Extra Declarations */
+--   /**
+--    * \brief A module import declaration.
+--    */
+--   CXCursor_ModuleImportDecl              = 600,
+--   CXCursor_FirstExtraDecl                = CXCursor_ModuleImportDecl,
+--   CXCursor_LastExtraDecl                 = CXCursor_ModuleImportDecl
+-- };
+#c
+enum CursorKind
+  { UnexposedDeclCursor                      = CXCursor_UnexposedDecl
+  , StructDeclCursor                         = CXCursor_StructDecl
+  , UnionDeclCursor                          = CXCursor_UnionDecl
+  , ClassDeclCursor                          = CXCursor_ClassDecl
+  , EnumDeclCursor                           = CXCursor_EnumDecl
+  , FieldDeclCursor                          = CXCursor_FieldDecl
+  , EnumConstantDeclCursor                   = CXCursor_EnumConstantDecl
+  , FunctionDeclCursor                       = CXCursor_FunctionDecl
+  , VarDeclCursor                            = CXCursor_VarDecl
+  , ParmDeclCursor                           = CXCursor_ParmDecl
+  , ObjCInterfaceDeclCursor                  = CXCursor_ObjCInterfaceDecl
+  , ObjCCategoryDeclCursor                   = CXCursor_ObjCCategoryDecl
+  , ObjCProtocolDeclCursor                   = CXCursor_ObjCProtocolDecl
+  , ObjCPropertyDeclCursor                   = CXCursor_ObjCPropertyDecl
+  , ObjCIvarDeclCursor                       = CXCursor_ObjCIvarDecl
+  , ObjCInstanceMethodDeclCursor             = CXCursor_ObjCInstanceMethodDecl
+  , ObjCClassMethodDeclCursor                = CXCursor_ObjCClassMethodDecl
+  , ObjCImplementationDeclCursor             = CXCursor_ObjCImplementationDecl
+  , ObjCCategoryImplDeclCursor               = CXCursor_ObjCCategoryImplDecl
+  , TypedefDeclCursor                        = CXCursor_TypedefDecl
+  , CXXMethodCursor                          = CXCursor_CXXMethod
+  , NamespaceCursor                          = CXCursor_Namespace
+  , LinkageSpecCursor                        = CXCursor_LinkageSpec
+  , ConstructorCursor                        = CXCursor_Constructor
+  , DestructorCursor                         = CXCursor_Destructor
+  , ConversionFunctionCursor                 = CXCursor_ConversionFunction
+  , TemplateTypeParameterCursor              = CXCursor_TemplateTypeParameter
+  , NonTypeTemplateParameterCursor           = CXCursor_NonTypeTemplateParameter
+  , TemplateTemplateParameterCursor          = CXCursor_TemplateTemplateParameter
+  , FunctionTemplateCursor                   = CXCursor_FunctionTemplate
+  , ClassTemplateCursor                      = CXCursor_ClassTemplate
+  , ClassTemplatePartialSpecializationCursor = CXCursor_ClassTemplatePartialSpecialization
+  , NamespaceAliasCursor                     = CXCursor_NamespaceAlias
+  , UsingDirectiveCursor                     = CXCursor_UsingDirective
+  , UsingDeclarationCursor                   = CXCursor_UsingDeclaration
+  , TypeAliasDeclCursor                      = CXCursor_TypeAliasDecl
+  , ObjCSynthesizeDeclCursor                 = CXCursor_ObjCSynthesizeDecl
+  , ObjCDynamicDeclCursor                    = CXCursor_ObjCDynamicDecl
+  , CXXAccessSpecifierCursor                 = CXCursor_CXXAccessSpecifier
+  , ObjCSuperClassRefCursor                  = CXCursor_ObjCSuperClassRef
+  , ObjCProtocolRefCursor                    = CXCursor_ObjCProtocolRef
+  , ObjCClassRefCursor                       = CXCursor_ObjCClassRef
+  , TypeRefCursor                            = CXCursor_TypeRef
+  , CXXBaseSpecifierCursor                   = CXCursor_CXXBaseSpecifier
+  , TemplateRefCursor                        = CXCursor_TemplateRef
+  , NamespaceRefCursor                       = CXCursor_NamespaceRef
+  , MemberRefCursor                          = CXCursor_MemberRef
+  , LabelRefCursor                           = CXCursor_LabelRef
+  , OverloadedDeclRefCursor                  = CXCursor_OverloadedDeclRef
+  , VariableRefCursor                        = CXCursor_VariableRef
+  , InvalidFileCursor                        = CXCursor_InvalidFile
+  , NoDeclFoundCursor                        = CXCursor_NoDeclFound
+  , NotImplementedCursor                     = CXCursor_NotImplemented
+  , InvalidCodeCursor                        = CXCursor_InvalidCode
+  , UnexposedExprCursor                      = CXCursor_UnexposedExpr
+  , DeclRefExprCursor                        = CXCursor_DeclRefExpr
+  , MemberRefExprCursor                      = CXCursor_MemberRefExpr
+  , CallExprCursor                           = CXCursor_CallExpr
+  , ObjCMessageExprCursor                    = CXCursor_ObjCMessageExpr
+  , BlockExprCursor                          = CXCursor_BlockExpr
+  , IntegerLiteralCursor                     = CXCursor_IntegerLiteral
+  , FloatingLiteralCursor                    = CXCursor_FloatingLiteral
+  , ImaginaryLiteralCursor                   = CXCursor_ImaginaryLiteral
+  , StringLiteralCursor                      = CXCursor_StringLiteral
+  , CharacterLiteralCursor                   = CXCursor_CharacterLiteral
+  , ParenExprCursor                          = CXCursor_ParenExpr
+  , UnaryOperatorCursor                      = CXCursor_UnaryOperator
+  , ArraySubscriptExprCursor                 = CXCursor_ArraySubscriptExpr
+  , BinaryOperatorCursor                     = CXCursor_BinaryOperator
+  , CompoundAssignOperatorCursor             = CXCursor_CompoundAssignOperator
+  , ConditionalOperatorCursor                = CXCursor_ConditionalOperator
+  , CStyleCastExprCursor                     = CXCursor_CStyleCastExpr
+  , CompoundLiteralExprCursor                = CXCursor_CompoundLiteralExpr
+  , InitListExprCursor                       = CXCursor_InitListExpr
+  , AddrLabelExprCursor                      = CXCursor_AddrLabelExpr
+  , StmtExprCursor                           = CXCursor_StmtExpr
+  , GenericSelectionExprCursor               = CXCursor_GenericSelectionExpr
+  , GNUNullExprCursor                        = CXCursor_GNUNullExpr
+  , CXXStaticCastExprCursor                  = CXCursor_CXXStaticCastExpr
+  , CXXDynamicCastExprCursor                 = CXCursor_CXXDynamicCastExpr
+  , CXXReinterpretCastExprCursor             = CXCursor_CXXReinterpretCastExpr
+  , CXXConstCastExprCursor                   = CXCursor_CXXConstCastExpr
+  , CXXFunctionalCastExprCursor              = CXCursor_CXXFunctionalCastExpr
+  , CXXTypeidExprCursor                      = CXCursor_CXXTypeidExpr
+  , CXXBoolLiteralExprCursor                 = CXCursor_CXXBoolLiteralExpr
+  , CXXNullPtrLiteralExprCursor              = CXCursor_CXXNullPtrLiteralExpr
+  , CXXThisExprCursor                        = CXCursor_CXXThisExpr
+  , CXXThrowExprCursor                       = CXCursor_CXXThrowExpr
+  , CXXNewExprCursor                         = CXCursor_CXXNewExpr
+  , CXXDeleteExprCursor                      = CXCursor_CXXDeleteExpr
+  , UnaryExprCursor                          = CXCursor_UnaryExpr
+  , ObjCStringLiteralCursor                  = CXCursor_ObjCStringLiteral
+  , ObjCEncodeExprCursor                     = CXCursor_ObjCEncodeExpr
+  , ObjCSelectorExprCursor                   = CXCursor_ObjCSelectorExpr
+  , ObjCProtocolExprCursor                   = CXCursor_ObjCProtocolExpr
+  , ObjCBridgedCastExprCursor                = CXCursor_ObjCBridgedCastExpr
+  , PackExpansionExprCursor                  = CXCursor_PackExpansionExpr
+  , SizeOfPackExprCursor                     = CXCursor_SizeOfPackExpr
+  , LambdaExprCursor                         = CXCursor_LambdaExpr
+  , ObjCBoolLiteralExprCursor                = CXCursor_ObjCBoolLiteralExpr
+  , ObjCSelfExprCursor                       = CXCursor_ObjCSelfExpr
+  , UnexposedStmtCursor                      = CXCursor_UnexposedStmt
+  , LabelStmtCursor                          = CXCursor_LabelStmt
+  , CompoundStmtCursor                       = CXCursor_CompoundStmt
+  , CaseStmtCursor                           = CXCursor_CaseStmt
+  , DefaultStmtCursor                        = CXCursor_DefaultStmt
+  , IfStmtCursor                             = CXCursor_IfStmt
+  , SwitchStmtCursor                         = CXCursor_SwitchStmt
+  , WhileStmtCursor                          = CXCursor_WhileStmt
+  , DoStmtCursor                             = CXCursor_DoStmt
+  , ForStmtCursor                            = CXCursor_ForStmt
+  , GotoStmtCursor                           = CXCursor_GotoStmt
+  , IndirectGotoStmtCursor                   = CXCursor_IndirectGotoStmt
+  , ContinueStmtCursor                       = CXCursor_ContinueStmt
+  , BreakStmtCursor                          = CXCursor_BreakStmt
+  , ReturnStmtCursor                         = CXCursor_ReturnStmt
+  , AsmStmtCursor                            = CXCursor_AsmStmt
+  , ObjCAtTryStmtCursor                      = CXCursor_ObjCAtTryStmt
+  , ObjCAtCatchStmtCursor                    = CXCursor_ObjCAtCatchStmt
+  , ObjCAtFinallyStmtCursor                  = CXCursor_ObjCAtFinallyStmt
+  , ObjCAtThrowStmtCursor                    = CXCursor_ObjCAtThrowStmt
+  , ObjCAtSynchronizedStmtCursor             = CXCursor_ObjCAtSynchronizedStmt
+  , ObjCAutoreleasePoolStmtCursor            = CXCursor_ObjCAutoreleasePoolStmt
+  , ObjCForCollectionStmtCursor              = CXCursor_ObjCForCollectionStmt
+  , CXXCatchStmtCursor                       = CXCursor_CXXCatchStmt
+  , CXXTryStmtCursor                         = CXCursor_CXXTryStmt
+  , CXXForRangeStmtCursor                    = CXCursor_CXXForRangeStmt
+  , SEHTryStmtCursor                         = CXCursor_SEHTryStmt
+  , SEHExceptStmtCursor                      = CXCursor_SEHExceptStmt
+  , SEHFinallyStmtCursor                     = CXCursor_SEHFinallyStmt
+  , MSAsmStmtCursor                          = CXCursor_MSAsmStmt
+  , NullStmtCursor                           = CXCursor_NullStmt
+  , DeclStmtCursor                           = CXCursor_DeclStmt
+  , OMPParallelDirectiveCursor               = CXCursor_OMPParallelDirective
+  , TranslationUnitCursor                    = CXCursor_TranslationUnit
+  , UnexposedAttrCursor                      = CXCursor_UnexposedAttr
+  , IBActionAttrCursor                       = CXCursor_IBActionAttr
+  , IBOutletAttrCursor                       = CXCursor_IBOutletAttr
+  , IBOutletCollectionAttrCursor             = CXCursor_IBOutletCollectionAttr
+  , CXXFinalAttrCursor                       = CXCursor_CXXFinalAttr
+  , CXXOverrideAttrCursor                    = CXCursor_CXXOverrideAttr
+  , AnnotateAttrCursor                       = CXCursor_AnnotateAttr
+  , AsmLabelAttrCursor                       = CXCursor_AsmLabelAttr
+  , PackedAttrCursor                         = CXCursor_PackedAttr
+  , PreprocessingDirectiveCursor             = CXCursor_PreprocessingDirective
+  , MacroDefinitionCursor                    = CXCursor_MacroDefinition
+  , MacroExpansionCursor                     = CXCursor_MacroExpansion
+  , InclusionDirectiveCursor                 = CXCursor_InclusionDirective
+  , ModuleImportDeclCursor                   = CXCursor_ModuleImportDecl
+ };
+#endc
+{#enum CursorKind{} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- CursorKind ranges.
+firstDeclCursor, lastDeclCursor, firstRefCursor, lastRefCursor         :: CursorKind
+firstInvalidCursor, lastInvalidCursor, firstExprCursor, lastExprCursor :: CursorKind
+firstStmtCursor, lastStmtCursor, firstAttrCursor, lastAttrCursor       :: CursorKind
+firstPreprocessingCursor, lastPreprocessingCursor                      :: CursorKind
+firstExtraDeclCursor, lastExtraDeclCursor                              :: CursorKind
+
+firstDeclCursor          = UnexposedDeclCursor
+lastDeclCursor           = CXXAccessSpecifierCursor
+firstRefCursor           = ObjCSuperClassRefCursor
+lastRefCursor            = VariableRefCursor
+firstInvalidCursor       = InvalidFileCursor
+lastInvalidCursor        = InvalidCodeCursor
+firstExprCursor          = UnexposedExprCursor
+lastExprCursor           = ObjCSelfExprCursor
+firstStmtCursor          = UnexposedStmtCursor
+lastStmtCursor           = OMPParallelDirectiveCursor
+firstAttrCursor          = UnexposedAttrCursor
+lastAttrCursor           = PackedAttrCursor
+firstPreprocessingCursor = PreprocessingDirectiveCursor
+lastPreprocessingCursor  = InclusionDirectiveCursor
+firstExtraDeclCursor     = ModuleImportDeclCursor
+lastExtraDeclCursor      = ModuleImportDeclCursor
+
+-- CursorKind aliases.
+gccAsmStmtCursor, macroInstantiationCursor :: CursorKind
+gccAsmStmtCursor         = AsmStmtCursor
+macroInstantiationCursor = MacroExpansionCursor
+
+-- typedef struct {
+--   const void *ASTNode;
+--   CXTranslationUnit TranslationUnit;
+-- } CXComment;
+data Comment s = Comment !(Ptr ()) !(Ptr ())
+                 deriving (Eq, Ord, Typeable)
+
+instance ClangValue Comment
+
+instance Storable (Comment s) where
+    sizeOf _ = sizeOfCXComment
+    {-# INLINE sizeOf #-}
+
+    alignment _ = alignOfCXComment
+    {-# INLINE alignment #-}
+
+    peek p = do
+      astNode <- {#get CXComment->ASTNode #} p
+      tu <- {#get CXComment->TranslationUnit #} p
+      return $! Comment astNode tu
+    {-# INLINE peek #-}
+
+    poke p (Comment astNode tu)= do
+      {#set CXComment->ASTNode #} p astNode
+      {#set CXComment->TranslationUnit #} p tu
+    {-# INLINE poke #-}
+
+-- typedef struct {
+--   enum CXCursorKind kind;
+--   int xdata;
+--   const void* data[3];
+-- } CXCursor;
+data Cursor s = Cursor !CursorKind !Int !(Ptr ()) !(Ptr ()) !(Ptr ())
+                deriving (Ord, Typeable)
+
+instance ClangValue Cursor
+
+instance Storable (Cursor s) where
+    sizeOf _ = sizeOfCXCursor
+    {-# INLINE sizeOf #-}
+
+    alignment _ = alignOfCXCursor
+    {-# INLINE alignment #-}
+
+    peek p = do
+      cursorKind <- {#get CXCursor->kind #} p
+      xdata <- {#get CXCursor->xdata #} p
+      cursorData <- {#get CXCursor->data #} p >>= peekArray 3
+      return $! Cursor (toEnum (fromIntegral cursorKind)) (fromIntegral xdata) (cursorData !! 0) (cursorData !! 1) (cursorData !! 2)
+    {-# INLINE peek #-}
+
+    poke p (Cursor kind xdata p0 p1 p2)= do
+      ptrsArray <- mallocArray 3
+      pokeArray ptrsArray [p0,p1,p2]
+      {#set CXCursor->kind #} p (fromIntegral (fromEnum kind))
+      {#set CXCursor->xdata #} p (fromIntegral xdata)
+      {#set CXCursor->data #} p (castPtr ptrsArray)
+    {-# INLINE poke #-}
+
+instance Eq (Cursor s) where
+    (Cursor aK aXdata aP1 aP2 aP3) == (Cursor bK bXdata bP1 bP2 bP3) =
+        (aK == bK) &&
+        (aXdata == bXdata) &&
+        (aP1 == bP1) &&
+        (aP2' == bP2') &&
+        (aP3 == bP3)
+      where
+        aP2' = if isDeclaration aK then intPtrToPtr 0 else aP2
+        bP2' = if isDeclaration bK then intPtrToPtr 0 else bP2
+    {-# INLINE (==) #-}
+
+instance Hashable (Cursor s) where
+    hashWithSalt salt (Cursor k _ p1 p2 _) =
+      let p = if isExpression k || isStatement k then p2 else p1
+          kindHash = hashWithSalt salt (fromEnum k)
+          pAsInt = fromIntegral (ptrToIntPtr p) :: Int
+      in hashWithSalt kindHash pAsInt
+    {-# INLINE hash #-}
+
+-- CXCursor clang_getNullCursor(void);
+getNullCursor :: ClangBase m => ClangT s m (Cursor s)
+getNullCursor =
+  return $ Cursor InvalidFileCursor 0 (intPtrToPtr 0) (intPtrToPtr 0) (intPtrToPtr 0)
+{-# INLINE getNullCursor #-}
+
+-- CXCursor clang_getTranslationUnitCursor(CXTranslationUnit);
+{# fun wrapped_clang_getTranslationUnitCursor as clang_getTranslationUnitCursor { id `Ptr ()' } -> `Ptr (Cursor s)' castPtr #}
+getTranslationUnitCursor :: Proxy s -> TranslationUnit s' -> IO (Cursor s)
+getTranslationUnitCursor _ (TranslationUnit tPtr) = clang_getTranslationUnitCursor tPtr >>= peek
+
+-- int clang_Cursor_isNull(CXCursor);
+cursor_isNull :: Cursor s -> Bool
+cursor_isNull (Cursor k xdata p1 p2 p3)
+  | k == InvalidFileCursor &&
+    xdata == 0 &&
+    p1 == intPtrToPtr 0 &&
+    p2 == intPtrToPtr 0 &&
+    p3 == intPtrToPtr 0
+      = True
+  | otherwise
+      = False
+{-# INLINE cursor_isNull #-}
+
+-- unsigned clang_hashCursor(CXCursor);
+{# fun clang_hashCursor {withVoided* %`Cursor a' } -> `Word32' #}
+hashCursor :: Cursor s -> IO Word32
+hashCursor c = clang_hashCursor c
+{-# INLINEABLE hashCursor #-}
+
+getCursorKind :: Cursor s -> CursorKind
+getCursorKind (Cursor k _ _ _ _) = k
+{-# INLINE getCursorKind #-}
+
+-- unsigned clang_isDeclaration(enum CursorKind);
+isDeclaration :: CursorKind -> Bool
+isDeclaration k =
+  (k >= firstDeclCursor && k <= lastDeclCursor) ||
+  (k >= firstExtraDeclCursor && k <= lastExtraDeclCursor)
+{-# INLINE isDeclaration #-}
+
+-- unsigned clang_isReference(enum CursorKind);
+isReference :: CursorKind -> Bool
+isReference k =
+  (k >= firstRefCursor && k <= lastRefCursor)
+{-# INLINE isReference #-}
+
+-- unsigned clang_isExpression(enum CursorKind);
+isExpression :: CursorKind -> Bool
+isExpression k =
+  (k >= firstExprCursor && k <= lastExprCursor)
+{-# INLINE isExpression #-}
+
+-- unsigned clang_isStatement(enum CursorKind);
+isStatement :: CursorKind -> Bool
+isStatement k =
+  (k >= firstStmtCursor && k <= lastStmtCursor)
+{-# INLINE isStatement #-}
+
+isAttribute :: CursorKind -> Bool
+isAttribute k =
+  (k >= firstAttrCursor && k <= lastAttrCursor)
+{-# INLINE isAttribute #-}
+
+-- unsigned clang_isInvalid(enum CursorKind);
+isInvalid :: CursorKind -> Bool
+isInvalid k =
+  (k >= firstInvalidCursor && k <= lastInvalidCursor)
+{-# INLINE isInvalid #-}
+
+-- unsigned clang_isTranslationUnit(enum CursorKind);
+isTranslationUnit :: CursorKind -> Bool
+isTranslationUnit TranslationUnitCursor = True
+isTranslationUnit _ = False
+{-# INLINE isTranslationUnit #-}
+
+-- unsigned clang_isPreprocessing(enum CursorKind);
+isPreprocessing :: CursorKind -> Bool
+isPreprocessing k =
+  (k >= firstPreprocessingCursor && k <= lastPreprocessingCursor)
+{-# INLINE isPreprocessing #-}
+
+-- unsigned clang_isUnexposed(enum CursorKind);
+isUnexposed :: CursorKind -> Bool
+isUnexposed k =
+  (k >= firstPreprocessingCursor && k <= lastPreprocessingCursor)
+{-# INLINE isUnexposed #-}
+
+-- enum CXLinkageKind {
+--   CXLinkage_Invalid,
+--   CXLinkage_NoLinkage,
+--   CXLinkage_Internal,
+--   CXLinkage_UniqueExternal,
+--   CXLinkage_External
+-- };
+#c
+enum LinkageKind
+  { Linkage_Invalid        = CXLinkage_Invalid
+  , Linkage_NoLinkage      = CXLinkage_NoLinkage
+  , Linkage_Internal       = CXLinkage_Internal
+  , Linkage_UniqueExternal = CXLinkage_UniqueExternal
+  , Linkage_External       = CXLinkage_External
+ };
+#endc
+{#enum LinkageKind {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- enum CXLinkageKind clang_getCursorLinkage(CXCursor cursor);
+{# fun clang_getCursorLinkage {withVoided* %`Cursor a' } -> `Int' #}
+getCursorLinkage :: Cursor s -> IO LinkageKind
+getCursorLinkage c = clang_getCursorLinkage c >>= return . toEnum
+
+-- enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor);
+{# fun clang_getCursorAvailability {withVoided* %`Cursor a' } -> `Int' #}
+getCursorAvailability :: Cursor s -> IO AvailabilityKind
+getCursorAvailability c = clang_getCursorAvailability c >>= return . toEnum
+
+data PlatformAvailability = PlatformAvailability
+  { availabilityPlatform      :: !B.ByteString
+  , availabilityIntroduced    :: !Version
+  , availabilityDeprecated    :: !Version
+  , availabilityObsoleted     :: !Version
+  , availabilityIsUnavailable :: !Bool
+  , availabilityMessage       :: !B.ByteString
+  } deriving (Eq, Ord, Typeable)
+
+instance Storable PlatformAvailability where
+  sizeOf _ = sizeOfCXPlatformAvailability
+  {-# INLINE sizeOf #-}
+
+  alignment _ = alignOfCXPlatformAvailability
+  {-# INLINE alignment #-}
+
+  peek p = do
+    (ClangString platD platF) <- peekByteOff p offsetCXPlatformAvailabilityPlatform
+    platform <- B.packCString =<< getCStringPtr platD platF
+
+    introduced <- peekByteOff p offsetCXPlatformAvailabilityIntroduced
+    deprecated <- peekByteOff p offsetCXPlatformAvailabilityDeprecated
+    obsoleted <- peekByteOff p offsetCXPlatformAvailabilityObsoleted
+    intUnavailable :: Int <- fromCInt <$> peekByteOff p offsetCXPlatformAvailabilityUnavailable
+
+    (ClangString msgD msgF) <- peekByteOff p offsetCXPlatformAvailabilityMessage
+    message <- B.packCString =<< getCStringPtr msgD msgF
+
+    return $! PlatformAvailability platform introduced deprecated obsoleted
+                                   (if intUnavailable == 0 then False else True)
+                                   message
+  {-# INLINE peek #-}
+
+  -- Since we can't construct ClangStrings, we can't really poke these.
+  poke _ _ = undefined
+  {-# INLINE poke #-}
+
+-- void clang_disposeCXPlatformAvailability(CXPlatformAvailability);
+{# fun clang_disposeCXPlatformAvailability { id `Ptr ()' } -> `()' #}
+disposeCXPlatformAvailability :: Ptr PlatformAvailability -> IO ()
+disposeCXPlatformAvailability p = clang_disposeCXPlatformAvailability (castPtr p)
+
+-- int clang_getCursorPlatformAvailability(CXCursor cursor,
+--                                         int *always_deprecated,
+--                                         CXString *deprecated_message,
+--                                         int *always_unavailable,
+--                                         CXString *unavailable_message,
+--                                         CXPlatformAvailability *availability,
+--                                         int availability_size);
+{# fun clang_getCursorPlatformAvailability {withVoided* %`Cursor a', alloca- `CInt' peek*, id `Ptr ()', alloca- `CInt' peek*, id `Ptr ()', id `Ptr ()', `Int' } -> `Int' #}
+unsafe_getCursorPlatformAvailability :: Cursor s' -> Ptr PlatformAvailability -> Int -> IO (Bool, ClangString (), Bool, ClangString (), Int)
+unsafe_getCursorPlatformAvailability c dest destLen =
+ alloca (\(dMsgPtr :: (Ptr (ClangString ()))) ->
+ alloca (\(uMsgPtr :: (Ptr (ClangString ()))) -> do
+   (size, ad, au) <- clang_getCursorPlatformAvailability
+                       c
+                       (castPtr dMsgPtr)
+                       (castPtr uMsgPtr)
+                       (castPtr dest)
+                       destLen
+   dm <- peek dMsgPtr
+   um <- peek uMsgPtr
+   return (toBool ad, dm, toBool au, um, size)))
+
+data PlatformAvailabilityInfo s = PlatformAvailabilityInfo
+  { availabilityAlwaysDeprecated   :: !Bool
+  , availabilityDeprecatedMessage  :: !(ClangString s)
+  , availabilityAlwaysUnavailable  :: !Bool
+  , availabilityUnavailableMessage :: !(ClangString s)
+  , availabilityInfo               :: ![PlatformAvailability]
+  } deriving (Eq, Ord, Typeable)
+
+instance ClangValue PlatformAvailabilityInfo
+
+getCursorPlatformAvailability :: ClangBase m => Cursor s'
+                              -> ClangT s m (PlatformAvailabilityInfo s)
+getCursorPlatformAvailability c = do
+    (ad, dMsg, au, uMsg, infos) <-
+      liftIO $ allocaArray maxPlatformAvailability $ \p -> do
+        (ad, dMsg, au, uMsg, outSize) <-
+          unsafe_getCursorPlatformAvailability c p maxPlatformAvailability
+        let count = min outSize maxPlatformAvailability
+        infos <- peekArray count p
+        forM_ [0..(count - 1)] $ \idx -> do
+          disposeCXPlatformAvailability (advancePtr p idx)
+        return (ad, dMsg, au, uMsg, infos)
+    dMsg' <- registerClangString $ return dMsg
+    uMsg' <- registerClangString $ return uMsg
+    return $ PlatformAvailabilityInfo ad dMsg' au uMsg' infos
+  where
+    maxPlatformAvailability = 32
+
+-- enum CXLanguageKind {
+--   CXLanguage_Invalid = 0,
+--   CXLanguage_C,
+--   CXLanguage_ObjC,
+--   CXLanguage_CPlusPlus
+-- };
+#c
+enum LanguageKind {
+    Language_Invalid   = CXLanguage_Invalid
+  , Language_C         = CXLanguage_C
+  , Language_ObjC      = CXLanguage_ObjC
+  , Language_CPlusPlus = CXLanguage_CPlusPlus
+  };
+#endc
+
+{#enum LanguageKind {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- enum CXLanguageKind clang_getCursorLanguage(CXCursor cursor);
+{# fun clang_getCursorLanguage {withVoided* %`Cursor a' } -> `Int' #}
+getCursorLanguage :: Cursor s -> IO LanguageKind
+getCursorLanguage c = clang_getCursorLanguage c >>= return . toEnum
+
+-- CXTranslationUnit clang_Cursor_getTranslationUnit(CXCursor);
+{# fun clang_Cursor_getTranslationUnit {withVoided* %`Cursor a' } -> `Ptr ()' id #}
+unsafe_Cursor_getTranslationUnit :: Cursor s -> IO (TranslationUnit ())
+unsafe_Cursor_getTranslationUnit c =
+  clang_Cursor_getTranslationUnit c >>= return . mkTranslationUnit
+
+-- Note that we do not register the translation unit! This function
+-- never creates a 'new' translation unit, so we don't need to dispose
+-- it. Moreover, since translation units aren't reference counted doing
+-- so will lead to crashes.
+cursor_getTranslationUnit :: ClangBase m => Cursor s' -> ClangT s m (TranslationUnit s)
+cursor_getTranslationUnit c = liftIO $ unsafeCoerce <$> unsafe_Cursor_getTranslationUnit c
+
+-- typedef struct CXCursorSetImpl *CXCursorSet;
+newtype CursorSet s = CursorSet { unCursorSet :: Ptr () }
+                      deriving (Eq, Ord, Typeable)
+
+instance ClangValue CursorSet
+
+-- void clang_disposeCXCursorSet(CXCursorSet cset);
+{# fun clang_disposeCXCursorSet { id `Ptr ()' } -> `()' #}
+disposeCXCursorSet :: CursorSet s -> IO ()
+disposeCXCursorSet cs = clang_disposeCXCursorSet (unCursorSet cs)
+
+registerCursorSet :: ClangBase m => IO (CursorSet ()) -> ClangT s m (CursorSet s)
+registerCursorSet action = do
+  (_, idx) <- clangAllocate (action >>= return . unsafeCoerce)
+                            (\i -> disposeCXCursorSet i)
+  return idx
+{-# INLINEABLE registerCursorSet #-}
+
+-- CXCursorSet clang_createCXCursorSet();
+{# fun clang_createCXCursorSet as clang_createCXCursorSet {} -> `Ptr ()' id #}
+unsafe_createCXCursorSet :: IO (CursorSet ())
+unsafe_createCXCursorSet = clang_createCXCursorSet >>= return . CursorSet
+
+createCXCursorSet :: ClangBase m => ClangT s m (CursorSet s)
+createCXCursorSet = registerCursorSet unsafe_createCXCursorSet
+
+-- unsigned clang_CXCursorSet_contains(CXCursorSet cset, CXCursor cursor);
+{# fun clang_CXCursorSet_contains {id `Ptr ()' ,withVoided* %`Cursor a' } -> `Bool' toBool #}
+cXCursorSet_contains :: CursorSet s -> Cursor s' -> IO Bool
+cXCursorSet_contains cs c =
+  clang_CXCursorSet_contains (unCursorSet cs) c
+
+-- unsigned clang_CXCursorSet_insert(CXCursorSet cset, CXCursor cursor);
+{# fun clang_CXCursorSet_insert {id `Ptr ()', withVoided* %`Cursor a' } -> `Bool' toBool #}
+cXCursorSet_insert :: CursorSet s -> Cursor s' -> IO Bool
+cXCursorSet_insert cs c =
+  clang_CXCursorSet_insert (unCursorSet cs) c
+
+-- CXCursor clang_getCursorSemanticParent(CXCursor cursor);
+{# fun wrapped_clang_getCursorSemanticParent as clang_getCursorSemanticParent {withVoided* %`Cursor a' } -> `Ptr (Cursor s)' castPtr #}
+getCursorSemanticParent :: Proxy s -> Cursor s' -> IO (Cursor s)
+getCursorSemanticParent _ c =
+  clang_getCursorSemanticParent c >>= peek
+
+-- CXCursor clang_getCursorLexicalParent(CXCursor cursor);
+{# fun wrapped_clang_getCursorLexicalParent as clang_getCursorLexicalParent {withVoided* %`Cursor a' } -> `Ptr (Cursor s)' castPtr #}
+getCursorLexicalParent :: Proxy s -> Cursor s' -> IO (Cursor s)
+getCursorLexicalParent _ c =
+  clang_getCursorLexicalParent c >>= peek
+
+-- void clang_disposeOverriddenCursors(CXCursor *overridden);
+{# fun clang_disposeOverriddenCursors { id `Ptr ()' } -> `()' #}
+disposeOverridden :: CursorList s -> IO ()
+disposeOverridden cl =
+ let (csPtr, _) = fromCursorList cl in
+ clang_disposeOverriddenCursors csPtr
+
+registerOverriddenList :: ClangBase m => IO UnsafeCursorList -> ClangT s m (CursorList s)
+registerOverriddenList action = do
+    (_, cursorList) <- clangAllocate (action >>= cursorListToVector) disposeOverridden
+    return cursorList
+{-# INLINEABLE registerOverriddenList #-}
+
+-- void clang_getOverriddenCursors(CXCursor cursor, CXCursor **overridden, unsigned *num_overridden);
+{# fun clang_getOverriddenCursors {withVoided* %`Cursor a', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getOverriddenCursors :: Cursor s -> IO UnsafeCursorList
+unsafe_getOverriddenCursors c = do
+  cxListPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr (Cursor s)))))
+  n <- clang_getOverriddenCursors c (castPtr cxListPtr)
+  free cxListPtr
+  return (toCursorList (cxListPtr, (fromIntegral n)))
+
+getOverriddenCursors :: ClangBase m => Cursor s' -> ClangT s m (CursorList s)
+getOverriddenCursors = registerOverriddenList . unsafe_getOverriddenCursors
+
+-- CXFile clang_getIncludedFile(CXCursor cursor);
+{# fun clang_getIncludedFile {withVoided* %`Cursor a' } -> `Ptr ()' id #}
+getIncludedFile :: Proxy s -> Cursor s' -> IO (Maybe (File s))
+getIncludedFile _ c =
+  clang_getIncludedFile c >>= return . maybeFile . File . castPtr
+
+-- CXCursor clang_getCursor(CXTranslationUnit, CXSourceLocation);
+{# fun wrapped_clang_getCursor as clang_getCursor { id `Ptr ()' , withVoided* `SourceLocation a' } -> `Ptr (Cursor s)' castPtr #}
+getCursor :: Proxy s -> TranslationUnit s' -> SourceLocation s'' -> IO (Cursor s)
+getCursor _ t s = clang_getCursor (unTranslationUnit t) s >>= peek
+
+-- CXSourceLocation clang_getCursorLocation(CXCursor);
+{# fun wrapped_clang_getCursorLocation as clang_getCursorLocation {withVoided* %`Cursor a' } -> `Ptr (SourceLocation s)' castPtr #}
+getCursorLocation :: Proxy s -> Cursor s' -> IO (SourceLocation s)
+getCursorLocation _ c =
+  clang_getCursorLocation c>>= peek
+{-# INLINEABLE getCursorLocation #-}
+
+-- Variant of clang_getCursorLocation that fuses a call to clang_getSpellingLocation.
+getCursorSpellingLocation :: Proxy s -> Cursor s' -> IO (Maybe (File s), Int, Int, Int)
+getCursorSpellingLocation _ c =
+  allocaBytes {#sizeof PtrPtrCXFile #} (\ptrToFilePtr ->
+  alloca (\(linePtr :: (Ptr CUInt)) ->
+  alloca (\(columnPtr :: (Ptr CUInt)) ->
+  alloca (\(offsetPtr :: (Ptr CUInt)) -> do
+    slPtr <- clang_getCursorLocation c
+    peek slPtr >>= \sl -> clang_getSpellingLocation sl ptrToFilePtr linePtr columnPtr offsetPtr
+    filePtr <- {#get *CXFile #} ptrToFilePtr
+    let _maybeFile = maybeFile (File filePtr)
+    line <- peek linePtr
+    column <- peek columnPtr
+    offset <- peek offsetPtr
+    return (_maybeFile, fromIntegral line, fromIntegral column, fromIntegral offset)))))
+{-# INLINEABLE getCursorSpellingLocation #-}
+
+-- CXSourceRange clang_getCursorExtent(CXCursor);
+{# fun wrapped_clang_getCursorExtent as clang_getCursorExtent {withVoided* %`Cursor a' } -> `Ptr (SourceRange s)' castPtr #}
+getCursorExtent :: Proxy s -> Cursor s' -> IO (SourceRange s)
+getCursorExtent _ c =
+  clang_getCursorExtent c >>= peek
+{-# INLINEABLE getCursorExtent #-}
+
+-- enum CXTypeKind {
+--   CXType_Invalid = 0,
+--   CXType_Unexposed = 1,
+--   CXType_Void = 2,
+--   CXType_Bool = 3,
+--   CXType_Char_U = 4,
+--   CXType_UChar = 5,
+--   CXType_Char16 = 6,
+--   CXType_Char32 = 7,
+--   CXType_UShort = 8,
+--   CXType_UInt = 9,
+--   CXType_ULong = 10,
+--   CXType_ULongLong = 11,
+--   CXType_UInt128 = 12,
+--   CXType_Char_S = 13,
+--   CXType_SChar = 14,
+--   CXType_WChar = 15,
+--   CXType_Short = 16,
+--   CXType_Int = 17,
+--   CXType_Long = 18,
+--   CXType_LongLong = 19,
+--   CXType_Int128 = 20,
+--   CXType_Float = 21,
+--   CXType_Double = 22,
+--   CXType_LongDouble = 23,
+--   CXType_NullPtr = 24,
+--   CXType_Overload = 25,
+--   CXType_Dependent = 26,
+--   CXType_ObjCId = 27,
+--   CXType_ObjCClass = 28,
+--   CXType_ObjCSel = 29,
+--   CXType_FirstBuiltin = CXType_Void,
+--   CXType_LastBuiltin  = CXType_ObjCSel,
+--   CXType_Complex = 100,
+--   CXType_Pointer = 101,
+--   CXType_BlockPointer = 102,
+--   CXType_LValueReference = 103,
+--   CXType_RValueReference = 104,
+--   CXType_Record = 105,
+--   CXType_Enum = 106,
+--   CXType_Typedef = 107,
+--   CXType_ObjCInterface = 108,
+--   CXType_ObjCObjectPointer = 109,
+--   CXType_FunctionNoProto = 110,
+--   CXType_FunctionProto = 111
+--   CXType_ConstantArray = 112
+--   CXType_Vector = 113,
+--   CXType_IncompleteArray = 114,
+--   CXType_VariableArray = 115,
+--   CXType_DependentSizedArray = 116,
+--   CXType_MemberPointer = 117
+-- };
+
+#c
+enum TypeKind
+  { Type_Invalid             = CXType_Invalid
+  , Type_Unexposed           = CXType_Unexposed
+  , Type_Void                = CXType_Void
+  , Type_Bool                = CXType_Bool
+  , Type_Char_U              = CXType_Char_U
+  , Type_UChar               = CXType_UChar
+  , Type_Char16              = CXType_Char16
+  , Type_Char32              = CXType_Char32
+  , Type_UShort              = CXType_UShort
+  , Type_UInt                = CXType_UInt
+  , Type_ULong               = CXType_ULong
+  , Type_ULongLong           = CXType_ULongLong
+  , Type_UInt128             = CXType_UInt128
+  , Type_Char_S              = CXType_Char_S
+  , Type_SChar               = CXType_SChar
+  , Type_WChar               = CXType_WChar
+  , Type_Short               = CXType_Short
+  , Type_Int                 = CXType_Int
+  , Type_Long                = CXType_Long
+  , Type_LongLong            = CXType_LongLong
+  , Type_Int128              = CXType_Int128
+  , Type_Float               = CXType_Float
+  , Type_Double              = CXType_Double
+  , Type_LongDouble          = CXType_LongDouble
+  , Type_NullPtr             = CXType_NullPtr
+  , Type_Overload            = CXType_Overload
+  , Type_Dependent           = CXType_Dependent
+  , Type_ObjCId              = CXType_ObjCId
+  , Type_ObjCClass           = CXType_ObjCClass
+  , Type_ObjCSel             = CXType_ObjCSel
+  , Type_Complex             = CXType_Complex
+  , Type_Pointer             = CXType_Pointer
+  , Type_BlockPointer        = CXType_BlockPointer
+  , Type_LValueReference     = CXType_LValueReference
+  , Type_RValueReference     = CXType_RValueReference
+  , Type_Record              = CXType_Record
+  , Type_Enum                = CXType_Enum
+  , Type_Typedef             = CXType_Typedef
+  , Type_ObjCInterface       = CXType_ObjCInterface
+  , Type_ObjCObjectPointer   = CXType_ObjCObjectPointer
+  , Type_FunctionNoProto     = CXType_FunctionNoProto
+  , Type_FunctionProto       = CXType_FunctionProto
+  , Type_ConstantArray       = CXType_ConstantArray
+  , Type_Vector              = CXType_Vector
+  , Type_IncompleteArray     = CXType_IncompleteArray
+  , Type_VariableArray       = CXType_VariableArray
+  , Type_DependentSizedArray = CXType_DependentSizedArray
+  , Type_MemberPointer       = CXType_MemberPointer
+ };
+#endc
+{# enum TypeKind {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+type_FirstBuiltin, type_LastBuiltin :: TypeKind
+type_FirstBuiltin = Type_Void
+type_LastBuiltin  = Type_ObjCSel
+
+-- enum CXCallingConv {
+--   CXCallingConv_Default = 0,
+--   CXCallingConv_C = 1,
+--   CXCallingConv_X86StdCall = 2,
+--   CXCallingConv_X86FastCall = 3,
+--   CXCallingConv_X86ThisCall = 4,
+--   CXCallingConv_X86Pascal = 5,
+--   CXCallingConv_AAPCS = 6,
+--   CXCallingConv_AAPCS_VFP = 7,
+--   CXCallingConv_IntelOclBicc = 9,
+--   CXCallingConv_X86_64Win64 = 10,
+--   CXCallingConv_X86_64SysV = 11,
+--   CXCallingConv_Invalid = 100,
+--   CXCallingConv_Unexposed = 200
+-- };
+#c
+enum CallingConv
+  { CallingConv_Default     = CXCallingConv_Default
+  , CallingConv_C           = CXCallingConv_C
+  , CallingConv_X86StdCall  = CXCallingConv_X86StdCall
+  , CallingConv_X86FastCall = CXCallingConv_X86FastCall
+  , CallingConv_X86ThisCall = CXCallingConv_X86ThisCall
+  , CallingConv_X86Pascal   = CXCallingConv_X86Pascal
+  , CallingConv_AAPCS       = CXCallingConv_AAPCS
+  , CallingConv_AAPCS_VFP   = CXCallingConv_AAPCS_VFP
+  , CallingConv_IntelOclBic = CXCallingConv_IntelOclBicc
+  , CallingConv_X86_64Win64 = CXCallingConv_X86_64Win64
+  , CallingConv_X86_64SysV  = CXCallingConv_X86_64SysV
+  , CallingConv_Invalid     = CXCallingConv_Invalid
+  , CallingConv_Unexposed   = CXCallingConv_Unexposed
+ };
+#endc
+{# enum CallingConv {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- typedef struct {
+--   enum CXTypeKind kind;
+--   void *data[2];
+-- } CXType;
+data Type s = Type !TypeKind !(Ptr ()) !(Ptr ())
+              deriving (Eq, Ord, Typeable)
+
+instance ClangValue Type
+
+instance Storable (Type s) where
+    sizeOf _ = {#sizeof CXType #}
+    {-# INLINE sizeOf #-}
+
+    alignment _ = {#alignof CXType #}
+    {-# INLINE alignment #-}
+
+    peek p = do
+      kindCInt <- {#get CXType->kind #} p
+      ptrsArray <- {#get CXType->data #} p >>= peekArray 2
+      return $! Type (toEnum (fromIntegral kindCInt)) (ptrsArray !! 0) (ptrsArray !! 1)
+    {-# INLINE peek #-}
+
+    poke p (Type kind p0 p1)= do
+      ptrsArray <- mallocArray 2
+      pokeArray ptrsArray [p0,p1]
+      {#set CXType->kind #} p (fromIntegral (fromEnum kind))
+      {#set CXType->data #} p (castPtr ptrsArray)
+    {-# INLINE poke #-}
+
+getTypeKind :: Type s -> TypeKind
+getTypeKind (Type k _ _) = k
+
+-- CXType clang_getCursorType(CXCursor C);
+{# fun wrapped_clang_getCursorType as clang_getCursorType {withVoided* %`Cursor a' } -> `Ptr (Type s)' castPtr #}
+getCursorType :: Proxy s -> Cursor s' -> IO (Type s)
+getCursorType proxy c =
+  clang_getCursorType c >>= peek
+
+-- CXString clang_getTypeSpelling(CXType CT);
+{# fun wrapped_clang_getTypeSpelling as clang_getTypeSpelling {withVoided* %`Type a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getTypeSpelling :: (Type s) -> IO (ClangString ())
+unsafe_getTypeSpelling t = do
+ cxString <- clang_getTypeSpelling t
+ peek cxString
+
+getTypeSpelling :: ClangBase m => (Type s') -> ClangT s m (ClangString s)
+getTypeSpelling = registerClangString . unsafe_getTypeSpelling
+
+-- CXType clang_getTypedefDeclUnderlyingType(CXCursor C);
+{# fun wrapped_clang_getTypedefDeclUnderlyingType as clang_getTypedefDeclUnderlyingType {withVoided* %`Cursor a' } -> `Ptr (Type s)' castPtr #}
+getTypedefDeclUnderlyingType :: Proxy s -> Cursor s' -> IO (Type s)
+getTypedefDeclUnderlyingType proxy c =
+  clang_getTypedefDeclUnderlyingType c >>= peek
+
+-- CXType clang_getEnumDeclIntegerType(CXCursor C);
+{# fun wrapped_clang_getEnumDeclIntegerType as clang_getEnumDeclIntegerType {withVoided* %`Cursor a' } -> `Ptr (Type s)' castPtr #}
+getEnumDeclIntegerType :: Proxy s -> Cursor s' -> IO (Type s)
+getEnumDeclIntegerType proxy c =
+  clang_getEnumDeclIntegerType c >>= peek
+
+-- long long clang_getEnumConstantDeclValue(CXCursor);
+{# fun clang_getEnumConstantDeclValue {withVoided* %`Cursor a' } -> `Int64' #}
+getEnumConstantDeclValue :: Cursor s -> IO Int64
+getEnumConstantDeclValue c = clang_getEnumConstantDeclValue c
+
+-- unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor);
+{# fun clang_getEnumConstantDeclUnsignedValue {withVoided* %`Cursor a' } -> `Word64' #}
+getEnumConstantDeclUnsignedValue :: Cursor s -> IO Word64
+getEnumConstantDeclUnsignedValue c = clang_getEnumConstantDeclUnsignedValue c
+
+-- int clang_getFieldDeclBitWidth(CXCursor C);
+-- %fun clang_getFieldDeclBitWidth :: Cursor s -> IO Int
+{# fun clang_getFieldDeclBitWidth {withVoided* %`Cursor a' } -> `Int' #}
+getFieldDeclBitWidth :: Cursor s -> IO Int
+getFieldDeclBitWidth c = clang_getFieldDeclBitWidth c
+
+-- int clang_Cursor_getNumArguments(CXCursor C);
+{# fun clang_Cursor_getNumArguments {withVoided* %`Cursor a' } -> `Int' #}
+cursor_getNumArguments :: Cursor s -> IO Int
+cursor_getNumArguments c = clang_Cursor_getNumArguments c
+
+-- CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i);
+{# fun wrapped_clang_Cursor_getArgument as clang_Cursor_getArgument {withVoided* %`Cursor a', `Int' } -> `Ptr (Cursor s)' castPtr #}
+cursor_getArgument :: Proxy s -> Cursor s' -> Int -> IO (Cursor s)
+cursor_getArgument _ c i = clang_Cursor_getArgument c i >>= peek
+
+-- unsigned clang_equalTypes(CXType A, CXType B);
+{# fun clang_equalTypes {withVoided* %`Type a',withVoided* %`Type b' } -> `Bool' toBool #}
+equalTypes :: Type s -> Type s' -> IO Bool
+equalTypes t1 t2 = clang_equalTypes t1 t2
+
+-- CXType clang_getCanonicalType(CXType T);
+{# fun wrapped_clang_getCanonicalType as clang_getCanonicalType {withVoided* %`Type a' } -> `Ptr (Type s)' castPtr #}
+getCanonicalType :: Proxy s -> Type s' -> IO (Type s)
+getCanonicalType proxy t = do
+  cPtr <- clang_getCanonicalType t
+  peek cPtr
+
+-- unsigned clang_isConstQualifiedType(CXType T);
+{# fun clang_isConstQualifiedType {withVoided* %`Type a' } -> `Bool' toBool #}
+isConstQualifiedType :: Type s -> IO Bool
+isConstQualifiedType t = clang_isConstQualifiedType t
+
+-- unsigned clang_isVolatileQualifiedType(CXType T);
+{# fun clang_isVolatileQualifiedType {withVoided* %`Type a' } -> `Bool' toBool #}
+isVolatileQualifiedType :: Type s -> IO Bool
+isVolatileQualifiedType t = clang_isVolatileQualifiedType t
+
+-- unsigned clang_isRestrictQualifiedType(CXType T);
+{# fun clang_isRestrictQualifiedType {withVoided* %`Type a' } -> `Bool' toBool #}
+isRestrictQualifiedType :: Type s -> IO Bool
+isRestrictQualifiedType t = clang_isRestrictQualifiedType t
+
+-- CXType clang_getPointeeType(CXType T);
+{# fun wrapped_clang_getPointeeType as clang_getPointeeType { withVoided* %`Type a' } -> `Ptr (Type s)' castPtr #}
+getPointeeType :: Proxy s -> Type s' -> IO (Type s)
+getPointeeType proxy t = do
+  cPtr <- clang_getPointeeType t
+  peek cPtr
+
+-- CXCursor clang_getTypeDeclaration(CXType T);
+{# fun wrapped_clang_getTypeDeclaration as clang_getTypeDeclaration { withVoided* %`Type a' } -> `Ptr (Cursor s)' castPtr #}
+getTypeDeclaration :: Proxy s -> Type s' -> IO (Cursor s)
+getTypeDeclaration _ t = do
+  cPtr <- clang_getTypeDeclaration t
+  peek cPtr
+
+-- CXString clang_getDeclObjCTypeEncoding(CXCursor C);
+{# fun wrapped_clang_getDeclObjCTypeEncoding as clang_getDeclObjCTypeEncoding {withVoided* %`Cursor a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getDeclObjCTypeEncoding :: Cursor s -> IO (ClangString ())
+unsafe_getDeclObjCTypeEncoding c = clang_getDeclObjCTypeEncoding c >>= peek
+
+getDeclObjCTypeEncoding :: ClangBase m => Cursor s' -> ClangT s m (ClangString s)
+getDeclObjCTypeEncoding = registerClangString . unsafe_getDeclObjCTypeEncoding
+
+-- CXString clang_getTypeKindSpelling(enum CXTypeKind K);
+{# fun wrapped_clang_getTypeKindSpelling as clang_getTypeKindSpelling { `CInt' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getTypeKindSpelling :: TypeKind -> IO (ClangString ())
+unsafe_getTypeKindSpelling tk = clang_getTypeKindSpelling (fromIntegral (fromEnum tk)) >>= peek
+
+getTypeKindSpelling :: ClangBase m => TypeKind -> ClangT s m (ClangString s)
+getTypeKindSpelling = registerClangString . unsafe_getTypeKindSpelling
+
+-- enum CXCallingConv clang_getFunctionTypeCallingConv(CXType T);
+{# fun clang_getFunctionTypeCallingConv { withVoided* %`Type a' } -> `CInt' id #}
+getFunctionTypeCallingConv :: Type s' -> IO CallingConv
+getFunctionTypeCallingConv t = clang_getFunctionTypeCallingConv t >>= return . toEnum . fromIntegral
+
+-- CXType clang_getResultType(CXType T);
+{# fun wrapped_clang_getResultType as clang_getResultType { withVoided* %`Type a' } -> `Ptr (Type s)' castPtr #}
+getResultType :: Proxy s -> Type s' -> IO (Type s)
+getResultType proxy t = clang_getResultType t >>= peek
+
+-- CXType clang_getNumArgTypes(CXType T);
+{# fun clang_getNumArgTypes { withVoided* %`Type a' } -> `Int' #}
+getNumArgTypes :: Type s -> IO Int
+getNumArgTypes t = clang_getNumArgTypes t
+
+-- CXType clang_getArgType(CXType T, int i);
+{# fun wrapped_clang_getArgType as clang_getArgType { withVoided* %`Type a', `Int' } -> `Ptr (Type s)' castPtr #}
+getArgType :: Proxy s -> Type s' -> Int -> IO (Type s)
+getArgType proxy t i = clang_getArgType t i >>= peek
+
+-- unsigned clang_isFunctionTypeVariadic(CXType T);
+{# fun clang_isFunctionTypeVariadic { withVoided* %`Type a' } -> `CUInt' id #}
+isFunctionTypeVariadic :: Type s -> IO Bool
+isFunctionTypeVariadic t = clang_isFunctionTypeVariadic t >>= return . (toBool :: Int -> Bool) . fromIntegral
+
+-- CXType clang_getCursorResultType(CXCursor C);
+{# fun wrapped_clang_getCursorResultType as clang_getCursorResultType {withVoided* %`Cursor a' } -> `Ptr (Type s)' castPtr #}
+getCursorResultType :: Proxy s -> Cursor s' -> IO (Type s)
+getCursorResultType p c = clang_getCursorResultType c >>= peek
+
+-- unsigned clang_isPODType(CXType T);
+{# fun clang_isPODType {withVoided* %`Type a' } -> `Bool' toBool #}
+isPODType :: Type s -> IO Bool
+isPODType t = clang_isPODType t
+
+-- CXType clang_getElementType(CXType T);
+{# fun wrapped_clang_getElementType as clang_getElementType { withVoided* %`Type a' } -> `Ptr (Type s)' castPtr #}
+getElementType :: Proxy s -> Type s' -> IO (Type s)
+getElementType proxy t = clang_getElementType t >>= peek
+
+-- long long clang_getNumElements(CXType T);
+{# fun clang_getNumElements { withVoided* %`Type a' } -> `Int64' #}
+getNumElements :: Type s -> IO Int64
+getNumElements t = clang_getNumElements t
+
+-- CXType clang_getArrayElementType(CXType T);
+{# fun wrapped_clang_getArrayElementType as clang_getArrayElementType { withVoided* %`Type a' } -> `Ptr (Type s)' castPtr #}
+getArrayElementType :: Proxy s -> Type s' -> IO (Type s)
+getArrayElementType proxy t = clang_getArrayElementType t >>= peek
+
+-- long long clang_getArraySize(CXType T);
+{# fun clang_getArraySize { withVoided* %`Type a' } -> `Int64' #}
+getArraySize :: Type s -> IO Int64
+getArraySize t = clang_getArraySize t
+
+-- enum CXTypeLayoutError {
+--   CXTypeLayoutError_Invalid = -1,
+--   CXTypeLayoutError_Incomplete = -2,
+--   CXTypeLayoutError_Dependent = -3,
+--   CXTypeLayoutError_NotConstantSize = -4,
+--   CXTypeLayoutError_InvalidFieldName = -5
+-- };
+#c
+enum TypeLayoutError
+  { TypeLayoutError_Invalid          = CXTypeLayoutError_Invalid
+  , TypeLayoutError_Incomplete       = CXTypeLayoutError_Incomplete
+  , TypeLayoutError_Dependent        = CXTypeLayoutError_Dependent
+  , TypeLayoutError_NotConstantSize  = CXTypeLayoutError_NotConstantSize
+  , TypeLayoutError_InvalidFieldName = CXTypeLayoutError_InvalidFieldName
+ };
+#endc
+{# enum TypeLayoutError {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+int64OrLayoutError :: Int64 -> Either TypeLayoutError Int64
+int64OrLayoutError v | v == -1   = Left TypeLayoutError_Invalid
+                     | v == -2   = Left TypeLayoutError_Incomplete
+                     | v == -3   = Left TypeLayoutError_Dependent
+                     | v == -4   = Left TypeLayoutError_NotConstantSize
+                     | v == -5   = Left TypeLayoutError_InvalidFieldName
+                     | otherwise = Right v
+
+-- long long clang_Type_getAlignOf(CXType T);
+{# fun clang_Type_getAlignOf { withVoided* %`Type a' } -> `Int64' #}
+type_getAlignOf :: Type s -> IO (Either TypeLayoutError Int64)
+type_getAlignOf t = clang_Type_getAlignOf t >>= return . int64OrLayoutError
+
+-- CXType clang_Type_getClassType(CXType T);
+{# fun wrapped_clang_Type_getClassType as clang_Type_getClassType { withVoided* %`Type a' } -> `Ptr (Type s)' castPtr #}
+type_getClassType :: Proxy s -> Type s' -> IO (Type s)
+type_getClassType proxy t = clang_getElementType t >>= peek
+
+-- long long clang_Type_getSizeOf(CXType T);
+{# fun clang_Type_getSizeOf { withVoided* %`Type a' } -> `Int64' #}
+type_getSizeOf :: Type s -> IO (Either TypeLayoutError Int64)
+type_getSizeOf t = clang_Type_getSizeOf t >>= return . int64OrLayoutError
+
+-- long long clang_Type_getOffsetOf(CXType T, const char *S);
+{# fun clang_Type_getOffsetOf { withVoided* %`Type a' , `CString' } -> `Int64' #}
+unsafe_Type_getOffsetOf :: Type s -> CString -> IO (Either TypeLayoutError Int64)
+unsafe_Type_getOffsetOf t s = clang_Type_getOffsetOf t s >>= return . int64OrLayoutError
+
+type_getOffsetOf :: ClangBase m => Type s' -> B.ByteString
+                 -> ClangT s m (Either TypeLayoutError Int64)
+type_getOffsetOf t field = liftIO $ B.useAsCString field $ \cField ->
+  unsafe_Type_getOffsetOf t cField
+
+-- enum CXRefQualifierKind {
+--   CXRefQualifier_None = 0,
+--   CXRefQualifier_LValue,
+--   CXRefQualifier_RValue
+-- };
+#c
+enum RefQualifierKind
+  { RefQualifier_None   = CXRefQualifier_None
+  , RefQualifier_LValue = CXRefQualifier_LValue
+  , RefQualifier_RValue = CXRefQualifier_RValue
+  };
+#endc
+{# enum RefQualifierKind {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T);
+{# fun clang_Type_getCXXRefQualifier { withVoided* %`Type a' } -> `Int' #}
+type_getCXXRefQualifier :: Type s -> IO RefQualifierKind
+type_getCXXRefQualifier t = clang_Type_getCXXRefQualifier t >>= return . toEnum
+
+
+-- unsigned clang_Cursor_isBitField(CXCursor C);
+{# fun clang_Cursor_isBitField {withVoided* %`Cursor a' } -> `Bool' toBool #}
+isBitField :: Cursor s -> IO Bool
+isBitField c = clang_Cursor_isBitField c
+
+-- unsigned clang_isVirtualBase(CXCursor);
+{# fun clang_isVirtualBase {withVoided* %`Cursor a' } -> `Bool' toBool #}
+isVirtualBase :: Cursor s -> IO Bool
+isVirtualBase c = clang_Cursor_isBitField c
+
+-- enum CX_CXXAccessSpecifier {
+--   CX_CXXInvalidAccessSpecifier,
+--   CX_CXXPublic,
+--   CX_CXXProtected,
+--   CX_CXXPrivate
+-- };
+#c
+enum CXXAccessSpecifier
+  { CXXInvalidAccessSpecifier = CX_CXXInvalidAccessSpecifier
+  , CXXPublic                 = CX_CXXPublic
+  , CXXProtected              = CX_CXXProtected
+  , CXXPrivate                = CX_CXXPrivate
+  };
+#endc
+
+{# enum CXXAccessSpecifier {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor);
+{# fun clang_getCXXAccessSpecifier {withVoided* %`Cursor a' } -> `Int' #}
+getCXXAccessSpecifier :: Cursor s -> IO CXXAccessSpecifier
+getCXXAccessSpecifier c = clang_getCXXAccessSpecifier c >>= return . toEnum
+
+-- unsigned clang_getNumOverloadedDecls(CXCursor cursor);
+{# fun clang_getNumOverloadedDecls {withVoided* %`Cursor a' } -> `CUInt' #}
+getNumOverloadedDecls :: Cursor s -> IO Int
+getNumOverloadedDecls c = clang_getNumOverloadedDecls c >>= return . fromIntegral
+
+-- CXCursor clang_getOverloadedDecl(CXCursor cursor,
+--                                                 unsigned index);
+{# fun wrapped_clang_getOverloadedDecl as clang_getOverloadedDecl {withVoided* %`Cursor a', `Int' } -> `Ptr (Cursor s)' castPtr #}
+getOverloadedDecl :: Proxy s -> Cursor s' -> Int -> IO (Cursor s)
+getOverloadedDecl _ c i = clang_getOverloadedDecl c i >>= peek
+
+-- CXType clang_getIBOutletCollectionType(CXCursor);
+{# fun wrapped_clang_getIBOutletCollectionType as clang_getIBOutletCollectionType {withVoided* %`Cursor a' } -> `Ptr (Type s)' castPtr #}
+getIBOutletCollectionType :: Proxy s -> Cursor s' -> IO (Type s)
+getIBOutletCollectionType proxy c = clang_getIBOutletCollectionType c >>= peek
+
+
+-- We deliberately don't export the constructor for UnsafeCursorList.
+-- The only way to unwrap it is registerCursorList.
+type CursorList s = DVS.Vector (Cursor s)
+instance ClangValueList Cursor
+data UnsafeCursorList = UnsafeCursorList !(Ptr ()) !Int
+
+-- void freeCursorList(CXCursor* cursors);
+{# fun freeCursorList as freeCursorList' { id `Ptr ()' } -> `()' #}
+freeCursorList :: CursorList s -> IO ()
+freeCursorList cl = let (ptr, _) = fromCursorList cl in freeCursorList' ptr
+
+registerCursorList :: ClangBase m => IO UnsafeCursorList -> ClangT s m (CursorList s)
+registerCursorList action = do
+    (_, cursorList) <- clangAllocate (action >>= cursorListToVector) freeCursorList
+    return cursorList
+{-# INLINEABLE registerCursorList #-}
+
+cursorListToVector :: Storable a => UnsafeCursorList -> IO (DVS.Vector a)
+cursorListToVector (UnsafeCursorList cs n) = do
+  fptr <- newForeignPtr_ (castPtr cs)
+  return $ DVS.unsafeFromForeignPtr fptr 0 n
+{-# INLINE cursorListToVector #-}
+
+fromCursorList :: CursorList s -> (Ptr (), Int)
+fromCursorList cs = let (p, _, _) = DVS.unsafeToForeignPtr cs in
+                   (castPtr $ Foreign.ForeignPtr.Unsafe.unsafeForeignPtrToPtr p, DVS.length cs)
+
+toCursorList :: (Ptr (), Int) -> UnsafeCursorList
+toCursorList (cs, n) = UnsafeCursorList cs n
+
+-- A more efficient alternative to clang_visitChildren.
+-- void getChildren(CXCursor parent, CXCursor** childrenOut, unsigned* countOut)
+{# fun getChildren as getChildren' {withVoided* %`Cursor a', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getChildren :: Cursor s -> IO UnsafeCursorList
+unsafe_getChildren c =
+ do
+   cxListPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr ()))))
+   n <- getChildren' c cxListPtr
+   cxList <- peek cxListPtr
+   free cxListPtr
+   return (toCursorList (cxList, fromIntegral n))
+
+getChildren :: ClangBase m => Cursor s' -> ClangT s m (CursorList s)
+getChildren = registerCursorList . unsafe_getChildren
+
+-- Like getChildren, but gets all transitive descendants.
+-- void getDescendants(CXCursor parent, CXCursor** childrenOut, unsigned* countOut)
+{# fun getDescendants as getDescendants' {withVoided* %`Cursor a', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getDescendants :: Cursor s -> IO UnsafeCursorList
+unsafe_getDescendants c =
+ do
+   cxListPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Cursor s))))
+   n <- getDescendants' c cxListPtr
+   cxList <- peek cxListPtr
+   free cxListPtr
+   return (toCursorList (cxList, fromIntegral n))
+
+getDescendants :: ClangBase m => Cursor s' -> ClangT s m (CursorList s)
+getDescendants = registerCursorList . unsafe_getDescendants
+
+-- void getDeclarations(CXTranslationUnit tu, CXCursor** declsOut, unsigned* declCountOut);
+{# fun getDeclarations as getDeclarations' { id `Ptr ()', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getDeclarations :: TranslationUnit s -> IO UnsafeCursorList
+unsafe_getDeclarations t = do
+   cxListPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr (Cursor ())))))
+   n <- getDeclarations' (unTranslationUnit t) cxListPtr
+   cxList <- peek cxListPtr
+   free cxListPtr
+   return (toCursorList (cxList, fromIntegral n))
+
+getDeclarations :: ClangBase m => TranslationUnit s' -> ClangT s m (CursorList s)
+getDeclarations = registerCursorList . unsafe_getDeclarations
+
+-- void getReferences(CXTranslationUnit tu, CXCursor** declsOut, unsigned* declCountOut);
+{# fun getReferences as getReferences' { id `Ptr ()', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getReferences :: TranslationUnit s -> IO UnsafeCursorList
+unsafe_getReferences t = do
+   cxListPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr ()))))
+   n <- getReferences' (unTranslationUnit t) cxListPtr
+   cxList <- peek cxListPtr
+   free cxListPtr
+   return (toCursorList (cxList, fromIntegral n))
+
+getReferences :: ClangBase m => TranslationUnit s' -> ClangT s m (CursorList s)
+getReferences = registerCursorList . unsafe_getReferences
+
+-- void getDeclarationsAndReferences(CXTranslationUnit tu,
+--                                   CXCursor** declsOut, unsigned* declCountOut,
+--                                   CXCursor** refsOut, unsigned* refCountOut);
+{# fun getDeclarationsAndReferences as getDeclarationsAndReferences'
+     { id `Ptr ()', id `Ptr (Ptr ())', alloca- `CUInt' peek*, id `Ptr (Ptr ())' , alloca- `CUInt' peek* } -> `()' #}
+unsafe_getDeclarationsAndReferences :: TranslationUnit s -> IO (UnsafeCursorList, UnsafeCursorList)
+unsafe_getDeclarationsAndReferences t =
+  alloca (\(declsPtr :: Ptr (Ptr ())) ->
+  alloca (\(refsPtr :: Ptr (Ptr ())) -> do
+   (nDecls, nRefs) <- getDeclarationsAndReferences' (unTranslationUnit t) (castPtr declsPtr) (castPtr refsPtr)
+   decls <- peek declsPtr
+   refs <- peek refsPtr
+   return ((toCursorList (decls, fromIntegral nDecls)), (toCursorList (refs, fromIntegral nRefs)))))
+
+-- %fun unsafe_getDeclarationsAndReferences :: TranslationUnit s -> IO (UnsafeCursorList, UnsafeCursorList)
+-- %call (translationUnit t)
+-- %code CXCursor* decls; unsigned declCount;
+-- %     CXCursor* refs; unsigned refCount;
+-- %     getDeclarationsAndReferences(t, &decls, &declCount, &refs, &refCount);
+-- %result (cursorList decls declCount, cursorList refs refCount)
+
+getDeclarationsAndReferences :: ClangBase m => TranslationUnit s'
+                             -> ClangT s m (CursorList s, CursorList s)
+getDeclarationsAndReferences tu = do
+  (ds, rs) <- liftIO $ unsafe_getDeclarationsAndReferences tu
+  (,) <$> registerCursorList (return ds) <*> registerCursorList (return rs)
+
+data ParentedCursor s = ParentedCursor
+  { parentCursor :: !(Cursor s)
+  , childCursor  :: !(Cursor s)
+  } deriving (Eq, Ord, Typeable)
+
+instance ClangValue ParentedCursor
+
+instance Storable (ParentedCursor s) where
+    sizeOf _ = sizeOfParentedCursor
+    {-# INLINE sizeOf #-}
+
+    alignment _ = alignOfParentedCursor
+    {-# INLINE alignment #-}
+
+    peek p = do
+      parent <- peekByteOff p offsetParentedCursorParent
+      child <- peekByteOff p offsetParentedCursorCursor
+      return $! ParentedCursor parent child
+    {-# INLINE peek #-}
+
+    poke p (ParentedCursor parent child) = do
+      pokeByteOff p offsetParentedCursorParent parent
+      pokeByteOff p offsetParentedCursorCursor child
+    {-# INLINE poke #-}
+
+-- We deliberately don't export the constructor for UnsafeParentedCursorList.
+-- The only way to unwrap it is registerParentedCursorList.
+type ParentedCursorList s = DVS.Vector (ParentedCursor s)
+instance ClangValueList ParentedCursor
+data UnsafeParentedCursorList = UnsafeParentedCursorList !(Ptr ()) !Int
+
+-- void freeParentedCursorList(struct ParentedCursor* parentedCursors);
+{# fun freeParentedCursorList as freeParentedCursorList' { id `Ptr ()' } -> `()' #}
+freeParentedCursorList :: ParentedCursorList s -> IO ()
+freeParentedCursorList pcl = let (pclPtr, _ ) = fromParentedCursorList pcl in freeParentedCursorList' pclPtr
+
+registerParentedCursorList :: ClangBase m => IO UnsafeParentedCursorList
+                           -> ClangT s m (ParentedCursorList s)
+registerParentedCursorList action = do
+    (_, pcList) <- clangAllocate (action >>= mkSafe) freeParentedCursorList
+    return pcList
+  where
+    mkSafe (UnsafeParentedCursorList cs n) = do
+      fptr <- newForeignPtr_ (castPtr cs)
+      return $ DVS.unsafeFromForeignPtr fptr 0 n
+{-# INLINEABLE registerParentedCursorList #-}
+
+fromParentedCursorList :: ParentedCursorList s -> (Ptr (), Int)
+fromParentedCursorList cs =
+  let (p, _, _) = DVS.unsafeToForeignPtr cs in
+  (castPtr $ Foreign.ForeignPtr.Unsafe.unsafeForeignPtrToPtr p, DVS.length cs)
+
+toParentedCursorList :: (Ptr (), Int) -> UnsafeParentedCursorList
+toParentedCursorList (cs, n) = UnsafeParentedCursorList cs n
+
+-- %dis parentedCursorList cs n = <fromParentedCursorList/toParentedCursorList> (ptr cs) (int n)
+
+-- Like getParentedDescendants, but pairs each descendant with its parent.
+-- void getParentedDescendants(CXCursor parent, struct ParentedCursor** descendantsOut,
+--                             unsigned* countOut)
+{# fun getParentedDescendants as getParentedDescendants' {withVoided* %`Cursor a', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getParentedDescendants :: Cursor s -> IO UnsafeParentedCursorList
+unsafe_getParentedDescendants c =
+ do
+   cxListPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr ()))))
+   n <- getParentedDescendants' c cxListPtr
+   cxList <- peek cxListPtr
+   free cxListPtr
+   return (toParentedCursorList (cxList, fromIntegral n))
+
+getParentedDescendants :: ClangBase m => Cursor s' -> ClangT s m (ParentedCursorList s)
+getParentedDescendants = registerParentedCursorList . unsafe_getParentedDescendants
+
+-- void getParentedDeclarations(CXTranslationUnit tu, CXCursor** declsOut, unsigned* declCountOut);
+{# fun getParentedDeclarations as getParentedDeclarations' { id `Ptr ()', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getParentedDeclarations :: TranslationUnit s -> IO UnsafeParentedCursorList
+unsafe_getParentedDeclarations t = do
+   cxListPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr (Cursor ())))))
+   n <- getParentedDeclarations' (unTranslationUnit t) (castPtr cxListPtr)
+   cxList <- peek cxListPtr
+   free cxListPtr
+   return (toParentedCursorList (cxList, fromIntegral n))
+
+getParentedDeclarations :: ClangBase m => TranslationUnit s' -> ClangT s m (ParentedCursorList s)
+getParentedDeclarations = registerParentedCursorList . unsafe_getParentedDeclarations
+
+-- void getParentedReferences(CXTranslationUnit tu, CXCursor** declsOut, unsigned* declCountOut);
+{# fun getParentedReferences as getParentedReferences' { id `Ptr ()', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getParentedReferences :: TranslationUnit s -> IO UnsafeParentedCursorList
+unsafe_getParentedReferences t = do
+   cxListPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr ()))))
+   n <- getParentedReferences' (unTranslationUnit t) cxListPtr
+   cxList <- peek cxListPtr
+   free cxListPtr
+   return (toParentedCursorList (cxList, fromIntegral n))
+
+getParentedReferences :: ClangBase m => TranslationUnit s' -> ClangT s m (ParentedCursorList s)
+getParentedReferences = registerParentedCursorList . unsafe_getParentedReferences
+
+-- void getParentedDeclarationsAndReferences(CXTranslationUnit tu,
+--                                           ParentedCursor** declsOut,
+--                                           unsigned* declCountOut,
+--                                           ParentedCursor** refsOut,
+--                                           unsigned* refCountOut);
+{# fun getParentedDeclarationsAndReferences as getParentedDeclarationsAndReferences'
+     { id `Ptr ()', id `Ptr (Ptr ())', alloca- `CUInt' peek*, id `Ptr (Ptr ())' , alloca- `CUInt' peek* } -> `()' #}
+unsafe_getParentedDeclarationsAndReferences :: TranslationUnit s -> IO (UnsafeParentedCursorList, UnsafeParentedCursorList)
+unsafe_getParentedDeclarationsAndReferences t = do
+   declsPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr ()))))
+   refsPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr ()))))
+   (nDecls, nRefs) <- getParentedDeclarationsAndReferences' (unTranslationUnit t) declsPtr refsPtr
+   decls <- peek declsPtr
+   refs <- peek refsPtr
+   free declsPtr
+   free refsPtr
+   return ((toParentedCursorList (decls, fromIntegral nDecls)), (toParentedCursorList (refs, fromIntegral nRefs)))
+
+getParentedDeclarationsAndReferences :: ClangBase m => TranslationUnit s'
+                                     -> ClangT s m (ParentedCursorList s, ParentedCursorList s)
+getParentedDeclarationsAndReferences tu = do
+  (ds, rs) <- liftIO $ unsafe_getParentedDeclarationsAndReferences tu
+  (,) <$> registerParentedCursorList (return ds) <*> registerParentedCursorList (return rs)
+
+-- CXString clang_getCursorUSR(CXCursor);
+{# fun wrapped_clang_getCursorUSR as clang_getCursorUSR {withVoided* %`Cursor a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCursorUSR :: Cursor s -> IO (ClangString ())
+unsafe_getCursorUSR c =
+  clang_getCursorUSR c >>= peek
+
+getCursorUSR :: ClangBase m => Cursor s' -> ClangT s m (ClangString s)
+getCursorUSR = registerClangString . unsafe_getCursorUSR
+
+-- CXString clang_constructUSR_ObjCClass(const char *class_name);
+{# fun wrapped_clang_constructUSR_ObjCClass as clang_constructUSR_ObjCClass { `CString' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_constructUSR_ObjCClass :: String -> IO (ClangString ())
+unsafe_constructUSR_ObjCClass s = withCString s (\sPtr -> clang_constructUSR_ObjCClass sPtr >>= peek)
+
+constructUSR_ObjCClass :: ClangBase m => String -> ClangT s m (ClangString s)
+constructUSR_ObjCClass = registerClangString . unsafe_constructUSR_ObjCClass
+
+-- CXString
+--   clang_constructUSR_ObjCCategory(const char *class_name,
+--                                  const char *category_name);
+{# fun wrapped_clang_constructUSR_ObjCCategory as clang_constructUSR_ObjCCategory { `CString', `CString' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_constructUSR_ObjCCategory :: String -> String -> IO (ClangString ())
+unsafe_constructUSR_ObjCCategory s p =
+  withCString s (\sPtr ->
+  withCString p (\pPtr ->
+    clang_constructUSR_ObjCCategory sPtr pPtr >>= peek))
+
+constructUSR_ObjCCategory :: ClangBase m => String -> String -> ClangT s m (ClangString s)
+constructUSR_ObjCCategory = (registerClangString .) . unsafe_constructUSR_ObjCCategory
+
+-- CXString
+--   clang_constructUSR_ObjCProtocol(const char *protocol_name);
+{# fun wrapped_clang_constructUSR_ObjCProtocol as clang_constructUSR_ObjCProtocol { `CString' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_constructUSR_ObjCProtocol :: String -> IO (ClangString ())
+unsafe_constructUSR_ObjCProtocol s = withCString s (\sPtr -> clang_constructUSR_ObjCProtocol sPtr >>= peek)
+
+constructUSR_ObjCProtocol :: ClangBase m => String -> ClangT s m (ClangString s)
+constructUSR_ObjCProtocol = registerClangString . unsafe_constructUSR_ObjCProtocol
+
+-- CXString clang_constructUSR_ObjCIvar(const char *name,
+--                                                     CXString classUSR);
+{# fun wrapped_clang_constructUSR_ObjCIvar as clang_constructUSR_ObjCIvar { `CString' , id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_constructUSR_ObjCIvar :: String -> Ptr () -> Word32 -> IO (ClangString ())
+unsafe_constructUSR_ObjCIvar s d f =
+  let clangString = ClangString  d f in
+  withCString s (\sPtr -> new clangString >>= \cs -> clang_constructUSR_ObjCIvar sPtr (castPtr cs) >>= peek)
+
+constructUSR_ObjCIvar :: ClangBase m => String -> ClangString s' -> ClangT s m (ClangString s)
+constructUSR_ObjCIvar s (ClangString d f) = registerClangString $ unsafe_constructUSR_ObjCIvar s d f
+
+-- CXString clang_constructUSR_ObjCMethod(const char *name,
+--                                                       unsigned isInstanceMethod,
+--                                                       CXString classUSR);
+{# fun wrapped_clang_constructUSR_ObjCMethod as clang_constructUSR_ObjCMethod { `CString' , `CUInt' , id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_constructUSR_ObjCMethod :: String -> Bool -> Ptr () -> Word32 -> IO (ClangString ())
+unsafe_constructUSR_ObjCMethod s b d f =
+  let clangString = ClangString  d f in
+  withCString s (\sPtr -> (new clangString >>= \cs -> clang_constructUSR_ObjCMethod sPtr (fromIntegral ((fromBool b) :: Int)) (castPtr cs) >>= peek))
+
+constructUSR_ObjCMethod :: ClangBase m => String -> Bool -> ClangString s' -> ClangT s m (ClangString s)
+constructUSR_ObjCMethod s b (ClangString d f) =
+  registerClangString $ unsafe_constructUSR_ObjCMethod s b d f
+
+-- CXString clang_constructUSR_ObjCProperty(const char *property,
+--                                                         CXString classUSR);
+{# fun wrapped_clang_constructUSR_ObjCProperty as clang_constructUSR_ObjCProperty { `CString' , id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_constructUSR_ObjCProperty :: String -> Ptr () -> Word32 -> IO (ClangString ())
+unsafe_constructUSR_ObjCProperty s d f =
+  let clangString = ClangString  d f in
+  withCString s (\sPtr -> (new clangString >>= \cs -> clang_constructUSR_ObjCProperty sPtr (castPtr cs) >>= peek))
+
+constructUSR_ObjCProperty :: ClangBase m => String -> ClangString s' -> ClangT s m (ClangString s)
+constructUSR_ObjCProperty s (ClangString d f) =
+  registerClangString $ unsafe_constructUSR_ObjCProperty s d f
+
+-- CXString clang_getCursorSpelling(CXCursor);
+{# fun wrapped_clang_getCursorSpelling as clang_getCursorSpelling {withVoided* %`Cursor a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCursorSpelling :: Cursor s -> IO (ClangString ())
+unsafe_getCursorSpelling c =
+  clang_getCursorSpelling c >>= peek
+
+getCursorSpelling :: ClangBase m => Cursor s' -> ClangT s m (ClangString s)
+getCursorSpelling = registerClangString . unsafe_getCursorSpelling
+
+-- CXSourceRange clang_Cursor_getSpellingNameRange(CXCursor,
+--                                                 unsigned pieceIndex,
+--                                                 unsigned options);
+{# fun wrapped_clang_Cursor_getSpellingNameRange as clang_Cursor_getSpellingNameRange {withVoided* %`Cursor a', `Int', `Int' } -> `Ptr (SourceRange s)' castPtr #}
+cursor_getSpellingNameRange :: Proxy s -> Cursor s' -> Int -> IO (SourceRange s)
+cursor_getSpellingNameRange _ c i = clang_Cursor_getSpellingNameRange c i 0 >>= peek
+
+-- CXString clang_getCursorDisplayName(CXCursor);
+{# fun wrapped_clang_getCursorDisplayName as clang_getCursorDisplayName {withVoided* %`Cursor a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCursorDisplayName :: Cursor s -> IO (ClangString ())
+unsafe_getCursorDisplayName c =
+  clang_getCursorDisplayName c >>= peek
+
+getCursorDisplayName :: ClangBase m => Cursor s' -> ClangT s m (ClangString s)
+getCursorDisplayName = registerClangString . unsafe_getCursorDisplayName
+
+-- CXCursor clang_getCursorReferenced(CXCursor);
+{# fun wrapped_clang_getCursorReferenced as clang_getCursorReferenced {withVoided* %`Cursor a' } -> `Ptr (Cursor s)' castPtr #}
+getCursorReferenced :: Proxy s -> Cursor s' -> IO (Cursor s)
+getCursorReferenced _ c =
+  clang_getCursorReferenced c >>= peek
+
+-- CXCursor clang_getCursorDefinition(CXCursor);
+{# fun wrapped_clang_getCursorDefinition as clang_getCursorDefinition {withVoided* %`Cursor a' } -> `Ptr (Cursor s)' castPtr #}
+getCursorDefinition :: Proxy s -> Cursor s' -> IO (Cursor s)
+getCursorDefinition _ c = clang_getCursorDefinition c >>= peek
+
+-- unsigned clang_isCursorDefinition(CXCursor);
+{# fun clang_isCursorDefinition {withVoided* %`Cursor a' } -> `Bool' toBool #}
+isCursorDefinition :: Cursor s -> IO Bool
+isCursorDefinition c = clang_isCursorDefinition c
+
+-- unsigned clang_Cursor_isDynamicCall(CXCursor);
+{# fun clang_Cursor_isDynamicCall {withVoided* %`Cursor a' } -> `Bool' toBool #}
+cursor_isDynamicCall :: Cursor s -> IO Bool
+cursor_isDynamicCall c = clang_Cursor_isDynamicCall c
+
+-- CXCursor clang_getCanonicalCursor(CXCursor);
+{# fun wrapped_clang_getCanonicalCursor as clang_getCanonicalCursor {withVoided* %`Cursor a' } -> `Ptr (Cursor s)' castPtr #}
+getCanonicalCursor :: Proxy s -> Cursor s' -> IO (Cursor s)
+getCanonicalCursor _ c =
+  clang_getCanonicalCursor c >>= peek
+
+-- int clang_Cursor_getObjCSelectorIndex(CXCursor);
+{# fun clang_Cursor_getObjCSelectorIndex {withVoided* %`Cursor a' } -> `Int'  #}
+cursor_getObjCSelectorIndex :: Cursor s -> IO Int
+cursor_getObjCSelectorIndex c = clang_Cursor_getObjCSelectorIndex c
+
+-- CXType clang_Cursor_getReceiverType(CXCursor C);
+{# fun wrapped_clang_Cursor_getReceiverType as clang_Cursor_getReceiverType {withVoided* %`Cursor a' } -> `Ptr (Type s)' castPtr #}
+cursor_getReceiverType :: Proxy s -> Cursor s' -> IO (Type s)
+cursor_getReceiverType proxy c =
+  clang_Cursor_getReceiverType c >>= peek
+
+-- typedef enum {
+--   CXObjCPropertyAttr_noattr    = 0x00,
+--   CXObjCPropertyAttr_readonly  = 0x01,
+--   CXObjCPropertyAttr_getter    = 0x02,
+--   CXObjCPropertyAttr_assign    = 0x04,
+--   CXObjCPropertyAttr_readwrite = 0x08,
+--   CXObjCPropertyAttr_retain    = 0x10,
+--   CXObjCPropertyAttr_copy      = 0x20,
+--   CXObjCPropertyAttr_nonatomic = 0x40,
+--   CXObjCPropertyAttr_setter    = 0x80,
+--   CXObjCPropertyAttr_atomic    = 0x100,
+--   CXObjCPropertyAttr_weak      = 0x200,
+--   CXObjCPropertyAttr_strong    = 0x400,
+--   CXObjCPropertyAttr_unsafe_unretained = 0x800
+-- } CXObjCPropertyAttrKind;
+
+#c
+enum ObjCPropertyAttrKind
+  { ObjCPropertyAttr_noattr           = CXObjCPropertyAttr_noattr
+  , ObjCPropertyAttr_readonly         = CXObjCPropertyAttr_readonly
+  , ObjCPropertyAttr_getter           = CXObjCPropertyAttr_getter
+  , ObjCPropertyAttr_assign           = CXObjCPropertyAttr_assign
+  , ObjCPropertyAttr_readwrite        = CXObjCPropertyAttr_readwrite
+  , ObjCPropertyAttr_retain           = CXObjCPropertyAttr_retain
+  , ObjCPropertyAttr_copy             = CXObjCPropertyAttr_copy
+  , ObjCPropertyAttr_nonatomic        = CXObjCPropertyAttr_nonatomic
+  , ObjCPropertyAttr_setter           = CXObjCPropertyAttr_setter
+  , ObjCPropertyAttr_atomic           = CXObjCPropertyAttr_atomic
+  , ObjCPropertyAttr_weak             = CXObjCPropertyAttr_weak
+  , ObjCPropertyAttr_strong           = CXObjCPropertyAttr_strong
+  , ObjCPropertyAttr_unsafe_unretained= CXObjCPropertyAttr_unsafe_unretained
+ };
+#endc
+{# enum ObjCPropertyAttrKind {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags ObjCPropertyAttrKind where
+  toBit ObjCPropertyAttr_noattr            = 0x0
+  toBit ObjCPropertyAttr_readonly          = 0x1
+  toBit ObjCPropertyAttr_getter            = 0x2
+  toBit ObjCPropertyAttr_assign            = 0x4
+  toBit ObjCPropertyAttr_readwrite         = 0x8
+  toBit ObjCPropertyAttr_retain            = 0x10
+  toBit ObjCPropertyAttr_copy              = 0x20
+  toBit ObjCPropertyAttr_nonatomic         = 0x40
+  toBit ObjCPropertyAttr_setter            = 0x80
+  toBit ObjCPropertyAttr_atomic            = 0x100
+  toBit ObjCPropertyAttr_weak              = 0x200
+  toBit ObjCPropertyAttr_strong            = 0x400
+  toBit ObjCPropertyAttr_unsafe_unretained = 0x800
+
+-- unsigned clang_Cursor_getObjCPropertyAttributes(CXCursor C, unsigned reserved);
+{# fun clang_Cursor_getObjCPropertyAttributes {withVoided* %`Cursor a', `Int' } -> `CUInt' #}
+cursor_getObjCPropertyAttributes :: Cursor s -> IO Int
+cursor_getObjCPropertyAttributes c = clang_Cursor_getObjCPropertyAttributes c 0 >>= return . fromIntegral
+
+-- typedef enum {
+--   CXObjCDeclQualifier_None = 0x0,
+--   CXObjCDeclQualifier_In = 0x1,
+--   CXObjCDeclQualifier_Inout = 0x2,
+--   CXObjCDeclQualifier_Out = 0x4,
+--   CXObjCDeclQualifier_Bycopy = 0x8,
+--   CXObjCDeclQualifier_Byref = 0x10,
+--   CXObjCDeclQualifier_Oneway = 0x20
+-- } CXObjCDeclQualifierKind;
+
+#c
+enum ObjCDeclQualifierKind
+  { ObjCDeclQualifier_None   = CXObjCDeclQualifier_None
+  , ObjCDeclQualifier_In     = CXObjCDeclQualifier_In
+  , ObjCDeclQualifier_Inout  = CXObjCDeclQualifier_Inout
+  , ObjCDeclQualifier_Out    = CXObjCDeclQualifier_Out
+  , ObjCDeclQualifier_Bycopy = CXObjCDeclQualifier_Bycopy
+  , ObjCDeclQualifier_Byref  = CXObjCDeclQualifier_Byref
+  , ObjCDeclQualifier_Oneway = CXObjCDeclQualifier_Oneway
+ };
+#endc
+{# enum ObjCDeclQualifierKind {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags ObjCDeclQualifierKind where
+  toBit ObjCDeclQualifier_None   = 0x0
+  toBit ObjCDeclQualifier_In     = 0x1
+  toBit ObjCDeclQualifier_Inout  = 0x2
+  toBit ObjCDeclQualifier_Out    = 0x4
+  toBit ObjCDeclQualifier_Bycopy = 0x8
+  toBit ObjCDeclQualifier_Byref  = 0x10
+  toBit ObjCDeclQualifier_Oneway = 0x20
+
+-- unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C);
+{# fun clang_Cursor_getObjCDeclQualifiers {withVoided* %`Cursor a' } -> `CUInt' #}
+cursor_getObjCDeclQualifiers :: Cursor s -> IO Int
+cursor_getObjCDeclQualifiers c =
+  clang_Cursor_getObjCDeclQualifiers c >>= return . fromIntegral
+
+-- unsigned clang_Cursor_isObjCOptional(CXCursor);
+{# fun clang_Cursor_isObjCOptional {withVoided* %`Cursor a' } -> `Bool' toBool #}
+cursor_isObjCOptional :: Cursor s -> IO Bool
+cursor_isObjCOptional c = clang_Cursor_isObjCOptional c
+
+-- unsigned clang_Cursor_isVariadic(CXCursor);
+{# fun clang_Cursor_isVariadic {withVoided* %`Cursor a' } -> `Bool' toBool #}
+cursor_isVariadic :: Cursor s -> IO Bool
+cursor_isVariadic c = clang_Cursor_isVariadic c
+
+-- CXSourceRange clang_Cursor_getCommentRange(CXCursor C);
+{# fun wrapped_clang_Cursor_getCommentRange as clang_Cursor_getCommentRange {withVoided* %`Cursor a' } -> `Ptr (SourceRange s)' castPtr #}
+cursor_getCommentRange :: Proxy s -> Cursor s' -> IO (SourceRange s)
+cursor_getCommentRange _ c = clang_Cursor_getCommentRange c >>= peek
+
+-- CXString clang_Cursor_getRawCommentText(CXCursor C);
+{# fun wrapped_clang_Cursor_getRawCommentText as clang_Cursor_getRawCommentText {withVoided* %`Cursor a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_Cursor_getRawCommentText :: Cursor s -> IO (ClangString ())
+unsafe_Cursor_getRawCommentText c =
+  clang_Cursor_getRawCommentText c >>= peek
+
+cursor_getRawCommentText :: ClangBase m => Cursor s' -> ClangT s m (ClangString s)
+cursor_getRawCommentText = registerClangString . unsafe_Cursor_getRawCommentText
+
+-- CXString clang_Cursor_getBriefCommentText(CXCursor C);
+{# fun wrapped_clang_Cursor_getBriefCommentText as clang_Cursor_getBriefCommentText {withVoided* %`Cursor a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_Cursor_getBriefCommentText :: Cursor s -> IO (ClangString ())
+unsafe_Cursor_getBriefCommentText c =
+  clang_Cursor_getBriefCommentText c >>= peek
+
+cursor_getBriefCommentText :: ClangBase m => Cursor s' -> ClangT s m (ClangString s)
+cursor_getBriefCommentText = registerClangString . unsafe_Cursor_getBriefCommentText
+
+-- CXComment clang_Cursor_getParsedComment(CXCursor C);
+
+{# fun wrapped_clang_Cursor_getParsedComment as clang_Cursor_getParsedComment {withVoided* %`Cursor a' } -> `Ptr (Comment s)' castPtr #}
+cursor_getParsedComment :: Proxy s -> Cursor s' -> IO (Comment s)
+cursor_getParsedComment _ c =
+  clang_Cursor_getParsedComment c >>= peek
+
+-- typedef void *CXModule;
+newtype Module s = Module { unModule :: Ptr () }
+                   deriving (Eq, Ord, Typeable)
+
+instance ClangValue Module
+
+-- %dis cxmodule p = <unModule/Module> (ptr p)
+
+maybeModule :: Module s' -> Maybe (Module s)
+maybeModule (Module p) | p == nullPtr = Nothing
+maybeModule f                         = Just (unsafeCoerce f)
+
+unMaybeModule :: Maybe (Module s') -> Module s
+unMaybeModule (Just f) = unsafeCoerce f
+unMaybeModule Nothing  = Module nullPtr
+
+-- CXModule clang_Cursor_getModule(CXCursor C);
+{# fun clang_Cursor_getModule {withVoided* %`Cursor a' } -> `Ptr ()' id #}
+cursor_getModule :: Proxy s -> Cursor s' -> IO (Module s)
+cursor_getModule _ c =
+  clang_Cursor_getModule c >>= return . Module
+
+-- CXFile clang_Module_getASTFile(CXModule Module);
+{# fun clang_Module_getASTFile { id `Ptr ()' } -> `Ptr ()' id #}
+module_getASTFile :: Proxy s -> Module s' -> IO (File s)
+module_getASTFile _ m = clang_Module_getASTFile (unModule m) >>= return . File
+
+-- CXModule clang_Module_getParent(CXModule Module);
+{# fun clang_Module_getParent { id `Ptr ()' } -> `Ptr ()' id #}
+module_getParent :: Proxy s -> Module s' -> IO (Maybe (Module s))
+module_getParent _ m = clang_Module_getParent (unModule m) >>= return . maybeModule . Module
+
+-- CXString clang_Module_getName(CXModule Module);
+{# fun wrapped_clang_Module_getName as clang_Module_getName { id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_Module_getName :: Module s -> IO (ClangString ())
+unsafe_Module_getName m = clang_Module_getName (unModule m) >>= peek
+
+module_getName :: ClangBase m => Module s' -> ClangT s m (ClangString s)
+module_getName = registerClangString . unsafe_Module_getName
+
+-- CXString clang_Module_getFullName(CXModule Module);
+{# fun wrapped_clang_Module_getFullName as clang_Module_getFullName { id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_Module_getFullName :: Module s -> IO (ClangString ())
+unsafe_Module_getFullName m = clang_Module_getFullName (unModule m) >>= peek
+
+module_getFullName :: ClangBase m => Module s' -> ClangT s m (ClangString s)
+module_getFullName = registerClangString . unsafe_Module_getFullName
+
+-- unsigned clang_Module_getNumTopLevelHeaders(CXTranslationUnit, CXModule Module);
+{# fun clang_Module_getNumTopLevelHeaders { id `Ptr ()', id `Ptr ()' } -> `Int' #}
+module_getNumTopLevelHeaders :: TranslationUnit s -> Module s' -> IO Int
+module_getNumTopLevelHeaders t m = clang_Module_getNumTopLevelHeaders (unTranslationUnit t) (unModule m)
+
+-- CXFile clang_Module_getTopLevelHeader(CXTranslationUnit, CXModule Module, unsigned Index);
+{# fun clang_Module_getTopLevelHeader { id `Ptr ()', id `Ptr ()', `Int' } -> `Ptr ()' id #}
+module_getTopLevelHeader :: Proxy s -> TranslationUnit s' -> Module s'' -> Int -> IO (File s)
+module_getTopLevelHeader _ t m i = clang_Module_getTopLevelHeader (unTranslationUnit t) (unModule m) i >>= return . File
+
+-- unsigned clang_CXXMethod_isPureVirtual(CXCursor C);
+{# fun clang_CXXMethod_isPureVirtual {withVoided* %`Cursor a' } -> `Bool' toBool #}
+cXXMethod_isPureVirtual :: Cursor s -> IO Bool
+cXXMethod_isPureVirtual c = clang_Cursor_isBitField c
+
+-- unsigned clang_CXXMethod_isStatic(CXCursor C);
+{# fun clang_CXXMethod_isStatic {withVoided* %`Cursor a' } -> `Bool' toBool #}
+cXXMethod_isStatic :: Cursor s -> IO Bool
+cXXMethod_isStatic c = clang_Cursor_isBitField c
+
+-- unsigned clang_CXXMethod_isVirtual(CXCursor C);
+{# fun clang_CXXMethod_isVirtual {withVoided* %`Cursor a' } -> `Bool' toBool #}
+cXXMethod_isVirtual :: Cursor s -> IO Bool
+cXXMethod_isVirtual c = clang_Cursor_isBitField c
+
+-- enum CXCursorKind clang_getTemplateCursorKind(CXCursor C);
+{# fun clang_getTemplateCursorKind {withVoided* %`Cursor a' } -> `Int' #}
+getTemplateCursorKind :: Cursor s -> IO CursorKind
+getTemplateCursorKind c =
+  clang_getTemplateCursorKind c >>= return . toEnum
+
+-- CXCursor clang_getSpecializedCursorTemplate(CXCursor C);
+{# fun wrapped_clang_getSpecializedCursorTemplate as clang_getSpecializedCursorTemplate {withVoided* %`Cursor a' } -> `Ptr (Cursor s)' castPtr #}
+getSpecializedCursorTemplate :: Proxy s -> Cursor s' -> IO (Cursor s)
+getSpecializedCursorTemplate _ c =
+  clang_getSpecializedCursorTemplate c >>= peek
+
+-- CXSourceRange clang_getCursorReferenceNameRange(CXCursor C,
+--                                                 unsigned NameFlags,
+--                                                 unsigned PieceIndex);
+{# fun wrapped_clang_getCursorReferenceNameRange as clang_getCursorReferenceNameRange {withVoided* %`Cursor a', `Int' , `Int' } -> `Ptr (SourceRange s)' castPtr #}
+getCursorReferenceNameRange :: Proxy s -> Cursor s' -> Int -> Int -> IO (SourceRange s)
+getCursorReferenceNameRange _ c fs idx = clang_getCursorReferenceNameRange c fs idx >>= peek
+
+-- enum CXNameRefFlags {
+--   CXNameRange_WantQualifier = 0x1,
+--   CXNameRange_WantTemplateArgs = 0x2,
+--   CXNameRange_WantSinglePiece = 0x4
+-- };
+#c
+enum NameRefFlags
+  { NameRange_WantQualifier    = CXNameRange_WantQualifier
+  , NameRange_WantTemplateArgs = CXNameRange_WantTemplateArgs
+  , NameRange_WantSinglePiece  = CXNameRange_WantSinglePiece
+  };
+#endc
+{# enum NameRefFlags {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags NameRefFlags where
+  toBit NameRange_WantQualifier    = 0x01
+  toBit NameRange_WantTemplateArgs = 0x02
+  toBit NameRange_WantSinglePiece  = 0x04
+
+-- enum CXCommentKind {
+--   CXComment_Null = 0,
+--   CXComment_Text = 1,
+--   CXComment_InlineCommand = 2,
+--   CXComment_HTMLStartTag = 3,
+--   CXComment_HTMLEndTag = 4,
+--   CXComment_Paragraph = 5,
+--   CXComment_BlockCommand = 6,
+--   CXComment_ParamCommand = 7,
+--   CXComment_TParamCommand = 8,
+--   CXComment_VerbatimBlockCommand = 9,
+--   CXComment_VerbatimBlockLine = 10,
+--   CXComment_VerbatimLine = 11,
+--   CXComment_FullComment = 12
+-- };
+#c
+enum CommentKind
+  { NullComment                 = CXComment_Null
+  , TextComment                 = CXComment_Text
+  , InlineCommandComment        = CXComment_InlineCommand
+  , HTMLStartTagComment         = CXComment_HTMLStartTag
+  , HTMLEndTagComment           = CXComment_HTMLEndTag
+  , ParagraphComment            = CXComment_Paragraph
+  , BlockCommandComment         = CXComment_BlockCommand
+  , ParamCommandComment         = CXComment_ParamCommand
+  , TParamCommandComment        = CXComment_TParamCommand
+  , VerbatimBlockCommandComment = CXComment_VerbatimBlockCommand
+  , VerbatimBlockLineComment    = CXComment_VerbatimBlockLine
+  , VerbatimLineComment         = CXComment_VerbatimLine
+  , FullComment                 = CXComment_FullComment
+ };
+#endc
+{# enum CommentKind {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- enum CXCommentInlineCommandRenderKind {
+--   CXCommentInlineCommandRenderKind_Normal,
+--   CXCommentInlineCommandRenderKind_Bold,
+--   CXCommentInlineCommandRenderKind_Monospaced,
+--   CXCommentInlineCommandRenderKind_Emphasized
+-- };
+
+-- | A rendering style which should be used for the associated inline command in the comment AST.
+#c
+enum InlineCommandRenderStyle
+  { NormalInlineCommandRenderStyle     = CXCommentInlineCommandRenderKind_Normal
+  , BoldInlineCommandRenderStyle       = CXCommentInlineCommandRenderKind_Bold
+  , MonospacedInlineCommandRenderStyle = CXCommentInlineCommandRenderKind_Monospaced
+  , EmphasizedInlineCommandRenderStyle = CXCommentInlineCommandRenderKind_Emphasized
+ };
+#endc
+{# enum InlineCommandRenderStyle {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+-- enum CXCommentParamPassDirection {
+--   CXCommentParamPassDirection_In,
+--   CXCommentParamPassDirection_Out,
+--   CXCommentParamPassDirection_InOut
+-- };
+
+-- | A parameter passing direction.
+#c
+enum ParamPassDirectionKind
+  { InParamPassDirection    = CXCommentParamPassDirection_In
+  , OutParamPassDirection   = CXCommentParamPassDirection_Out
+  , InOutParamPassDirection = CXCommentParamPassDirection_InOut
+  };
+#endc
+{#enum ParamPassDirectionKind {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- enum CXCommentKind clang_Comment_getKind(CXComment Comment);
+{# fun clang_Comment_getKind {withVoided* %`Comment a' } -> `Int' #}
+comment_getKind :: Comment s -> IO CommentKind
+comment_getKind c =
+  clang_Comment_getKind c >>= return . toEnum
+
+-- unsigned clang_Comment_getNumChildren(CXComment Comment);
+{# fun clang_Comment_getNumChildren {withVoided* %`Comment a' } -> `Int' #}
+comment_getNumChildren :: Comment s -> IO Int
+comment_getNumChildren c =
+  clang_Comment_getNumChildren c
+
+-- CXComment clang_Comment_getChild(CXComment Comment, unsigned ChildIdx);
+{# fun clang_Comment_getChild {withVoided* %`Comment a', `Int' } -> `Ptr (Comment s)' castPtr #}
+comment_getChild :: Proxy s -> Comment s' -> Int -> IO (Comment s)
+comment_getChild _ c i = clang_Comment_getChild c i >>= peek
+
+-- unsigned clang_Comment_isWhitespace(CXComment Comment);
+{# fun clang_Comment_isWhitespace {withVoided* %`Comment a' } -> `Bool' toBool #}
+comment_isWhitespace :: Comment s -> IO Bool
+comment_isWhitespace c = clang_Comment_isWhitespace c
+
+-- unsigned clang_InlineContentComment_hasTrailingNewline(CXComment Comment);
+{# fun clang_InlineContentComment_hasTrailingNewline {withVoided* %`Comment a' } -> `Bool' toBool #}
+inlineContentComment_hasTrailingNewline :: Comment s -> IO Bool
+inlineContentComment_hasTrailingNewline c = clang_InlineContentComment_hasTrailingNewline c
+
+-- CXString clang_TextComment_getText(CXComment Comment);
+{# fun wrapped_clang_TextComment_getText as clang_TextComment_getText {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_TextComment_getText :: Comment s -> IO (ClangString ())
+unsafe_TextComment_getText c =
+  clang_TextComment_getText c >>= peek
+
+textComment_getText :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+textComment_getText = registerClangString . unsafe_TextComment_getText
+
+-- CXString clang_InlineCommandComment_getCommandName(CXComment Comment);
+{# fun clang_InlineCommandComment_getCommandName {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_InlineCommandComment_getCommandName :: Comment s -> IO (ClangString ())
+unsafe_InlineCommandComment_getCommandName c =
+  clang_InlineCommandComment_getCommandName c >>= peek
+
+inlineCommandComment_getCommandName :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+inlineCommandComment_getCommandName = registerClangString . unsafe_InlineCommandComment_getCommandName
+
+-- enum CXCommentInlineCommandRenderKind clang_InlineCommandComment_getRenderKind(CXComment Comment);
+{# fun clang_InlineCommandComment_getRenderKind {withVoided* %`Comment a' } -> `Int' #}
+inlineCommandComment_getRenderKind :: Comment s -> IO InlineCommandRenderStyle
+inlineCommandComment_getRenderKind c =
+  clang_InlineCommandComment_getRenderKind c >>= return . toEnum
+
+-- unsigned clang_InlineCommandComment_getNumArgs(CXComment Comment);
+{# fun clang_InlineCommandComment_getNumArgs {withVoided* %`Comment a' } -> `Int' #}
+inlineCommandComment_getNumArgs :: Comment s -> IO Int
+inlineCommandComment_getNumArgs c =
+  clang_InlineCommandComment_getNumArgs c
+
+-- CXString clang_InlineCommandComment_getArgText(CXComment Comment, unsigned ArgIdx);
+{# fun clang_InlineCommandComment_getArgText {withVoided* %`Comment a', `Int' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_InlineCommandComment_getArgText :: Comment s -> Int -> IO (ClangString ())
+unsafe_InlineCommandComment_getArgText c idx =
+  clang_InlineCommandComment_getArgText c idx >>= peek
+
+inlineCommandComment_getArgText :: ClangBase m => Comment s' -> Int -> ClangT s m (ClangString s)
+inlineCommandComment_getArgText = (registerClangString .) . unsafe_InlineCommandComment_getArgText
+
+-- CXString clang_HTMLTagComment_getTagName(CXComment Comment);
+{# fun wrapped_clang_HTMLTagComment_getTagName as clang_HTMLTagComment_getTagName {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_HTMLTagComment_getTagName :: Comment s -> IO (ClangString ())
+unsafe_HTMLTagComment_getTagName c =
+  clang_HTMLTagComment_getTagName c >>= peek
+
+hTMLTagComment_getTagName :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+hTMLTagComment_getTagName = registerClangString . unsafe_HTMLTagComment_getTagName
+
+-- unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment Comment);
+{# fun clang_HTMLStartTagComment_isSelfClosing {withVoided* %`Comment a' } -> `Bool' toBool #}
+hTMLStartTagComment_isSelfClosing :: Comment s -> IO Bool
+hTMLStartTagComment_isSelfClosing c = clang_HTMLStartTagComment_isSelfClosing c
+
+-- unsigned clang_HTMLStartTag_getNumAttrs(CXComment Comment);
+{# fun clang_HTMLStartTag_getNumAttrs {withVoided* %`Comment a' } -> `Int' #}
+hTMLStartTag_getNumAttrs :: Comment s -> IO Int
+hTMLStartTag_getNumAttrs c =
+  clang_HTMLStartTag_getNumAttrs c
+
+-- CXString clang_HTMLStartTag_getAttrName(CXComment Comment, unsigned AttrIdx);
+{# fun clang_HTMLStartTag_getAttrName {withVoided* %`Comment a', `Int' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_HTMLStartTag_getAttrName :: Comment s -> Int -> IO (ClangString ())
+unsafe_HTMLStartTag_getAttrName c idx =
+  clang_HTMLStartTag_getAttrName c idx >>= peek
+
+hTMLStartTag_getAttrName :: ClangBase m => Comment s' -> Int -> ClangT s m (ClangString s)
+hTMLStartTag_getAttrName = (registerClangString .) . unsafe_HTMLStartTag_getAttrName
+
+-- CXString clang_HTMLStartTag_getAttrValue(CXComment Comment, unsigned AttrIdx);
+{# fun clang_HTMLStartTag_getAttrValue {withVoided* %`Comment a', `Int' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_HTMLStartTag_getAttrValue :: Comment s -> Int -> IO (ClangString ())
+unsafe_HTMLStartTag_getAttrValue c idx =
+  clang_HTMLStartTag_getAttrValue c idx >>= peek
+
+hTMLStartTag_getAttrValue :: ClangBase m => Comment s' -> Int -> ClangT s m (ClangString s)
+hTMLStartTag_getAttrValue = (registerClangString .) . unsafe_HTMLStartTag_getAttrValue
+
+-- CXString clang_BlockCommandComment_getCommandName(CXComment Comment);
+{# fun clang_BlockCommandComment_getCommandName {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_BlockCommandComment_getCommandName :: Comment s -> IO (ClangString ())
+unsafe_BlockCommandComment_getCommandName c =
+  clang_BlockCommandComment_getCommandName c >>= peek
+
+blockCommandComment_getCommandName :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+blockCommandComment_getCommandName = registerClangString . unsafe_BlockCommandComment_getCommandName
+
+-- unsigned clang_BlockCommandComment_getNumArgs(CXComment Comment);
+{# fun clang_BlockCommandComment_getNumArgs {withVoided* %`Comment a' } -> `Int' #}
+blockCommandComment_getNumArgs :: Comment s -> IO Int
+blockCommandComment_getNumArgs c =
+  clang_BlockCommandComment_getNumArgs c
+
+-- CXString clang_BlockCommandComment_getArgText(CXComment Comment, unsigned ArgIdx);
+{# fun clang_BlockCommandComment_getArgText {withVoided* %`Comment a', `Int' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_BlockCommandComment_getArgText :: Comment s -> Int -> IO (ClangString ())
+unsafe_BlockCommandComment_getArgText c idx =
+  clang_BlockCommandComment_getArgText c idx >>= peek
+
+blockCommandComment_getArgText :: ClangBase m => Comment s' -> Int -> ClangT s m (ClangString s)
+blockCommandComment_getArgText = (registerClangString .) . unsafe_BlockCommandComment_getArgText
+
+-- CXComment clang_BlockCommandComment_getParagraph(CXComment Comment);
+{# fun clang_BlockCommandComment_getParagraph {withVoided* %`Comment a' } -> `Ptr (Comment s)' castPtr #}
+blockCommandComment_getParagraph :: Proxy s -> Comment s' -> IO (Comment s)
+blockCommandComment_getParagraph _ c =
+  clang_BlockCommandComment_getParagraph c >>= peek
+
+-- CXString clang_ParamCommandComment_getParamName(CXComment Comment);
+{# fun clang_ParamCommandComment_getParamName {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_ParamCommandComment_getParamName :: Comment s -> IO (ClangString ())
+unsafe_ParamCommandComment_getParamName c =
+  clang_ParamCommandComment_getParamName c >>= peek
+
+paramCommandComment_getParamName :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+paramCommandComment_getParamName = registerClangString . unsafe_ParamCommandComment_getParamName
+
+-- unsigned clang_ParamCommandComment_isParamIndexValid(CXComment Comment);
+{# fun clang_ParamCommandComment_isParamIndexValid {withVoided* %`Comment a' } -> `Bool' toBool #}
+paramCommandComment_isParamIndexValid :: Comment s -> IO Bool
+paramCommandComment_isParamIndexValid c =
+  clang_ParamCommandComment_isParamIndexValid c
+
+-- unsigned clang_ParamCommandComment_getParamIndex(CXComment Comment);
+{# fun clang_ParamCommandComment_getParamIndex {withVoided* %`Comment a' } -> `Int' #}
+paramCommandComment_getParamIndex :: Comment s -> IO Int
+paramCommandComment_getParamIndex c =
+  clang_ParamCommandComment_getParamIndex c
+
+-- unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment Comment);
+{# fun clang_ParamCommandComment_isDirectionExplicit {withVoided* %`Comment a' } -> `Bool' toBool #}
+paramCommandComment_isDirectionExplicit :: Comment s -> IO Bool
+paramCommandComment_isDirectionExplicit c =
+  clang_ParamCommandComment_isDirectionExplicit c
+
+-- enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(CXComment Comment);
+{# fun clang_ParamCommandComment_getDirection {withVoided* %`Comment a' } -> `Int' #}
+paramCommandComment_getDirection :: Comment s -> IO ParamPassDirectionKind
+paramCommandComment_getDirection c =
+  clang_ParamCommandComment_getDirection c >>= return . toEnum
+
+-- CXString clang_TParamCommandComment_getParamName(CXComment Comment);
+{# fun clang_TParamCommandComment_getParamName {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_TParamCommandComment_getParamName :: Comment s -> IO (ClangString ())
+unsafe_TParamCommandComment_getParamName c =
+  clang_TParamCommandComment_getParamName c >>= peek
+
+tParamCommandComment_getParamName :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+tParamCommandComment_getParamName = registerClangString . unsafe_TParamCommandComment_getParamName
+
+-- unsigned clang_TParamCommandComment_isParamPositionValid(CXComment Comment);
+{# fun clang_TParamCommandComment_isParamPositionValid {withVoided* %`Comment a' } -> `Bool' toBool #}
+tParamCommandComment_isParamPositionValid :: Comment s -> IO Bool
+tParamCommandComment_isParamPositionValid c =
+  clang_TParamCommandComment_isParamPositionValid c
+
+-- unsigned clang_TParamCommandComment_getDepth(CXComment Comment);
+{# fun clang_TParamCommandComment_getDepth { withVoided* %`Comment a' } -> `Int' #}
+tParamCommandComment_getDepth :: Comment s -> IO Int
+tParamCommandComment_getDepth c =
+  clang_TParamCommandComment_getDepth c
+
+-- unsigned clang_TParamCommandComment_getIndex(CXComment Comment, unsigned Depth);
+{# fun clang_TParamCommandComment_getIndex {withVoided* %`Comment a', `Int' } -> `Int' #}
+tParamCommandComment_getIndex :: Comment s -> Int -> IO Int
+tParamCommandComment_getIndex c idx =
+  clang_TParamCommandComment_getIndex c idx
+
+-- CXString clang_VerbatimBlockLineComment_getText(CXComment Comment);
+{# fun clang_VerbatimBlockLineComment_getText {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_VerbatimBlockLineComment_getText :: Comment s -> IO (ClangString ())
+unsafe_VerbatimBlockLineComment_getText c =
+  clang_VerbatimBlockLineComment_getText c >>= peek
+
+verbatimBlockLineComment_getText :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+verbatimBlockLineComment_getText = registerClangString . unsafe_VerbatimBlockLineComment_getText
+
+-- CXString clang_VerbatimLineComment_getText(CXComment Comment);
+{# fun wrapped_clang_VerbatimLineComment_getText as clang_VerbatimLineComment_getText {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_VerbatimLineComment_getText :: Comment s -> IO (ClangString ())
+unsafe_VerbatimLineComment_getText c =
+  clang_VerbatimLineComment_getText c >>= peek
+
+verbatimLineComment_getText :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+verbatimLineComment_getText = registerClangString . unsafe_VerbatimLineComment_getText
+
+-- CXString clang_HTMLTagComment_getAsString(CXComment Comment);
+{# fun wrapped_clang_HTMLTagComment_getAsString as clang_HTMLTagComment_getAsString {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_HTMLTagComment_getAsString :: Comment s -> IO (ClangString ())
+unsafe_HTMLTagComment_getAsString c =
+  clang_HTMLTagComment_getAsString c >>= peek
+
+hTMLTagComment_getAsString :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+hTMLTagComment_getAsString = registerClangString . unsafe_HTMLTagComment_getAsString
+
+-- CXString clang_FullComment_getAsHTML(CXComment Comment);
+{# fun wrapped_clang_FullComment_getAsHTML as clang_FullComment_getAsHTML {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_FullComment_getAsHTML :: Comment s -> IO (ClangString ())
+unsafe_FullComment_getAsHTML c =
+  clang_FullComment_getAsHTML c >>= peek
+
+fullComment_getAsHTML :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+fullComment_getAsHTML = registerClangString . unsafe_FullComment_getAsHTML
+
+-- CXString clang_FullComment_getAsXML(CXComment Comment);
+{# fun wrapped_clang_FullComment_getAsXML as clang_FullComment_getAsXML {withVoided* %`Comment a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_FullComment_getAsXML :: Comment s -> IO (ClangString ())
+unsafe_FullComment_getAsXML c =
+  clang_FullComment_getAsXML c >>= peek
+
+fullComment_getAsXML :: ClangBase m => Comment s' -> ClangT s m (ClangString s)
+fullComment_getAsXML = registerClangString . unsafe_FullComment_getAsXML
+
+-- typedef enum CXTokenKind {
+--   CXToken_Punctuation,
+--   CXToken_Keyword,
+--   CXToken_Identifier,
+--   CXToken_Literal,
+--   CXToken_Comment
+-- } CXTokenKind;
+#c
+enum TokenKind
+  { PunctuationToken = CXToken_Punctuation
+  , KeywordToken     = CXToken_Keyword
+  , IdentifierToken  = CXToken_Identifier
+  , LiteralToken     = CXToken_Literal
+  , CommentToken     = CXToken_Comment
+ };
+#endc
+{# enum TokenKind {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- typedef struct {
+--   unsigned int_data[4];
+--   void *ptr_data;
+-- } CXToken;
+data Token s = Token !Int !Int !Int !Int !(Ptr ())
+               deriving (Eq, Ord, Typeable)
+
+instance ClangValue Token
+
+instance Storable (Token s) where
+    sizeOf _ = sizeOfCXToken
+    {-# INLINE sizeOf #-}
+
+    alignment _ = alignOfCXToken
+    {-# INLINE alignment #-}
+
+    peek p = do
+      int_data <- {#get CXToken->int_data #} p >>= peekArray 4
+      ptr_data <- {#get CXToken->ptr_data #} p
+      return $! Token (fromIntegral (int_data !! 0)) (fromIntegral (int_data !! 1)) (fromIntegral (int_data !! 2)) (fromIntegral (int_data !! 3)) ptr_data
+    {-# INLINE peek #-}
+
+    poke p (Token i0 i1 i2 i3 ptr_data) = do
+      intsArray <- mallocArray 4
+      pokeArray intsArray (map fromIntegral [i0,i1,i2,i3])
+      {#set CXToken->int_data #} p intsArray
+      {#set CXToken->ptr_data #} p ptr_data
+    {-# INLINE poke #-}
+
+-- CXTokenKind clang_getTokenKind(CXToken);
+{# fun clang_getTokenKind { withVoided* %`Token s' } -> `Int' #}
+getTokenKind :: Token s -> IO TokenKind
+getTokenKind t =
+  clang_getTokenKind t  >>= return . toEnum
+
+-- CXString clang_getTokenSpelling(CXTranslationUnit, CXToken);
+{# fun wrapped_clang_getTokenSpelling as clang_getTokenSpelling { id `Ptr ()', withVoided* %`Token s' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getTokenSpelling :: TranslationUnit s -> Token s' -> IO (ClangString ())
+unsafe_getTokenSpelling tu t =
+   clang_getTokenSpelling (unTranslationUnit tu) t >>= peek
+
+getTokenSpelling :: ClangBase m => TranslationUnit s' -> Token s'' -> ClangT s m (ClangString s)
+getTokenSpelling = (registerClangString .) . unsafe_getTokenSpelling
+
+-- CXSourceLocation clang_getTokenLocation(CXTranslationUnit,
+--                                                        CXToken);
+{# fun wrapped_clang_getTokenLocation as clang_getTokenLocation { id `Ptr ()', withVoided* %`Token a' } -> `Ptr (SourceLocation s)' castPtr #}
+getTokenLocation :: Proxy s -> TranslationUnit t -> Token s' -> IO (SourceLocation s)
+getTokenLocation _ tu t =
+  clang_getTokenLocation (unTranslationUnit tu) t >>= peek
+
+-- CXSourceRange clang_getTokenExtent(CXTranslationUnit, CXToken);
+{# fun wrapped_clang_getTokenExtent as clang_getTokenExtent { id `Ptr ()', withVoided* %`Token a' } -> `Ptr (SourceRange s)' castPtr #}
+getTokenExtent :: Proxy s -> TranslationUnit t -> Token s' -> IO (SourceRange s)
+getTokenExtent _ tu t =
+  clang_getTokenExtent (unTranslationUnit tu) t >>= peek
+
+-- We deliberately don't export the constructor for UnsafeTokenList.
+-- The only way to unwrap it is registerTokenList.
+type TokenList s = DVS.Vector (Token s)
+instance ClangValueList Token
+data UnsafeTokenList = UnsafeTokenList !(Ptr ()) !Int
+
+foreign import ccall unsafe "FFI_stub_ffi.h clang_disposeTokens" clang_disposeTokens :: Ptr () -> Ptr () -> CUInt -> IO ()
+
+disposeTokens :: TranslationUnit s -> TokenList s' -> IO ()
+disposeTokens tu tl =
+ let (tPtr, n) = fromTokenList tl in
+ clang_disposeTokens (unTranslationUnit tu) tPtr (fromIntegral n)
+
+registerTokenList :: ClangBase m => TranslationUnit s' -> IO UnsafeTokenList
+                  -> ClangT s m (TokenList s)
+registerTokenList tu action = do
+    (_, tokenList) <- clangAllocate (action >>= tokenListToVector) (disposeTokens tu)
+    return tokenList
+{-# INLINEABLE registerTokenList #-}
+
+tokenListToVector :: Storable a => UnsafeTokenList -> IO (DVS.Vector a)
+tokenListToVector (UnsafeTokenList ts n) = do
+  fptr <- newForeignPtr_ (castPtr ts)
+  return $ DVS.unsafeFromForeignPtr fptr 0 n
+{-# INLINE tokenListToVector #-}
+
+fromTokenList :: TokenList s -> (Ptr (), Int)
+fromTokenList ts = let (p, _, _) = DVS.unsafeToForeignPtr ts in
+                   (castPtr $ Foreign.ForeignPtr.Unsafe.unsafeForeignPtrToPtr p, DVS.length ts)
+
+toTokenList :: (Ptr (), Int) -> UnsafeTokenList
+toTokenList (ts, n) = UnsafeTokenList ts n
+
+-- void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
+--                                    CXToken **Tokens, unsigned *NumTokens);
+{# fun clang_tokenize { id `Ptr ()',withVoided* %`SourceRange a', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()'#}
+unsafe_tokenize :: TranslationUnit s -> SourceRange s' -> IO UnsafeTokenList
+unsafe_tokenize tu sr = do
+  tokensPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr (Token ())))))
+  numTokens <- clang_tokenize (unTranslationUnit tu) sr (castPtr tokensPtr)
+  return (toTokenList (tokensPtr, fromIntegral numTokens))
+
+tokenize :: ClangBase m => TranslationUnit s' -> SourceRange s'' -> ClangT s m (TokenList s)
+tokenize tu = registerTokenList tu . unsafe_tokenize tu
+
+-- TODO: test me
+-- Note that registerCursorList can be used for the result of this
+-- function because it just calls free() to dispose of the list.
+--
+-- void clang_annotateTokens(CXTranslationUnit TU,
+--                                          CXToken *Tokens, unsigned NumTokens,
+--                                          CXCursor *Cursors);
+{# fun clang_annotateTokens { id `Ptr ()', id `Ptr ()', `Int', id `Ptr ()' } -> `()' id#}
+unsafe_annotateTokens :: TranslationUnit s -> TokenList s' -> IO UnsafeCursorList
+unsafe_annotateTokens tu tl =
+  let (tPtr, numTokens) = fromTokenList tl in
+  do
+    cPtr <- mallocBytes ((sizeOf (undefined :: (Ptr (Cursor ())))) * numTokens)
+    clang_annotateTokens (unTranslationUnit tu) tPtr numTokens (castPtr cPtr)
+    return (toCursorList (cPtr, numTokens))
+
+annotateTokens :: ClangBase m => TranslationUnit s' -> TokenList s'' -> ClangT s m (CursorList s)
+annotateTokens = (registerCursorList .) . unsafe_annotateTokens
+
+-- CXString clang_getCursorKindSpelling(enum CXCursorKind Kind);
+{# fun wrapped_clang_getCursorKindSpelling as clang_getCursorKindSpelling { `CInt' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCursorKindSpelling :: CursorKind -> IO (ClangString ())
+unsafe_getCursorKindSpelling ck = clang_getCursorKindSpelling (fromIntegral (fromEnum ck)) >>= peek
+
+getCursorKindSpelling :: ClangBase m => CursorKind -> ClangT s m (ClangString s)
+getCursorKindSpelling = registerClangString . unsafe_getCursorKindSpelling
+
+-- void clang_enableStackTraces(void);
+foreign import ccall unsafe "clang-c/Index.h clang_enableStackTraces" enableStackTraces :: IO ()
+
+-- typedef void *CXCompletionString;
+
+-- | A semantic string that describes a code completion result.
+--
+-- A 'CompletionString' describes the formatting of a code completion
+-- result as a single \"template\" of text that should be inserted into the
+-- source buffer when a particular code completion result is selected.
+-- Each semantic string is made up of some number of \"chunks\", each of which
+-- contains some text along with a description of what that text means.
+--
+-- See 'ChunkKind' for more details about the role each kind of chunk plays.
+newtype CompletionString s = CompletionString (Ptr ())
+                             deriving (Eq, Ord, Typeable)
+
+instance ClangValue CompletionString
+
+-- typedef struct {
+--   enum CXCursorKind CursorKind;
+--   CXCompletionString CompletionString;
+-- } CXCompletionResult;
+data CompletionResult s = CompletionResult !CursorKind !(CompletionString s)
+                          deriving (Eq, Ord, Typeable)
+
+instance ClangValue CompletionResult
+
+-- enum CXCompletionChunkKind {
+--   CXCompletionChunk_Optional,
+--   CXCompletionChunk_TypedText,
+--   CXCompletionChunk_Text,
+--   CXCompletionChunk_Placeholder,
+--   CXCompletionChunk_Informative,
+--   CXCompletionChunk_CurrentParameter,
+--   CXCompletionChunk_LeftParen,
+--   CXCompletionChunk_RightParen,
+--   CXCompletionChunk_LeftBracket,
+--   CXCompletionChunk_RightBracket,
+--   CXCompletionChunk_LeftBrace,
+--   CXCompletionChunk_RightBrace,
+--   CXCompletionChunk_LeftAngle,
+--   CXCompletionChunk_RightAngle,
+--   CXCompletionChunk_Comma,
+--   CXCompletionChunk_ResultType,
+--   CXCompletionChunk_Colon,
+--   CXCompletionChunk_SemiColon,
+--   CXCompletionChunk_Equal,
+--   CXCompletionChunk_HorizontalSpace,
+--   CXCompletionChunk_VerticalSpace
+-- };
+
+-- | Describes a single piece of text within a code completion string.
+--
+-- * 'OptionalChunkKind': A code completion string that describes "optional" text that
+--   could be a part of the template (but is not required).
+--   This is the only kind of chunk that has a code completion
+--   string for its representation. The code completion string describes an
+--   describes an additional part of the template that is completely optional.
+--   For example, optional chunks can be used to describe the placeholders for
+--   arguments that match up with defaulted function parameters.
+--
+-- * 'TypedTextChunkKind': Text that a user would be expected to type to get this
+--   code completion result.
+--   There will be exactly one \"typed text\" chunk in a semantic string, which
+--   will typically provide the spelling of a keyword or the name of a
+--   declaration that could be used at the current code point. Clients are
+--   expected to filter the code completion results based on the text in this
+--   chunk.
+--
+-- * 'TextChunkKind': Text that should be inserted as part of a code completion result.
+--   A \"text\" chunk represents text that is part of the template to be
+--   inserted into user code should this particular code completion result
+--   be selected.
+--
+-- * 'PlaceholderChunkKind': Placeholder text that should be replaced by the user.
+--   A \"placeholder\" chunk marks a place where the user should insert text
+--   into the code completion template. For example, placeholders might mark
+--   the function parameters for a function declaration, to indicate that the
+--   user should provide arguments for each of those parameters. The actual
+--   text in a placeholder is a suggestion for the text to display before
+--   the user replaces the placeholder with real code.
+--
+-- * 'InformativeChunkKind': Informative text that should be displayed but never inserted as
+--   part of the template.
+--   An \"informative\" chunk contains annotations that can be displayed to
+--   help the user decide whether a particular code completion result is the
+--   right option, but which is not part of the actual template to be inserted
+--   by code completion.
+--
+-- * 'CurrentParameterChunkKind': Text that describes the current parameter
+--   when code completion is referring to a function call, message send, or
+--   template specialization.
+--   A \"current parameter\" chunk occurs when code completion is providing
+--   information about a parameter corresponding to the argument at the
+--   code completion point. For example, given a function \"int add(int x, int y);\"
+--   and the source code \"add(\", where the code completion point is after the
+--   \"(\", the code completion string will contain a \"current parameter\" chunk
+--   for \"int x\", indicating that the current argument will initialize that
+--   parameter. After typing further, to \"add(17\", (where the code completion
+--   point is after the \",\"), the code completion string will contain a
+--   \"current parameter\" chunk to \"int y\".
+--
+-- * 'LeftParenChunkKind': A left parenthesis (\'(\'), used to initiate a function call or
+--   signal the beginning of a function parameter list.
+--
+-- * 'RightParenChunkKind': A right parenthesis (\')\'), used to finish a function call or
+--   signal the end of a function parameter list.
+--
+-- * 'LeftBracketChunkKind': A left bracket (\'[\').
+--
+-- * 'RightBracketChunkKind': A right bracket (\']\').
+--
+-- * 'LeftBraceChunkKind': A left brace (\'{\').
+--
+-- * 'RightBraceChunkKind': A right brace (\'}\').
+--
+-- * 'LeftAngleChunkKind': A left angle bracket (\'<\').
+--
+-- * 'RightAngleChunkKind': A right angle bracket (\'>\').
+--
+-- * 'CommaChunkKind': A comma separator (\',\').
+--
+-- * 'ResultTypeChunkKind': Text that specifies the result type of a given result.
+--   This special kind of informative chunk is not meant to be inserted into
+--   the text buffer. Rather, it is meant to illustrate the type that an
+--   expression using the given completion string would have.
+--
+-- * 'ColonChunkKind': A colon (\':\').
+--
+-- * 'SemiColonChunkKind': A semicolon (\';\').
+--
+-- * 'EqualChunkKind': An \'=\' sign.
+--
+-- * 'HorizontalSpaceChunkKind': Horizontal space (\' \').
+--
+-- * 'VerticalSpaceChunkKind': Vertical space (\'\\n\'), after which it is generally
+--   a good idea to perform indentation.
+#c
+enum ChunkKind
+  { OptionalChunkKind         = CXCompletionChunk_Optional
+  , TypedTextChunkKind        = CXCompletionChunk_TypedText
+  , TextChunkKind             = CXCompletionChunk_Text
+  , PlaceholderChunkKind      = CXCompletionChunk_Placeholder
+  , InformativeChunkKind      = CXCompletionChunk_Informative
+  , CurrentParameterChunkKind = CXCompletionChunk_CurrentParameter
+  , LeftParenChunkKind        = CXCompletionChunk_LeftParen
+  , RightParenChunkKind       = CXCompletionChunk_RightParen
+  , LeftBracketChunkKind      = CXCompletionChunk_LeftBracket
+  , RightBracketChunkKind     = CXCompletionChunk_RightBracket
+  , LeftBraceChunkKind        = CXCompletionChunk_LeftBrace
+  , RightBraceChunkKind       = CXCompletionChunk_RightBrace
+  , LeftAngleChunkKind        = CXCompletionChunk_LeftAngle
+  , RightAngleChunkKind       = CXCompletionChunk_RightAngle
+  , CommaChunkKind            = CXCompletionChunk_Comma
+  , ResultTypeChunkKind       = CXCompletionChunk_ResultType
+  , ColonChunkKind            = CXCompletionChunk_Colon
+  , SemiColonChunkKind        = CXCompletionChunk_SemiColon
+  , EqualChunkKind            = CXCompletionChunk_Equal
+  , HorizontalSpaceChunkKind  = CXCompletionChunk_HorizontalSpace
+  , VerticalSpaceChunkKind    = CXCompletionChunk_VerticalSpace
+ };
+#endc
+{# enum ChunkKind {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+-- enum CXCompletionChunkKind
+-- clang_getCompletionChunkKind(CXCompletionString completion_string,
+--                              unsigned chunk_number);
+{# fun clang_getCompletionChunkKind { id `Ptr ()', `Int'} -> `Int' #}
+getCompletionChunkKind :: CompletionString s -> Int -> IO ChunkKind
+getCompletionChunkKind (CompletionString ptr) i = clang_getCompletionChunkKind ptr i >>= return . toEnum
+
+-- CXString
+-- clang_getCompletionChunkText(CXCompletionString completion_string,
+--                              unsigned chunk_number);
+{# fun wrapped_clang_getCompletionChunkText as clang_getCompletionChunkText { id `Ptr ()' , `Int' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCompletionChunkText :: CompletionString s -> Int -> IO (ClangString ())
+unsafe_getCompletionChunkText (CompletionString ptr) i = clang_getCompletionChunkText ptr i >>= peek
+
+getCompletionChunkText :: ClangBase m => CompletionString s' -> Int -> ClangT s m (ClangString s)
+getCompletionChunkText = (registerClangString .) . unsafe_getCompletionChunkText
+
+-- CXCompletionString
+-- clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
+--                                          unsigned chunk_number);
+{# fun clang_getCompletionChunkCompletionString { id `Ptr ()' , `Int' } -> `Ptr ()' id #}
+getCompletionChunkCompletionString :: CompletionString s -> Int -> IO (CompletionString s')
+getCompletionChunkCompletionString (CompletionString ptr) i =
+  clang_getCompletionChunkCompletionString ptr i >>= return . CompletionString
+
+-- unsigned
+-- clang_getNumCompletionChunks(CXCompletionString completion_string);
+{# fun clang_getNumCompletionChunks { id `Ptr ()' } -> `Int' #}
+getNumCompletionChunks :: CompletionString s -> IO Int
+getNumCompletionChunks (CompletionString ptr) = clang_getNumCompletionChunks ptr
+
+-- unsigned
+-- clang_getCompletionPriority(CXCompletionString completion_string);
+{# fun clang_getCompletionPriority { id `Ptr ()' } -> `Int' #}
+getCompletionPriority :: CompletionString s -> IO Int
+getCompletionPriority (CompletionString ptr) = clang_getCompletionPriority ptr
+
+-- enum CXAvailabilityKind
+-- clang_getCompletionAvailability(CXCompletionString completion_string);
+{# fun clang_getCompletionAvailability { id `Ptr ()' } -> `Int' #}
+getCompletionAvailability :: CompletionString s ->  IO AvailabilityKind
+getCompletionAvailability (CompletionString ptr) = clang_getCompletionAvailability ptr >>= return . toEnum
+
+-- unsigned clang_getCompletionNumAnnotations(CXCompletionString completion_string);
+{# fun clang_getCompletionNumAnnotations { id `Ptr ()' } -> `Int' #}
+getCompletionNumAnnotations :: CompletionString s -> IO Int
+getCompletionNumAnnotations (CompletionString ptr) = clang_getCompletionNumAnnotations ptr
+
+-- CXString clang_getCompletionAnnotation(CXCompletionString completion_string,
+--                                        unsigned annotation_number);
+{# fun wrapped_clang_getCompletionAnnotation as clang_getCompletionAnnotation { id `Ptr ()' , `Int' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCompletionAnnotation :: CompletionString s -> Int -> IO (ClangString ())
+unsafe_getCompletionAnnotation (CompletionString ptr) i = clang_getCompletionAnnotation ptr i >>= peek
+
+getCompletionAnnotation :: ClangBase m => CompletionString s' -> Int -> ClangT s m (ClangString s)
+getCompletionAnnotation = (registerClangString .) . unsafe_getCompletionAnnotation
+
+-- CXString clang_getCompletionParent(CXCompletionString completion_string,
+--                                    enum CXCursorKind *kind);
+{# fun wrapped_clang_getCompletionParent as clang_getCompletionParent { id `Ptr ()' , `CInt' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCompletionParent :: CompletionString s  -> IO (ClangString ())
+unsafe_getCompletionParent (CompletionString ptr) = clang_getCompletionParent ptr 0 >>= peek
+
+getCompletionParent :: ClangBase m => CompletionString s' -> ClangT s m (ClangString s)
+getCompletionParent = registerClangString . unsafe_getCompletionParent
+
+-- CXString clang_getCompletionBriefComment(CXCompletionString completion_string);
+{# fun wrapped_clang_getCompletionBriefComment as clang_getCompletionBriefComment { id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCompletionBriefComment :: CompletionString s  -> IO (ClangString ())
+unsafe_getCompletionBriefComment (CompletionString ptr) = clang_getCompletionBriefComment ptr >>= peek
+
+getCompletionBriefComment :: ClangBase m => CompletionString s' -> ClangT s m (ClangString s)
+getCompletionBriefComment = registerClangString . unsafe_getCompletionBriefComment
+
+-- CXCompletionString clang_getCursorCompletionString(CXCursor cursor);
+{# fun clang_getCursorCompletionString {withVoided* %`Cursor a' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_getCursorCompletionString :: Cursor s'  -> IO (ClangString ())
+unsafe_getCursorCompletionString c =
+  clang_getCursorCompletionString c >>= peek
+
+getCursorCompletionString :: ClangBase m => Cursor s' -> ClangT s m (CompletionString s)
+getCursorCompletionString c =
+  unsafeCoerce <$> (liftIO $ unsafe_getCursorCompletionString c)
+
+-- enum CXCodeComplete_Flags {
+--   CXCodeComplete_IncludeMacros = 0x01,
+--   CXCodeComplete_IncludeCodePatterns = 0x02,
+--   CXCodeComplete_IncludeBriefComments = 0x04
+-- };
+
+-- | Flags that can be used to modify the behavior of 'codeCompleteAt'.
+--
+-- * 'IncludeMacros': Whether to include macros within the set of code
+--   completions returned.
+--
+-- * 'IncludeCodePatterns': Whether to include code patterns for language constructs
+--   within the set of code completions, e.g., 'for' loops.
+--
+-- * 'IncludeBriefComments': Whether to include brief documentation within the set of code
+--   completions returned.
+#c
+enum CodeCompleteFlags
+  { IncludeMacros        = CXCodeComplete_IncludeMacros
+  , IncludeCodePatterns  = CXCodeComplete_IncludeCodePatterns
+  , IncludeBriefComments = CXCodeComplete_IncludeBriefComments
+ };
+#endc
+{# enum CodeCompleteFlags {} deriving  (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags CodeCompleteFlags where
+  toBit IncludeMacros        = 0x01
+  toBit IncludeCodePatterns  = 0x02
+  toBit IncludeBriefComments = 0x04
+
+-- unsigned clang_defaultCodeCompleteOptions(void);
+{# fun clang_defaultCodeCompleteOptions as defaultCodeCompleteOptions {} -> `Int' #}
+
+-- typedef struct {
+--   CXCompletionResult *Results;
+--   unsigned NumResults;
+-- } CXCodeCompleteResults;
+
+-- | The results of code completion.
+newtype CodeCompleteResults s = CodeCompleteResults { unCodeCompleteResults :: Ptr () }
+                                deriving (Eq, Ord, Typeable)
+
+instance ClangValue CodeCompleteResults
+
+-- void clang_disposeCodeCompleteResults(CXCodeCompleteResults *Results);
+{# fun clang_disposeCodeCompleteResults { id `Ptr ()' } -> `()' #}
+disposeCodeCompleteResults :: CodeCompleteResults s -> IO ()
+disposeCodeCompleteResults rs = clang_disposeCodeCompleteResults (unCodeCompleteResults rs)
+
+registerCodeCompleteResults :: ClangBase m => IO (CodeCompleteResults ())
+                            -> ClangT s m (CodeCompleteResults s)
+registerCodeCompleteResults action = do
+  (_, ccrs) <- clangAllocate (action >>= return . unsafeCoerce)
+                             disposeCodeCompleteResults
+  return ccrs
+{-# INLINEABLE registerCodeCompleteResults #-}
+
+-- CXCodeCompleteResults *clang_codeCompleteAt(CXTranslationUnit TU,
+--                                             const char *complete_filename,
+--                                             unsigned complete_line,
+--                                             unsigned complete_column,
+--                                             struct CXUnsavedFile *unsaved_files,
+--                                             unsigned num_unsaved_files,
+--                                             unsigned options);
+{# fun clang_codeCompleteAt { id `Ptr ()', `CString', `Int', `Int', id `Ptr ()', `Int', `Int' } -> `Ptr ()' id #}
+unsafe_codeCompleteAt :: TranslationUnit s -> String -> Int -> Int -> Ptr CUnsavedFile -> Int -> Int -> IO (CodeCompleteResults ())
+unsafe_codeCompleteAt tu s i1 i2 ufs nufs i3 =
+  withCString s (\sPtr -> clang_codeCompleteAt (unTranslationUnit tu) sPtr i1 i2 (castPtr ufs) nufs i3 >>= return . CodeCompleteResults)
+
+codeCompleteAt :: ClangBase m => TranslationUnit s' -> String -> Int -> Int
+               -> DV.Vector UnsavedFile -> Int -> ClangT s m (CodeCompleteResults s)
+codeCompleteAt tu f l c ufs os =
+  registerCodeCompleteResults $
+    withUnsavedFiles ufs $ \ufsPtr ufsLen ->
+      unsafe_codeCompleteAt tu f l c ufsPtr ufsLen os
+
+-- This function, along with codeCompleteGetResult, exist to allow iteration over
+-- the completion strings at the Haskell level. They're (obviously) not real
+-- libclang functions.
+{# fun codeCompleteGetNumResults as codeCompleteGetNumResults' { id `Ptr ()' } -> `Int' #}
+codeCompleteGetNumResults :: CodeCompleteResults s -> IO Int
+codeCompleteGetNumResults rs = codeCompleteGetNumResults' (unCodeCompleteResults rs)
+
+-- We don't need to register CompletionStrings; they're always owned by another object.
+-- They still need to be scoped, though.
+{# fun codeCompleteGetResult as codeCompleteGetResult' { id `Ptr ()', `CInt', id `Ptr (Ptr ())' } -> `CInt' id #}
+unsafe_codeCompleteGetResult :: CodeCompleteResults s -> Int -> IO (CompletionString (), CursorKind)
+unsafe_codeCompleteGetResult rs idx = do
+ sPtr <- mallocBytes (sizeOf (undefined :: (Ptr (Ptr ()))))
+ kind <- codeCompleteGetResult' (unCodeCompleteResults rs) (fromIntegral idx) (castPtr sPtr)
+ return ((CompletionString sPtr), toEnum (fromIntegral kind))
+
+codeCompleteGetResult :: ClangBase m => CodeCompleteResults s' -> Int
+                      -> ClangT s m (CompletionString s, CursorKind)
+codeCompleteGetResult rs n = do
+  (string, kind) <- liftIO $ unsafe_codeCompleteGetResult rs n
+  return (unsafeCoerce string, kind)
+
+-- void clang_sortCodeCompletionResults(CXCompletionResult *Results,
+--                                      unsigned NumResults);
+{# fun clang_sortCodeCompletionResults { id `Ptr ()', `Int' } -> `()' #}
+sortCodeCompletionResults :: CodeCompleteResults s -> IO ()
+sortCodeCompletionResults rs =
+  let results = unCodeCompleteResults rs in
+  do
+    rPtr <- peek (results `plusPtr` offsetCXCodeCompleteResultsResults)
+    numRs <- peek (results `plusPtr` offsetCXCodeCompleteResultsNumResults)
+    clang_sortCodeCompletionResults rPtr numRs
+
+-- unsigned clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *Results);
+{# fun clang_codeCompleteGetNumDiagnostics { id `Ptr ()' } -> `Int' #}
+codeCompleteGetNumDiagnostics :: CodeCompleteResults s -> IO Int
+codeCompleteGetNumDiagnostics rs = clang_codeCompleteGetNumDiagnostics (unCodeCompleteResults rs)
+
+-- CXDiagnostic clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *Results,
+--                                              unsigned Index);
+{# fun clang_codeCompleteGetDiagnostic { id `Ptr ()' , `Int' } -> `Ptr ()' id #}
+unsafe_codeCompleteGetDiagnostic :: CodeCompleteResults s -> Int -> IO (Diagnostic ())
+unsafe_codeCompleteGetDiagnostic rs idx =
+   clang_codeCompleteGetDiagnostic (unCodeCompleteResults rs) idx >>= return . mkDiagnostic
+
+codeCompleteGetDiagnostic :: ClangBase m => CodeCompleteResults s' -> Int
+                          -> ClangT s m (Diagnostic s)
+codeCompleteGetDiagnostic = (registerDiagnostic .) . unsafe_codeCompleteGetDiagnostic
+
+-- enum CXCompletionContext {
+--   CXCompletionContext_Unexposed = 0,
+--   CXCompletionContext_AnyType = 1 << 0,
+--   CXCompletionContext_AnyValue = 1 << 1,
+--   CXCompletionContext_ObjCObjectValue = 1 << 2,
+--   CXCompletionContext_ObjCSelectorValue = 1 << 3,
+--   CXCompletionContext_CXXClassTypeValue = 1 << 4,
+--   CXCompletionContext_DotMemberAccess = 1 << 5,
+--   CXCompletionContext_ArrowMemberAccess = 1 << 6,
+--   CXCompletionContext_ObjCPropertyAccess = 1 << 7,
+--   CXCompletionContext_EnumTag = 1 << 8,
+--   CXCompletionContext_UnionTag = 1 << 9,
+--   CXCompletionContext_StructTag = 1 << 10,
+--   CXCompletionContext_ClassTag = 1 << 11,
+--   CXCompletionContext_Namespace = 1 << 12,
+--   CXCompletionContext_NestedNameSpecifier = 1 << 13,
+--   CXCompletionContext_ObjCInterface = 1 << 14,
+--   CXCompletionContext_ObjCProtocol = 1 << 15,
+--   CXCompletionContext_ObjCCategory = 1 << 16,
+--   CXCompletionContext_ObjCInstanceMessage = 1 << 17,
+--   CXCompletionContext_ObjCClassMessage = 1 << 18,
+--   CXCompletionContext_ObjCSelectorName = 1 << 19,
+--   CXCompletionContext_MacroName = 1 << 20,
+--   CXCompletionContext_NaturalLanguage = 1 << 21,
+--   CXCompletionContext_Unknown = ((1 << 22) - 1) -- Set all
+                            --   contexts... Not a real value.
+-- };
+
+-- | Contexts under which completion may occur. Multiple contexts may be
+-- present at the same time.
+--
+-- * 'UnexposedCompletionContext': The context for completions is unexposed,
+--   as only Clang results should be included.
+--
+-- * 'AnyTypeCompletionContext': Completions for any possible type should be
+--   included in the results.
+--
+-- * 'AnyValueCompletionContext': Completions for any possible value (variables,
+--   function calls, etc.) should be included in the results.
+--
+-- * 'ObjCObjectValueCompletionContext': Completions for values that resolve to
+--   an Objective-C object should be included in the results.
+--
+-- * 'ObjCSelectorValueCompletionContext': Completions for values that resolve
+--   to an Objective-C selector should be included in the results.
+--
+-- * 'CXXClassTypeValueCompletionContext': Completions for values that resolve
+--   to a C++ class type should be included in the results.
+--
+-- * 'DotMemberAccessCompletionContext': Completions for fields of the member
+--   being accessed using the dot operator should be included in the results.
+--
+-- * 'ArrowMemberAccessCompletionContext': Completions for fields of the member
+--   being accessed using the arrow operator should be included in the results.
+--
+-- * 'ObjCPropertyAccessCompletionContext': Completions for properties of the
+--   Objective-C object being accessed using the dot operator should be included in the results.
+--
+-- * 'EnumTagCompletionContext': Completions for enum tags should be included in the results.
+--
+-- * 'UnionTagCompletionContext': Completions for union tags should be included in the results.
+--
+-- * 'StructTagCompletionContext': Completions for struct tags should be included in the
+--   results.
+--
+-- * 'ClassTagCompletionContext': Completions for C++ class names should be included in the
+--   results.
+--
+-- * 'NamespaceCompletionContext': Completions for C++ namespaces and namespace aliases should
+--   be included in the results.
+--
+-- * 'NestedNameSpecifierCompletionContext': Completions for C++ nested name specifiers should
+--   be included in the results.
+--
+-- * 'ObjCInterfaceCompletionContext': Completions for Objective-C interfaces (classes) should
+--   be included in the results.
+--
+-- * 'ObjCProtocolCompletionContext': Completions for Objective-C protocols should be included
+--   in the results.
+--
+-- * 'ObjCCategoryCompletionContext': Completions for Objective-C categories should be included
+--   in the results.
+--
+-- * 'ObjCInstanceMessageCompletionContext': Completions for Objective-C instance messages
+--   should be included in the results.
+--
+-- * 'ObjCClassMessageCompletionContext': Completions for Objective-C class messages should be
+--   included in the results.
+--
+-- * 'ObjCSelectorNameCompletionContext': Completions for Objective-C selector names should be
+--   included in the results.
+--
+-- * 'MacroNameCompletionContext': Completions for preprocessor macro names should be included
+--   in the results.
+--
+-- * 'NaturalLanguageCompletionContext': Natural language completions should be included in the
+--   results.
+#c
+enum CompletionContext
+  { UnexposedCompletionContext            = CXCompletionContext_Unexposed
+  , AnyTypeCompletionContext              = CXCompletionContext_AnyType
+  , AnyValueCompletionContext             = CXCompletionContext_AnyValue
+  , ObjCObjectValueCompletionContext      = CXCompletionContext_ObjCObjectValue
+  , ObjCSelectorValueCompletionContext    = CXCompletionContext_ObjCSelectorValue
+  , CXXClassTypeValueCompletionContext    = CXCompletionContext_CXXClassTypeValue
+  , DotMemberAccessCompletionContext      = CXCompletionContext_DotMemberAccess
+  , ArrowMemberAccessCompletionContext    = CXCompletionContext_ArrowMemberAccess
+  , ObjCPropertyAccessCompletionContext   = CXCompletionContext_ObjCPropertyAccess
+  , EnumTagCompletionContext              = CXCompletionContext_EnumTag
+  , UnionTagCompletionContext             = CXCompletionContext_UnionTag
+  , StructTagCompletionContext            = CXCompletionContext_StructTag
+  , ClassTagCompletionContext             = CXCompletionContext_ClassTag
+  , NamespaceCompletionContext            = CXCompletionContext_Namespace
+  , NestedNameSpecifierCompletionContext  = CXCompletionContext_NestedNameSpecifier
+  , ObjCInterfaceCompletionContext        = CXCompletionContext_ObjCInterface
+  , ObjCProtocolCompletionContext         = CXCompletionContext_ObjCProtocol
+  , ObjCCategoryCompletionContext         = CXCompletionContext_ObjCCategory
+  , ObjCInstanceMessageCompletionContext  = CXCompletionContext_ObjCInstanceMessage
+  , ObjCClassMessageCompletionContext     = CXCompletionContext_ObjCClassMessage
+  , ObjCSelectorNameCompletionContext     = CXCompletionContext_ObjCSelectorName
+  , MacroNameCompletionContext            = CXCompletionContext_MacroName
+  , NaturalLanguageCompletionContext      = CXCompletionContext_NaturalLanguage
+ };
+#endc
+{# enum CompletionContext {} deriving (Bounded, Eq, Ord, Read, Show, Typeable) #}
+
+instance BitFlags CompletionContext where
+  type FlagInt CompletionContext             = Int64
+  toBit UnexposedCompletionContext           = 0x0
+  toBit AnyTypeCompletionContext             = 0x1
+  toBit AnyValueCompletionContext            = 0x2
+  toBit ObjCObjectValueCompletionContext     = 0x4
+  toBit ObjCSelectorValueCompletionContext   = 0x8
+  toBit CXXClassTypeValueCompletionContext   = 0x10
+  toBit DotMemberAccessCompletionContext     = 0x20
+  toBit ArrowMemberAccessCompletionContext   = 0x40
+  toBit ObjCPropertyAccessCompletionContext  = 0x80
+  toBit EnumTagCompletionContext             = 0x100
+  toBit UnionTagCompletionContext            = 0x200
+  toBit StructTagCompletionContext           = 0x400
+  toBit ClassTagCompletionContext            = 0x800
+  toBit NamespaceCompletionContext           = 0x1000
+  toBit NestedNameSpecifierCompletionContext = 0x2000
+  toBit ObjCInterfaceCompletionContext       = 0x4000
+  toBit ObjCProtocolCompletionContext        = 0x8000
+  toBit ObjCCategoryCompletionContext        = 0x10000
+  toBit ObjCInstanceMessageCompletionContext = 0x20000
+  toBit ObjCClassMessageCompletionContext    = 0x40000
+  toBit ObjCSelectorNameCompletionContext    = 0x80000
+  toBit MacroNameCompletionContext           = 0x100000
+  toBit NaturalLanguageCompletionContext     = 0x200000
+
+-- unsigned long long clang_codeCompleteGetContexts(CXCodeCompleteResults *Results);
+{# fun clang_codeCompleteGetContexts { id `Ptr ()' } -> `Int64' #}
+codeCompleteGetContexts :: CodeCompleteResults s -> IO Int64
+codeCompleteGetContexts rs = clang_codeCompleteGetContexts (unCodeCompleteResults rs)
+
+-- enum CXCursorKind clang_codeCompleteGetContainerKind(CXCodeCompleteResults *Results,
+--                                                      unsigned *IsIncomplete);
+{# fun clang_codeCompleteGetContainerKind { id `Ptr ()', id `Ptr CUInt' } -> `Int' #}
+codeCompleteGetContainerKind :: CodeCompleteResults s -> IO (CursorKind, Bool)
+codeCompleteGetContainerKind rs =
+  alloca (\(iPtr :: (Ptr CUInt)) -> do
+     k <- clang_codeCompleteGetContainerKind (unCodeCompleteResults rs) iPtr
+     bool <- peek iPtr
+     return (toEnum k, toBool ((fromIntegral bool) :: Int)))
+
+-- CXString clang_codeCompleteGetContainerUSR(CXCodeCompleteResults *Results);
+{# fun clang_codeCompleteGetContainerUSR { id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_codeCompleteGetContainerUSR :: CodeCompleteResults s -> IO (ClangString ())
+unsafe_codeCompleteGetContainerUSR rs = clang_codeCompleteGetContainerUSR (unCodeCompleteResults rs) >>= peek
+
+codeCompleteGetContainerUSR :: ClangBase m => CodeCompleteResults s' -> ClangT s m (ClangString s)
+codeCompleteGetContainerUSR = registerClangString . unsafe_codeCompleteGetContainerUSR
+
+-- CXString clang_codeCompleteGetObjCSelector(CXCodeCompleteResults *Results);
+{# fun clang_codeCompleteGetObjCSelector { id `Ptr ()' } -> `Ptr (ClangString ())' castPtr #}
+unsafe_codeCompleteGetObjCSelector :: CodeCompleteResults s -> IO (ClangString ())
+unsafe_codeCompleteGetObjCSelector rs = clang_codeCompleteGetObjCSelector (unCodeCompleteResults rs) >>= peek
+
+codeCompleteGetObjCSelector :: ClangBase m => CodeCompleteResults s' -> ClangT s m (ClangString s)
+codeCompleteGetObjCSelector = registerClangString . unsafe_codeCompleteGetObjCSelector
+
+-- CXString clang_getClangVersion();
+{# fun wrapped_clang_getClangVersion as clang_getClangVersion {} -> `Ptr (ClangString ())' castPtr #}
+unsafe_getClangVersion :: IO (ClangString ())
+unsafe_getClangVersion = clang_getClangVersion >>= peek
+
+getClangVersion :: ClangBase m => ClangT s m (ClangString s)
+getClangVersion = registerClangString $ unsafe_getClangVersion
+
+-- -- void clang_toggleCrashRecovery(unsigned isEnabled);
+{# fun clang_toggleCrashRecovery as toggleCrashRecovery' { `Int' } -> `()' #}
+toggleCrashRecovery :: Bool -> IO ()
+toggleCrashRecovery b = toggleCrashRecovery' (fromBool b)
+
+data Inclusion s = Inclusion !(File s) !(SourceLocation s) !Bool
+                   deriving (Eq, Ord, Typeable)
+
+instance ClangValue Inclusion
+
+instance Storable (Inclusion s) where
+    sizeOf _ = sizeOfInclusion
+    {-# INLINE sizeOf #-}
+
+    alignment _ = alignOfInclusion
+    {-# INLINE alignment #-}
+
+    peek p = do
+      let fromCUChar = fromIntegral :: Num b => CUChar -> b
+      file <- File <$> peekByteOff p offsetInclusionInclusion
+      sl <- peekByteOff p offsetInclusionLocation
+      isDirect :: Int <- fromCUChar <$> peekByteOff p offsetInclusionIsDirect
+      return $! Inclusion file sl (if isDirect == 0 then False else True)
+    {-# INLINE peek #-}
+
+    poke p (Inclusion (File file) sl isDirect) = do
+      let toCUChar = fromIntegral :: Integral a => a -> CUChar
+      pokeByteOff p offsetInclusionInclusion file
+      pokeByteOff p offsetInclusionLocation sl
+      pokeByteOff p offsetInclusionIsDirect
+           (toCUChar $ if isDirect then 1 :: Int else 0)
+    {-# INLINE poke #-}
+
+type InclusionList s = DVS.Vector (Inclusion s)
+instance ClangValueList Inclusion
+data UnsafeInclusionList = UnsafeInclusionList !(Ptr ()) !Int
+
+-- void freeInclusions(struct Inclusion* inclusions);
+{# fun freeInclusionList as freeInclusionList' { id `Ptr ()' } -> `()' #}
+freeInclusions :: InclusionList s -> IO ()
+freeInclusions is =
+  let (isPtr, n) = fromInclusionList is in
+  freeInclusionList' isPtr
+
+registerInclusionList :: ClangBase m => IO UnsafeInclusionList -> ClangT s m (InclusionList s)
+registerInclusionList action = do
+    (_, inclusionList) <- clangAllocate (action >>= mkSafe) freeInclusions
+    return inclusionList
+  where
+    mkSafe (UnsafeInclusionList is n) = do
+      fptr <- newForeignPtr_ (castPtr is)
+      return $ DVS.unsafeFromForeignPtr fptr 0 n
+{-# INLINEABLE registerInclusionList #-}
+
+fromInclusionList :: InclusionList s -> (Ptr (), Int)
+fromInclusionList is = let (p, _, _) = DVS.unsafeToForeignPtr is in
+                       (castPtr $ Foreign.ForeignPtr.Unsafe.unsafeForeignPtrToPtr p, DVS.length is)
+
+toInclusionList :: (Ptr (), Int) -> UnsafeInclusionList
+toInclusionList (is, n) = UnsafeInclusionList is n
+
+#c
+typedef Inclusion** PtrPtrInclusion;
+#endc
+
+-- A more efficient alternative to clang_getInclusions.
+-- void getInclusions(CXTranslationUnit tu, struct Inclusion** inclusionsOut, unsigned* countOut)
+{# fun getInclusions as getInclusions' { id `Ptr ()', id `Ptr (Ptr ())', alloca- `CUInt' peek* } -> `()' #}
+unsafe_getInclusions :: TranslationUnit s -> IO UnsafeInclusionList
+unsafe_getInclusions tu = do
+  iPtrPtr <- mallocBytes {#sizeof PtrPtrInclusion #}
+  n <- getInclusions' (unTranslationUnit tu) (castPtr iPtrPtr)
+  firstInclusion <- peek (castPtr iPtrPtr :: Ptr (Ptr ()))
+  free iPtrPtr
+  return (toInclusionList (firstInclusion, fromIntegral n))
+
+
+getInclusions :: ClangBase m => TranslationUnit s' -> ClangT s m (InclusionList s)
+getInclusions = registerInclusionList . unsafe_getInclusions
+
+-- typedef void* CXRemapping;
+newtype Remapping s = Remapping { unRemapping :: Ptr () }
+                      deriving (Eq, Ord, Typeable)
+
+instance ClangValue Remapping
+
+mkRemapping :: Ptr () -> Remapping ()
+mkRemapping = Remapping
+
+-- void clang_remap_dispose(CXRemapping);
+{# fun clang_remap_dispose { id `Ptr ()' } -> `()' #}
+remap_dispose :: Remapping s -> IO ()
+remap_dispose d = clang_remap_dispose (unRemapping d)
+
+registerRemapping :: ClangBase m => IO (Remapping ()) -> ClangT s m (Remapping s)
+registerRemapping action = do
+  (_, idx) <- clangAllocate (action >>= return . unsafeCoerce)
+                            (\i -> remap_dispose i)
+  return idx
+{-# INLINEABLE registerRemapping #-}
+
+-- %dis remapping i = <unRemapping/mkRemapping> (ptr i)
+
+maybeRemapping :: Remapping s' -> Maybe (Remapping s)
+maybeRemapping (Remapping p) | p == nullPtr = Nothing
+maybeRemapping f                            = Just (unsafeCoerce f)
+
+unMaybeRemapping :: Maybe (Remapping s') -> Remapping s
+unMaybeRemapping (Just f) = unsafeCoerce f
+unMaybeRemapping Nothing  = Remapping nullPtr
+
+-- CXRemapping clang_getRemappings(const char *path);
+{# fun clang_getRemappings { `CString' } -> `Ptr ()' id #}
+unsafe_getRemappings :: FilePath -> IO (Maybe (Remapping ()))
+unsafe_getRemappings fp =
+  withCString fp (\sPtr -> clang_getRemappings sPtr >>= return . maybeRemapping . mkRemapping )
+
+getRemappings :: ClangBase m => FilePath -> ClangT s m (Maybe (Remapping s))
+getRemappings path = do
+  mRemappings <- liftIO $ unsafe_getRemappings path
+  case mRemappings of
+    Just remappings -> Just <$> registerRemapping (return remappings)
+    Nothing         -> return Nothing
+
+-- CXRemapping clang_getRemappingsFromFileList(const char **filePaths, unsigned numFiles);
+{# fun clang_getRemappingsFromFileList { id `Ptr CString' , `Int' } -> `Ptr ()' id #}
+unsafe_getRemappingsFromFileList :: Ptr CString -> Int -> IO (Maybe (Remapping ()))
+unsafe_getRemappingsFromFileList paths numPaths =
+  clang_getRemappingsFromFileList paths numPaths >>= return . maybeRemapping . mkRemapping
+
+getRemappingsFromFileList :: ClangBase m => [FilePath] -> ClangT s m (Maybe (Remapping s))
+getRemappingsFromFileList paths = do
+  mRemappings <- liftIO $ withStringList paths unsafe_getRemappingsFromFileList
+  case mRemappings of
+    Just remappings -> Just <$> registerRemapping (return remappings)
+    Nothing         -> return Nothing
+
+-- unsigned clang_remap_getNumFiles(CXRemapping);
+{# fun clang_remap_getNumFiles { id `Ptr ()' } -> `Int' #}
+remap_getNumFiles :: Remapping s -> IO Int
+remap_getNumFiles remaps =
+  clang_remap_getNumFiles (unRemapping remaps)
+
+-- void clang_remap_getFilenames(CXRemapping, unsigned index,
+--                               CXString *original, CXString *transformed);
+{# fun clang_remap_getFilenames { id `Ptr ()', `Int', id `Ptr ()', id `Ptr ()' } -> `()' #}
+unsafe_remap_getFilenames :: Remapping s -> Int -> IO (ClangString (), ClangString ())
+unsafe_remap_getFilenames remaps idx = do
+    origPtr <- mallocBytes (sizeOf (undefined :: (Ptr (ClangString ()))))
+    txPtr <- mallocBytes (sizeOf (undefined :: (Ptr (ClangString ()))))
+    clang_remap_getFilenames (unRemapping remaps) idx origPtr txPtr
+    orig <- peek (castPtr origPtr)
+    tx <- peek (castPtr txPtr)
+    free origPtr
+    free txPtr
+    return (orig, tx)
+
+remap_getFilenames :: ClangBase m => Remapping s' -> Int -> ClangT s m (ClangString s, ClangString s)
+remap_getFilenames r idx = do
+  (orig, tr) <- liftIO $ unsafe_remap_getFilenames r idx
+  (,) <$> registerClangString (return orig) <*> registerClangString (return tr)
diff --git a/src/Clang/Internal/FFIConstants.hsc b/src/Clang/Internal/FFIConstants.hsc
new file mode 100644
--- /dev/null
+++ b/src/Clang/Internal/FFIConstants.hsc
@@ -0,0 +1,161 @@
+{-# OPTIONS_GHC -fno-warn-missing-signatures #-}
+
+module Clang.Internal.FFIConstants
+( sizeOfCXCursor
+, alignOfCXCursor
+, offsetCXCursorKind
+, offsetCXCursorXData
+, offsetCXCursorP1
+, offsetCXCursorP2
+, offsetCXCursorP3
+, sizeOfParentedCursor
+, alignOfParentedCursor
+, offsetParentedCursorParent
+, offsetParentedCursorCursor
+, sizeOfInclusion
+, alignOfInclusion
+, offsetInclusionInclusion
+, offsetInclusionLocation
+, offsetInclusionIsDirect
+, sizeOfCXSourceLocation
+, alignOfCXSourceLocation
+, offsetCXSourceLocationP1
+, offsetCXSourceLocationP2
+, offsetCXSourceLocationData
+, sizeOfCXSourceRange
+, alignOfCXSourceRange
+, offsetCXSourceRangeP1
+, offsetCXSourceRangeP2
+, offsetCXSourceRangeBegin
+, offsetCXSourceRangeEnd
+, sizeOfCXToken
+, alignOfCXToken
+, offsetCXTokenI1
+, offsetCXTokenI2
+, offsetCXTokenI3
+, offsetCXTokenI4
+, offsetCXTokenData
+, sizeOfCXUnsavedFile
+, alignOfCXUnsavedFile
+, offsetCXUnsavedFileFilename
+, offsetCXUnsavedFileContents
+, offsetCXUnsavedFileContentsLen
+, sizeOfCXComment
+, alignOfCXComment
+, offsetCXCommentASTNode
+, offsetCXCommentTranslationUnit
+, sizeOfCXVersion
+, alignOfCXVersion
+, offsetCXVersionMajor
+, offsetCXVersionMinor
+, offsetCXVersionSubminor
+, sizeOfCXString
+, alignOfCXString
+, offsetCXStringData
+, offsetCXStringFlags
+, sizeOfCXPlatformAvailability
+, alignOfCXPlatformAvailability
+, offsetCXPlatformAvailabilityPlatform
+, offsetCXPlatformAvailabilityIntroduced
+, offsetCXPlatformAvailabilityDeprecated
+, offsetCXPlatformAvailabilityObsoleted
+, offsetCXPlatformAvailabilityUnavailable
+, offsetCXPlatformAvailabilityMessage
+, sizeOfCXCodeCompleteResults
+, alignOfCXCodeCompleteResults
+, offsetCXCodeCompleteResultsResults
+, offsetCXCodeCompleteResultsNumResults
+) where
+
+#include <stddef.h>
+#include "clang-c/Index.h"
+#include "clang-c/Documentation.h"
+#include "visitors.h"
+
+-- CXCursor constants.
+sizeOfCXCursor = (#const sizeof(CXCursor)) :: Int
+alignOfCXCursor = (#const 4) :: Int  -- in C11, could use alignof()
+offsetCXCursorKind = (#const offsetof(CXCursor, kind)) :: Int
+offsetCXCursorXData = (#const offsetof(CXCursor, xdata)) :: Int
+offsetCXCursorP1 = (#const offsetof(CXCursor, data)) :: Int
+offsetCXCursorP2 = (#const offsetof(CXCursor, data) + sizeof(void*)) :: Int
+offsetCXCursorP3 = (#const offsetof(CXCursor, data) + 2 * sizeof(void*)) :: Int
+
+-- ParentedCursor constants.
+sizeOfParentedCursor = (#const sizeof(ParentedCursor)) :: Int
+alignOfParentedCursor = (#const 4) :: Int
+offsetParentedCursorParent = (#const offsetof(ParentedCursor, parent)) :: Int
+offsetParentedCursorCursor = (#const offsetof(ParentedCursor, cursor)) :: Int
+
+-- Inclusion constants.
+sizeOfInclusion = (#const sizeof(Inclusion)) :: Int
+alignOfInclusion = (#const 4) :: Int
+offsetInclusionInclusion = (#const offsetof(Inclusion, inclusion)) :: Int
+offsetInclusionLocation = (#const offsetof(Inclusion, location)) :: Int
+offsetInclusionIsDirect = (#const offsetof(Inclusion, isDirect)) :: Int
+
+-- SourceLocation constants.
+sizeOfCXSourceLocation = (#const sizeof(CXSourceLocation)) :: Int
+alignOfCXSourceLocation = (#const 4) :: Int
+offsetCXSourceLocationP1 = (#const offsetof(CXSourceLocation, ptr_data)) :: Int
+offsetCXSourceLocationP2 = (#const offsetof(CXSourceLocation, ptr_data) + sizeof(void*)) :: Int
+offsetCXSourceLocationData = (#const offsetof(CXSourceLocation, int_data)) :: Int
+
+-- SourceRange constants.
+sizeOfCXSourceRange = (#const sizeof(CXSourceRange)) :: Int
+alignOfCXSourceRange = (#const 4) :: Int
+offsetCXSourceRangeP1 = (#const offsetof(CXSourceRange, ptr_data)) :: Int
+offsetCXSourceRangeP2 = (#const offsetof(CXSourceRange, ptr_data) + sizeof(void*)) :: Int
+offsetCXSourceRangeBegin= (#const offsetof(CXSourceRange, begin_int_data)) :: Int
+offsetCXSourceRangeEnd = (#const offsetof(CXSourceRange, end_int_data) + sizeof(unsigned)) :: Int
+
+-- CXToken constants.
+sizeOfCXToken = (#const sizeof(CXToken)) :: Int
+alignOfCXToken = (#const 4) :: Int
+offsetCXTokenI1 = (#const offsetof(CXToken, int_data)) :: Int
+offsetCXTokenI2 = (#const offsetof(CXToken, int_data) + sizeof(unsigned)) :: Int
+offsetCXTokenI3 = (#const offsetof(CXToken, int_data) + 2 * sizeof(unsigned)) :: Int
+offsetCXTokenI4 = (#const offsetof(CXToken, int_data) + 3 * sizeof(unsigned)) :: Int
+offsetCXTokenData = (#const offsetof(CXToken, ptr_data)) :: Int
+
+-- CXUnsavedFile constants.
+sizeOfCXUnsavedFile = (#const sizeof(struct CXUnsavedFile)) :: Int
+alignOfCXUnsavedFile = (#const 4) :: Int
+offsetCXUnsavedFileFilename = (#const offsetof(struct CXUnsavedFile, Filename)) :: Int
+offsetCXUnsavedFileContents = (#const offsetof(struct CXUnsavedFile, Contents)) :: Int
+offsetCXUnsavedFileContentsLen = (#const offsetof(struct CXUnsavedFile, Length)) :: Int
+
+-- CXComment constants.
+sizeOfCXComment = (#const sizeof(CXComment)) :: Int
+alignOfCXComment = (#const 4) :: Int
+offsetCXCommentASTNode = (#const offsetof(CXComment, ASTNode)) :: Int
+offsetCXCommentTranslationUnit = (#const offsetof(CXComment, TranslationUnit)) :: Int
+
+-- CXVersion constants.
+sizeOfCXVersion = (#const sizeof(CXVersion)) :: Int
+alignOfCXVersion = (#const 4) :: Int
+offsetCXVersionMajor = (#const offsetof(CXVersion, Major)) :: Int
+offsetCXVersionMinor = (#const offsetof(CXVersion, Minor)) :: Int
+offsetCXVersionSubminor = (#const offsetof(CXVersion, Subminor)) :: Int
+
+-- CXString constants.
+sizeOfCXString = (#const sizeof(CXString)) :: Int
+alignOfCXString = (#const 4) :: Int
+offsetCXStringData = (#const offsetof(CXString, data)) :: Int
+offsetCXStringFlags = (#const offsetof(CXString, private_flags)) :: Int
+
+-- CXPlatformAvailability constants.
+sizeOfCXPlatformAvailability = (#const sizeof(CXPlatformAvailability)) :: Int
+alignOfCXPlatformAvailability = (#const 4) :: Int
+offsetCXPlatformAvailabilityPlatform = (#const offsetof(CXPlatformAvailability, Platform)) :: Int
+offsetCXPlatformAvailabilityIntroduced = (#const offsetof(CXPlatformAvailability, Introduced)) :: Int
+offsetCXPlatformAvailabilityDeprecated = (#const offsetof(CXPlatformAvailability, Deprecated)) :: Int
+offsetCXPlatformAvailabilityObsoleted = (#const offsetof(CXPlatformAvailability, Obsoleted)) :: Int
+offsetCXPlatformAvailabilityUnavailable = (#const offsetof(CXPlatformAvailability, Unavailable)) :: Int
+offsetCXPlatformAvailabilityMessage = (#const offsetof(CXPlatformAvailability, Message)) :: Int
+
+-- CXCodeCompleteResults constants.
+sizeOfCXCodeCompleteResults = (#const sizeof(CXString)) :: Int
+alignOfCXCodeCompleteResults = (#const 4) :: Int
+offsetCXCodeCompleteResultsResults = (#const offsetof(CXCodeCompleteResults, Results)) :: Int
+offsetCXCodeCompleteResultsNumResults = (#const offsetof(CXCodeCompleteResults, NumResults)) :: Int
diff --git a/src/Clang/Internal/Monad.hs b/src/Clang/Internal/Monad.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Internal/Monad.hs
@@ -0,0 +1,81 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE EmptyDataDecls #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE RankNTypes #-}
+{-# LANGUAGE UndecidableInstances #-}
+{-# LANGUAGE ImpredicativeTypes #-}
+
+module Clang.Internal.Monad
+( ClangT
+, ClangBase
+, ClangValue(..)
+, ClangValueList(..)
+, Proxy
+, runClangT
+, clangScope
+, clangAllocate
+, mkProxy
+) where
+
+import Control.Applicative
+import Control.Monad.Base
+import Control.Monad.Trans
+import Control.Monad.Trans.Resource
+import qualified Data.Vector.Storable as DVS
+import Unsafe.Coerce (unsafeCoerce)  -- With GHC 7.8 we can use the safer 'coerce'.
+
+newtype ClangT s m a = ClangT
+  { unClangT :: ResourceT m a
+  } deriving (Applicative, Functor, Monad, MonadIO, MonadThrow, MonadTrans)
+
+instance MonadBase b m => MonadBase b (ClangT s m) where
+  liftBase = lift . liftBase
+
+instance ClangBase m => MonadResource (ClangT s m) where
+  liftResourceT = transClangT liftIO
+
+transClangT :: (m a -> n b) -> ResourceT m a -> ClangT s n b
+transClangT f rt = ClangT $ transResourceT f rt
+
+type ClangBase m = MonadResourceBase m
+
+data Proxy s
+
+runClangT :: ClangBase m => (forall s. ClangT s m a) -> m a
+runClangT f = runResourceT . unClangT $ f
+{-# INLINEABLE runClangT #-}
+
+-- | Runs a monadic computation with libclang and frees all the
+-- resources allocated by that computation immediately.
+clangScope :: ClangBase m => (forall s. ClangT s m a) -> ClangT s' m a
+clangScope = lift . runClangT
+{-# INLINEABLE clangScope #-}
+
+clangAllocate :: ClangBase m => IO a -> (a -> IO ()) -> ClangT s m (ReleaseKey, a)
+clangAllocate = allocate
+{-# INLINEABLE clangAllocate #-}
+
+mkProxy :: Proxy s
+mkProxy = undefined
+{-# INLINE mkProxy #-}
+
+class ClangValue v where
+  -- | Promotes a value from an outer scope to the current inner scope.
+  -- The value's lifetime remains that of the outer scope.
+  -- This is never necessary, but it may allow you to write code more naturally in
+  -- some situations, since it can occasionally be inconvenient that variables
+  -- from different scopes are different types.
+  fromOuterScope :: ClangBase m => v s' -> ClangT s m (v s)
+  fromOuterScope = return . unsafeCoerce
+
+class ClangValueList v where
+  -- | Promotes a list from an outer scope to the current inner scope.
+  -- The list's lifetime remains that of the outer scope.
+  -- This is never necessary, but it may allow you to write code more naturally in
+  -- some situations, since it can occasionally be inconvenient that variables
+  -- from different scopes are different types.
+  listFromOuterScope :: ClangBase m => DVS.Vector (v s') -> ClangT s m (DVS.Vector (v s))
+  listFromOuterScope = return . unsafeCoerce
diff --git a/src/Clang/Location.hs b/src/Clang/Location.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Location.hs
@@ -0,0 +1,106 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for manipulating 'FFI.SourceLocation's, which map a location in a
+-- translation unit to a location in on-disk or in-memory files.
+--
+-- This module is intended to be imported qualified.
+module Clang.Location
+(
+
+-- * Creating locations
+  create
+, createForOffset
+, createInvalid
+
+-- * Mapping locations to files
+, getExpansionLocation
+, getPresumedLocation
+, getSpellingLocation
+, getFileLocation
+
+-- * Analyzing locations
+, getCursor
+, isInSystemHeader
+, isFromMainFile
+
+) where
+
+import Control.Monad.IO.Class
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+import System.IO.Unsafe (unsafePerformIO)
+
+-- | Retrieves a 'FFI.SourceLocation' representing the given location in the source code.
+create :: ClangBase m
+       => FFI.TranslationUnit s'  -- ^ The translation unit.
+       -> FFI.File s''            -- ^ The file.
+       -> Int                     -- ^ The line.
+       -> Int                     -- ^ The column.
+       -> ClangT s m (FFI.SourceLocation s)  -- ^ A 'FFI.SourceLocation' value representing
+                                                  -- the location.
+create tu f line col = liftIO $ FFI.getLocation mkProxy tu f line col
+
+-- | Like 'create', but uses an offset instead of a line and column.
+createForOffset :: ClangBase m
+                => FFI.TranslationUnit s'  -- ^ The translation unit.
+                -> FFI.File s''            -- ^ The file.
+                -> Int                     -- ^ The offset.
+                -> ClangT s m (FFI.SourceLocation s)  -- ^ A 'FFI.SourceLocation' value
+                                                           -- representing the location.
+createForOffset tu f off = liftIO $ FFI.getLocationForOffset mkProxy tu f off
+
+-- | Creates an invalid 'FFI.SourceLocation'.
+createInvalid :: ClangBase m => ClangT s m (FFI.SourceLocation s)
+createInvalid = liftIO $ FFI.getNullLocation mkProxy
+
+-- | Retrieves the 'FFI.File', line, column, and offset associated with the given location.
+--
+-- If the location points into a macro expansion, retrieves the location of the macro expansion.
+-- This may be a position that doesn't exist in the original source.
+getExpansionLocation :: ClangBase m => FFI.SourceLocation s'
+                     -> ClangT s m (Maybe (FFI.File s), Int, Int, Int)
+getExpansionLocation l = liftIO $ FFI.getExpansionLocation mkProxy l
+
+-- | Retrieves the 'FFI.File', line, and column associated with the given location, as
+-- interpreted by the C preprocessor.
+--
+-- This may differ from the results given by 'getExpansionLocation' because it takes '#line'
+-- directives into account, which 'getExpansionLocation' ignores.
+getPresumedLocation :: ClangBase m => FFI.SourceLocation s'
+                    -> ClangT s m (FFI.ClangString s, Int, Int)
+getPresumedLocation = FFI.getPresumedLocation
+
+-- | Retrieves the 'FFI.File', line, column, and offset associated with the given location.
+--
+-- If the location points into a macro expansion, returns the corresponding position in the
+-- original source. This may be where the macro was defined or where it was instantiated,
+-- depending on what exactly the location points to.
+getSpellingLocation :: ClangBase m => FFI.SourceLocation s'
+                    -> ClangT s m (Maybe (FFI.File s), Int, Int, Int)
+getSpellingLocation l = liftIO $ FFI.getSpellingLocation mkProxy l
+
+-- | Retrieves the 'FFI.File', line, column, and offset associated with the given location.
+--
+-- If the location points into a macro expansion, returns the position where the macro was
+-- expanded or the position of the macro argument, if the cursor points at a macro argument.
+getFileLocation :: ClangBase m => FFI.SourceLocation s'
+                    -> ClangT s m (Maybe (FFI.File s), Int, Int, Int)
+getFileLocation l = liftIO $ FFI.getFileLocation mkProxy l
+
+-- | Retrieves an AST cursor at the given source location.
+--
+-- The cursor can be traversed using the functions in "Clang.Cursor".
+getCursor :: ClangBase m => FFI.TranslationUnit s' -> FFI.SourceLocation s''
+          -> ClangT s m (FFI.Cursor s)
+getCursor tu sl = liftIO $ FFI.getCursor mkProxy tu sl
+
+-- | Returns 'True' if the given location is inside a system header.
+isInSystemHeader :: FFI.SourceLocation s' -> Bool
+isInSystemHeader l = unsafePerformIO $ FFI.location_isInSystemHeader l
+
+-- | Returns 'True' if the given location is from the main file of the associated translation
+-- unit.
+isFromMainFile :: FFI.SourceLocation s' -> Bool
+isFromMainFile l = unsafePerformIO $ FFI.location_isFromMainFile l
diff --git a/src/Clang/Module.hs b/src/Clang/Module.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Module.hs
@@ -0,0 +1,50 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for manipulating 'FFI.Module's. An 'FFI.Module' value
+-- may be obtained using 'Clang.Cursor.getModule'.
+--
+-- This module is intended to be imported qualified.
+module Clang.Module
+( getASTFile
+, getParent
+, getName
+, getFullName
+, getTopLevelHeaders
+) where
+
+import Control.Monad
+import Control.Monad.IO.Class
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Retrieves the 'FFI.File' which contains the provided module.
+getASTFile :: ClangBase m => FFI.Module s' -> ClangT s m (FFI.File s)
+getASTFile m = liftIO $ FFI.module_getASTFile mkProxy m
+
+-- | Given an module, returns either
+--
+--   * the parent module (for example, for \'std.vector\' the \'std\'
+--     module will be returned), or
+--
+--   * 'Nothing' if the module is top-level.
+getParent :: ClangBase m => FFI.Module s' -> ClangT s m (Maybe (FFI.Module s))
+getParent m = liftIO $ FFI.module_getParent mkProxy m
+
+-- | Retrieves the name of a module. For example, for \'std.vector\',
+-- 'getName' will return \'vector\'.
+getName :: ClangBase m => FFI.Module s' -> ClangT s m (FFI.ClangString s)
+getName = FFI.module_getName
+
+-- | Retrieves the full name of a module, e.g. \'std.vector\'.
+getFullName :: ClangBase m => FFI.Module s' -> ClangT s m (FFI.ClangString s)
+getFullName = FFI.module_getFullName
+
+-- | Returns the list of top-level headers associated with the given module.
+getTopLevelHeaders :: ClangBase m => FFI.TranslationUnit s' -> FFI.Module s''
+                   -> ClangT s m [FFI.File s]
+getTopLevelHeaders tu m = do
+  numHeaders <- liftIO $ FFI.module_getNumTopLevelHeaders tu m
+  forM [0..(numHeaders - 1)] $ \idx ->
+    liftIO $ FFI.module_getTopLevelHeader mkProxy tu m idx
diff --git a/src/Clang/Range.hs b/src/Clang/Range.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Range.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for manipulating 'FFI.SourceRange's, which represent a range of
+-- locations in the source code between two points.
+--
+-- This module is intended to be imported qualified.
+module Clang.Range
+(
+
+-- * Creating ranges
+  create
+, createInvalid
+
+-- * Analyzing ranges
+, getStart
+, getEnd
+, isInvalid
+
+) where
+
+import Control.Monad.IO.Class
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+import System.IO.Unsafe (unsafePerformIO)
+
+-- | Creates a 'FFI.SourceRange' representing the range between two locations.
+create :: ClangBase m
+       => FFI.SourceLocation s'   -- ^ Starting location.
+       -> FFI.SourceLocation s''  -- ^ Ending location.
+       -> ClangT s m (FFI.SourceRange s)
+create from to = liftIO $ FFI.getRange mkProxy from to
+
+-- | Creates an invalid 'FFI.SourceRange'.
+createInvalid :: ClangBase m => ClangT s m (FFI.SourceRange s)
+createInvalid = liftIO $ FFI.getNullRange mkProxy
+
+-- | Retrieves the beginning of the given range.
+getStart :: ClangBase m => FFI.SourceRange s' -> ClangT s m (FFI.SourceLocation s)
+getStart sr = liftIO $ FFI.getRangeStart mkProxy sr
+
+-- | Retrieves the end of the given range.
+getEnd :: ClangBase m => FFI.SourceRange s' -> ClangT s m (FFI.SourceLocation s)
+getEnd sr = liftIO $ FFI.getRangeEnd mkProxy sr
+
+-- | Returns 'True' if the given range is invalid.
+isInvalid :: FFI.SourceRange s' -> Bool
+isInvalid r = unsafePerformIO $ FFI.range_isNull r
diff --git a/src/Clang/Remapping.hs b/src/Clang/Remapping.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Remapping.hs
@@ -0,0 +1,37 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for manipulating remappings.
+--
+-- This module is intended to be imported qualified.
+module Clang.Remapping
+( getRemappings
+, getRemappingsFromFileList
+, getRemappedFiles
+) where
+
+import Control.Monad.IO.Class
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Given a 'FilePath' for a file, returns information about the remappings that
+-- apply to that file. If an error occurs, returns 'Nothing'.
+getRemappings :: ClangBase m => FilePath -> ClangT s m (Maybe (FFI.Remapping s))
+getRemappings = FFI.getRemappings
+
+-- | Given a list of 'FilePath's, returns information about the
+-- remappings that apply to the corresponding files. If an error
+-- occurs, returns 'Nothing'.
+getRemappingsFromFileList :: ClangBase m => [FilePath] -> ClangT s m (Maybe (FFI.Remapping s))
+getRemappingsFromFileList = FFI.getRemappingsFromFileList
+
+-- | Retrieves a list of the remappings described by a
+-- 'FFI.Remapping'. Each entry in the list consists of a pair.
+-- The first element is the original filename, and the second element
+-- is the filename it has been remapped to.
+getRemappedFiles :: ClangBase m => FFI.Remapping s'
+                 -> ClangT s m [(FFI.ClangString s, FFI.ClangString s)]
+getRemappedFiles remaps = do
+  numRemaps <- liftIO $ FFI.remap_getNumFiles remaps
+  mapM (FFI.remap_getFilenames remaps) [0..(numRemaps - 1)]
diff --git a/src/Clang/String.hs b/src/Clang/String.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/String.hs
@@ -0,0 +1,51 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | This module contains functions for working with
+-- 'FFI.ClangString's, which represent strings that are part of the
+-- libclang AST or managed by its API.
+--
+-- This module is intended to be imported qualified.
+module Clang.String (
+-- * Conversions
+  unpack
+, unpackText
+, unpackByteString
+
+-- * Unsafe conversions
+, unsafeUnpackByteString
+) where
+
+import qualified Data.ByteString as B
+import qualified Data.Text as T
+import qualified Data.Text.Encoding as TE
+import qualified Data.Text.Encoding.Error as TEE
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Converts an 'FFI.ClangString' to a 'String'.
+unpack :: ClangBase m => FFI.ClangString s' -> ClangT s m String
+unpack = FFI.getString
+
+-- | Converts an 'FFI.ClangString' to a 'T.Text'.
+unpackText :: ClangBase m => FFI.ClangString s' -> ClangT s m T.Text
+unpackText s = do
+  -- Since unsafeGetByteString does not make a copy, this doesn't actually
+  -- require the two copies that it appears to employ.
+  str <- FFI.unsafeGetByteString s
+  return $! TE.decodeUtf8With TEE.lenientDecode str
+
+-- | Converts an 'FFI.ClangString' to a 'B.ByteString'. This is faster
+-- than 'unpack' and 'unpackText' since it requires no encoding.
+unpackByteString :: ClangBase m => FFI.ClangString s' -> ClangT s m B.ByteString
+unpackByteString = FFI.getByteString
+
+-- | Creates a 'B.ByteString' that shares the underlying memory of the
+-- 'FFI.ClangString'. This is very fast since no copying has to be
+-- done. However, it's also unsafe because the 'B.ByteString' may outlive
+-- the scope of the 'FFI.ClangString', leading to corruption of
+-- its contents or crashes. It's the caller's responsibility to
+-- prevent this.
+unsafeUnpackByteString :: ClangBase m => FFI.ClangString s' -> ClangT s m B.ByteString
+unsafeUnpackByteString = FFI.unsafeGetByteString
diff --git a/src/Clang/Token.hs b/src/Clang/Token.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Token.hs
@@ -0,0 +1,90 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for manipulating 'Clang.Token's.
+--
+-- This module is intended to be imported qualified.
+module Clang.Token
+(
+-- * Token lists
+  tokenize
+, List
+
+-- * Token kinds
+, getKind
+
+-- * Mapping between tokens and source code
+, getSpelling
+, getLocation
+, getExtent
+, annotateTokens
+) where
+
+import Control.Monad.IO.Class
+import qualified Data.Vector.Storable as DVS
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Tokenizes the source code described by the given range into raw
+-- lexical tokens.
+tokenize :: ClangBase m
+         => FFI.TranslationUnit s'  -- ^ The translation list
+                                    -- containing the source code.
+         -> FFI.SourceRange s''     -- ^ The source range in which text
+                                    -- should be tokenized.
+         -> ClangT s m (List s)
+tokenize = FFI.tokenize
+
+-- | A list of tokens, stored as a 'DVS.Vector' for efficiency.
+type List s = DVS.Vector (FFI.Token s)
+
+-- | Determines the kind of the given token, expressed as a
+-- 'FFI.TokenKind' value.
+getKind :: ClangBase m => FFI.Token s' -> ClangT s m FFI.TokenKind
+getKind t = liftIO $ FFI.getTokenKind t
+
+-- | Retrieves the \'spelling\', or textual representation, of the
+-- given token.
+getSpelling :: ClangBase m => FFI.TranslationUnit s' -> FFI.Token s'' -> ClangT s m (FFI.ClangString s)
+getSpelling = FFI.getTokenSpelling
+
+-- | Returns the source location of the given token.
+getLocation :: ClangBase m => FFI.TranslationUnit s' -> FFI.Token s''
+            -> ClangT s m (FFI.SourceLocation s)
+getLocation tu tk = liftIO $ FFI.getTokenLocation mkProxy tu tk
+
+-- | Retrieves the source range that covers the given token.
+getExtent :: ClangBase m => FFI.TranslationUnit s' -> FFI.Token s''
+          -> ClangT s m (FFI.SourceRange s)
+getExtent tu tk = liftIO $ FFI.getTokenExtent mkProxy tu tk
+
+-- | Annotates the given set of tokens by providing cursors for each token
+-- that can be mapped to a specific entity within the abstract syntax tree.
+-- 
+-- This is equivalent to invoking 'Clang.Cursor.getCursor' on the
+-- source locations of each of these tokens. The cursors provided are
+-- filtered, so that only those cursors that have a direct
+-- correspondence to the token are accepted. For example, given a
+-- function call \'f(x)\', 'Clang.Cursor.getCursor' would provide the
+-- following cursors:
+-- 
+--   * When the cursor is over the \'f\', a 'Clang.DeclRefExpr' cursor
+--     referring to \'f\'.
+--
+--   * When the cursor is over the \'(\' or the \')\', a
+--     'Clang.CallExpr' referring to \'f\'.
+--
+--   * When the cursor is over the \'x\', a 'Clang.DeclRefExpr' cursor
+--     referring to \'x\'.
+-- 
+-- Only the first and last of these cursors will occur within the
+-- annotate, since the tokens \'f\' and \'x\' directly refer to a function
+-- and a variable, respectively, but the parentheses are just a small
+-- part of the full syntax of the function call expression, which is
+-- not provided as an annotation.
+annotateTokens :: ClangBase m
+               => FFI.TranslationUnit s' -- ^ The translation unit that owns the tokens.
+               -> List s''               -- ^ The tokens to annotate.
+               -> ClangT s m (FFI.CursorList s)
+annotateTokens = FFI.annotateTokens
diff --git a/src/Clang/TranslationUnit.hs b/src/Clang/TranslationUnit.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/TranslationUnit.hs
@@ -0,0 +1,195 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE RankNTypes #-}
+
+-- | Functions for manipulating translation units.
+--
+-- To start analyzing a translation unit, call 'Index.withNew' to create a new index and
+-- call 'withParsed' in the callback. Inside the callback for 'withParsed', you'll have
+-- access to a 'FFI.TranslationUnit' value; you can call 'getCursor' to turn that into an
+-- AST cursor which can be traversed using the functions in "Clang.Cursor".
+--
+-- This module is intended to be imported qualified.
+module Clang.TranslationUnit
+(
+
+-- * Creating a translation unit
+  withParsed
+, withLoaded
+, withReparsing
+, FFI.TranslationUnitFlags
+, FFI.ReparseFlags
+, ReparsingCallback
+, ParseContinuation(..)
+
+-- * Saving
+, save
+, FFI.SaveTranslationUnitFlags
+
+-- AST traversal and metadata
+, getCursor
+, getDiagnosticSet
+, getSpelling
+
+) where
+
+import Data.Traversable
+import Control.Monad.IO.Class
+import Data.Maybe (fromMaybe)
+import qualified Data.Vector as DV
+-- import System.FilePath ((</>))
+
+import Clang.Internal.BitFlags
+import Clang.Internal.Monad
+import qualified Clang.Internal.FFI as FFI
+-- import Paths_LibClang (getDataFileName)
+
+-- | Creates a translation unit by parsing source code.
+--
+-- Note that not all command line arguments which are accepted by the \'clang\' frontend can
+-- be used here. You should avoid passing \'-c\', \'-o\', \'-fpch-deps\', and the various
+-- \'-M\' options. If you provide a 'FilePath' when calling 'withParsed', also be sure not
+-- to provide the filename in the command line arguments as well.
+withParsed :: ClangBase m
+           => FFI.Index s'  -- ^ The index into which the translation unit should be loaded.
+           -> Maybe FilePath  -- ^ The file to load, or 'Nothing' if the file is specified in
+                              --   the command line arguments.
+           -> [String]  -- ^ The command line arguments libclang should use when compiling this
+                        --   file. Most arguments which you'd use with the \'clang\' frontend
+                        --   are accepted.
+           -> DV.Vector FFI.UnsavedFile  -- ^ Unsaved files which may be needed to parse this
+                                         --   translation unit. This may include the source
+                                         --   file itself or any file it includes.
+           -> [FFI.TranslationUnitFlags]  -- ^ Flags that affect the processing of this
+                                          --   translation unit.
+           -> (forall s. FFI.TranslationUnit s -> ClangT s m a)  -- ^ A callback.
+           -> ClangT s' m (Maybe a)  -- ^ The return value of the callback, or 'Nothing'
+                                     --   if the file couldn't be parsed.
+withParsed idx mayPath args ufs flags f = do
+    -- liftIO $ FFI.setClangResourcesPath idx =<< clangResourcesPath
+    mayTU <- FFI.parseTranslationUnit idx mayPath args ufs (orFlags flags)
+    traverse go mayTU
+  where
+    go tu = clangScope $ f =<< fromOuterScope tu
+
+-- | Creates a translation unit by loading a saved AST file.
+--
+-- Such an AST file can be created using 'save'.
+withLoaded :: ClangBase m
+           => FFI.Index s'  -- ^ The index into which the translation unit should be loaded.
+           -> FilePath      -- ^ The file to load.
+           -> (forall s. FFI.TranslationUnit s -> ClangT s m a)  -- ^ A callback.
+           -> ClangT s' m a
+withLoaded idx path f = do
+  -- liftIO $ FFI.setClangResourcesPath idx =<< clangResourcesPath
+  f =<< FFI.createTranslationUnit idx path
+
+
+-- | Creates a translation unit by parsing source code.
+--
+-- This works like 'withParsed', except that the translation unit can be reparsed over and over
+-- again by returning a 'Reparse' value from the callback. This is useful for interactive
+-- analyses like code completion. Processing can be stopped by returning a 'ParseComplete' value.
+withReparsing :: ClangBase m
+              => FFI.Index s'  -- ^ The index into which the translation unit should be loaded.
+              -> Maybe FilePath  -- ^ The file to load, or 'Nothing' if the file is specified in
+                                 --   the command line arguments.
+              -> [String]  -- ^ The command line arguments libclang should use when compiling
+                           --   this file. Most arguments which you'd use with the \'clang\'
+                           --   frontend are accepted.
+              -> DV.Vector FFI.UnsavedFile  -- ^ Unsaved files which may be needed to parse this
+                                            --   translation unit. This may include the source
+                                            --   file itself or any file it includes.
+              -> [FFI.TranslationUnitFlags]  -- ^ Flags that affect the processing of this
+                                             --   translation unit.
+              -> ReparsingCallback m r  -- ^ A callback which uses the translation unit. May be
+                                        --   called many times depending on the return value.
+                                        --   See 'ParseContinuation' for more information.
+              -> ClangT s' m (Maybe r)  -- ^ The return value of the callback, as passed to
+                                        --   'ParseComplete', or 'Nothing' if the file could
+                                        --   not be parsed.
+withReparsing idx mayPath args ufs flags f = do
+    -- liftIO $ FFI.setClangResourcesPath idx =<< clangResourcesPath
+    mayTU <- FFI.parseTranslationUnit idx mayPath args ufs (orFlags flags)
+    case mayTU of
+      Nothing -> return Nothing
+      Just tu -> iterReparse f tu
+
+iterReparse :: ClangBase m
+            => ReparsingCallback m r
+            -> FFI.TranslationUnit s'
+            -> ClangT s' m (Maybe r)
+iterReparse f tu = do
+  cont <- clangScope $ f =<< fromOuterScope tu
+  case cont of
+    Reparse nextF ufs mayFlags ->
+      do res <- FFI.reparseTranslationUnit tu ufs (makeFlags mayFlags)
+         if res then iterReparse nextF tu
+                else return Nothing
+    ParseComplete finalVal -> return $ Just finalVal
+  where
+    makeFlags = orFlags . (fromMaybe [FFI.DefaultReparseFlags])
+
+
+-- | A callback for use with 'withReparsing'.
+type ReparsingCallback m r = forall s. FFI.TranslationUnit s
+                          -> ClangT s m (ParseContinuation m r)
+
+-- | A continuation returned by a 'ReparsingCallback'.
+data ParseContinuation m r
+  -- | 'Reparse' signals that the translation unit should be reparsed. It contains a callback
+  -- which will be called with the updated translation unit after reparsing, a 'DV.Vector' of
+  -- unsaved files which may be needed to reparse, and a set of flags affecting reparsing. The
+  -- default reparsing flags can be requested by specifying 'Nothing'.
+  = Reparse (ReparsingCallback m r) (DV.Vector FFI.UnsavedFile) (Maybe [FFI.ReparseFlags])
+
+  -- | 'ParseComplete' signals that processing is finished. It contains a final result which
+  -- will be returned by 'withReparsing'.
+  | ParseComplete r
+
+-- clangResourcesPath :: IO FilePath
+-- clangResourcesPath =
+--   getDataFileName $ "build" </> "out" </> "lib" </> "clang" </> "3.4"
+
+-- | Saves a translation unit as an AST file with can be loaded later using 'withLoaded'.
+save :: ClangBase m
+     => FFI.TranslationUnit s'  -- ^ The translation unit to save.
+     -> FilePath                -- ^ The filename to save to.
+     -> Maybe [FFI.SaveTranslationUnitFlags]  -- ^ Flags that affect saving, or 'Nothing' for
+                                              --   the default set of flags.
+     -> ClangT s m Bool
+save t fname mayFlags = liftIO $ FFI.saveTranslationUnit t fname (orFlags flags)
+  where flags = fromMaybe [FFI.DefaultSaveTranslationUnitFlags] mayFlags
+
+{-
+-- | Reparses the provided translation unit using the same command line arguments
+-- that were originally used to parse it. If the file has changed on disk, or if
+-- the unsaved files have changed, those changes will become visible.
+--
+-- Note that 'reparse' invalidates all cursors and source locations that refer into
+-- the reparsed translation unit. This makes it unsafe. However, 'reparse' can be
+-- more efficient than calling 'withParsed' a second time.
+reparse :: ClangBase m
+        => FFI.TranslationUnit s'    -- ^ The translation unit to reparse.
+        -> DV.Vector FFI.UnsavedFile -- ^ Unsaved files which may be needed to reparse
+                                     --   this translation unit.
+        -> Maybe [FFI.ReparseFlags]  -- ^ Flags that affect reparsing, or 'Nothing' for the
+                                     --   default set of flags.
+        -> ClangT s m Bool
+reparse t ufs mayFlags = FFI.reparseTranslationUnit t ufs (orFlags flags)
+  where flags = fromMaybe [FFI.DefaultReparseFlags] mayFlags
+-}
+
+-- | Retrieve the cursor associated with this translation unit. This cursor is the root of
+-- this translation unit's AST; you can begin exploring the AST further using the functions
+-- in "Clang.Cursor".
+getCursor :: ClangBase m => FFI.TranslationUnit s' -> ClangT s m (FFI.Cursor s)
+getCursor tu = liftIO $ FFI.getTranslationUnitCursor mkProxy tu
+
+-- | Retrieve the complete set of diagnostics associated with the given translation unit.
+getDiagnosticSet :: ClangBase m => FFI.TranslationUnit s'-> ClangT s m (FFI.DiagnosticSet s)
+getDiagnosticSet = FFI.getDiagnosticSetFromTU
+
+-- | Retrieve a textual representation of this translation unit.
+getSpelling :: ClangBase m => FFI.TranslationUnit s' -> ClangT s m (FFI.ClangString s)
+getSpelling = FFI.getTranslationUnitSpelling
diff --git a/src/Clang/Type.hs b/src/Clang/Type.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Type.hs
@@ -0,0 +1,142 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+module Clang.Type
+( isSameType
+, getTypeSpelling
+, getKind
+, getCanonicalType
+, getPointeeType
+, getResultType
+, getNumArgTypes
+, getArgType
+, isFunctionTypeVariadic
+
+, getTypedefDeclUnderlyingType
+, getEnumDeclIntegerType
+, getEnumConstantDeclValue
+, getEnumConstantDeclUnsignedValue
+, getFieldDeclBitWidth
+
+, isConstQualifiedType
+, isVolatileQualifiedType
+, isRestrictQualifiedType
+, isPODType
+, getElementType
+, getNumElements
+, getArrayElementType
+, getArraySize
+, getAlignOf
+, getSizeOf
+, getOffsetOf
+, getClassType
+, getCXXRefQualifier
+, isVirtualBase
+, getFunctionTypeCallingConv
+
+, getTypeKindSpelling
+) where
+
+import Control.Monad.IO.Class
+import qualified Data.ByteString as B
+import Data.Int (Int64)
+import Data.Word (Word64)
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+isSameType :: ClangBase m => FFI.Type s' -> FFI.Type s'' -> ClangT s m Bool
+isSameType a b = liftIO $ FFI.equalTypes a b
+
+getTypeSpelling :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.ClangString s)
+getTypeSpelling = FFI.getTypeSpelling
+
+getTypedefDeclUnderlyingType :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Type s)
+getTypedefDeclUnderlyingType c = liftIO $ FFI.getTypedefDeclUnderlyingType mkProxy c
+
+getEnumDeclIntegerType :: ClangBase m => FFI.Cursor s' -> ClangT s m (FFI.Type s)
+getEnumDeclIntegerType c = liftIO $ FFI.getEnumDeclIntegerType mkProxy c
+
+getEnumConstantDeclValue :: ClangBase m => FFI.Cursor s' -> ClangT s m Int64
+getEnumConstantDeclValue c = liftIO $ FFI.getEnumConstantDeclValue c
+
+getEnumConstantDeclUnsignedValue :: ClangBase m => FFI.Cursor s' -> ClangT s m Word64
+getEnumConstantDeclUnsignedValue c = liftIO $ FFI.getEnumConstantDeclUnsignedValue c
+
+getFieldDeclBitWidth :: ClangBase m => FFI.Cursor s' -> ClangT s m (Maybe Int)
+getFieldDeclBitWidth c = do
+  bitWidth <- liftIO $ FFI.getFieldDeclBitWidth c
+  return $ if bitWidth < 0 then Nothing
+                           else Just bitWidth
+    
+getKind :: ClangBase m => FFI.Type s' -> ClangT s m FFI.TypeKind
+getKind = return . FFI.getTypeKind
+
+getCanonicalType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
+getCanonicalType t = liftIO $ FFI.getCanonicalType mkProxy t
+
+getPointeeType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
+getPointeeType t = liftIO $ FFI.getPointeeType mkProxy t
+
+getResultType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
+getResultType t = liftIO $ FFI.getResultType mkProxy t
+
+getNumArgTypes :: ClangBase m => FFI.Type s' -> ClangT s m Int
+getNumArgTypes t = liftIO $ FFI.getNumArgTypes t
+
+getArgType :: ClangBase m => FFI.Type s' -> Int -> ClangT s m (FFI.Type s)
+getArgType t i = liftIO $ FFI.getArgType mkProxy t i
+
+isFunctionTypeVariadic :: ClangBase m => FFI.Type s' -> ClangT s m Bool
+isFunctionTypeVariadic t = liftIO $ FFI.isFunctionTypeVariadic t
+
+isConstQualifiedType :: ClangBase m => FFI.Type s' -> ClangT s m Bool
+isConstQualifiedType t = liftIO $ FFI.isConstQualifiedType t
+
+isVolatileQualifiedType :: ClangBase m => FFI.Type s' -> ClangT s m Bool
+isVolatileQualifiedType t = liftIO $ FFI.isVolatileQualifiedType t
+
+isRestrictQualifiedType :: ClangBase m => FFI.Type s' -> ClangT s m Bool
+isRestrictQualifiedType t = liftIO $ FFI.isRestrictQualifiedType t
+
+isPODType :: ClangBase m => FFI.Type s' -> ClangT s m Bool
+isPODType t = liftIO $ FFI.isPODType t
+
+getElementType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
+getElementType t = liftIO $ FFI.getElementType mkProxy t
+
+getNumElements :: ClangBase m => FFI.Type s' -> ClangT s m Int64
+getNumElements t = liftIO $ FFI.getNumElements t
+
+getArrayElementType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
+getArrayElementType t = liftIO $ FFI.getArrayElementType mkProxy t
+
+getArraySize :: ClangBase m => FFI.Type s' -> ClangT s m Int64
+getArraySize t = liftIO $ FFI.getArraySize t
+
+getAlignOf :: ClangBase m => FFI.Type s' -> ClangT s m (Either FFI.TypeLayoutError Int64)
+getAlignOf t = liftIO $ FFI.type_getAlignOf t
+
+getSizeOf :: ClangBase m => FFI.Type s' -> ClangT s m (Either FFI.TypeLayoutError Int64)
+getSizeOf t = liftIO $ FFI.type_getSizeOf t
+
+getOffsetOf :: ClangBase m => FFI.Type s' -> B.ByteString
+            -> ClangT s m (Either FFI.TypeLayoutError Int64)
+getOffsetOf = FFI.type_getOffsetOf
+
+getClassType :: ClangBase m => FFI.Type s' -> ClangT s m (FFI.Type s)
+getClassType t = liftIO $ FFI.type_getClassType mkProxy t
+
+getCXXRefQualifier :: ClangBase m => FFI.Type s' -> ClangT s m FFI.RefQualifierKind
+getCXXRefQualifier t = liftIO $ FFI.type_getCXXRefQualifier t
+
+isVirtualBase :: ClangBase m => FFI.Cursor s' -> ClangT s m Bool
+isVirtualBase c = liftIO $ FFI.isVirtualBase c
+
+getFunctionTypeCallingConv :: ClangBase m => FFI.Type s' -> ClangT s m FFI.CallingConv
+getFunctionTypeCallingConv t = liftIO $ FFI.getFunctionTypeCallingConv t
+
+
+-- Typekind functions
+getTypeKindSpelling :: ClangBase m => FFI.TypeKind -> ClangT s m (FFI.ClangString s)
+getTypeKindSpelling = FFI.getTypeKindSpelling
diff --git a/src/Clang/USR.hs b/src/Clang/USR.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/USR.hs
@@ -0,0 +1,79 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | Functions for manipulating 'Unified Symbol Resolution' values, or
+-- \'USRs\'. USRs are strings that provide an unambiguous reference to a
+-- symbol. Any two cursors that refer to the same semantic entity will
+-- have the same USR, even if they occur in different translation
+-- units. This is very useful when attempting to cross-reference
+-- between different source files in a project.
+--
+-- Most often, using USRs simply means retrieving the USR that
+-- corresponds to a 'Clang.Cursor'. You can do this using
+-- 'Clang.Cursor.getUSR', and then convert to a Haskell string using
+-- the functions in "Clang.String".
+--
+-- This module is intended to be imported qualified.
+module Clang.USR
+( createFromObjCClass
+, createFromObjCCategory
+, createFromObjCProtocol
+, createFromObjCIvar
+, createFromObjCInstanceMethod
+, createFromObjCClassMethod
+, createFromObjCProperty
+) where
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Construct a USR for the specified Objective-C class.
+createFromObjCClass :: ClangBase m
+                    => String  -- ^ A class name.
+                    -> ClangT s m (FFI.ClangString s)
+createFromObjCClass = FFI.constructUSR_ObjCClass
+
+-- | Construct a USR for the specified Objective-C category.
+createFromObjCCategory :: ClangBase m
+                       => String  -- ^ A class name.
+                       -> String  -- ^ A category name.
+                       -> ClangT s m (FFI.ClangString s)
+createFromObjCCategory = FFI.constructUSR_ObjCCategory
+
+-- | Construct a USR for the specified Objective-C protocol.
+createFromObjCProtocol :: ClangBase m
+                       => String  -- ^ A protocol name.
+                       -> ClangT s m (FFI.ClangString s)
+createFromObjCProtocol = FFI.constructUSR_ObjCProtocol
+
+-- | Construct a USR for the specified Objective-C instance variable,
+-- given the USR for its containing class.
+createFromObjCIvar :: ClangBase m
+                   => String              -- ^ An instance variable name.
+                   -> FFI.ClangString s'  -- ^ A class USR.
+                   -> ClangT s m (FFI.ClangString s)
+createFromObjCIvar = FFI.constructUSR_ObjCIvar
+
+-- | Construct a USR for the specified Objective-C instance method, given the USR
+-- for its containing class.
+createFromObjCInstanceMethod :: ClangBase m
+                             => String              -- ^ A method name.
+                             -> FFI.ClangString s'  -- ^ A class USR.
+                             -> ClangT s m (FFI.ClangString s)
+createFromObjCInstanceMethod name = FFI.constructUSR_ObjCMethod name True
+
+-- | Construct a USR for the specified Objective-C class method, given the USR
+-- for its containing class.
+createFromObjCClassMethod :: ClangBase m
+                          => String              -- ^ A method name.
+                          -> FFI.ClangString s'  -- ^ A class USR.
+                          -> ClangT s m (FFI.ClangString s)
+createFromObjCClassMethod name = FFI.constructUSR_ObjCMethod name False
+
+-- | Construct a USR for the specified Objective-C property, given the USR
+-- for its containing class.
+createFromObjCProperty :: ClangBase m
+                       => String              -- ^ A property name.
+                       -> FFI.ClangString s'  -- ^ A class USR.
+                       -> ClangT s m (FFI.ClangString s)
+createFromObjCProperty = FFI.constructUSR_ObjCProperty
diff --git a/src/Clang/UnsavedFile.hs b/src/Clang/UnsavedFile.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/UnsavedFile.hs
@@ -0,0 +1,44 @@
+-- | Functions for working with unsaved files.
+--
+-- Unsaved files are used to represent files which are in memory, but haven't
+-- yet been written to disk. You'll need to use unsaved files for situations
+-- like supporting autocomplete in an editor without requiring the user to save
+-- for up-to-date completions. See "Clang.TranslationUnit" for details about
+-- using unsaved files.
+--
+-- This module is intended to be imported qualified.
+module Clang.UnsavedFile
+( 
+
+-- * Creating an unsaved file
+  new
+
+-- * Field accessors
+, filename
+, contents
+
+-- * Updates
+, updateContents
+
+) where
+
+import qualified Data.ByteString as B
+
+import qualified Clang.Internal.FFI as FFI
+
+-- | Create a new unsaved file.
+new :: B.ByteString -> B.ByteString -> FFI.UnsavedFile
+new = FFI.newUnsavedFile
+
+-- | Retrieve the filename of an unsaved file.
+filename :: FFI.UnsavedFile -> B.ByteString
+filename = FFI.unsavedFilename
+
+-- | Retrieve the contents of an unsaved file.
+contents :: FFI.UnsavedFile -> B.ByteString
+contents = FFI.unsavedContents
+
+-- | Update the contents of an unsaved file. This is more efficient than creating
+-- a new unsaved file with the same filename.
+updateContents :: FFI.UnsavedFile -> B.ByteString -> FFI.UnsavedFile
+updateContents = FFI.updateUnsavedContents
diff --git a/src/Clang/Version.hs b/src/Clang/Version.hs
new file mode 100644
--- /dev/null
+++ b/src/Clang/Version.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE ConstraintKinds #-}
+{-# LANGUAGE FlexibleContexts #-}
+
+-- | This module allows you to query the version of libclang that this
+-- library provides bindings for.
+module Clang.Version
+( getVersion
+, apiVersion
+, encodedAPIVersion
+) where
+
+import qualified Clang.Internal.FFI as FFI
+import Clang.Internal.Monad
+
+-- | Return a version string, suitable for showing to a user, but not
+-- intended to be parsed (the format is not guaranteed to be stable).
+-- This is the version usually used for libclang packages and public
+-- documentation.
+getVersion :: ClangBase m => ClangT s m (FFI.ClangString s)
+getVersion = FFI.getClangVersion
+
+-- | The API version, in (major, minor) format. This is a semantic
+-- version that tracks only the libclang API itself. It's unrelated to
+-- the associated LLVM or libclang version.
+apiVersion :: (Int, Int)
+apiVersion = (FFI.versionMajor, FFI.versionMinor)
+
+-- | The API version, encoded as a single number.
+encodedAPIVersion :: Int
+encodedAPIVersion = FFI.encodedVersion
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,25 @@
+LLVM_CFG=../build/out/bin/llvm-config
+CC=gcc
+CFLAGS=-std=gnu99 
+LLVM_CFLAGS=$(shell $(LLVM_CFG) --cflags)
+LDFLAGS=$(shell $(LLVM_CFG) --ldflags)
+LIBS=-ldl -pthread -Wl,-rpath -Wl,$(shell $(LLVM_CFG) --libdir) $(shell $(LLVM_CFG) --libs core) -lclang
+
+all: Test_Diagnostics_c Test_Diagnostics_hs Test_InclusionVisitor_c Test_InclusionVisitor_hs Test_ChildVisitor_c Test_ChildVisitor_hs
+
+test: all
+	@echo "########### TESTING ##############"
+	@./runTest.sh Test_Diagnostics Test_Diagnostics.c
+	@./runTest.sh Test_InclusionVisitor Test_InclusionVisitor.c
+	@./runTest.sh Test_ChildVisitor Test_ChildVisitor.c
+
+%_c : %.c
+	$(CC) $(CFLAGS) $(LLVM_CFLAGS) -o $@ $< $(LDFLAGS) $(LIBS)
+
+%_hs : %.hs
+	cd .. && cabal exec -- ghc -o test/$@ test/$<
+
+clean:
+	rm *_c *_hs *.o *.hi
+
+.PHONY = all clean test
diff --git a/test/Test_ChildVisitor.c b/test/Test_ChildVisitor.c
new file mode 100644
--- /dev/null
+++ b/test/Test_ChildVisitor.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <clang-c/Index.h>
+
+enum CXChildVisitResult visitor(CXCursor cursor, CXCursor parent, CXClientData data)
+{
+  enum CXCursorKind cKind = clang_getCursorKind(cursor);
+  CXString nameString = clang_getCursorDisplayName(cursor);
+  CXString typeString = clang_getCursorKindSpelling(cKind);
+  printf("Name:%s, Kind:%s\n", clang_getCString(nameString), clang_getCString(typeString));
+  clang_disposeString(nameString);
+  clang_disposeString(typeString);
+  return CXChildVisit_Continue;
+}
+
+int main(int argc, char * argv[])
+{
+  CXIndex index = clang_createIndex(0, 0);
+  CXTranslationUnit txUnit = clang_parseTranslationUnit(index, 0, (const char * const *) argv, argc, 0, 0, CXTranslationUnit_None);
+
+  CXCursor cur = clang_getTranslationUnitCursor(txUnit);
+  clang_visitChildren(cur, visitor, NULL);
+
+  clang_disposeTranslationUnit(txUnit);
+  clang_disposeIndex(index);
+  return 0;
+}
diff --git a/test/Test_ChildVisitor.hs b/test/Test_ChildVisitor.hs
new file mode 100644
--- /dev/null
+++ b/test/Test_ChildVisitor.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE FlexibleContexts #-}
+import System.Environment(getArgs)
+import Control.Monad.IO.Class(liftIO)
+import Text.Printf(printf)
+import qualified Data.Vector.Storable as DVS(mapM_)
+
+import Clang.String(unpack)
+import Clang.TranslationUnit(getCursor)
+import Clang(parseSourceFile, getChildren)
+import Clang.Cursor(getKind, getDisplayName, getCursorKindSpelling)
+
+test tu = getCursor tu >>= getChildren >>= DVS.mapM_ printInfo
+    where printInfo c = do
+            name <- getDisplayName c >>= unpack
+            tstr <- getCursorKindSpelling (getKind c) >>= unpack
+            liftIO $ printf "Name:%s, Kind:%s\n" name tstr
+
+main = do
+  (arg:args) <- getArgs
+  parseSourceFile arg args test
diff --git a/test/Test_Diagnostics.c b/test/Test_Diagnostics.c
new file mode 100644
--- /dev/null
+++ b/test/Test_Diagnostics.c
@@ -0,0 +1,22 @@
+#include <stdio.h>
+#include <clang-c/Index.h>
+
+int main(int argc, const char * argv[])
+{
+  CXIndex index = clang_createIndex(0, 0);
+  CXTranslationUnit txUnit = clang_parseTranslationUnit(index, 0, argv, argc, 0, 0, CXTranslationUnit_None);
+
+  unsigned n = clang_getNumDiagnostics(txUnit);
+  /* printf("numDiags:%d\n", n); */
+  for(unsigned i = 0, n = clang_getNumDiagnostics(txUnit); i != n; ++i)
+  {
+    CXDiagnostic diag = clang_getDiagnostic(txUnit, i);
+    CXString str = clang_formatDiagnostic(diag, clang_defaultDiagnosticDisplayOptions());
+    printf("Diag:%s\n", clang_getCString(str));
+    clang_disposeString(str);
+  }
+
+  clang_disposeTranslationUnit(txUnit);
+  clang_disposeIndex(index);
+  return 0;
+}
diff --git a/test/Test_Diagnostics.hs b/test/Test_Diagnostics.hs
new file mode 100644
--- /dev/null
+++ b/test/Test_Diagnostics.hs
@@ -0,0 +1,16 @@
+{-# LANGUAGE FlexibleContexts #-}
+import System.Environment(getArgs)
+import Control.Monad.IO.Class(liftIO)
+import Clang.String(unpack)
+import Clang.TranslationUnit(getDiagnosticSet)
+import Clang(parseSourceFile)
+import qualified Clang.Diagnostic as Diagnostic(format, getElements)
+
+test tu = do getDiagnosticSet tu >>= Diagnostic.getElements >>= mapM_ printDiag
+    where printDiag d = Diagnostic.format Nothing d >>=
+                        unpack >>=
+                        (liftIO . putStrLn . ("Diag:" ++))
+
+main = do
+  (arg:args) <- getArgs
+  parseSourceFile arg args test
diff --git a/test/Test_Diagnostics_FFI.hs b/test/Test_Diagnostics_FFI.hs
new file mode 100644
--- /dev/null
+++ b/test/Test_Diagnostics_FFI.hs
@@ -0,0 +1,20 @@
+import System(getArgs)
+import Data.Maybe(fromJust, isJust)
+import qualified Clang.FFI as Clang
+-- import qualified Clang.TranslationUnit as Clang
+-- import qualified Clang.Diagnostic as Diagnostic
+
+main = do
+  args <- getArgs
+  index <- Clang.createIndex False False
+  mtu <- Clang.parseTranslationUnit index Nothing args [] 0
+  let tu = if isJust mtu then fromJust mtu else error "No TXUnit!"
+  defDisplayOpts <- Clang.defaultDiagnosticDisplayOptions
+  let printDiag i = do
+         diag <- Clang.getDiagnostic tu i
+         clstr <- Clang.formatDiagnostic diag defDisplayOpts
+         str <- Clang.getCString clstr
+         putStrLn $ "Diag:" ++ str
+  numDiags <- Clang.getNumDiagnostics tu
+  putStrLn $ "numDiags:" ++ show numDiags
+  mapM_ printDiag [0..numDiags]
diff --git a/test/Test_InclusionVisitor.c b/test/Test_InclusionVisitor.c
new file mode 100644
--- /dev/null
+++ b/test/Test_InclusionVisitor.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <clang-c/Index.h>
+
+void inclusionVisitor(CXFile file, CXSourceLocation * srcLocs, unsigned numSrcLocs, CXClientData data)
+{
+  if(0 == numSrcLocs)
+    return;
+  CXString fname = clang_getFileName(file);
+  printf("Included:%s\n",clang_getCString(fname));
+  clang_disposeString(fname);
+}
+
+int main(int argc, const char * argv[])
+{
+  CXIndex index = clang_createIndex(0, 0);
+  CXTranslationUnit txUnit = clang_parseTranslationUnit(index, 0, argv, argc, 0, 0, CXTranslationUnit_None);
+
+  clang_getInclusions(txUnit, inclusionVisitor, NULL);
+
+  clang_disposeTranslationUnit(txUnit);
+  clang_disposeIndex(index);
+  return 0;
+}
diff --git a/test/Test_InclusionVisitor.hs b/test/Test_InclusionVisitor.hs
new file mode 100644
--- /dev/null
+++ b/test/Test_InclusionVisitor.hs
@@ -0,0 +1,17 @@
+{-# LANGUAGE FlexibleContexts #-}
+import System.Environment(getArgs)
+import Control.Monad.IO.Class(liftIO)
+import qualified Data.Vector.Storable as DVS(mapM_)
+
+import Clang.String(unpack)
+import Clang.File(getName)
+import Clang(parseSourceFile, getInclusions, Inclusion(..))
+
+test tu = getInclusions tu >>= DVS.mapM_ printInclusion
+    where printInclusion (Inclusion fname _ _) = do
+            name <- getName fname >>= unpack
+            liftIO $ putStrLn $ "Included:" ++ name
+
+main = do
+  (arg:args) <- getArgs
+  parseSourceFile arg args test
diff --git a/test/runTest.sh b/test/runTest.sh
new file mode 100644
--- /dev/null
+++ b/test/runTest.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+TEST=$1
+CTEST=${TEST}_c
+HSTEST=${TEST}_hs
+
+shift
+
+TMPFILE=`mktemp -t libclangtest_XXX`
+TMPFILE_C=$TMPFILE.ref
+TMPFILE_HS=$TMPFILE.test
+./$CTEST $* | grep -v "'linker' input unused" > $TMPFILE_C
+./$HSTEST $* | grep -v "'linker' input unused" > $TMPFILE_HS
+if [ -n "`diff $TMPFILE_C $TMPFILE_HS`" ]
+then
+  echo FAILED: $TEST refOutput: $TMPFILE_C  testOutput: $TMPFILE_HS
+else
+  echo SUCCESS: $TEST
+  rm $TMPFILE_HS $TMPFILE_C
+fi
