summaryrefslogtreecommitdiffstats
path: root/bindings
diff options
context:
space:
mode:
authorDavid L. Jones <dlj@google.com>2017-11-10 01:07:01 +0000
committerDavid L. Jones <dlj@google.com>2017-11-10 01:07:01 +0000
commit41af1698c520ea38edf83e7c91f1e519d34f20c1 (patch)
tree05c516cb7514d80a5e8deccb07cd0f7c228b70d4 /bindings
parentcd1b175aa96d9d675c09fc54dfd96ba41e3f2279 (diff)
parent4d085086c74a8fbce197f61548f488a63f300933 (diff)
Creating branches/google/testing and tags/google/testing/ from r317203
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/google/testing@317856 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'bindings')
-rw-r--r--bindings/python/clang/__init__.py8
-rw-r--r--bindings/python/clang/cindex.py318
-rw-r--r--bindings/python/tests/cindex/test_cursor.py83
-rw-r--r--bindings/python/tests/cindex/test_diagnostics.py8
-rw-r--r--bindings/python/tests/cindex/test_exception_specification_kind.py27
-rw-r--r--bindings/python/tests/cindex/test_index.py2
-rw-r--r--bindings/python/tests/cindex/test_linkage.py30
-rw-r--r--bindings/python/tests/cindex/test_tls_kind.py37
-rw-r--r--bindings/python/tests/cindex/test_translation_unit.py7
-rw-r--r--bindings/python/tests/cindex/test_type.py17
10 files changed, 496 insertions, 41 deletions
diff --git a/bindings/python/clang/__init__.py b/bindings/python/clang/__init__.py
index fba49e38c9..88f3081238 100644
--- a/bindings/python/clang/__init__.py
+++ b/bindings/python/clang/__init__.py
@@ -20,13 +20,5 @@ The available modules are:
Bindings for the Clang indexing library.
"""
-
-# Python 3 uses unicode for strings. The bindings, in particular the interaction
-# with ctypes, need modifying to handle conversions between unicode and
-# c-strings.
-import sys
-if sys.version_info[0] != 2:
- raise Exception("Only Python 2 is supported.")
-
__all__ = ['cindex']
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 48fc8b13a2..d72dd14ef9 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -67,6 +67,63 @@ import collections
import clang.enumerations
+import sys
+if sys.version_info[0] == 3:
+ # Python 3 strings are unicode, translate them to/from utf8 for C-interop.
+ class c_interop_string(c_char_p):
+
+ def __init__(self, p=None):
+ if p is None:
+ p = ""
+ if isinstance(p, str):
+ p = p.encode("utf8")
+ super(c_char_p, self).__init__(p)
+
+ def __str__(self):
+ return self.value
+
+ @property
+ def value(self):
+ if super(c_char_p, self).value is None:
+ return None
+ return super(c_char_p, self).value.decode("utf8")
+
+ @classmethod
+ def from_param(cls, param):
+ if isinstance(param, str):
+ return cls(param)
+ if isinstance(param, bytes):
+ return cls(param)
+ if param is None:
+ # Support passing null to C functions expecting char arrays
+ return None
+ raise TypeError("Cannot convert '{}' to '{}'".format(type(param).__name__, cls.__name__))
+
+ @staticmethod
+ def to_python_string(x, *args):
+ return x.value
+
+ def b(x):
+ if isinstance(x, bytes):
+ return x
+ return x.encode('utf8')
+
+ xrange = range
+
+elif sys.version_info[0] == 2:
+ # Python 2 strings are utf8 byte strings, no translation is needed for
+ # C-interop.
+ c_interop_string = c_char_p
+
+ def _to_python_string(x, *args):
+ return x
+
+ c_interop_string.to_python_string = staticmethod(_to_python_string)
+
+ def b(x):
+ return x
+
+
# ctypes doesn't implicitly convert c_void_p to the appropriate wrapper
# object. This is a problem, because it means that from_parameter will see an
# integer and pass the wrong value on platforms where int != void*. Work around
@@ -153,10 +210,11 @@ class _CXString(Structure):
conf.lib.clang_disposeString(self)
@staticmethod
- def from_result(res, fn, args):
+ def from_result(res, fn=None, args=None):
assert isinstance(res, _CXString)
return conf.lib.clang_getCString(res)
+
class SourceLocation(Structure):
"""
A SourceLocation represents a particular location within a source file.
@@ -404,8 +462,7 @@ class Diagnostic(object):
"""The command-line option that disables this diagnostic."""
disable = _CXString()
conf.lib.clang_getDiagnosticOption(self, byref(disable))
-
- return conf.lib.clang_getCString(disable)
+ return _CXString.from_result(disable)
def format(self, options=None):
"""
@@ -418,8 +475,7 @@ class Diagnostic(object):
options = conf.lib.clang_defaultDiagnosticDisplayOptions()
if options & ~Diagnostic._FormatOptionsMask:
raise ValueError('Invalid format options')
- formatted = conf.lib.clang_formatDiagnostic(self, options)
- return conf.lib.clang_getCString(formatted)
+ return conf.lib.clang_formatDiagnostic(self, options)
def __repr__(self):
return "<Diagnostic severity %r, location %r, spelling %r>" % (
@@ -596,7 +652,7 @@ class CursorKind(BaseEnumeration):
@staticmethod
def get_all_kinds():
"""Return all CursorKind enumeration instances."""
- return filter(None, CursorKind._kinds)
+ return [x for x in CursorKind._kinds if not x is None]
def is_declaration(self):
"""Test if this is a declaration kind."""
@@ -727,7 +783,7 @@ CursorKind.CONVERSION_FUNCTION = CursorKind(26)
# A C++ template type parameter
CursorKind.TEMPLATE_TYPE_PARAMETER = CursorKind(27)
-# A C++ non-type template paramater.
+# A C++ non-type template parameter.
CursorKind.TEMPLATE_NON_TYPE_PARAMETER = CursorKind(28)
# A C++ template template parameter.
@@ -1312,6 +1368,30 @@ TemplateArgumentKind.DECLARATION = TemplateArgumentKind(2)
TemplateArgumentKind.NULLPTR = TemplateArgumentKind(3)
TemplateArgumentKind.INTEGRAL = TemplateArgumentKind(4)
+### Exception Specification Kinds ###
+class ExceptionSpecificationKind(BaseEnumeration):
+ """
+ An ExceptionSpecificationKind describes the kind of exception specification
+ that a function has.
+ """
+
+ # The required BaseEnumeration declarations.
+ _kinds = []
+ _name_map = None
+
+ def __repr__(self):
+ return 'ExceptionSpecificationKind.{}'.format(self.name)
+
+ExceptionSpecificationKind.NONE = ExceptionSpecificationKind(0)
+ExceptionSpecificationKind.DYNAMIC_NONE = ExceptionSpecificationKind(1)
+ExceptionSpecificationKind.DYNAMIC = ExceptionSpecificationKind(2)
+ExceptionSpecificationKind.MS_ANY = ExceptionSpecificationKind(3)
+ExceptionSpecificationKind.BASIC_NOEXCEPT = ExceptionSpecificationKind(4)
+ExceptionSpecificationKind.COMPUTED_NOEXCEPT = ExceptionSpecificationKind(5)
+ExceptionSpecificationKind.UNEVALUATED = ExceptionSpecificationKind(6)
+ExceptionSpecificationKind.UNINSTANTIATED = ExceptionSpecificationKind(7)
+ExceptionSpecificationKind.UNPARSED = ExceptionSpecificationKind(8)
+
### Cursors ###
class Cursor(Structure):
@@ -1399,6 +1479,11 @@ class Cursor(Structure):
"""
return conf.lib.clang_CXXMethod_isVirtual(self)
+ def is_scoped_enum(self):
+ """Returns True if the cursor refers to a scoped enum declaration.
+ """
+ return conf.lib.clang_EnumDecl_isScoped(self)
+
def get_definition(self):
"""
If the cursor is a reference to a declaration or a declaration of
@@ -1467,6 +1552,22 @@ class Cursor(Structure):
return self._loc
@property
+ def linkage(self):
+ """Return the linkage of this cursor."""
+ if not hasattr(self, '_linkage'):
+ self._linkage = conf.lib.clang_getCursorLinkage(self)
+
+ return LinkageKind.from_id(self._linkage)
+
+ @property
+ def tls_kind(self):
+ """Return the thread-local storage (TLS) kind of this cursor."""
+ if not hasattr(self, '_tls_kind'):
+ self._tls_kind = conf.lib.clang_getCursorTLSKind(self)
+
+ return TLSKind.from_id(self._tls_kind)
+
+ @property
def extent(self):
"""
Return the source range (the range of text) occupied by the entity
@@ -1489,6 +1590,16 @@ class Cursor(Structure):
return StorageClass.from_id(self._storage_class)
@property
+ def availability(self):
+ """
+ Retrieves the availability of the entity pointed at by the cursor.
+ """
+ if not hasattr(self, '_availability'):
+ self._availability = conf.lib.clang_getCursorAvailability(self)
+
+ return AvailabilityKind.from_id(self._availability)
+
+ @property
def access_specifier(self):
"""
Retrieves the access specifier (if any) of the entity pointed at by the
@@ -1532,6 +1643,18 @@ class Cursor(Structure):
return self._result_type
@property
+ def exception_specification_kind(self):
+ '''
+ Retrieve the exception specification kind, which is one of the values
+ from the ExceptionSpecificationKind enumeration.
+ '''
+ if not hasattr(self, '_exception_specification_kind'):
+ exc_kind = conf.lib.clang_getCursorExceptionSpecificationType(self)
+ self._exception_specification_kind = ExceptionSpecificationKind.from_id(exc_kind)
+
+ return self._exception_specification_kind
+
+ @property
def underlying_typedef_type(self):
"""Return the underlying type of a typedef declaration.
@@ -1813,6 +1936,24 @@ StorageClass.OPENCLWORKGROUPLOCAL = StorageClass(5)
StorageClass.AUTO = StorageClass(6)
StorageClass.REGISTER = StorageClass(7)
+### Availability Kinds ###
+
+class AvailabilityKind(BaseEnumeration):
+ """
+ Describes the availability of an entity.
+ """
+
+ # The unique kind objects, indexed by id.
+ _kinds = []
+ _name_map = None
+
+ def __repr__(self):
+ return 'AvailabilityKind.%s' % (self.name,)
+
+AvailabilityKind.AVAILABLE = AvailabilityKind(0)
+AvailabilityKind.DEPRECATED = AvailabilityKind(1)
+AvailabilityKind.NOT_AVAILABLE = AvailabilityKind(2)
+AvailabilityKind.NOT_ACCESSIBLE = AvailabilityKind(3)
### C++ access specifiers ###
@@ -1908,6 +2049,47 @@ TypeKind.DEPENDENTSIZEDARRAY = TypeKind(116)
TypeKind.MEMBERPOINTER = TypeKind(117)
TypeKind.AUTO = TypeKind(118)
TypeKind.ELABORATED = TypeKind(119)
+TypeKind.PIPE = TypeKind(120)
+TypeKind.OCLIMAGE1DRO = TypeKind(121)
+TypeKind.OCLIMAGE1DARRAYRO = TypeKind(122)
+TypeKind.OCLIMAGE1DBUFFERRO = TypeKind(123)
+TypeKind.OCLIMAGE2DRO = TypeKind(124)
+TypeKind.OCLIMAGE2DARRAYRO = TypeKind(125)
+TypeKind.OCLIMAGE2DDEPTHRO = TypeKind(126)
+TypeKind.OCLIMAGE2DARRAYDEPTHRO = TypeKind(127)
+TypeKind.OCLIMAGE2DMSAARO = TypeKind(128)
+TypeKind.OCLIMAGE2DARRAYMSAARO = TypeKind(129)
+TypeKind.OCLIMAGE2DMSAADEPTHRO = TypeKind(130)
+TypeKind.OCLIMAGE2DARRAYMSAADEPTHRO = TypeKind(131)
+TypeKind.OCLIMAGE3DRO = TypeKind(132)
+TypeKind.OCLIMAGE1DWO = TypeKind(133)
+TypeKind.OCLIMAGE1DARRAYWO = TypeKind(134)
+TypeKind.OCLIMAGE1DBUFFERWO = TypeKind(135)
+TypeKind.OCLIMAGE2DWO = TypeKind(136)
+TypeKind.OCLIMAGE2DARRAYWO = TypeKind(137)
+TypeKind.OCLIMAGE2DDEPTHWO = TypeKind(138)
+TypeKind.OCLIMAGE2DARRAYDEPTHWO = TypeKind(139)
+TypeKind.OCLIMAGE2DMSAAWO = TypeKind(140)
+TypeKind.OCLIMAGE2DARRAYMSAAWO = TypeKind(141)
+TypeKind.OCLIMAGE2DMSAADEPTHWO = TypeKind(142)
+TypeKind.OCLIMAGE2DARRAYMSAADEPTHWO = TypeKind(143)
+TypeKind.OCLIMAGE3DWO = TypeKind(144)
+TypeKind.OCLIMAGE1DRW = TypeKind(145)
+TypeKind.OCLIMAGE1DARRAYRW = TypeKind(146)
+TypeKind.OCLIMAGE1DBUFFERRW = TypeKind(147)
+TypeKind.OCLIMAGE2DRW = TypeKind(148)
+TypeKind.OCLIMAGE2DARRAYRW = TypeKind(149)
+TypeKind.OCLIMAGE2DDEPTHRW = TypeKind(150)
+TypeKind.OCLIMAGE2DARRAYDEPTHRW = TypeKind(151)
+TypeKind.OCLIMAGE2DMSAARW = TypeKind(152)
+TypeKind.OCLIMAGE2DARRAYMSAARW = TypeKind(153)
+TypeKind.OCLIMAGE2DMSAADEPTHRW = TypeKind(154)
+TypeKind.OCLIMAGE2DARRAYMSAADEPTHRW = TypeKind(155)
+TypeKind.OCLIMAGE3DRW = TypeKind(156)
+TypeKind.OCLSAMPLER = TypeKind(157)
+TypeKind.OCLEVENT = TypeKind(158)
+TypeKind.OCLQUEUE = TypeKind(159)
+TypeKind.OCLRESERVEID = TypeKind(160)
class RefQualifierKind(BaseEnumeration):
"""Describes a specific ref-qualifier of a type."""
@@ -1926,6 +2108,42 @@ RefQualifierKind.NONE = RefQualifierKind(0)
RefQualifierKind.LVALUE = RefQualifierKind(1)
RefQualifierKind.RVALUE = RefQualifierKind(2)
+class LinkageKind(BaseEnumeration):
+ """Describes the kind of linkage of a cursor."""
+
+ # The unique kind objects, indexed by id.
+ _kinds = []
+ _name_map = None
+
+ def from_param(self):
+ return self.value
+
+ def __repr__(self):
+ return 'LinkageKind.%s' % (self.name,)
+
+LinkageKind.INVALID = LinkageKind(0)
+LinkageKind.NO_LINKAGE = LinkageKind(1)
+LinkageKind.INTERNAL = LinkageKind(2)
+LinkageKind.UNIQUE_EXTERNAL = LinkageKind(3)
+LinkageKind.EXTERNAL = LinkageKind(4)
+
+class TLSKind(BaseEnumeration):
+ """Describes the kind of thread-local storage (TLS) of a cursor."""
+
+ # The unique kind objects, indexed by id.
+ _kinds = []
+ _name_map = None
+
+ def from_param(self):
+ return self.value
+
+ def __repr__(self):
+ return 'TLSKind.%s' % (self.name,)
+
+TLSKind.NONE = TLSKind(0)
+TLSKind.DYNAMIC = TLSKind(1)
+TLSKind.STATIC = TLSKind(2)
+
class Type(Structure):
"""
The type of an element in the abstract syntax tree.
@@ -2066,6 +2284,12 @@ class Type(Structure):
return conf.lib.clang_isFunctionTypeVariadic(self)
+ def get_address_space(self):
+ return conf.lib.clang_getAddressSpace(self)
+
+ def get_typedef_name(self):
+ return conf.lib.clang_getTypedefName(self)
+
def is_pod(self):
"""Determine whether this Type represents plain old data (POD)."""
return conf.lib.clang_isPODType(self)
@@ -2128,7 +2352,7 @@ class Type(Structure):
"""
Retrieve the offset of a field in the record.
"""
- return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname))
+ return conf.lib.clang_Type_getOffsetOf(self, fieldname)
def get_ref_qualifier(self):
"""
@@ -2152,6 +2376,14 @@ class Type(Structure):
callbacks['fields_visit'](visitor), fields)
return iter(fields)
+ def get_exception_specification_kind(self):
+ """
+ Return the kind of the exception specification; a value from
+ the ExceptionSpecificationKind enumeration.
+ """
+ return ExceptionSpecificationKind.from_id(
+ conf.lib.clang.getExceptionSpecificationType(self))
+
@property
def spelling(self):
"""Retrieve the spelling of this Type."""
@@ -2239,7 +2471,7 @@ class CompletionChunk:
def spelling(self):
if self.__kindNumber in SpellingCache:
return SpellingCache[self.__kindNumber]
- return conf.lib.clang_getCompletionChunkText(self.cs, self.key).spelling
+ return conf.lib.clang_getCompletionChunkText(self.cs, self.key)
# We do not use @CachedProperty here, as the manual implementation is
# apparently still significantly faster. Please profile carefully if you
@@ -2345,7 +2577,7 @@ class CompletionString(ClangObject):
return " | ".join([str(a) for a in self]) \
+ " || Priority: " + str(self.priority) \
+ " || Availability: " + str(self.availability) \
- + " || Brief comment: " + str(self.briefComment.spelling)
+ + " || Brief comment: " + str(self.briefComment)
availabilityKinds = {
0: CompletionChunk.Kind("Available"),
@@ -2542,7 +2774,7 @@ class TranslationUnit(ClangObject):
args_array = None
if len(args) > 0:
- args_array = (c_char_p * len(args))(* args)
+ args_array = (c_char_p * len(args))(*[b(x) for x in args])
unsaved_array = None
if len(unsaved_files) > 0:
@@ -2551,8 +2783,8 @@ class TranslationUnit(ClangObject):
if hasattr(contents, "read"):
contents = contents.read()
- unsaved_array[i].name = name
- unsaved_array[i].contents = contents
+ unsaved_array[i].name = b(name)
+ unsaved_array[i].contents = b(contents)
unsaved_array[i].length = len(contents)
ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array,
@@ -2797,8 +3029,8 @@ class TranslationUnit(ClangObject):
print(value)
if not isinstance(value, str):
raise TypeError('Unexpected unsaved file contents.')
- unsaved_files_array[i].name = name
- unsaved_files_array[i].contents = value
+ unsaved_files_array[i].name = b(name)
+ unsaved_files_array[i].contents = b(value)
unsaved_files_array[i].length = len(value)
ptr = conf.lib.clang_codeCompleteAt(self, path, line, column,
unsaved_files_array, len(unsaved_files), options)
@@ -2833,7 +3065,7 @@ class File(ClangObject):
@property
def name(self):
"""Return the complete file and path name of the file."""
- return conf.lib.clang_getCString(conf.lib.clang_getFileName(self))
+ return conf.lib.clang_getFileName(self)
@property
def time(self):
@@ -3042,6 +3274,7 @@ class Token(Structure):
def cursor(self):
"""The Cursor this Token corresponds to."""
cursor = Cursor()
+ cursor._tu = self._tu
conf.lib.clang_annotateTokens(self._tu, byref(self), 1, byref(cursor))
@@ -3064,7 +3297,7 @@ functionList = [
[c_object_p]),
("clang_CompilationDatabase_fromDirectory",
- [c_char_p, POINTER(c_uint)],
+ [c_interop_string, POINTER(c_uint)],
c_object_p,
CompilationDatabase.from_result),
@@ -3074,7 +3307,7 @@ functionList = [
CompileCommands.from_result),
("clang_CompilationDatabase_getCompileCommands",
- [c_object_p, c_char_p],
+ [c_object_p, c_interop_string],
c_object_p,
CompileCommands.from_result),
@@ -3109,7 +3342,7 @@ functionList = [
c_uint),
("clang_codeCompleteAt",
- [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int],
+ [TranslationUnit, c_interop_string, c_int, c_int, c_void_p, c_int, c_int],
POINTER(CCRStructure)),
("clang_codeCompleteGetDiagnostic",
@@ -3125,7 +3358,7 @@ functionList = [
c_object_p),
("clang_createTranslationUnit",
- [Index, c_char_p],
+ [Index, c_interop_string],
c_object_p),
("clang_CXXConstructor_isConvertingConstructor",
@@ -3168,6 +3401,10 @@ functionList = [
[Cursor],
bool),
+ ("clang_EnumDecl_isScoped",
+ [Cursor],
+ bool),
+
("clang_defaultDiagnosticDisplayOptions",
[],
c_uint),
@@ -3215,7 +3452,8 @@ functionList = [
("clang_formatDiagnostic",
[Diagnostic, c_uint],
- _CXString),
+ _CXString,
+ _CXString.from_result),
("clang_getArgType",
[Type, c_uint],
@@ -3255,7 +3493,8 @@ functionList = [
("clang_getCompletionBriefComment",
[c_void_p],
- _CXString),
+ _CXString,
+ _CXString.from_result),
("clang_getCompletionChunkCompletionString",
[c_void_p, c_int],
@@ -3267,7 +3506,8 @@ functionList = [
("clang_getCompletionChunkText",
[c_void_p, c_int],
- _CXString),
+ _CXString,
+ _CXString.from_result),
("clang_getCompletionPriority",
[c_void_p],
@@ -3275,12 +3515,17 @@ functionList = [
("clang_getCString",
[_CXString],
- c_char_p),
+ c_interop_string,
+ c_interop_string.to_python_string),
("clang_getCursor",
[TranslationUnit, SourceLocation],
Cursor),
+ ("clang_getCursorAvailability",
+ [Cursor],
+ c_int),
+
("clang_getCursorDefinition",
[Cursor],
Cursor,
@@ -3422,12 +3667,13 @@ functionList = [
Type.from_result),
("clang_getFile",
- [TranslationUnit, c_char_p],
+ [TranslationUnit, c_interop_string],
c_object_p),
("clang_getFileName",
[File],
- _CXString), # TODO go through _CXString.from_result?
+ _CXString,
+ _CXString.from_result),
("clang_getFileTime",
[File],
@@ -3551,7 +3797,8 @@ functionList = [
("clang_getTUResourceUsageName",
[c_uint],
- c_char_p),
+ c_interop_string,
+ c_interop_string.to_python_string),
("clang_getTypeDeclaration",
[Type],
@@ -3563,6 +3810,11 @@ functionList = [
Type,
Type.from_result),
+ ("clang_getTypedefName",
+ [Type],
+ _CXString,
+ _CXString.from_result),
+
("clang_getTypeKindSpelling",
[c_uint],
_CXString,
@@ -3646,7 +3898,7 @@ functionList = [
bool),
("clang_parseTranslationUnit",
- [Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int],
+ [Index, c_interop_string, c_void_p, c_int, c_void_p, c_int, c_int],
c_object_p),
("clang_reparseTranslationUnit",
@@ -3654,7 +3906,7 @@ functionList = [
c_int),
("clang_saveTranslationUnit",
- [TranslationUnit, c_char_p, c_uint],
+ [TranslationUnit, c_interop_string, c_uint],
c_int),
("clang_tokenize",
@@ -3726,7 +3978,7 @@ functionList = [
Type.from_result),
("clang_Type_getOffsetOf",
- [Type, c_char_p],
+ [Type, c_interop_string],
c_longlong),
("clang_Type_getSizeOf",
@@ -3785,7 +4037,8 @@ def register_functions(lib, ignore_errors):
def register(item):
return register_function(lib, item, ignore_errors)
- map(register, functionList)
+ for f in functionList:
+ register(f)
class Config:
library_path = None
@@ -3888,6 +4141,7 @@ conf = Config()
register_enumerations()
__all__ = [
+ 'AvailabilityKind',
'Config',
'CodeCompletionResults',
'CompilationDatabase',
@@ -3899,8 +4153,10 @@ __all__ = [
'File',
'FixIt',
'Index',
+ 'LinkageKind',
'SourceLocation',
'SourceRange',
+ 'TLSKind',
'TokenKind',
'Token',
'TranslationUnitLoadError',
diff --git a/bindings/python/tests/cindex/test_cursor.py b/bindings/python/tests/cindex/test_cursor.py
index 8103e96df4..8ff0695154 100644
--- a/bindings/python/tests/cindex/test_cursor.py
+++ b/bindings/python/tests/cindex/test_cursor.py
@@ -1,6 +1,7 @@
import ctypes
import gc
+from clang.cindex import AvailabilityKind
from clang.cindex import CursorKind
from clang.cindex import TemplateArgumentKind
from clang.cindex import TranslationUnit
@@ -255,6 +256,22 @@ def test_is_virtual_method():
assert foo.is_virtual_method()
assert not bar.is_virtual_method()
+def test_is_scoped_enum():
+ """Ensure Cursor.is_scoped_enum works."""
+ source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};'
+ tu = get_tu(source, lang='cpp')
+
+ cls = get_cursor(tu, 'X')
+ regular_enum = get_cursor(tu, 'RegularEnum')
+ scoped_enum = get_cursor(tu, 'ScopedEnum')
+ assert cls is not None
+ assert regular_enum is not None
+ assert scoped_enum is not None
+
+ assert not cls.is_scoped_enum()
+ assert not regular_enum.is_scoped_enum()
+ assert scoped_enum.is_scoped_enum()
+
def test_underlying_type():
tu = get_tu('typedef int foo;')
typedef = get_cursor(tu, 'foo')
@@ -361,6 +378,26 @@ def test_annotation_attribute():
else:
assert False, "Couldn't find annotation"
+def test_annotation_template():
+ annotation = '__attribute__ ((annotate("annotation")))'
+ for source, kind in [
+ ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE),
+ ('class %s foo {};', CursorKind.CLASS_TEMPLATE),
+ ]:
+ source = 'template<typename T> ' + (source % annotation)
+ tu = get_tu(source, lang="cpp")
+
+ foo = get_cursor(tu, 'foo')
+ assert foo is not None
+ assert foo.kind == kind
+
+ for c in foo.get_children():
+ if c.kind == CursorKind.ANNOTATE_ATTR:
+ assert c.displayname == "annotation"
+ break
+ else:
+ assert False, "Couldn't find annotation for {}".format(kind)
+
def test_result_type():
tu = get_tu('int foo();')
foo = get_cursor(tu, 'foo')
@@ -369,6 +406,30 @@ def test_result_type():
t = foo.result_type
assert t.kind == TypeKind.INT
+def test_availability():
+ tu = get_tu('class A { A(A const&) = delete; };', lang='cpp')
+
+ # AvailabilityKind.AVAILABLE
+ cursor = get_cursor(tu, 'A')
+ assert cursor.kind == CursorKind.CLASS_DECL
+ assert cursor.availability == AvailabilityKind.AVAILABLE
+
+ # AvailabilityKind.NOT_AVAILABLE
+ cursors = get_cursors(tu, 'A')
+ for c in cursors:
+ if c.kind == CursorKind.CONSTRUCTOR:
+ assert c.availability == AvailabilityKind.NOT_AVAILABLE
+ break
+ else:
+ assert False, "Could not find cursor for deleted constructor"
+
+ # AvailabilityKind.DEPRECATED
+ tu = get_tu('void test() __attribute__((deprecated));', lang='cpp')
+ cursor = get_cursor(tu, 'test')
+ assert cursor.availability == AvailabilityKind.DEPRECATED
+
+ # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results
+
def test_get_tokens():
"""Ensure we can map cursors back to tokens."""
tu = get_tu('int foo(int i);')
@@ -379,6 +440,28 @@ def test_get_tokens():
assert tokens[0].spelling == 'int'
assert tokens[1].spelling == 'foo'
+def test_get_token_cursor():
+ """Ensure we can map tokens to cursors."""
+ tu = get_tu('class A {}; int foo(A var = A());', lang='cpp')
+ foo = get_cursor(tu, 'foo')
+
+ for cursor in foo.walk_preorder():
+ if cursor.kind.is_expression() and not cursor.kind.is_statement():
+ break
+ else:
+ assert False, "Could not find default value expression"
+
+ tokens = list(cursor.get_tokens())
+ assert len(tokens) == 4, [t.spelling for t in tokens]
+ assert tokens[0].spelling == '='
+ assert tokens[1].spelling == 'A'
+ assert tokens[2].spelling == '('
+ assert tokens[3].spelling == ')'
+ t_cursor = tokens[1].cursor
+ assert t_cursor.kind == CursorKind.TYPE_REF
+ r_cursor = t_cursor.referenced # should not raise an exception
+ assert r_cursor.kind == CursorKind.CLASS_DECL
+
def test_get_arguments():
tu = get_tu('void foo(int i, int j);')
foo = get_cursor(tu, 'foo')
diff --git a/bindings/python/tests/cindex/test_diagnostics.py b/bindings/python/tests/cindex/test_diagnostics.py
index ba6e545e8b..23cbe89f65 100644
--- a/bindings/python/tests/cindex/test_diagnostics.py
+++ b/bindings/python/tests/cindex/test_diagnostics.py
@@ -92,3 +92,11 @@ def test_diagnostic_children():
assert children[0].spelling.endswith('declared here')
assert children[0].location.line == 1
assert children[0].location.column == 1
+
+def test_diagnostic_string_repr():
+ tu = get_tu('struct MissingSemicolon{}')
+ assert len(tu.diagnostics) == 1
+ d = tu.diagnostics[0]
+
+ assert repr(d) == '<Diagnostic severity 3, location <SourceLocation file \'t.c\', line 1, column 26>, spelling "expected \';\' after struct">'
+
diff --git a/bindings/python/tests/cindex/test_exception_specification_kind.py b/bindings/python/tests/cindex/test_exception_specification_kind.py
new file mode 100644
index 0000000000..543d47f7db
--- /dev/null
+++ b/bindings/python/tests/cindex/test_exception_specification_kind.py
@@ -0,0 +1,27 @@
+import clang.cindex
+from clang.cindex import ExceptionSpecificationKind
+from .util import get_tu
+
+
+def find_function_declarations(node, declarations=[]):
+ if node.kind == clang.cindex.CursorKind.FUNCTION_DECL:
+ declarations.append((node.spelling, node.exception_specification_kind))
+ for child in node.get_children():
+ declarations = find_function_declarations(child, declarations)
+ return declarations
+
+
+def test_exception_specification_kind():
+ source = """int square1(int x);
+ int square2(int x) noexcept;
+ int square3(int x) noexcept(noexcept(x * x));"""
+
+ tu = get_tu(source, lang='cpp', flags=['-std=c++14'])
+
+ declarations = find_function_declarations(tu.cursor)
+ expected = [
+ ('square1', ExceptionSpecificationKind.NONE),
+ ('square2', ExceptionSpecificationKind.BASIC_NOEXCEPT),
+ ('square3', ExceptionSpecificationKind.COMPUTED_NOEXCEPT)
+ ]
+ assert declarations == expected
diff --git a/bindings/python/tests/cindex/test_index.py b/bindings/python/tests/cindex/test_index.py
index dc173f04d2..ef76692a52 100644
--- a/bindings/python/tests/cindex/test_index.py
+++ b/bindings/python/tests/cindex/test_index.py
@@ -13,3 +13,5 @@ def test_parse():
assert isinstance(index, Index)
tu = index.parse(os.path.join(kInputsDir, 'hello.cpp'))
assert isinstance(tu, TranslationUnit)
+ tu = index.parse(None, ['-c', os.path.join(kInputsDir, 'hello.cpp')])
+ assert isinstance(tu, TranslationUnit)
diff --git a/bindings/python/tests/cindex/test_linkage.py b/bindings/python/tests/cindex/test_linkage.py
new file mode 100644
index 0000000000..2f056d5140
--- /dev/null
+++ b/bindings/python/tests/cindex/test_linkage.py
@@ -0,0 +1,30 @@
+
+from clang.cindex import LinkageKind
+from clang.cindex import Cursor
+from clang.cindex import TranslationUnit
+
+from .util import get_cursor
+from .util import get_tu
+
+def test_linkage():
+ """Ensure that linkage specifers are available on cursors"""
+
+ tu = get_tu("""
+void foo() { int no_linkage; }
+static int internal;
+namespace { extern int unique_external; }
+extern int external;
+""", lang = 'cpp')
+
+ no_linkage = get_cursor(tu.cursor, 'no_linkage')
+ assert no_linkage.linkage == LinkageKind.NO_LINKAGE;
+
+ internal = get_cursor(tu.cursor, 'internal')
+ assert internal.linkage == LinkageKind.INTERNAL
+
+ unique_external = get_cursor(tu.cursor, 'unique_external')
+ assert unique_external.linkage == LinkageKind.UNIQUE_EXTERNAL
+
+ external = get_cursor(tu.cursor, 'external')
+ assert external.linkage == LinkageKind.EXTERNAL
+
diff --git a/bindings/python/tests/cindex/test_tls_kind.py b/bindings/python/tests/cindex/test_tls_kind.py
new file mode 100644
index 0000000000..6a03c0d5ee
--- /dev/null
+++ b/bindings/python/tests/cindex/test_tls_kind.py
@@ -0,0 +1,37 @@
+
+from clang.cindex import TLSKind
+from clang.cindex import Cursor
+from clang.cindex import TranslationUnit
+
+from .util import get_cursor
+from .util import get_tu
+
+def test_tls_kind():
+ """Ensure that thread-local storage kinds are available on cursors."""
+
+ tu = get_tu("""
+int tls_none;
+thread_local int tls_dynamic;
+_Thread_local int tls_static;
+""", lang = 'cpp')
+
+ tls_none = get_cursor(tu.cursor, 'tls_none')
+ assert tls_none.tls_kind == TLSKind.NONE;
+
+ tls_dynamic = get_cursor(tu.cursor, 'tls_dynamic')
+ assert tls_dynamic.tls_kind == TLSKind.DYNAMIC
+
+ tls_static = get_cursor(tu.cursor, 'tls_static')
+ assert tls_static.tls_kind == TLSKind.STATIC
+
+ # The following case tests '__declspec(thread)'. Since it is a Microsoft
+ # specific extension, specific flags are required for the parser to pick
+ # these up.
+ flags = ['-fms-extensions', '-target', 'x86_64-unknown-windows-win32']
+ tu = get_tu("""
+__declspec(thread) int tls_declspec;
+""", lang = 'cpp', flags=flags)
+
+ tls_declspec = get_cursor(tu.cursor, 'tls_declspec')
+ assert tls_declspec.tls_kind == TLSKind.STATIC
+
diff --git a/bindings/python/tests/cindex/test_translation_unit.py b/bindings/python/tests/cindex/test_translation_unit.py
index be6cd671ae..65d1ee02ff 100644
--- a/bindings/python/tests/cindex/test_translation_unit.py
+++ b/bindings/python/tests/cindex/test_translation_unit.py
@@ -59,9 +59,12 @@ int SOME_DEFINE;
assert spellings[-1] == 'y'
def test_unsaved_files_2():
- import StringIO
+ try:
+ from StringIO import StringIO
+ except:
+ from io import StringIO
tu = TranslationUnit.from_source('fake.c', unsaved_files = [
- ('fake.c', StringIO.StringIO('int x;'))])
+ ('fake.c', StringIO('int x;'))])
spellings = [c.spelling for c in tu.cursor.get_children()]
assert spellings[-1] == 'x'
diff --git a/bindings/python/tests/cindex/test_type.py b/bindings/python/tests/cindex/test_type.py
index f2184338be..6ee0773828 100644
--- a/bindings/python/tests/cindex/test_type.py
+++ b/bindings/python/tests/cindex/test_type.py
@@ -37,37 +37,44 @@ def test_a_struct():
assert not fields[0].type.is_const_qualified()
assert fields[0].type.kind == TypeKind.INT
assert fields[0].type.get_canonical().kind == TypeKind.INT
+ assert fields[0].type.get_typedef_name() == ''
assert fields[1].spelling == 'b'
assert not fields[1].type.is_const_qualified()
assert fields[1].type.kind == TypeKind.TYPEDEF
assert fields[1].type.get_canonical().kind == TypeKind.INT
assert fields[1].type.get_declaration().spelling == 'I'
+ assert fields[1].type.get_typedef_name() == 'I'
assert fields[2].spelling == 'c'
assert not fields[2].type.is_const_qualified()
assert fields[2].type.kind == TypeKind.LONG
assert fields[2].type.get_canonical().kind == TypeKind.LONG
+ assert fields[2].type.get_typedef_name() == ''
assert fields[3].spelling == 'd'
assert not fields[3].type.is_const_qualified()
assert fields[3].type.kind == TypeKind.ULONG
assert fields[3].type.get_canonical().kind == TypeKind.ULONG
+ assert fields[3].type.get_typedef_name() == ''
assert fields[4].spelling == 'e'
assert not fields[4].type.is_const_qualified()
assert fields[4].type.kind == TypeKind.LONG
assert fields[4].type.get_canonical().kind == TypeKind.LONG
+ assert fields[4].type.get_typedef_name() == ''
assert fields[5].spelling == 'f'
assert fields[5].type.is_const_qualified()
assert fields[5].type.kind == TypeKind.INT
assert fields[5].type.get_canonical().kind == TypeKind.INT
+ assert fields[5].type.get_typedef_name() == ''
assert fields[6].spelling == 'g'
assert not fields[6].type.is_const_qualified()
assert fields[6].type.kind == TypeKind.POINTER
assert fields[6].type.get_pointee().kind == TypeKind.INT
+ assert fields[6].type.get_typedef_name() == ''
assert fields[7].spelling == 'h'
assert not fields[7].type.is_const_qualified()
@@ -75,6 +82,7 @@ def test_a_struct():
assert fields[7].type.get_pointee().kind == TypeKind.POINTER
assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER
assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT
+ assert fields[7].type.get_typedef_name() == ''
def test_references():
"""Ensure that a Type maintains a reference to a TranslationUnit."""
@@ -404,3 +412,12 @@ def test_decay():
assert a.kind == TypeKind.INCOMPLETEARRAY
assert a.element_type.kind == TypeKind.INT
assert a.get_canonical().kind == TypeKind.INCOMPLETEARRAY
+
+def test_addrspace():
+ """Ensure the address space can be queried"""
+ tu = get_tu('__attribute__((address_space(2))) int testInteger = 3;', 'c')
+
+ testInteger = get_cursor(tu, 'testInteger')
+
+ assert testInteger is not None, "Could not find testInteger."
+ assert testInteger.type.get_address_space() == 2