summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-08-05 10:21:21 +0200
committerLars Knoll <lars.knoll@qt.io>2020-08-07 13:35:45 +0200
commit096e268764397f781e72619e3b5f546d5786cae1 (patch)
treebdd0db7dc4e682125792a78b781b1f3064051a37 /src/corelib
parent3f64d770037a0e3adc9685eb0a1d326515f87b42 (diff)
Avoid UB in moc generated code
Introduce a Q_OFFSETOF() macro that uses the optional support of offsetof() for non standard layout types and disables the corresponding compiler warnings. All our supported compilers support offsetof() on non standard layout types. Use the macro to do the offset calculations required in moc generated code to replace a manual offset calculation that was dereferencing a null pointer. Change-Id: I4aab3af3c8bbaa90372f2234aa1cf8399d023c22 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/global/qcompilerdetection.h5
-rw-r--r--src/corelib/global/qglobal.h11
2 files changed, 16 insertions, 0 deletions
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index b02f1b0a1b..df68d5acf7 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -1254,6 +1254,7 @@
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786)
# define QT_WARNING_DISABLE_FLOAT_COMPARE QT_WARNING_DISABLE_INTEL(1572)
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF
#elif defined(Q_CC_INTEL)
/* icc: Intel compiler on Linux or OS X */
# define QT_WARNING_PUSH QT_DO_PRAGMA(warning(push))
@@ -1264,6 +1265,7 @@
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786)
# define QT_WARNING_DISABLE_FLOAT_COMPARE QT_WARNING_DISABLE_INTEL(1572)
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF
#elif defined(Q_CC_MSVC) && !defined(Q_CC_CLANG)
# undef QT_DO_PRAGMA /* not needed */
# define QT_WARNING_PUSH __pragma(warning(push))
@@ -1274,6 +1276,7 @@
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_MSVC(4996)
# define QT_WARNING_DISABLE_FLOAT_COMPARE
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF
#elif defined(Q_CC_CLANG)
# define QT_WARNING_PUSH QT_DO_PRAGMA(clang diagnostic push)
# define QT_WARNING_POP QT_DO_PRAGMA(clang diagnostic pop)
@@ -1283,6 +1286,7 @@
# define QT_WARNING_DISABLE_MSVC(number)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations")
# define QT_WARNING_DISABLE_FLOAT_COMPARE QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF QT_WARNING_DISABLE_CLANG("-Winvalid-offsetof")
#elif defined(Q_CC_GNU) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)
# define QT_WARNING_PUSH QT_DO_PRAGMA(GCC diagnostic push)
# define QT_WARNING_POP QT_DO_PRAGMA(GCC diagnostic pop)
@@ -1292,6 +1296,7 @@
# define QT_WARNING_DISABLE_MSVC(number)
# define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
# define QT_WARNING_DISABLE_FLOAT_COMPARE QT_WARNING_DISABLE_GCC("-Wfloat-equal")
+# define QT_WARNING_DISABLE_INVALID_OFFSETOF QT_WARNING_DISABLE_GCC("-Winvalid-offsetof")
#else // All other compilers, GCC < 4.6 and MSVC < 2008
# define QT_WARNING_DISABLE_GCC(text)
# define QT_WARNING_PUSH
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 539e3e7cda..94de9fd79e 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1316,6 +1316,17 @@ template <typename T> struct QEnableIf<true, T> { typedef T Type; };
#define QT_DEFINE_PLATFORM_INTERFACE(...) QT_OVERLOADED_MACRO(QT_DEFINE_PLATFORM_INTERFACE, QPlatformInterface, __VA_ARGS__)
#define QT_DEFINE_PRIVATE_PLATFORM_INTERFACE(...) QT_OVERLOADED_MACRO(QT_DEFINE_PLATFORM_INTERFACE, QPlatformInterface::Private, __VA_ARGS__)
+// This macro can be used to calculate member offsets for types with a non standard layout.
+// It uses the fact that offsetof() is allowed to support those types since C++17 as an optional
+// feature. All our compilers do support this, but some issue a warning, so we wrap the offsetof()
+// call in a macro that disables the compiler warning.
+#define Q_OFFSETOF(Class, member) \
+ []() -> size_t { \
+ QT_WARNING_PUSH QT_WARNING_DISABLE_INVALID_OFFSETOF \
+ return offsetof(Class, member); \
+ QT_WARNING_POP \
+ }()
+
QT_END_NAMESPACE
// We need to keep QTypeInfo, QSysInfo, QFlags, qDebug & family in qglobal.h for compatibility with Qt 4.