From 435aaeefe99c3ee93b4dc4061d1732fa0b14c317 Mon Sep 17 00:00:00 2001 From: Jonathan Coe Date: Fri, 13 Jan 2017 16:06:59 +0000 Subject: [PATCH] Revert "Support for Python 3 in libclang python bindings" This reverts commit 4464581bb63e9789e9ee231a8c8800be5f614743. Memory access issues on Linux were reported by Mathieu Duponchelle and discussed here: https://reviews.llvm.org/D26082. llvm-svn: 291907 --- clang/bindings/python/clang/cindex.py | 145 +++++++----------- .../tests/cindex/test_translation_unit.py | 8 +- 2 files changed, 56 insertions(+), 97 deletions(-) diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py index c22d2510c62c..c1c7590fe9f3 100644 --- a/clang/bindings/python/clang/cindex.py +++ b/clang/bindings/python/clang/cindex.py @@ -64,7 +64,6 @@ call is efficient. from ctypes import * import collections -import sys import clang.enumerations @@ -74,33 +73,6 @@ import clang.enumerations # this by marshalling object arguments as void**. c_object_p = POINTER(c_void_p) -if sys.version_info[0] > 2: -# Python 3 strings are unicode, translate them to/from utf8 for C-interop -# Python 3 replaces xrange with range, we want xrange behaviour - xrange = range - - class c_string_p(c_char_p): - def __init__(self, p=None): - if type(p) == str: - p = p.encode("utf8") - super(c_char_p, self).__init__(p) - - def __str__(self): - return str(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): - return cls(param) -else: - c_string_p = c_char_p - - callbacks = {} ### Exception Classes ### @@ -175,7 +147,7 @@ class CachedProperty(object): class _CXString(Structure): """Helper for transforming CXString results.""" - _fields_ = [("spelling", c_string_p), ("free", c_int)] + _fields_ = [("spelling", c_char_p), ("free", c_int)] def __del__(self): conf.lib.clang_disposeString(self) @@ -357,7 +329,7 @@ class Diagnostic(object): @property def spelling(self): - return str(conf.lib.clang_getDiagnosticSpelling(self)) + return conf.lib.clang_getDiagnosticSpelling(self) @property def ranges(self): @@ -386,8 +358,8 @@ class Diagnostic(object): def __getitem__(self, key): range = SourceRange() - value = str(conf.lib.clang_getDiagnosticFixIt(self.diag, key, - byref(range))) + value = conf.lib.clang_getDiagnosticFixIt(self.diag, key, + byref(range)) if len(value) == 0: raise IndexError @@ -420,12 +392,12 @@ class Diagnostic(object): @property def category_name(self): """The string name of the category for this diagnostic.""" - return str(conf.lib.clang_getDiagnosticCategoryText(self)) + return conf.lib.clang_getDiagnosticCategoryText(self) @property def option(self): """The command-line option that enables this diagnostic.""" - return str(conf.lib.clang_getDiagnosticOption(self, None)) + return conf.lib.clang_getDiagnosticOption(self, None) @property def disable_option(self): @@ -433,7 +405,7 @@ class Diagnostic(object): disable = _CXString() conf.lib.clang_getDiagnosticOption(self, byref(disable)) - return str(conf.lib.clang_getCString(disable)) + return conf.lib.clang_getCString(disable) def format(self, options=None): """ @@ -582,8 +554,8 @@ class BaseEnumeration(object): if value >= len(self.__class__._kinds): self.__class__._kinds += [None] * (value - len(self.__class__._kinds) + 1) if self.__class__._kinds[value] is not None: - raise ValueError('{0} value {1} already loaded'.format( - str(self.__class__), value)) + raise ValueError,'{0} value {1} already loaded'.format( + str(self.__class__), value) self.value = value self.__class__._kinds[value] = self self.__class__._name_map = None @@ -600,12 +572,12 @@ class BaseEnumeration(object): for key, value in self.__class__.__dict__.items(): if isinstance(value, self.__class__): self._name_map[value] = key - return str(self._name_map[self]) + return self._name_map[self] @classmethod def from_id(cls, id): if id >= len(cls._kinds) or cls._kinds[id] is None: - raise ValueError('Unknown template argument kind %d' % id) + raise ValueError,'Unknown template argument kind %d' % id return cls._kinds[id] def __repr__(self): @@ -624,7 +596,7 @@ class CursorKind(BaseEnumeration): @staticmethod def get_all_kinds(): """Return all CursorKind enumeration instances.""" - return [x for x in CursorKind._kinds if x] + return filter(None, CursorKind._kinds) def is_declaration(self): """Test if this is a declaration kind.""" @@ -1457,9 +1429,9 @@ class Cursor(Structure): def spelling(self): """Return the spelling of the entity pointed at by the cursor.""" if not hasattr(self, '_spelling'): - self._spelling = str(conf.lib.clang_getCursorSpelling(self)) + self._spelling = conf.lib.clang_getCursorSpelling(self) - return str(self._spelling) + return self._spelling @property def displayname(self): @@ -1471,7 +1443,7 @@ class Cursor(Structure): arguments of a class template specialization. """ if not hasattr(self, '_displayname'): - self._displayname = str(conf.lib.clang_getCursorDisplayName(self)) + self._displayname = conf.lib.clang_getCursorDisplayName(self) return self._displayname @@ -1479,7 +1451,7 @@ class Cursor(Structure): def mangled_name(self): """Return the mangled name for the entity referenced by this cursor.""" if not hasattr(self, '_mangled_name'): - self._mangled_name = str(conf.lib.clang_Cursor_getMangling(self)) + self._mangled_name = conf.lib.clang_Cursor_getMangling(self) return self._mangled_name @@ -1618,7 +1590,7 @@ class Cursor(Structure): self._objc_type_encoding = \ conf.lib.clang_getDeclObjCTypeEncoding(self) - return str(self._objc_type_encoding) + return self._objc_type_encoding @property def hash(self): @@ -1665,23 +1637,17 @@ class Cursor(Structure): @property def brief_comment(self): """Returns the brief comment text associated with that Cursor""" - r = conf.lib.clang_Cursor_getBriefCommentText(self) - if not r: - return None - return str(r) + return conf.lib.clang_Cursor_getBriefCommentText(self) @property def raw_comment(self): """Returns the raw comment text associated with that Cursor""" - r = conf.lib.clang_Cursor_getRawCommentText(self) - if not r: - return None - return str(r) + return conf.lib.clang_Cursor_getRawCommentText(self) def get_arguments(self): """Return an iterator for accessing the arguments of this cursor.""" num_args = conf.lib.clang_Cursor_getNumArguments(self) - for i in xrange(0, num_args): + for i in range(0, num_args): yield conf.lib.clang_Cursor_getArgument(self, i) def get_num_template_arguments(self): @@ -1811,7 +1777,7 @@ class StorageClass(object): if value >= len(StorageClass._kinds): StorageClass._kinds += [None] * (value - len(StorageClass._kinds) + 1) if StorageClass._kinds[value] is not None: - raise ValueError('StorageClass already loaded') + raise ValueError,'StorageClass already loaded' self.value = value StorageClass._kinds[value] = self StorageClass._name_map = None @@ -1832,7 +1798,7 @@ class StorageClass(object): @staticmethod def from_id(id): if id >= len(StorageClass._kinds) or not StorageClass._kinds[id]: - raise ValueError('Unknown storage class %d' % id) + raise ValueError,'Unknown storage class %d' % id return StorageClass._kinds[id] def __repr__(self): @@ -1885,7 +1851,7 @@ class TypeKind(BaseEnumeration): @property def spelling(self): """Retrieve the spelling of this TypeKind.""" - return str(conf.lib.clang_getTypeKindSpelling(self.value)) + return conf.lib.clang_getTypeKindSpelling(self.value) def __repr__(self): return 'TypeKind.%s' % (self.name,) @@ -2161,7 +2127,7 @@ class Type(Structure): """ Retrieve the offset of a field in the record. """ - return conf.lib.clang_Type_getOffsetOf(self, fieldname) + return conf.lib.clang_Type_getOffsetOf(self, c_char_p(fieldname)) def get_ref_qualifier(self): """ @@ -2188,7 +2154,7 @@ class Type(Structure): @property def spelling(self): """Retrieve the spelling of this Type.""" - return str(conf.lib.clang_getTypeSpelling(self)) + return conf.lib.clang_getTypeSpelling(self) def __eq__(self, other): if type(other) != type(self): @@ -2220,7 +2186,7 @@ class ClangObject(object): class _CXUnsavedFile(Structure): """Helper for passing unsaved file arguments.""" - _fields_ = [("name", c_string_p), ("contents", c_string_p), ('length', c_ulong)] + _fields_ = [("name", c_char_p), ("contents", c_char_p), ('length', c_ulong)] # Functions calls through the python interface are rather slow. Fortunately, # for most symboles, we do not need to perform a function call. Their spelling @@ -2266,7 +2232,7 @@ class CompletionChunk: self.__kindNumberCache = -1 def __repr__(self): - return "{'" + str(self.spelling) + "', " + str(self.kind) + "}" + return "{'" + self.spelling + "', " + str(self.kind) + "}" @CachedProperty def spelling(self): @@ -2575,9 +2541,7 @@ class TranslationUnit(ClangObject): args_array = None if len(args) > 0: - args_array = (c_string_p * len(args))() - for i,a in enumerate(args): - args_array[i] = c_string_p(a) + args_array = (c_char_p * len(args))(* args) unsaved_array = None if len(unsaved_files) > 0: @@ -2586,8 +2550,8 @@ class TranslationUnit(ClangObject): if hasattr(contents, "read"): contents = contents.read() - unsaved_array[i].name = c_string_p(name) - unsaved_array[i].contents = c_string_p(contents) + unsaved_array[i].name = name + unsaved_array[i].contents = contents unsaved_array[i].length = len(contents) ptr = conf.lib.clang_parseTranslationUnit(index, filename, args_array, @@ -2642,7 +2606,7 @@ class TranslationUnit(ClangObject): @property def spelling(self): """Get the original translation unit source file name.""" - return str(conf.lib.clang_getTranslationUnitSpelling(self)) + return conf.lib.clang_getTranslationUnitSpelling(self) def get_includes(self): """ @@ -2765,9 +2729,9 @@ class TranslationUnit(ClangObject): # FIXME: It would be great to support an efficient version # of this, one day. value = value.read() - print(value) + print value if not isinstance(value, str): - raise TypeError('Unexpected unsaved file contents.') + raise TypeError,'Unexpected unsaved file contents.' unsaved_files_array[i].name = name unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) @@ -2829,11 +2793,11 @@ class TranslationUnit(ClangObject): # FIXME: It would be great to support an efficient version # of this, one day. value = value.read() - print(value) + print value if not isinstance(value, str): - raise TypeError('Unexpected unsaved file contents.') - unsaved_files_array[i].name = c_string_p(name) - unsaved_files_array[i].contents = c_string_p(value) + raise TypeError,'Unexpected unsaved file contents.' + unsaved_files_array[i].name = name + unsaved_files_array[i].contents = value unsaved_files_array[i].length = len(value) ptr = conf.lib.clang_codeCompleteAt(self, path, line, column, unsaved_files_array, len(unsaved_files), options) @@ -2868,7 +2832,7 @@ class File(ClangObject): @property def name(self): """Return the complete file and path name of the file.""" - return str(conf.lib.clang_getCString(conf.lib.clang_getFileName(self))) + return conf.lib.clang_getCString(conf.lib.clang_getFileName(self)) @property def time(self): @@ -2876,7 +2840,7 @@ class File(ClangObject): return conf.lib.clang_getFileTime(self) def __str__(self): - return str(self.name) + return self.name def __repr__(self): return "" % (self.name) @@ -2945,12 +2909,12 @@ class CompileCommand(object): @property def directory(self): """Get the working directory for this CompileCommand""" - return str(conf.lib.clang_CompileCommand_getDirectory(self.cmd)) + return conf.lib.clang_CompileCommand_getDirectory(self.cmd) @property def filename(self): """Get the working filename for this CompileCommand""" - return str(conf.lib.clang_CompileCommand_getFilename(self.cmd)) + return conf.lib.clang_CompileCommand_getFilename(self.cmd) @property def arguments(self): @@ -2962,7 +2926,7 @@ class CompileCommand(object): """ length = conf.lib.clang_CompileCommand_getNumArgs(self.cmd) for i in xrange(length): - yield str(conf.lib.clang_CompileCommand_getArg(self.cmd, i)) + yield conf.lib.clang_CompileCommand_getArg(self.cmd, i) class CompileCommands(object): """ @@ -3056,7 +3020,7 @@ class Token(Structure): This is the textual representation of the token in source. """ - return str(conf.lib.clang_getTokenSpelling(self._tu, self)) + return conf.lib.clang_getTokenSpelling(self._tu, self) @property def kind(self): @@ -3099,7 +3063,7 @@ functionList = [ [c_object_p]), ("clang_CompilationDatabase_fromDirectory", - [c_string_p, POINTER(c_uint)], + [c_char_p, POINTER(c_uint)], c_object_p, CompilationDatabase.from_result), @@ -3109,7 +3073,7 @@ functionList = [ CompileCommands.from_result), ("clang_CompilationDatabase_getCompileCommands", - [c_object_p, c_string_p], + [c_object_p, c_char_p], c_object_p, CompileCommands.from_result), @@ -3144,7 +3108,7 @@ functionList = [ c_uint), ("clang_codeCompleteAt", - [TranslationUnit, c_string_p, c_int, c_int, c_void_p, c_int, c_int], + [TranslationUnit, c_char_p, c_int, c_int, c_void_p, c_int, c_int], POINTER(CCRStructure)), ("clang_codeCompleteGetDiagnostic", @@ -3160,7 +3124,7 @@ functionList = [ c_object_p), ("clang_createTranslationUnit", - [Index, c_string_p], + [Index, c_char_p], c_object_p), ("clang_CXXConstructor_isConvertingConstructor", @@ -3310,7 +3274,7 @@ functionList = [ ("clang_getCString", [_CXString], - c_string_p), + c_char_p), ("clang_getCursor", [TranslationUnit, SourceLocation], @@ -3457,7 +3421,7 @@ functionList = [ Type.from_result), ("clang_getFile", - [TranslationUnit, c_string_p], + [TranslationUnit, c_char_p], c_object_p), ("clang_getFileName", @@ -3586,7 +3550,7 @@ functionList = [ ("clang_getTUResourceUsageName", [c_uint], - c_string_p), + c_char_p), ("clang_getTypeDeclaration", [Type], @@ -3681,7 +3645,7 @@ functionList = [ bool), ("clang_parseTranslationUnit", - [Index, c_string_p, c_void_p, c_int, c_void_p, c_int, c_int], + [Index, c_char_p, c_void_p, c_int, c_void_p, c_int, c_int], c_object_p), ("clang_reparseTranslationUnit", @@ -3689,7 +3653,7 @@ functionList = [ c_int), ("clang_saveTranslationUnit", - [TranslationUnit, c_string_p, c_uint], + [TranslationUnit, c_char_p, c_uint], c_int), ("clang_tokenize", @@ -3761,7 +3725,7 @@ functionList = [ Type.from_result), ("clang_Type_getOffsetOf", - [Type, c_string_p], + [Type, c_char_p], c_longlong), ("clang_Type_getSizeOf", @@ -3820,8 +3784,7 @@ def register_functions(lib, ignore_errors): def register(item): return register_function(lib, item, ignore_errors) - for f in functionList: - register(f) + map(register, functionList) class Config: library_path = None diff --git a/clang/bindings/python/tests/cindex/test_translation_unit.py b/clang/bindings/python/tests/cindex/test_translation_unit.py index f959cf4aafcc..be6cd671ae0c 100644 --- a/clang/bindings/python/tests/cindex/test_translation_unit.py +++ b/clang/bindings/python/tests/cindex/test_translation_unit.py @@ -59,13 +59,9 @@ int SOME_DEFINE; assert spellings[-1] == 'y' def test_unsaved_files_2(): - try: - from StringIO import StringIO - except: - from io import StringIO - + import StringIO tu = TranslationUnit.from_source('fake.c', unsaved_files = [ - ('fake.c', StringIO('int x;'))]) + ('fake.c', StringIO.StringIO('int x;'))]) spellings = [c.spelling for c in tu.cursor.get_children()] assert spellings[-1] == 'x'