From d35aedd0fbd4b3456c1b3104e96b8567df13e6b5 Mon Sep 17 00:00:00 2001 From: Oleg Grenrus Date: Tue, 10 Dec 2024 14:50:02 +0200 Subject: [PATCH] Add hs-bindgen-bootstrap We are far away from dog fooding hs-bindgen for libclang bindings, but writing them by hand is tedious We should had done something like this long ago. This doesn't generate the high-level bindings; that's not challenging in itself; but arranging the module structure for it to work is. --- cabal.project | 1 + .../hs-bindgen-bootstrap.cabal | 55 ++++ .../src/hs-bindgen-bootstrap.hs | 247 +++++++++++++++++ hs-bindgen-libclang/cbits/clang_wrappers.h | 114 +------- .../cbits/clang_wrappers_ffi.h | 251 ++++++++++++++++++ hs-bindgen-libclang/hs-bindgen-libclang.cabal | 1 + .../src/HsBindgen/Clang/LowLevel/Core.hs | 87 +----- .../src/HsBindgen/Clang/LowLevel/FFI.hs | 208 +++++++++++++++ imports.h | 77 ++++++ 9 files changed, 843 insertions(+), 198 deletions(-) create mode 100644 hs-bindgen-bootstrap/hs-bindgen-bootstrap.cabal create mode 100644 hs-bindgen-bootstrap/src/hs-bindgen-bootstrap.hs create mode 100644 hs-bindgen-libclang/cbits/clang_wrappers_ffi.h create mode 100644 hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/FFI.hs create mode 100644 imports.h diff --git a/cabal.project b/cabal.project index e22f3aa2..ce81b252 100644 --- a/cabal.project +++ b/cabal.project @@ -1,6 +1,7 @@ packages: hs-bindgen-patterns packages: hs-bindgen packages: hs-bindgen-libclang +packages: hs-bindgen-bootstrap packages: ansi-diff tests: True diff --git a/hs-bindgen-bootstrap/hs-bindgen-bootstrap.cabal b/hs-bindgen-bootstrap/hs-bindgen-bootstrap.cabal new file mode 100644 index 00000000..b39eb617 --- /dev/null +++ b/hs-bindgen-bootstrap/hs-bindgen-bootstrap.cabal @@ -0,0 +1,55 @@ +cabal-version: 3.0 +name: hs-bindgen-bootstrap +version: 0.1.0 +license: BSD-3-Clause +license-file: LICENSE +author: Edsko de Vries +maintainer: edsko@well-typed.com +category: Development +build-type: Simple +synopsis: Generate Haskell bindings from C headers +extra-doc-files: CHANGELOG.md +tested-with: , GHC==9.2.8 + , GHC==9.4.8 + , GHC==9.6.6 + , GHC==9.8.2 + , GHC==9.10.1 + +common lang + ghc-options: + -Wall + -Widentities + -Wprepositive-qualified-module + -Wredundant-constraints + -Wunused-packages + -Wno-unticked-promoted-constructors + build-depends: + base >= 4.16 && < 4.21 + default-language: + GHC2021 + default-extensions: + DataKinds + DefaultSignatures + DeriveAnyClass + DerivingStrategies + DerivingVia + DisambiguateRecordFields + LambdaCase + MultiWayIf + OverloadedStrings + PatternSynonyms + QuantifiedConstraints + RecordWildCards + TypeApplications + TypeFamilies + UndecidableInstances + ViewPatterns + if impl(ghc >= 9.8) + default-extensions: + TypeAbstractions + +executable hs-bindgen-bootstrap + import: lang + hs-source-dirs: src + main-is: hs-bindgen-bootstrap.hs + build-depends: base <5, bytestring, parsec diff --git a/hs-bindgen-bootstrap/src/hs-bindgen-bootstrap.hs b/hs-bindgen-bootstrap/src/hs-bindgen-bootstrap.hs new file mode 100644 index 00000000..c4782565 --- /dev/null +++ b/hs-bindgen-bootstrap/src/hs-bindgen-bootstrap.hs @@ -0,0 +1,247 @@ +module Main (main) where + +import Control.Applicative (many, (<|>)) +import Data.ByteString qualified as BS +import Data.Char (isLetter) +import Data.List (stripPrefix) +import Text.Parsec qualified as P +import Text.Parsec.ByteString (Parser) + +------------------------------------------------------------------------------- +-- "config" +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- main +------------------------------------------------------------------------------- + +main :: IO () +main = do + bs <- BS.readFile "imports.h" + decls <- case P.parse (whitespace *> many declP <* P.eof) "imports.h" bs of + Left err -> print err >> fail "parse error" + Right decls -> return decls + + -- low-level FFI module + do + let contents = ffiModule decls + putStr contents + writeFile "hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/FFI.hs" contents + + do + let contents = wrappers decls + putStr contents + writeFile "hs-bindgen-libclang/cbits/clang_wrappers_ffi.h" contents + + +------------------------------------------------------------------------------- +-- declarations +------------------------------------------------------------------------------- + +data Decl + = FunDecl Var [Var] + | Comment String + deriving Show + +data Var = Var [String] String + deriving Show + +------------------------------------------------------------------------------- +-- parser +------------------------------------------------------------------------------- + +whitespace :: Parser () +whitespace = P.skipMany (P.satisfy (\c -> c == ' ' || c == '\n')) + +lexeme :: Parser a -> Parser a +lexeme p = p <* whitespace + +cident :: Parser String +cident = lexeme $ do + h <- P.satisfy $ \c -> c == '_' || isLetter c + t <- many $ P.satisfy $ \c -> c == '_' || isLetter c -- or num + return (h : t) + +-- we cheat a bit, we don't recognise *. +varDecl :: Parser Var +varDecl = do + x <- cident + y <- cident + go (x :) y + where + go :: ([String] -> [String]) -> String -> Parser Var + go xs y = (cident >>= \z -> go (xs . (y : )) z) <|> return (Var (xs []) y) + +funDeclP :: Parser Decl +funDeclP = do + fun <- varDecl + _ <- lexeme (P.char '(') + args <- varDecl `P.sepBy` lexeme (P.char ',') + _ <- lexeme (P.char ')') + _ <- lexeme (P.char ';') + return (FunDecl fun args) + +commentP :: Parser Decl +commentP = do + _ <- P.string "//" + comment <- many $ P.satisfy $ \c -> c /= '\n' + _ <- lexeme (P.char '\n') + return (Comment comment) + +declP :: Parser Decl +declP = P.choice + [ funDeclP + , commentP + ] + +------------------------------------------------------------------------------- +-- Haskell FFI +------------------------------------------------------------------------------- + +ffiModule :: [Decl] -> String +ffiModule ds = unlines $ + header ++ + concatMap ffiDecl ds + where + header :: [String] + header = + [ "{-| this module is autogenerated with cabal run hs-bindgen-bootstrap -}" + , "module HsBindgen.Clang.LowLevel.FFI (module HsBindgen.Clang.LowLevel.FFI) where" + , "import Foreign.C.Types" + , "import HsBindgen.Clang.Internal.ByValue" + , "import HsBindgen.Clang.LowLevel.Core.Enums" + , "import HsBindgen.Clang.LowLevel.Core.Structs" + , "import HsBindgen.Patterns" + ] + +ffiDecl :: Decl -> [String] +ffiDecl (Comment comment) = + [ "--" ++ comment + , "" + ] +ffiDecl (FunDecl (Var rtype name) args) + | isStruct rtype + = + [ "foreign import capi unsafe \"clang_wrappers.h\"" + , " " ++ name' ++ " :: " ++ foldr argumentTy (toHaskellType Res rtype) args ++ " -> IO ()" + , "" + ] + + | otherwise + = + [ "foreign import capi unsafe \"clang_wrappers.h\"" + , " " ++ name' ++ " :: " ++ foldr argumentTy ("IO " ++ toHaskellType Res rtype) args + , "" + ] + where + -- TODO: we don't mangle names if there aren't struct resutls args + name' = case stripPrefix "clang_" name of + Nothing -> error $ name ++ " doesn't start with clang_" + Just sfx -> "wrap_" ++ sfx + + argumentTy :: Var -> String -> String + argumentTy (Var ty _) rest = toHaskellType Arg ty ++ " -> " ++ rest + +------------------------------------------------------------------------------- +-- (wrapper) Header generation +------------------------------------------------------------------------------- + +wrappers :: [Decl] -> String +wrappers ds = unlines $ + header ++ + concatMap wrapDecl ds + where + header :: [String] + header = + [ "/* this header is autogenerated with cabal run hs-bindgen-bootstrap */" + ] + +wrapDecl :: Decl -> [String] +wrapDecl (Comment comment) = + [ "/*" ++ comment ++ " */" + , "" + ] +wrapDecl decl@(FunDecl (Var rtype rname) args) + | isStruct rtype + = + [ "static inline void " ++ rname' ++ "(" ++ foldr argumentTy (toCType Res rtype ++ " result") args ++ ") {" + , " *result = " ++ rname ++ "(" ++ foldr callArg "" args ++ ");" + , "}" + , "" + ] + + | any isStructVar args + = + [ "static inline " ++ toCType Res rtype ++ " " ++ rname' ++ "(" ++ foldr argumentTy "" args ++ ") {" + , " return " ++ rname ++ "(" ++ foldr callArg "" args ++ ");" + , "}" + , "" + ] + + | otherwise + = + [ "/* " ++ show decl ++ " */" + , "" + ] + where + rname' = case stripPrefix "clang_" rname of + Nothing -> error $ rname ++ " doesn't start with clang_" + Just sfx -> "wrap_" ++ sfx + + argumentTy :: Var -> String -> String + argumentTy (Var atype aname) rest = commaArg (toCType Arg atype ++ " " ++ aname) rest + + callArg :: Var -> String -> String + callArg (Var atype aname) rest + | isStruct atype = commaArg ("*" ++ aname) rest + | otherwise = commaArg aname rest + +commaArg :: String -> String -> String +commaArg x "" = x +commaArg x y = x ++ ", " ++ y + +------------------------------------------------------------------------------- +-- Utilities +------------------------------------------------------------------------------- + +isStruct :: [String] -> Bool +isStruct ["CXType"] = True +isStruct ["CXString"] = True +isStruct ["CXCursor"] = True +isStruct _ = False + +isStructVar :: Var -> Bool +isStructVar (Var ty _) = isStruct ty + +-- | result or argument +data RA = Res | Arg + +haskellRA :: RA -> String +haskellRA Res = "W " +haskellRA Arg = "R " + +toHaskellType :: RA -> [String] -> String +toHaskellType ra ["CXType"] = haskellRA ra ++ "CXType_" +toHaskellType ra ["CXString"] = haskellRA ra ++ "CXString_" +toHaskellType ra ["CXCursor"] = haskellRA ra ++ "CXCursor_" +toHaskellType _ ["enum","CXTypeKind"] = "SimpleEnum CXTypeKind" +toHaskellType _ ["long","long"] = "CLLong" +toHaskellType _ ["unsigned","long","long"] = "CULLong" +toHaskellType _ ["unsigned"] = "CUInt" +toHaskellType _ ["int"] = "CInt" +toHaskellType _ ty = error $ "Unknown type " ++ unwords ty + +cRA :: RA -> String +cRA Res = "" +cRA Arg = "const " + +toCType :: RA -> [String] -> String +toCType ra ["CXType"] = cRA ra ++ "CXType*" +toCType ra ["CXString"] = cRA ra ++ "CXString*" +toCType ra ["CXCursor"] = cRA ra ++ "CXCursor*" +toCType _ ["enum","CXTypeKind"] = "enum CXTypeKind" +toCType _ ["long","long"] = "long long" +toCType _ ["unsigned","long","long"] = "unsigned long long" +toCType _ ["unsigned"] = "unsigned" +toCType _ ["int"] = "int" +toCType _ ty = error $ "Unknown type " ++ unwords ty diff --git a/hs-bindgen-libclang/cbits/clang_wrappers.h b/hs-bindgen-libclang/cbits/clang_wrappers.h index a38d8099..cae2d20f 100644 --- a/hs-bindgen-libclang/cbits/clang_wrappers.h +++ b/hs-bindgen-libclang/cbits/clang_wrappers.h @@ -2,8 +2,8 @@ #define CLANG_WRAPPERS_H #include - #include +#include "clang_wrappers_ffi.h" /** * Versioning @@ -174,10 +174,6 @@ static inline enum CXCursorKind wrap_getCursorKind(const CXCursor* cursor) { return clang_getCursorKind(*cursor); } -static inline void wrap_getNullCursor(CXCursor *result) { - *result = clang_getNullCursor(); -} - static inline void wrap_getCursorKindSpelling(enum CXCursorKind Kind, CXString* result) { *result = clang_getCursorKindSpelling(Kind); } @@ -250,78 +246,6 @@ static inline enum CXTypeKind wrap_cxtKind(const CXType* type) { return type->kind; } -static inline void wrap_getCursorType(const CXCursor* C, CXType* result) { - *result = clang_getCursorType(*C); -} - -static inline void wrap_getTypeKindSpelling(enum CXTypeKind K, CXString* result) { - *result = clang_getTypeKindSpelling(K); -} - -static inline void wrap_getTypeSpelling(const CXType* CT, CXString* result) { - *result = clang_getTypeSpelling(*CT); -} - -static inline void wrap_getTypedefDeclUnderlyingType(const CXCursor* C, CXType* result) { - *result = clang_getTypedefDeclUnderlyingType(*C); -} - -static inline void wrap_getEnumDeclIntegerType(const CXCursor* C, CXType* result) { - *result = clang_getEnumDeclIntegerType(*C); -} - -static inline unsigned wrap_Cursor_isBitField(const CXCursor* C) { - return clang_Cursor_isBitField(*C); -} - -static inline int wrap_getFieldDeclBitWidth(const CXCursor* C) { - return clang_getFieldDeclBitWidth(*C); -} - -static inline void wrap_getPointeeType(const CXType* T, CXType* result) { - *result = clang_getPointeeType(*T); -} - -static inline void wrap_getArrayElementType(const CXType* T, CXType* result) { - *result = clang_getArrayElementType(*T); -} - -static inline long long wrap_getArraySize(const CXType* T) { - return clang_getArraySize(*T); -} - -static inline long long wrap_Type_getSizeOf(const CXType* T) { - return clang_Type_getSizeOf(*T); -} - -static inline long long wrap_Type_getAlignOf(const CXType* T) { - return clang_Type_getAlignOf(*T); -} - -static inline unsigned wrap_Type_isTransparentTagTypedef(const CXType *T) { - return clang_Type_isTransparentTagTypedef(*T); -} - -static inline long long wrap_Cursor_getOffsetOfField(const CXCursor* C) { - return clang_Cursor_getOffsetOfField(*C); -} - -static inline unsigned wrap_Cursor_isAnonymous(const CXCursor* C) { - return clang_Cursor_isAnonymous(*C); -} - -static inline unsigned wrap_Cursor_isAnonymousRecordDecl(const CXCursor *C) { - return clang_Cursor_isAnonymousRecordDecl(*C); -} - -static inline long long wrap_getEnumConstantDeclValue(const CXCursor *C) { - return clang_getEnumConstantDeclValue(*C); -} - -static inline unsigned wrap_equalTypes(const CXType *A, const CXType *B) { - return clang_equalTypes(*A, *B); -} - static inline signed int wrap_compareTypes(const CXType *A, const CXType *B) { if (A->data[0] < B->data[0]) { return -1; @@ -338,14 +262,6 @@ static inline signed int wrap_compareTypes(const CXType *A, const CXType *B) { } } -static inline void wrap_getCanonicalType(const CXType* T, CXType* result) { - *result = clang_getCanonicalType(*T); -} - -static inline void wrap_getTypedefName(const CXType* CT, CXString* result) { - *result = clang_getTypedefName(*CT); -} - /** * Call `clang_getUnqualifiedType` * @@ -360,34 +276,6 @@ static inline void wrap_getUnqualifiedType(const CXType* CT, CXType* result) { #endif } -static inline void wrap_getTypeDeclaration(const CXType* T, CXCursor* result) { - *result = clang_getTypeDeclaration(*T); -} - -static inline void wrap_getResultType(const CXType *T, CXType *result) { - *result = clang_getResultType(*T); -} - -static inline int wrap_getNumArgTypes(const CXType *T) { - return clang_getNumArgTypes(*T); -} - -static inline void wrap_getArgType(const CXType *T, unsigned n, CXType *result) { - *result = clang_getArgType(*T, n); -} - -static inline void wrap_Type_getNamedType(const CXType* T, CXType* result) { - *result = clang_Type_getNamedType(*T); -} - -static inline void wrap_Type_getModifiedType(const CXType* T, CXType* result) { - *result = clang_Type_getModifiedType(*T); -} - -static inline void wrap_Type_getValueType(const CXType* CT, CXType* result) { - *result = clang_Type_getValueType(*CT); -} - /** * Mapping between cursors and source code */ diff --git a/hs-bindgen-libclang/cbits/clang_wrappers_ffi.h b/hs-bindgen-libclang/cbits/clang_wrappers_ffi.h new file mode 100644 index 00000000..fc8d32a1 --- /dev/null +++ b/hs-bindgen-libclang/cbits/clang_wrappers_ffi.h @@ -0,0 +1,251 @@ +/* this header is autogenerated with cabal run hs-bindgen-bootstrap */ +/* Type information for CXCursors https://clang.llvm.org/doxygen/group__CINDEX__TYPES.html */ + +static inline void wrap_getCursorType(const CXCursor* C, CXType* result) { + *result = clang_getCursorType(*C); +} + +static inline void wrap_getTypeSpelling(const CXType* CT, CXString* result) { + *result = clang_getTypeSpelling(*CT); +} + +static inline void wrap_getTypedefDeclUnderlyingType(const CXCursor* C, CXType* result) { + *result = clang_getTypedefDeclUnderlyingType(*C); +} + +static inline void wrap_getEnumDeclIntegerType(const CXCursor* C, CXType* result) { + *result = clang_getEnumDeclIntegerType(*C); +} + +static inline long long wrap_getEnumConstantDeclValue(const CXCursor* C) { + return clang_getEnumConstantDeclValue(*C); +} + +static inline unsigned long long wrap_getEnumConstantDeclUnsignedValue(const CXCursor* C) { + return clang_getEnumConstantDeclUnsignedValue(*C); +} + +static inline unsigned wrap_Cursor_isBitField(const CXCursor* C) { + return clang_Cursor_isBitField(*C); +} + +static inline int wrap_getFieldDeclBitWidth(const CXCursor* C) { + return clang_getFieldDeclBitWidth(*C); +} + +static inline int wrap_Cursor_getNumArguments(const CXCursor* C) { + return clang_Cursor_getNumArguments(*C); +} + +static inline void wrap_Cursor_getArgument(const CXCursor* C, unsigned i, CXCursor* result) { + *result = clang_Cursor_getArgument(*C, i); +} + +/* int clang_Cursor_getNumTemplateArguments (CXCursor C); // C++ */ + +/* enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind (CXCursor C, unsigned I); // C++ */ + +/* CXType clang_Cursor_getTemplateArgumentType (CXCursor C, unsigned I); // C++ */ + +/* long long clang_Cursor_getTemplateArgumentValue (CXCursor C, unsigned I); // C++ */ + +/* unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue (CXCursor C, unsigned I); // C++ */ + +static inline unsigned wrap_equalTypes(const CXType* A, const CXType* B) { + return clang_equalTypes(*A, *B); +} + +static inline void wrap_getCanonicalType(const CXType* T, CXType* result) { + *result = clang_getCanonicalType(*T); +} + +static inline unsigned wrap_isConstQualifiedType(const CXType* T) { + return clang_isConstQualifiedType(*T); +} + +static inline unsigned wrap_Cursor_isMacroFunctionLike(const CXCursor* C) { + return clang_Cursor_isMacroFunctionLike(*C); +} + +static inline unsigned wrap_Cursor_isMacroBuiltin(const CXCursor* C) { + return clang_Cursor_isMacroBuiltin(*C); +} + +static inline unsigned wrap_Cursor_isFunctionInlined(const CXCursor* C) { + return clang_Cursor_isFunctionInlined(*C); +} + +static inline unsigned wrap_isVolatileQualifiedType(const CXType* T) { + return clang_isVolatileQualifiedType(*T); +} + +static inline unsigned wrap_isRestrictQualifiedType(const CXType* T) { + return clang_isRestrictQualifiedType(*T); +} + +static inline unsigned wrap_getAddressSpace(const CXType* T) { + return clang_getAddressSpace(*T); +} + +static inline void wrap_getTypedefName(const CXType* CT, CXString* result) { + *result = clang_getTypedefName(*CT); +} + +static inline void wrap_getPointeeType(const CXType* T, CXType* result) { + *result = clang_getPointeeType(*T); +} + +/* CXType clang_getUnqualifiedType (CXType CT); // this is special case */ + +/* CXType clang_getNonReferenceType (CXType CT); // this is apparently special case as well (not available in older libclang) */ + +static inline void wrap_getTypeDeclaration(const CXType* T, CXCursor* result) { + *result = clang_getTypeDeclaration(*T); +} + +/* CXString clang_getDeclObjCTypeEncoding (CXCursor C); // Objective C */ + +/* CXString clang_Type_getObjCEncoding (CXType type); // Objective C */ + +static inline void wrap_getTypeKindSpelling(enum CXTypeKind K, CXString* result) { + *result = clang_getTypeKindSpelling(K); +} + +/* enum CXCallingConv clang_getFunctionTypeCallingConv (CXType T); // no enum */ + +static inline void wrap_getResultType(const CXType* T, CXType* result) { + *result = clang_getResultType(*T); +} + +/* int clang_getExceptionSpecificationType (CXType T); // C++ */ + +static inline int wrap_getNumArgTypes(const CXType* T) { + return clang_getNumArgTypes(*T); +} + +static inline void wrap_getArgType(const CXType* T, unsigned i, CXType* result) { + *result = clang_getArgType(*T, i); +} + +static inline void wrap_Type_getObjCObjectBaseType(const CXType* T, CXType* result) { + *result = clang_Type_getObjCObjectBaseType(*T); +} + +static inline unsigned wrap_Type_getNumObjCProtocolRefs(const CXType* T) { + return clang_Type_getNumObjCProtocolRefs(*T); +} + +static inline void wrap_Type_getObjCProtocolDecl(const CXType* T, unsigned i, CXCursor* result) { + *result = clang_Type_getObjCProtocolDecl(*T, i); +} + +static inline unsigned wrap_Type_getNumObjCTypeArgs(const CXType* T) { + return clang_Type_getNumObjCTypeArgs(*T); +} + +static inline void wrap_Type_getObjCTypeArg(const CXType* T, unsigned i, CXType* result) { + *result = clang_Type_getObjCTypeArg(*T, i); +} + +static inline unsigned wrap_isFunctionTypeVariadic(const CXType* T) { + return clang_isFunctionTypeVariadic(*T); +} + +static inline void wrap_getCursorResultType(const CXCursor* C, CXType* result) { + *result = clang_getCursorResultType(*C); +} + +static inline int wrap_getCursorExceptionSpecificationType(const CXCursor* C) { + return clang_getCursorExceptionSpecificationType(*C); +} + +static inline unsigned wrap_isPODType(const CXType* T) { + return clang_isPODType(*T); +} + +static inline void wrap_getElementType(const CXType* T, CXType* result) { + *result = clang_getElementType(*T); +} + +static inline long long wrap_getNumElements(const CXType* T) { + return clang_getNumElements(*T); +} + +static inline void wrap_getArrayElementType(const CXType* T, CXType* result) { + *result = clang_getArrayElementType(*T); +} + +static inline long long wrap_getArraySize(const CXType* T) { + return clang_getArraySize(*T); +} + +static inline void wrap_Type_getNamedType(const CXType* T, CXType* result) { + *result = clang_Type_getNamedType(*T); +} + +static inline unsigned wrap_Type_isTransparentTagTypedef(const CXType* T) { + return clang_Type_isTransparentTagTypedef(*T); +} + +/* enum CXTypeNullabilityKind clang_Type_getNullability (CXType T); // no enum */ + +static inline long long wrap_Type_getAlignOf(const CXType* T) { + return clang_Type_getAlignOf(*T); +} + +/* CXType clang_Type_getClassType (CXType T); // C++ */ + +static inline long long wrap_Type_getSizeOf(const CXType* T) { + return clang_Type_getSizeOf(*T); +} + +/* long long clang_Type_getOffsetOf (CXType T, const char *S) // TODO: generator doesn't know * yet */ + +static inline void wrap_Type_getModifiedType(const CXType* T, CXType* result) { + *result = clang_Type_getModifiedType(*T); +} + +static inline void wrap_Type_getValueType(const CXType* CT, CXType* result) { + *result = clang_Type_getValueType(*CT); +} + +static inline long long wrap_Cursor_getOffsetOfField(const CXCursor* C) { + return clang_Cursor_getOffsetOfField(*C); +} + +static inline unsigned wrap_Cursor_isAnonymous(const CXCursor* C) { + return clang_Cursor_isAnonymous(*C); +} + +static inline unsigned wrap_Cursor_isAnonymousRecordDecl(const CXCursor* C) { + return clang_Cursor_isAnonymousRecordDecl(*C); +} + +/* unsigned clang_Cursor_isInlineNamespace (CXCursor C); // C++ */ + +/* int clang_Type_getNumTemplateArguments (CXType T); // C++ */ + +/* CXType clang_Type_getTemplateArgumentAsType (CXType T, unsigned i); // C++ */ + +/* enum CXRefQualifierKind clang_Type_getCXXRefQualifier (CXType T); // C++ */ + +/* unsigned clang_isVirtualBase (CXCursor); // C++ */ + +/* enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier (CXCursor); // C++ */ + +/* enum CX_BinaryOperatorKind clang_Cursor_getBinaryOpcode (CXCursor C); // C++ */ + +/* CXString clang_Cursor_getBinaryOpcodeStr (enum CX_BinaryOperatorKind Op); // C++ */ + +/* enum CX_StorageClass clang_Cursor_getStorageClass (CXCursor); // no enum */ + +/* unsigned clang_getNumOverloadedDecls (CXCursor cursor); // C++ */ + +/* CXCursor clang_getOverloadedDecl (CXCursor cursor, unsigned index); // C++ */ + +/* Cursor manipulations https://clang.llvm.org/doxygen/group__CINDEX__CURSOR__MANIP.html */ + +static inline void wrap_getNullCursor(CXCursor* result) { + *result = clang_getNullCursor(); +} + diff --git a/hs-bindgen-libclang/hs-bindgen-libclang.cabal b/hs-bindgen-libclang/hs-bindgen-libclang.cabal index ffae40e0..ab7af947 100644 --- a/hs-bindgen-libclang/hs-bindgen-libclang.cabal +++ b/hs-bindgen-libclang/hs-bindgen-libclang.cabal @@ -64,6 +64,7 @@ library HsBindgen.Clang.HighLevel HsBindgen.Clang.HighLevel.Types other-modules: + HsBindgen.Clang.LowLevel.FFI HsBindgen.Clang.LowLevel.Core.Enums HsBindgen.Clang.LowLevel.Core.Instances HsBindgen.Clang.LowLevel.Core.Structs diff --git a/hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/Core.hs b/hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/Core.hs index 2aa5ed45..906f2bcb 100644 --- a/hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/Core.hs +++ b/hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/Core.hs @@ -197,6 +197,7 @@ import GHC.Stack import System.IO.Unsafe (unsafePerformIO, unsafeDupablePerformIO) import HsBindgen.Clang.Args +import HsBindgen.Clang.LowLevel.FFI import HsBindgen.Clang.LowLevel.Core.Enums import HsBindgen.Clang.LowLevel.Core.Instances () import HsBindgen.Clang.LowLevel.Core.Structs @@ -639,9 +640,6 @@ foreign import capi unsafe "clang_wrappers.h wrap_getCursorLexicalParent" foreign import capi unsafe "clang_wrappers.h wrap_getCursorKind" wrap_getCursorKind :: R CXCursor_ -> IO (SimpleEnum CXCursorKind) -foreign import capi unsafe "clang_wrappers.h wrap_getNullCursor" - wrap_getNullCursor :: W CXCursor_ -> IO () - foreign import capi unsafe "clang_wrappers.h wrap_getCursorKindSpelling" wrap_getCursorKindSpelling :: SimpleEnum CXCursorKind -> W CXString_ -> IO () @@ -1003,93 +1001,12 @@ instance Ord CXType where foreign import capi unsafe "clang_wrappers.h wrap_cxtKind" wrap_cxtKind :: R CXType_ -> IO (SimpleEnum CXTypeKind) -foreign import capi unsafe "clang_wrappers.h wrap_getCursorType" - wrap_getCursorType :: R CXCursor_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h wrap_getTypeKindSpelling" - wrap_getTypeKindSpelling :: SimpleEnum CXTypeKind -> W CXString_ -> IO () - -foreign import capi unsafe "clang_wrappers.h wrap_getTypeSpelling" - wrap_getTypeSpelling :: R CXType_ -> W CXString_ -> IO () - -foreign import capi unsafe "clang_wrappers.h wrap_getTypedefDeclUnderlyingType" - wrap_getTypedefDeclUnderlyingType :: R CXCursor_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h wrap_getEnumDeclIntegerType" - wrap_getEnumDeclIntegerType :: R CXCursor_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h wrap_Cursor_isBitField" - wrap_Cursor_isBitField :: R CXCursor_ -> IO CUInt - -foreign import capi unsafe "clang_wrappers.h wrap_getFieldDeclBitWidth" - wrap_getFieldDeclBitWidth :: R CXCursor_ -> IO CInt - -foreign import capi unsafe "clang_wrappers.h wrap_getPointeeType" - wrap_getPointeeType :: R CXType_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h wrap_getArrayElementType" - wrap_getArrayElementType :: R CXType_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h wrap_getArraySize" - wrap_getArraySize :: R CXType_ -> IO CLLong - -foreign import capi unsafe "clang_wrappers.h wrap_Type_getSizeOf" - wrap_Type_getSizeOf :: R CXType_ -> IO CLLong - -foreign import capi unsafe "clang_wrappers.h wrap_Type_getAlignOf" - wrap_getAlignOf :: R CXType_ -> IO CLLong - -foreign import capi unsafe "clang_wrappers.h wrap_Type_isTransparentTagTypedef" - wrap_Type_isTransparentTagTypedef :: R CXType_ -> IO CUInt - -foreign import capi unsafe "clang_wrappers.h wrap_Cursor_getOffsetOfField" - wrap_Cursor_getOffsetOfField :: R CXCursor_ -> IO CLLong - -foreign import capi unsafe "clang_wrappers.h wrap_Cursor_isAnonymous" - wrap_Cursor_isAnonymous :: R CXCursor_ -> IO CUInt - -foreign import capi unsafe "clang_wrappers.h wrap_Cursor_isAnonymousRecordDecl" - wrap_Cursor_isAnonymousRecordDecl :: R CXCursor_ -> IO CUInt - -foreign import capi unsafe "clang_wrappers.h wrap_getEnumConstantDeclValue" - wrap_getEnumConstantDeclValue :: R CXCursor_ -> IO CLLong - -foreign import capi unsafe "clang_wrappers.h" - wrap_equalTypes :: R CXType_ -> R CXType_ -> IO CUInt - foreign import capi unsafe "clang_wrappers.h" wrap_compareTypes :: R CXType_ -> R CXType_ -> IO CInt -foreign import capi unsafe "clang_wrappers.h" - wrap_getCanonicalType :: R CXType_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h" - wrap_getTypedefName :: R CXType_ -> W CXString_ -> IO () - foreign import capi unsafe "clang_wrappers.h" wrap_getUnqualifiedType :: R CXType_ -> W CXType_ -> IO () -foreign import capi unsafe "clang_wrappers.h" - wrap_getTypeDeclaration :: R CXType_ -> W CXCursor_ -> IO () - -foreign import capi unsafe "clang_wrappers.h" - wrap_getResultType :: R CXType_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h" - wrap_getNumArgTypes :: R CXType_ -> IO CInt - -foreign import capi unsafe "clang_wrappers.h" - wrap_getArgType :: R CXType_ -> CUInt -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h" - wrap_Type_getNamedType :: R CXType_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h" - wrap_Type_getModifiedType :: R CXType_ -> W CXType_ -> IO () - -foreign import capi unsafe "clang_wrappers.h" - wrap_Type_getValueType :: R CXType_ -> W CXType_ -> IO () - -- | Extract the @kind@ field from a @CXType@ struct -- -- @@ -1203,7 +1120,7 @@ clang_Type_getSizeOf typ = clang_Type_getAlignOf :: HasCallStack => CXType -> IO CLLong clang_Type_getAlignOf typ = onHaskellHeap typ $ \typ' -> ensureNotInRange @CXTypeLayoutError $ - wrap_getAlignOf typ' + wrap_Type_getAlignOf typ' -- | Determine if a typedef is 'transparent' tag. -- diff --git a/hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/FFI.hs b/hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/FFI.hs new file mode 100644 index 00000000..3198ebe0 --- /dev/null +++ b/hs-bindgen-libclang/src/HsBindgen/Clang/LowLevel/FFI.hs @@ -0,0 +1,208 @@ +{-| this module is autogenerated with cabal run hs-bindgen-bootstrap -} +module HsBindgen.Clang.LowLevel.FFI (module HsBindgen.Clang.LowLevel.FFI) where +import Foreign.C.Types +import HsBindgen.Clang.Internal.ByValue +import HsBindgen.Clang.LowLevel.Core.Enums +import HsBindgen.Clang.LowLevel.Core.Structs +import HsBindgen.Patterns +-- Type information for CXCursors https://clang.llvm.org/doxygen/group__CINDEX__TYPES.html + +foreign import capi unsafe "clang_wrappers.h" + wrap_getCursorType :: R CXCursor_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_getTypeSpelling :: R CXType_ -> W CXString_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_getTypedefDeclUnderlyingType :: R CXCursor_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_getEnumDeclIntegerType :: R CXCursor_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_getEnumConstantDeclValue :: R CXCursor_ -> IO CLLong + +foreign import capi unsafe "clang_wrappers.h" + wrap_getEnumConstantDeclUnsignedValue :: R CXCursor_ -> IO CULLong + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_isBitField :: R CXCursor_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_getFieldDeclBitWidth :: R CXCursor_ -> IO CInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_getNumArguments :: R CXCursor_ -> IO CInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_getArgument :: R CXCursor_ -> CUInt -> W CXCursor_ -> IO () + +-- int clang_Cursor_getNumTemplateArguments (CXCursor C); // C++ + +-- enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind (CXCursor C, unsigned I); // C++ + +-- CXType clang_Cursor_getTemplateArgumentType (CXCursor C, unsigned I); // C++ + +-- long long clang_Cursor_getTemplateArgumentValue (CXCursor C, unsigned I); // C++ + +-- unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue (CXCursor C, unsigned I); // C++ + +foreign import capi unsafe "clang_wrappers.h" + wrap_equalTypes :: R CXType_ -> R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_getCanonicalType :: R CXType_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_isConstQualifiedType :: R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_isMacroFunctionLike :: R CXCursor_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_isMacroBuiltin :: R CXCursor_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_isFunctionInlined :: R CXCursor_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_isVolatileQualifiedType :: R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_isRestrictQualifiedType :: R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_getAddressSpace :: R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_getTypedefName :: R CXType_ -> W CXString_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_getPointeeType :: R CXType_ -> W CXType_ -> IO () + +-- CXType clang_getUnqualifiedType (CXType CT); // this is special case + +-- CXType clang_getNonReferenceType (CXType CT); // this is apparently special case as well (not available in older libclang) + +foreign import capi unsafe "clang_wrappers.h" + wrap_getTypeDeclaration :: R CXType_ -> W CXCursor_ -> IO () + +-- CXString clang_getDeclObjCTypeEncoding (CXCursor C); // Objective C + +-- CXString clang_Type_getObjCEncoding (CXType type); // Objective C + +foreign import capi unsafe "clang_wrappers.h" + wrap_getTypeKindSpelling :: SimpleEnum CXTypeKind -> W CXString_ -> IO () + +-- enum CXCallingConv clang_getFunctionTypeCallingConv (CXType T); // no enum + +foreign import capi unsafe "clang_wrappers.h" + wrap_getResultType :: R CXType_ -> W CXType_ -> IO () + +-- int clang_getExceptionSpecificationType (CXType T); // C++ + +foreign import capi unsafe "clang_wrappers.h" + wrap_getNumArgTypes :: R CXType_ -> IO CInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_getArgType :: R CXType_ -> CUInt -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getObjCObjectBaseType :: R CXType_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getNumObjCProtocolRefs :: R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getObjCProtocolDecl :: R CXType_ -> CUInt -> W CXCursor_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getNumObjCTypeArgs :: R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getObjCTypeArg :: R CXType_ -> CUInt -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_isFunctionTypeVariadic :: R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_getCursorResultType :: R CXCursor_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_getCursorExceptionSpecificationType :: R CXCursor_ -> IO CInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_isPODType :: R CXType_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_getElementType :: R CXType_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_getNumElements :: R CXType_ -> IO CLLong + +foreign import capi unsafe "clang_wrappers.h" + wrap_getArrayElementType :: R CXType_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_getArraySize :: R CXType_ -> IO CLLong + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getNamedType :: R CXType_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_isTransparentTagTypedef :: R CXType_ -> IO CUInt + +-- enum CXTypeNullabilityKind clang_Type_getNullability (CXType T); // no enum + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getAlignOf :: R CXType_ -> IO CLLong + +-- CXType clang_Type_getClassType (CXType T); // C++ + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getSizeOf :: R CXType_ -> IO CLLong + +-- long long clang_Type_getOffsetOf (CXType T, const char *S) // TODO: generator doesn't know * yet + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getModifiedType :: R CXType_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_Type_getValueType :: R CXType_ -> W CXType_ -> IO () + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_getOffsetOfField :: R CXCursor_ -> IO CLLong + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_isAnonymous :: R CXCursor_ -> IO CUInt + +foreign import capi unsafe "clang_wrappers.h" + wrap_Cursor_isAnonymousRecordDecl :: R CXCursor_ -> IO CUInt + +-- unsigned clang_Cursor_isInlineNamespace (CXCursor C); // C++ + +-- int clang_Type_getNumTemplateArguments (CXType T); // C++ + +-- CXType clang_Type_getTemplateArgumentAsType (CXType T, unsigned i); // C++ + +-- enum CXRefQualifierKind clang_Type_getCXXRefQualifier (CXType T); // C++ + +-- unsigned clang_isVirtualBase (CXCursor); // C++ + +-- enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier (CXCursor); // C++ + +-- enum CX_BinaryOperatorKind clang_Cursor_getBinaryOpcode (CXCursor C); // C++ + +-- CXString clang_Cursor_getBinaryOpcodeStr (enum CX_BinaryOperatorKind Op); // C++ + +-- enum CX_StorageClass clang_Cursor_getStorageClass (CXCursor); // no enum + +-- unsigned clang_getNumOverloadedDecls (CXCursor cursor); // C++ + +-- CXCursor clang_getOverloadedDecl (CXCursor cursor, unsigned index); // C++ + +-- Cursor manipulations https://clang.llvm.org/doxygen/group__CINDEX__CURSOR__MANIP.html + +foreign import capi unsafe "clang_wrappers.h" + wrap_getNullCursor :: W CXCursor_ -> IO () + diff --git a/imports.h b/imports.h new file mode 100644 index 00000000..4786e54c --- /dev/null +++ b/imports.h @@ -0,0 +1,77 @@ +// Type information for CXCursors https://clang.llvm.org/doxygen/group__CINDEX__TYPES.html +CXType clang_getCursorType (CXCursor C); +CXString clang_getTypeSpelling (CXType CT); +CXType clang_getTypedefDeclUnderlyingType (CXCursor C); +CXType clang_getEnumDeclIntegerType (CXCursor C); +long long clang_getEnumConstantDeclValue (CXCursor C); +unsigned long long clang_getEnumConstantDeclUnsignedValue (CXCursor C); +unsigned clang_Cursor_isBitField (CXCursor C); +int clang_getFieldDeclBitWidth (CXCursor C); +int clang_Cursor_getNumArguments (CXCursor C); +CXCursor clang_Cursor_getArgument (CXCursor C, unsigned i); +// int clang_Cursor_getNumTemplateArguments (CXCursor C); // C++ +// enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind (CXCursor C, unsigned I); // C++ +// CXType clang_Cursor_getTemplateArgumentType (CXCursor C, unsigned I); // C++ +// long long clang_Cursor_getTemplateArgumentValue (CXCursor C, unsigned I); // C++ +// unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue (CXCursor C, unsigned I); // C++ +unsigned clang_equalTypes (CXType A, CXType B); +CXType clang_getCanonicalType (CXType T); +unsigned clang_isConstQualifiedType (CXType T); +unsigned clang_Cursor_isMacroFunctionLike (CXCursor C); +unsigned clang_Cursor_isMacroBuiltin (CXCursor C); +unsigned clang_Cursor_isFunctionInlined (CXCursor C); +unsigned clang_isVolatileQualifiedType (CXType T); +unsigned clang_isRestrictQualifiedType (CXType T); +unsigned clang_getAddressSpace (CXType T); +CXString clang_getTypedefName (CXType CT); +CXType clang_getPointeeType (CXType T); +// CXType clang_getUnqualifiedType (CXType CT); // this is special case +// CXType clang_getNonReferenceType (CXType CT); // this is apparently special case as well (not available in older libclang) +CXCursor clang_getTypeDeclaration (CXType T); +// CXString clang_getDeclObjCTypeEncoding (CXCursor C); // Objective C +// CXString clang_Type_getObjCEncoding (CXType type); // Objective C +CXString clang_getTypeKindSpelling (enum CXTypeKind K); +// enum CXCallingConv clang_getFunctionTypeCallingConv (CXType T); // no enum +CXType clang_getResultType (CXType T); +// int clang_getExceptionSpecificationType (CXType T); // C++ +int clang_getNumArgTypes (CXType T); +CXType clang_getArgType (CXType T, unsigned i); +CXType clang_Type_getObjCObjectBaseType (CXType T); +unsigned clang_Type_getNumObjCProtocolRefs (CXType T); +CXCursor clang_Type_getObjCProtocolDecl (CXType T, unsigned i); +unsigned clang_Type_getNumObjCTypeArgs (CXType T); +CXType clang_Type_getObjCTypeArg (CXType T, unsigned i); +unsigned clang_isFunctionTypeVariadic (CXType T); +CXType clang_getCursorResultType (CXCursor C); +int clang_getCursorExceptionSpecificationType (CXCursor C); +unsigned clang_isPODType (CXType T); +CXType clang_getElementType (CXType T); +long long clang_getNumElements (CXType T); +CXType clang_getArrayElementType (CXType T); +long long clang_getArraySize (CXType T); +CXType clang_Type_getNamedType (CXType T); +unsigned clang_Type_isTransparentTagTypedef (CXType T); +// enum CXTypeNullabilityKind clang_Type_getNullability (CXType T); // no enum +long long clang_Type_getAlignOf (CXType T); +// CXType clang_Type_getClassType (CXType T); // C++ +long long clang_Type_getSizeOf (CXType T); +// long long clang_Type_getOffsetOf (CXType T, const char *S) // TODO: generator doesn't know * yet +CXType clang_Type_getModifiedType (CXType T); +CXType clang_Type_getValueType (CXType CT); +long long clang_Cursor_getOffsetOfField (CXCursor C); +unsigned clang_Cursor_isAnonymous (CXCursor C); +unsigned clang_Cursor_isAnonymousRecordDecl (CXCursor C); +// unsigned clang_Cursor_isInlineNamespace (CXCursor C); // C++ +// int clang_Type_getNumTemplateArguments (CXType T); // C++ +// CXType clang_Type_getTemplateArgumentAsType (CXType T, unsigned i); // C++ +// enum CXRefQualifierKind clang_Type_getCXXRefQualifier (CXType T); // C++ +// unsigned clang_isVirtualBase (CXCursor); // C++ +// enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier (CXCursor); // C++ +// enum CX_BinaryOperatorKind clang_Cursor_getBinaryOpcode (CXCursor C); // C++ +// CXString clang_Cursor_getBinaryOpcodeStr (enum CX_BinaryOperatorKind Op); // C++ +// enum CX_StorageClass clang_Cursor_getStorageClass (CXCursor); // no enum +// unsigned clang_getNumOverloadedDecls (CXCursor cursor); // C++ +// CXCursor clang_getOverloadedDecl (CXCursor cursor, unsigned index); // C++ + +// Cursor manipulations https://clang.llvm.org/doxygen/group__CINDEX__CURSOR__MANIP.html +CXCursor clang_getNullCursor ();