[python] Add support for CXType to python bindings.
Patch by Anders Waldenborg!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137797 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 8cadcaa..2110170 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -634,6 +634,14 @@
         """
         return Cursor_extent(self)
 
+    @property
+    def type(self):
+        """
+        Retrieve the type (if any) of of the entity pointed at by the
+        cursor.
+        """
+        return Cursor_type(self)
+
     def get_children(self):
         """Return an iterator for accessing the children of this cursor."""
 
@@ -656,6 +664,165 @@
             return None
         return res
 
+
+### Type Kinds ###
+
+class TypeKind(object):
+    """
+    Describes the kind of type.
+    """
+
+    # The unique kind objects, indexed by id.
+    _kinds = []
+    _name_map = None
+
+    def __init__(self, value):
+        if value >= len(TypeKind._kinds):
+            TypeKind._kinds += [None] * (value - len(TypeKind._kinds) + 1)
+        if TypeKind._kinds[value] is not None:
+            raise ValueError,'TypeKind already loaded'
+        self.value = value
+        TypeKind._kinds[value] = self
+        TypeKind._name_map = None
+
+    def from_param(self):
+        return self.value
+
+    @property
+    def name(self):
+        """Get the enumeration name of this cursor kind."""
+        if self._name_map is None:
+            self._name_map = {}
+            for key,value in TypeKind.__dict__.items():
+                if isinstance(value,TypeKind):
+                    self._name_map[value] = key
+        return self._name_map[self]
+
+    @staticmethod
+    def from_id(id):
+        if id >= len(TypeKind._kinds) or TypeKind._kinds[id] is None:
+            raise ValueError,'Unknown cursor kind'
+        return TypeKind._kinds[id]
+
+    def __repr__(self):
+        return 'TypeKind.%s' % (self.name,)
+
+
+
+TypeKind.INVALID = TypeKind(0)
+TypeKind.UNEXPOSED = TypeKind(1)
+TypeKind.VOID = TypeKind(2)
+TypeKind.BOOL = TypeKind(3)
+TypeKind.CHAR_U = TypeKind(4)
+TypeKind.UCHAR = TypeKind(5)
+TypeKind.CHAR16 = TypeKind(6)
+TypeKind.CHAR32 = TypeKind(7)
+TypeKind.USHORT = TypeKind(8)
+TypeKind.UINT = TypeKind(9)
+TypeKind.ULONG = TypeKind(10)
+TypeKind.ULONGLONG = TypeKind(11)
+TypeKind.UINT128 = TypeKind(12)
+TypeKind.CHAR_S = TypeKind(13)
+TypeKind.SCHAR = TypeKind(14)
+TypeKind.WCHAR = TypeKind(15)
+TypeKind.SHORT = TypeKind(16)
+TypeKind.INT = TypeKind(17)
+TypeKind.LONG = TypeKind(18)
+TypeKind.LONGLONG = TypeKind(19)
+TypeKind.INT128 = TypeKind(20)
+TypeKind.FLOAT = TypeKind(21)
+TypeKind.DOUBLE = TypeKind(22)
+TypeKind.LONGDOUBLE = TypeKind(23)
+TypeKind.NULLPTR = TypeKind(24)
+TypeKind.OVERLOAD = TypeKind(25)
+TypeKind.DEPENDENT = TypeKind(26)
+TypeKind.OBJCID = TypeKind(27)
+TypeKind.OBJCCLASS = TypeKind(28)
+TypeKind.OBJCSEL = TypeKind(29)
+TypeKind.COMPLEX = TypeKind(100)
+TypeKind.POINTER = TypeKind(101)
+TypeKind.BLOCKPOINTER = TypeKind(102)
+TypeKind.LVALUEREFERENCE = TypeKind(103)
+TypeKind.RVALUEREFERENCE = TypeKind(104)
+TypeKind.RECORD = TypeKind(105)
+TypeKind.ENUM = TypeKind(106)
+TypeKind.TYPEDEF = TypeKind(107)
+TypeKind.OBJCINTERFACE = TypeKind(108)
+TypeKind.OBJCOBJECTPOINTER = TypeKind(109)
+TypeKind.FUNCTIONNOPROTO = TypeKind(110)
+TypeKind.FUNCTIONPROTO = TypeKind(111)
+
+
+class Type(Structure):
+    """
+    The type of an element in the abstract syntax tree.
+    """
+    _fields_ = [("_kind_id", c_int), ("data", c_void_p * 2)]
+
+    @property
+    def kind(self):
+        """Return the kind of this type."""
+        return TypeKind.from_id(self._kind_id)
+
+    @staticmethod
+    def from_result(res, fn, args):
+        assert isinstance(res, Type)
+        return res
+
+    def get_canonical(self):
+        """
+        Return the canonical type for a Type.
+
+        Clang's type system explicitly models typedefs and all the
+        ways a specific type can be represented.  The canonical type
+        is the underlying type with all the "sugar" removed.  For
+        example, if 'T' is a typedef for 'int', the canonical type for
+        'T' would be 'int'.
+        """
+        return Type_get_canonical(self)
+
+    def is_const_qualified(self):
+        """
+        Determine whether a Type has the "const" qualifier set,
+        without looking through typedefs that may have added "const"
+        at a different level.
+        """
+        return Type_is_const_qualified(self)
+
+    def is_volatile_qualified(self):
+        """
+        Determine whether a Type has the "volatile" qualifier set,
+        without looking through typedefs that may have added
+        "volatile" at a different level.
+        """
+        return Type_is_volatile_qualified(self)
+
+    def is_restrict_qualified(self):
+        """
+        Determine whether a Type has the "restrict" qualifier set,
+        without looking through typedefs that may have added
+        "restrict" at a different level.
+        """
+        return Type_is_restrict_qualified(self)
+
+    def get_pointee(self):
+        """
+        For pointer types, returns the type of the pointee.
+        """
+        return Type_get_pointee(self)
+
+    def get_declaration(self):
+        """
+        Return the cursor for the declaration of the given type.
+        """
+        return Type_get_declaration(self)
+
+    def get_result(self):
+        """
+        Retrieve the result type associated with a function type.
+        """
+        return Type_get_result(self)
+
 ## CIndex Objects ##
 
 # CIndex objects (derived from ClangObject) are essentially lightweight
@@ -1210,11 +1377,50 @@
 Cursor_ref.restype = Cursor
 Cursor_ref.errcheck = Cursor.from_result
 
+Cursor_type = lib.clang_getCursorType
+Cursor_type.argtypes = [Cursor]
+Cursor_type.restype = Type
+Cursor_type.errcheck = Type.from_result
+
 Cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object)
 Cursor_visit = lib.clang_visitChildren
 Cursor_visit.argtypes = [Cursor, Cursor_visit_callback, py_object]
 Cursor_visit.restype = c_uint
 
+# Type Functions
+Type_get_canonical = lib.clang_getCanonicalType
+Type_get_canonical.argtypes = [Type]
+Type_get_canonical.restype = Type
+Type_get_canonical.errcheck = Type.from_result
+
+Type_is_const_qualified = lib.clang_isConstQualifiedType
+Type_is_const_qualified.argtypes = [Type]
+Type_is_const_qualified.restype = bool
+
+Type_is_volatile_qualified = lib.clang_isVolatileQualifiedType
+Type_is_volatile_qualified.argtypes = [Type]
+Type_is_volatile_qualified.restype = bool
+
+Type_is_restrict_qualified = lib.clang_isRestrictQualifiedType
+Type_is_restrict_qualified.argtypes = [Type]
+Type_is_restrict_qualified.restype = bool
+
+Type_get_pointee = lib.clang_getPointeeType
+Type_get_pointee.argtypes = [Type]
+Type_get_pointee.restype = Type
+Type_get_pointee.errcheck = Type.from_result
+
+Type_get_declaration = lib.clang_getTypeDeclaration
+Type_get_declaration.argtypes = [Type]
+Type_get_declaration.restype = Cursor
+Type_get_declaration.errcheck = Cursor.from_result
+
+Type_get_result = lib.clang_getResultType
+Type_get_result.argtypes = [Type]
+Type_get_result.restype = Type
+Type_get_result.errcheck = Type.from_result
+
+
 # Index Functions
 Index_create = lib.clang_createIndex
 Index_create.argtypes = [c_int, c_int]
@@ -1313,6 +1519,6 @@
 
 ###
 
-__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind',
+__all__ = ['Index', 'TranslationUnit', 'Cursor', 'CursorKind', 'Type', 'TypeKind',
            'Diagnostic', 'FixIt', 'CodeCompletionResults', 'SourceRange',
            'SourceLocation', 'File']
diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py
index a653ba7..04e4838 100644
--- a/bindings/python/tests/cindex/test_cursor.py
+++ b/bindings/python/tests/cindex/test_cursor.py
@@ -1,4 +1,4 @@
-from clang.cindex import Index, CursorKind
+from clang.cindex import Index, CursorKind, TypeKind
 
 kInput = """\
 // FIXME: Find nicer way to drop builtins and other cruft.
@@ -47,8 +47,10 @@
     assert len(s0_nodes) == 2
     assert s0_nodes[0].kind == CursorKind.FIELD_DECL
     assert s0_nodes[0].spelling == 'a'
+    assert s0_nodes[0].type.kind == TypeKind.INT
     assert s0_nodes[1].kind == CursorKind.FIELD_DECL
     assert s0_nodes[1].spelling == 'b'
+    assert s0_nodes[1].type.kind == TypeKind.INT
 
     assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
     assert tu_nodes[1].spelling == 's1'