[cfe-commits] r156846 - in /cfe/trunk/bindings/python: clang/cindex.py tests/cindex/test_cursor.py tests/cindex/test_type.py
Gregory Szorc
gregory.szorc at gmail.com
Tue May 15 12:51:02 PDT 2012
Author: gps
Date: Tue May 15 14:51:02 2012
New Revision: 156846
URL: http://llvm.org/viewvc/llvm-project?rev=156846&view=rev
Log:
[clang.py] Store reference to TranslationUnit in Cursor and Type
Modified:
cfe/trunk/bindings/python/clang/cindex.py
cfe/trunk/bindings/python/tests/cindex/test_cursor.py
cfe/trunk/bindings/python/tests/cindex/test_type.py
Modified: cfe/trunk/bindings/python/clang/cindex.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/clang/cindex.py?rev=156846&r1=156845&r2=156846&view=diff
==============================================================================
--- cfe/trunk/bindings/python/clang/cindex.py (original)
+++ cfe/trunk/bindings/python/clang/cindex.py Tue May 15 14:51:02 2012
@@ -929,7 +929,12 @@
@staticmethod
def from_location(tu, location):
- return Cursor_get(tu, location)
+ # We store a reference to the TU in the instance so the TU won't get
+ # collected before the cursor.
+ cursor = Cursor_get(tu, location)
+ cursor._tu = tu
+
+ return cursor
def __eq__(self, other):
return Cursor_eq(self, other)
@@ -1127,6 +1132,13 @@
return self._lexical_parent
+ @property
+ def translation_unit(self):
+ """Returns the TranslationUnit to which this Cursor belongs."""
+ # If this triggers an AttributeError, the instance was not properly
+ # created.
+ return self._tu
+
def get_children(self):
"""Return an iterator for accessing the children of this cursor."""
@@ -1135,6 +1147,9 @@
# FIXME: Document this assertion in API.
# FIXME: There should just be an isNull method.
assert child != Cursor_null()
+
+ # Create reference to TU so it isn't GC'd before Cursor.
+ child._tu = self._tu
children.append(child)
return 1 # continue
children = []
@@ -1147,6 +1162,22 @@
# FIXME: There should just be an isNull method.
if res == Cursor_null():
return None
+
+ # Store a reference to the TU in the Python object so it won't get GC'd
+ # before the Cursor.
+ tu = None
+ for arg in args:
+ if isinstance(arg, TranslationUnit):
+ tu = arg
+ break
+
+ if hasattr(arg, 'translation_unit'):
+ tu = arg.translation_unit
+ break
+
+ assert tu is not None
+
+ res._tu = tu
return res
@@ -1324,9 +1355,26 @@
return result
+ @property
+ def translation_unit(self):
+ """The TranslationUnit to which this Type is associated."""
+ # If this triggers an AttributeError, the instance was not properly
+ # instantiated.
+ return self._tu
+
@staticmethod
def from_result(res, fn, args):
assert isinstance(res, Type)
+
+ tu = None
+ for arg in args:
+ if hasattr(arg, 'translation_unit'):
+ tu = arg.translation_unit
+ break
+
+ assert tu is not None
+ res._tu = tu
+
return res
def get_canonical(self):
Modified: cfe/trunk/bindings/python/tests/cindex/test_cursor.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/tests/cindex/test_cursor.py?rev=156846&r1=156845&r2=156846&view=diff
==============================================================================
--- cfe/trunk/bindings/python/tests/cindex/test_cursor.py (original)
+++ cfe/trunk/bindings/python/tests/cindex/test_cursor.py Tue May 15 14:51:02 2012
@@ -1,4 +1,7 @@
+import gc
+
from clang.cindex import CursorKind
+from clang.cindex import TranslationUnit
from clang.cindex import TypeKind
from .util import get_cursor
from .util import get_cursors
@@ -38,6 +41,8 @@
tu_nodes = list(it)
assert len(tu_nodes) == 3
+ for cursor in tu_nodes:
+ assert cursor.translation_unit is not None
assert tu_nodes[0] != tu_nodes[1]
assert tu_nodes[0].kind == CursorKind.STRUCT_DECL
@@ -47,6 +52,7 @@
assert tu_nodes[0].location.line == 4
assert tu_nodes[0].location.column == 8
assert tu_nodes[0].hash > 0
+ assert tu_nodes[0].translation_unit is not None
s0_nodes = list(tu_nodes[0].get_children())
assert len(s0_nodes) == 2
@@ -67,6 +73,23 @@
assert tu_nodes[2].displayname == 'f0(int, int)'
assert tu_nodes[2].is_definition() == True
+def test_references():
+ """Ensure that references to TranslationUnit are kept."""
+ tu = get_tu('int x;')
+ cursors = list(tu.cursor.get_children())
+ assert len(cursors) > 0
+
+ cursor = cursors[0]
+ assert isinstance(cursor.translation_unit, TranslationUnit)
+
+ # Delete reference to TU and perform a full GC.
+ del tu
+ gc.collect()
+ assert isinstance(cursor.translation_unit, TranslationUnit)
+
+ # If the TU was destroyed, this should cause a segfault.
+ parent = cursor.semantic_parent
+
def test_canonical():
source = 'struct X; struct X; struct X { int member; };'
tu = get_tu(source)
Modified: cfe/trunk/bindings/python/tests/cindex/test_type.py
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/bindings/python/tests/cindex/test_type.py?rev=156846&r1=156845&r2=156846&view=diff
==============================================================================
--- cfe/trunk/bindings/python/tests/cindex/test_type.py (original)
+++ cfe/trunk/bindings/python/tests/cindex/test_type.py Tue May 15 14:51:02 2012
@@ -1,4 +1,7 @@
+import gc
+
from clang.cindex import CursorKind
+from clang.cindex import TranslationUnit
from clang.cindex import TypeKind
from nose.tools import raises
from .util import get_cursor
@@ -28,6 +31,7 @@
assert teststruct is not None, "Could not find teststruct."
fields = list(teststruct.get_children())
assert all(x.kind == CursorKind.FIELD_DECL for x in fields)
+ assert all(x.translation_unit is not None for x in fields)
assert fields[0].spelling == 'a'
assert not fields[0].type.is_const_qualified()
@@ -72,6 +76,26 @@
assert fields[7].type.get_pointee().get_pointee().kind == TypeKind.POINTER
assert fields[7].type.get_pointee().get_pointee().get_pointee().kind == TypeKind.INT
+def test_references():
+ """Ensure that a Type maintains a reference to a TranslationUnit."""
+
+ tu = get_tu('int x;')
+ children = list(tu.cursor.get_children())
+ assert len(children) > 0
+
+ cursor = children[0]
+ t = cursor.type
+
+ assert isinstance(t.translation_unit, TranslationUnit)
+
+ # Delete main TranslationUnit reference and force a GC.
+ del tu
+ gc.collect()
+ assert isinstance(t.translation_unit, TranslationUnit)
+
+ # If the TU was destroyed, this should cause a segfault.
+ decl = t.get_declaration()
+
constarrayInput="""
struct teststruct {
void *A[2];
More information about the cfe-commits
mailing list