summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h')
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h57
1 files changed, 46 insertions, 11 deletions
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index 0cdb63f17c9..634d6e89601 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -151,6 +151,30 @@ template <typename T> T Retain(PyObject *obj) {
return std::move(thing);
}
+// This class can be used like a utility function to convert from
+// a llvm-friendly Twine into a null-terminated const char *,
+// which is the form python C APIs want their strings in.
+//
+// Example:
+// const llvm::Twine &some_twine;
+// PyFoo_Bar(x, y, z, NullTerminated(some_twine));
+//
+// Why a class instead of a function? If the twine isn't already null
+// terminated, it will need a temporary buffer to copy the string
+// into. We need that buffer to stick around for the lifetime of the
+// statement.
+class NullTerminated {
+ const char *str;
+ llvm::SmallString<32> storage;
+
+public:
+ NullTerminated(const llvm::Twine &twine) {
+ llvm::StringRef ref = twine.toNullTerminatedStringRef(storage);
+ str = ref.begin();
+ }
+ operator const char *() { return str; }
+};
+
} // namespace python
enum class PyInitialValue { Invalid, Empty };
@@ -323,10 +347,11 @@ public:
return python::Take<PythonObject>(obj);
}
- llvm::Expected<PythonObject> GetAttribute(const char *name) const {
+ llvm::Expected<PythonObject> GetAttribute(const llvm::Twine &name) const {
+ using namespace python;
if (!m_py_obj)
return nullDeref();
- PyObject *obj = PyObject_GetAttrString(m_py_obj, name);
+ PyObject *obj = PyObject_GetAttrString(m_py_obj, NullTerminated(name));
if (!obj)
return exception();
return python::Take<PythonObject>(obj);
@@ -392,10 +417,11 @@ public:
// This can be eliminated once we drop python 2 support.
static void Convert(PyRefType &type, PyObject *&py_obj) {}
- using PythonObject::Reset;
+ void Reset() { PythonObject::Reset(); }
- void Reset(PyRefType type, PyObject *py_obj) {
- Reset();
+ void Reset(PyRefType type, PyObject *py_obj) = delete;
+
+ TypedPythonObject(PyRefType type, PyObject *py_obj) {
if (!py_obj)
return;
T::Convert(type, py_obj);
@@ -405,8 +431,6 @@ public:
Py_DECREF(py_obj);
}
- TypedPythonObject(PyRefType type, PyObject *py_obj) { Reset(type, py_obj); }
-
TypedPythonObject() {}
};
@@ -562,9 +586,9 @@ public:
const PythonObject &value); // DEPRECATED
llvm::Expected<PythonObject> GetItem(const PythonObject &key) const;
- llvm::Expected<PythonObject> GetItem(const char *key) const;
+ llvm::Expected<PythonObject> GetItem(const llvm::Twine &key) const;
llvm::Error SetItem(const PythonObject &key, const PythonObject &value) const;
- llvm::Error SetItem(const char *key, const PythonObject &value) const;
+ llvm::Error SetItem(const llvm::Twine &key, const PythonObject &value) const;
StructuredData::DictionarySP CreateStructuredDictionary() const;
};
@@ -592,9 +616,9 @@ public:
return std::move(mod.get());
}
- static llvm::Expected<PythonModule> Import(const char *name);
+ static llvm::Expected<PythonModule> Import(const llvm::Twine &name);
- llvm::Expected<PythonObject> Get(const char *name);
+ llvm::Expected<PythonObject> Get(const llvm::Twine &name);
PythonDictionary GetDictionary() const;
};
@@ -708,6 +732,17 @@ template <typename T> T unwrapOrSetPythonException(llvm::Expected<T> expected) {
return T();
}
+namespace python {
+// This is only here to help incrementally migrate old, exception-unsafe
+// code.
+template <typename T> T unwrapIgnoringErrors(llvm::Expected<T> expected) {
+ if (expected)
+ return std::move(expected.get());
+ llvm::consumeError(expected.takeError());
+ return T();
+}
+} // namespace python
+
} // namespace lldb_private
#endif
OpenPOWER on IntegriCloud