[clang.py] Store reference to TranslationUnit in Cursor and Type

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156846 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/bindings/python/clang/cindex.py b/bindings/python/clang/cindex.py
index 54a3bfd..c599faa 100644
--- a/bindings/python/clang/cindex.py
+++ b/bindings/python/clang/cindex.py
@@ -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):