Clang: Free us from specific Qt versions

More precisely, free us from specific Q_MOC_RUN/QT_NO_META_MACROS code
paths in QtCore/qobjectdefs.h.

In order to track signals and slots we provided custom definitions of
e.g. "Q_SIGNAL" by including qt5-qobjectdefs-injected.h with "-include".
We also had to ensure that those macros were not overwritten by Qt's
qobjectdefs.h, which we did by defining QT_NO_META_MACROS. However, this
came with a cost: we needed to replicate all the other macro definitions
in the Q_MOC_RUN/QT_NO_META_MACROS code path, e.g. Q_INTERFACES. This
bound us to specific versions of qobjectdefs.h and occasionally we had
to adapt (see change 4eafa2e02b).

The new approach wraps Qt's qobjectdefs.h with the help of
"include_next". In the wrapper header, we only redefine what is
necessary.

The "include_next" directive is originally a GNU extension. Clang seems
to support it unconditionally, as [1] implicitly states.

[1] http://clang.llvm.org/docs/LanguageExtensions.html#include-file-checking-macros

Change-Id: Ic1a263f94b178349cb32bfdbb074ad5e6e0761ee
Reviewed-by: Christian Kandeler <christian.kandeler@theqtcompany.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
This commit is contained in:
Nikolai Kosjar
2015-07-27 10:47:08 +02:00
parent 9be93b6962
commit 4f7649633c
2 changed files with 33 additions and 47 deletions

View File

@@ -28,44 +28,35 @@
** **
****************************************************************************/ ****************************************************************************/
#define QT_NO_META_MACROS // Include qobjectdefs.h from Qt ...
#include_next <qobjectdefs.h>
#if defined(QT_NO_KEYWORDS) #pragma clang diagnostic push
# define QT_NO_EMIT #pragma clang diagnostic ignored "-Wmacro-redefined"
#else
# ifndef QT_NO_SIGNALS_SLOTS_KEYWORDS // ...and redefine macros for tagging signals/slots
# define signals public __attribute__((annotate("qt_signal"))) #ifdef signals
# define slots __attribute__((annotate("qt_slot"))) # define signals public __attribute__((annotate("qt_signal")))
# endif
#endif #endif
#define Q_SIGNALS public __attribute__((annotate("qt_signal")))
#define Q_SLOTS slots __attribute__((annotate("qt_slot")))
#define Q_SIGNAL __attribute__((annotate("qt_signal")))
#define Q_SLOT __attribute__((annotate("qt_slot")))
#define Q_PRIVATE_SLOT(d, signature)
#define Q_EMIT #ifdef slots
#ifndef QT_NO_EMIT # define slots __attribute__((annotate("qt_slot")))
# define emit
#endif #endif
#define Q_CLASSINFO(name, value)
#define Q_PLUGIN_METADATA(x)
#define Q_INTERFACES(x)
#define Q_PROPERTY(text)
#define Q_PRIVATE_PROPERTY(d, text)
#define Q_REVISION(v)
#define Q_OVERRIDE(text)
#define Q_ENUMS(x)
#define Q_FLAGS(x)
#define Q_ENUM(x)
#define Q_FLAG(x)
#define Q_SCRIPTABLE
#define Q_INVOKABLE
#define Q_GADGET \ #ifdef Q_SIGNALS
public: \ # define Q_SIGNALS public __attribute__((annotate("qt_signal")))
static const QMetaObject staticMetaObject; \ #endif
private:
#define SIGNAL(a) #a #ifdef Q_SLOTS
#define SLOT(a) #a # define Q_SLOTS slots __attribute__((annotate("qt_slot")))
#endif
#ifdef Q_SIGNAL
# define Q_SIGNAL __attribute__((annotate("qt_signal")))
#endif
#ifdef Q_SLOT
# define Q_SLOT __attribute__((annotate("qt_slot")))
#endif
#pragma clang diagnostic pop

View File

@@ -130,8 +130,8 @@ public:
optionsBuilder.addToolchainAndProjectDefines(); optionsBuilder.addToolchainAndProjectDefines();
optionsBuilder.addResourceDirOptions(); optionsBuilder.addResourceDirOptions();
optionsBuilder.addWrappedQtHeadersIncludePath();
optionsBuilder.addHeaderPathOptions(); optionsBuilder.addHeaderPathOptions();
optionsBuilder.addInjectedHeaderWithCustomQtMacros();
optionsBuilder.addProjectConfigFileInclude(); optionsBuilder.addProjectConfigFileInclude();
optionsBuilder.addExtraOptions(); optionsBuilder.addExtraOptions();
@@ -160,19 +160,14 @@ private:
} }
} }
void addInjectedHeaderWithCustomQtMacros() void addWrappedQtHeadersIncludePath()
{ {
static const QString injectedHeader = ICore::instance()->resourcePath() static const QString wrappedQtHeaders = ICore::instance()->resourcePath()
+ QLatin1String("/cplusplus/qt%1-qobjectdefs-injected.h"); + QLatin1String("/cplusplus/wrappedQtHeaders");
// if (pPart->qtVersion == ProjectPart::Qt4) { if (m_projectPart->qtVersion != ProjectPart::NoQt) {
// builder.addOption(QLatin1String("-include")); add(QLatin1String("-I") + wrappedQtHeaders);
// builder.addOption(injectedHeader.arg(QLatin1Char('4'))); add(QLatin1String("-I") + wrappedQtHeaders + QLatin1String("/QtCore"));
// }
if (m_projectPart->qtVersion == ProjectPart::Qt5) {
add(QLatin1String("-include"));
add(injectedHeader.arg(QLatin1Char('5')));
} }
} }