qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 2/3] qobject: assume base of a qobject is at offset


From: Marc-André Lureau
Subject: [Qemu-devel] [PATCH 2/3] qobject: assume base of a qobject is at offset 0
Date: Wed, 21 Mar 2018 14:40:04 +0100

Simplify casting to QObject by not requiring the definition of the
type and assuming base QObject is at offset 0. Add a static check for
this.

Use the QEMU_GENERIC macro for keeping type safety check and error
when given an unknown type.

Signed-off-by: Marc-André Lureau <address@hidden>
---
 include/qapi/qmp/qobject.h | 36 ++++++++++++++++++++++++++++++++++--
 qobject/qobject.c          |  9 +++++++++
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/include/qapi/qmp/qobject.h b/include/qapi/qmp/qobject.h
index e022707578..d0aead35ec 100644
--- a/include/qapi/qmp/qobject.h
+++ b/include/qapi/qmp/qobject.h
@@ -39,8 +39,40 @@ struct QObject {
     size_t refcnt;
 };
 
-/* Get the 'base' part of an object */
-#define QOBJECT(obj) (&(obj)->base)
+/* This function gives an error if an invalid pointer type is passed
+ * to QOBJECT.  For optimized builds, we can rely on dead-code
+ * elimination from the compiler, and give the errors already at link
+ * time.
+ */
+#if defined(__OPTIMIZE__) && !defined(__SANITIZE_ADDRESS__)
+const void * qobject_unknown_type(const void *);
+#else
+static inline const void *
+qobject_unknown_type(const void *unused)
+{
+    abort();
+    return NULL;
+}
+#endif
+
+/* A typecast, checking for the type of arguments */
+/* QObject is at offset 0, for all QObject-derived types */
+#define QOBJECT(x) QEMU_GENERIC(x,              \
+    (QNull *, (QObject *) x),                   \
+    (const QNull *, (const QObject *) x),       \
+    (QNum *, (QObject *) x),                    \
+    (const QNum *, (const QObject *) x),        \
+    (QString *, (QObject *) x),                 \
+    (const QString *, (const QObject *) x),     \
+    (QDict *, (QObject *) x),                   \
+    (const QDict *, (const QObject *) x),       \
+    (QList *, (QObject *) x),                   \
+    (const QList *, (const QObject *) x),       \
+    (QBool *, (QObject *) x),                   \
+    (const QBool *, (const QObject *) x),       \
+    (QObject *, x),                             \
+    (const QObject *, x),                       \
+    qobject_unknown_type(x))
 
 /* High-level interface for qobject_incref() */
 #define QINCREF(obj)      \
diff --git a/qobject/qobject.c b/qobject/qobject.c
index 23600aa1c1..87649c5be5 100644
--- a/qobject/qobject.c
+++ b/qobject/qobject.c
@@ -16,6 +16,15 @@
 #include "qapi/qmp/qlist.h"
 #include "qapi/qmp/qstring.h"
 
+QEMU_BUILD_BUG_MSG(
+    offsetof(QNull, base) != 0 ||
+    offsetof(QNum, base) != 0 ||
+    offsetof(QString, base) != 0 ||
+    offsetof(QDict, base) != 0 ||
+    offsetof(QList, base) != 0 ||
+    offsetof(QBool, base) != 0,
+    "base qobject must be at offset 0");
+
 static void (*qdestroy[QTYPE__MAX])(QObject *) = {
     [QTYPE_NONE] = NULL,               /* No such object exists */
     [QTYPE_QNULL] = NULL,              /* qnull_ is indestructible */
-- 
2.16.2.521.g9aa15f885a




reply via email to

[Prev in Thread] Current Thread [Next in Thread]