[vlc-commits] [Git][videolan/vlc][3.0.x] contrib: qt: Backport patches for moc from Qt 5.7 and 5.8

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sat May 16 14:39:07 UTC 2026



Felix Paul Kühne pushed to branch 3.0.x at VideoLAN / VLC


Commits:
d312dcf7 by Martin Storsjö at 2026-05-15T15:35:29+03:00
contrib: qt: Backport patches for moc from Qt 5.7 and 5.8

This fixes building Qt with libc++ version 22. This version of
libc++ seems to use some cases of "namespace Foo::Bar {" (instead
of two nested "namespace Foo {" and "namespace Bar {".

While this seems like a trivial construct to avoid on the libc++
side, it's not incorrect C++ as far as I know, and avoiding
specific patterns of correct C++ in libc++ to avoid issues in
a 10 year old version of Qt is probably not worthwhile.

The old version of moc errored out on this construct, and these
patches seem to make it process the headers without error.
None of the patches specifically seem to mention dealing with this,
but this backports enough of newer changes into moc to make it
parse these headers correctly.

- - - - -


5 changed files:

- + contrib/src/qt/0020-Moc-use-const-and-const-APIs-more.patch
- + contrib/src/qt/0021-Moc-use-QStringBuilder-more.patch
- + contrib/src/qt/0022-Don-t-error-out-on-preprocessor-concatenation-of-two.patch
- + contrib/src/qt/0023-moc-get-the-system-defines-from-the-compiler-itself.patch
- contrib/src/qt/rules.mak


Changes:

=====================================
contrib/src/qt/0020-Moc-use-const-and-const-APIs-more.patch
=====================================
@@ -0,0 +1,234 @@
+From 5478583eeac83bd67cb0bc93258f9c1c1fb5b673 Mon Sep 17 00:00:00 2001
+From: Anton Kudryavtsev <a.kudryavtsev at netris.ru>
+Date: Thu, 14 Apr 2016 09:23:41 +0300
+Subject: [PATCH 20/23] Moc: use const (and const APIs) more
+
+For CoW types, prefer const methods to avoid needless detach()ing.
+
+Change-Id: Iefc33552d826aa30320e52acd2d421c9bdae127e
+Reviewed-by: Edward Welbourne <edward.welbourne at theqtcompany.com>
+Reviewed-by: Marc Mutz <marc.mutz at kdab.com>
+Backport-Of: 777d46b40360c302a49fc5b789cee6d0d05f840a (v5.7.0)
+---
+ src/tools/moc/generator.cpp    |  2 +-
+ src/tools/moc/main.cpp         |  2 +-
+ src/tools/moc/moc.cpp          | 28 ++++++++++++++--------------
+ src/tools/moc/preprocessor.cpp | 18 +++++++++---------
+ 4 files changed, 25 insertions(+), 25 deletions(-)
+
+diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
+index 8cbeb4ce788..dcb7de00bcf 100644
+--- a/src/tools/moc/generator.cpp
++++ b/src/tools/moc/generator.cpp
+@@ -84,7 +84,7 @@ Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, con
+     , knownGadgets(knownGadgets)
+ {
+     if (cdef->superclassList.size())
+-        purestSuperClass = cdef->superclassList.first().first;
++        purestSuperClass = cdef->superclassList.constFirst().first;
+ }
+ 
+ static inline int lengthOfEscapeSequence(const QByteArray &s, int i)
+diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
+index 18fbc977abf..9292a6cf748 100644
+--- a/src/tools/moc/main.cpp
++++ b/src/tools/moc/main.cpp
+@@ -359,7 +359,7 @@ int runMoc(int argc, char **argv)
+         int spos = filename.lastIndexOf(QDir::separator());
+         int ppos = filename.lastIndexOf(QLatin1Char('.'));
+         // spos >= -1 && ppos > spos => ppos >= 0
+-        moc.noInclude = (ppos > spos && filename[ppos + 1].toLower() != QLatin1Char('h'));
++        moc.noInclude = (ppos > spos && filename.at(ppos + 1).toLower() != QLatin1Char('h'));
+     }
+     if (defaultInclude) {
+         if (moc.includePath.isEmpty()) {
+diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
+index 5534cdd6b85..f7a2a07df70 100644
+--- a/src/tools/moc/moc.cpp
++++ b/src/tools/moc/moc.cpp
+@@ -142,7 +142,7 @@ bool Moc::parseClassHead(ClassDef *def)
+         } while (test(COMMA));
+ 
+         if (!def->superclassList.isEmpty()
+-            && knownGadgets.contains(def->superclassList.first().first)) {
++            && knownGadgets.contains(def->superclassList.constFirst().first)) {
+             // Q_GADGET subclasses are treated as Q_GADGETs
+             knownGadgets.insert(def->classname, def->qualified);
+             knownGadgets.insert(def->qualified, def->qualified);
+@@ -322,7 +322,7 @@ void Moc::parseFunctionArguments(FunctionDef *def)
+     }
+ 
+     if (!def->arguments.isEmpty()
+-        && def->arguments.last().normalizedType == "QPrivateSignal") {
++        && def->arguments.constLast().normalizedType == "QPrivateSignal") {
+         def->arguments.removeLast();
+         def->isPrivateSignal = true;
+     }
+@@ -740,7 +740,7 @@ void Moc::parse()
+                         if (funcDef.isConstructor) {
+                             if ((access == FunctionDef::Public) && funcDef.isInvokable) {
+                                 def.constructorList += funcDef;
+-                                while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
++                                while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
+                                     funcDef.wasCloned = true;
+                                     funcDef.arguments.removeLast();
+                                     def.constructorList += funcDef;
+@@ -753,7 +753,7 @@ void Moc::parse()
+                                 def.publicList += funcDef;
+                             if (funcDef.isSlot) {
+                                 def.slotList += funcDef;
+-                                while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
++                                while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
+                                     funcDef.wasCloned = true;
+                                     funcDef.arguments.removeLast();
+                                     def.slotList += funcDef;
+@@ -762,7 +762,7 @@ void Moc::parse()
+                                     ++def.revisionedMethods;
+                             } else if (funcDef.isSignal) {
+                                 def.signalList += funcDef;
+-                                while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
++                                while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
+                                     funcDef.wasCloned = true;
+                                     funcDef.arguments.removeLast();
+                                     def.signalList += funcDef;
+@@ -771,7 +771,7 @@ void Moc::parse()
+                                     ++def.revisionedMethods;
+                             } else if (funcDef.isInvokable) {
+                                 def.methodList += funcDef;
+-                                while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
++                                while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
+                                     funcDef.wasCloned = true;
+                                     funcDef.arguments.removeLast();
+                                     def.methodList += funcDef;
+@@ -847,7 +847,7 @@ void Moc::generate(FILE *out)
+ {
+     QByteArray fn = filename;
+     int i = filename.length()-1;
+-    while (i>0 && filename[i-1] != '/' && filename[i-1] != '\\')
++    while (i > 0 && filename.at(i - 1) != '/' && filename.at(i - 1) != '\\')
+         --i;                                // skip path
+     if (i >= 0)
+         fn = filename.mid(i);
+@@ -863,7 +863,7 @@ void Moc::generate(FILE *out)
+             includePath += '/';
+         for (int i = 0; i < includeFiles.size(); ++i) {
+             QByteArray inc = includeFiles.at(i);
+-            if (inc[0] != '<' && inc[0] != '"') {
++            if (inc.at(0) != '<' && inc.at(0) != '"') {
+                 if (includePath.size() && includePath != "./")
+                     inc.prepend(includePath);
+                 inc = '\"' + inc + '\"';
+@@ -871,7 +871,7 @@ void Moc::generate(FILE *out)
+             fprintf(out, "#include %s\n", inc.constData());
+         }
+     }
+-    if (classList.size() && classList.first().classname == "Qt")
++    if (classList.size() && classList.constFirst().classname == "Qt")
+         fprintf(out, "#include <QtCore/qobject.h>\n");
+ 
+     fprintf(out, "#include <QtCore/qbytearray.h>\n"); // For QByteArrayData
+@@ -959,7 +959,7 @@ void Moc::parseSlots(ClassDef *def, FunctionDef::Access access)
+             ++def->revisionedMethods;
+         }
+         def->slotList += funcDef;
+-        while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
++        while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
+             funcDef.wasCloned = true;
+             funcDef.arguments.removeLast();
+             def->slotList += funcDef;
+@@ -1015,7 +1015,7 @@ void Moc::parseSignals(ClassDef *def)
+             ++def->revisionedMethods;
+         }
+         def->signalList += funcDef;
+-        while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
++        while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
+             funcDef.wasCloned = true;
+             funcDef.arguments.removeLast();
+             def->signalList += funcDef;
+@@ -1053,7 +1053,7 @@ void Moc::createPropertyDef(PropertyDef &propDef)
+     next();
+     propDef.name = lexem();
+     while (test(IDENTIFIER)) {
+-        QByteArray l = lexem();
++        const QByteArray l = lexem();
+         if (l[0] == 'C' && l == "CONSTANT") {
+             propDef.constant = true;
+             continue;
+@@ -1389,7 +1389,7 @@ void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access)
+     funcDef.access = access;
+     parseFunction(&funcDef, true);
+     def->slotList += funcDef;
+-    while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) {
++    while (funcDef.arguments.size() > 0 && funcDef.arguments.constLast().isDefault) {
+         funcDef.wasCloned = true;
+         funcDef.arguments.removeLast();
+         def->slotList += funcDef;
+@@ -1533,7 +1533,7 @@ void Moc::checkSuperClasses(ClassDef *def)
+         if (interface2IdMap.contains(superClass)) {
+             bool registeredInterface = false;
+             for (int i = 0; i < def->interfaceList.count(); ++i)
+-                if (def->interfaceList.at(i).first().className == superClass) {
++                if (def->interfaceList.at(i).constFirst().className == superClass) {
+                     registeredInterface = true;
+                     break;
+                 }
+diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
+index 2b04b678fa4..9388992de2d 100644
+--- a/src/tools/moc/preprocessor.cpp
++++ b/src/tools/moc/preprocessor.cpp
+@@ -208,13 +208,13 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
+                     // STRING_LITERAL handling in moc
+                     if (!Preprocessor::preprocessOnly
+                         && !symbols.isEmpty()
+-                        && symbols.last().token == STRING_LITERAL) {
++                        && symbols.constLast().token == STRING_LITERAL) {
+ 
+-                        QByteArray newString = symbols.last().unquotedLexem();
++                        QByteArray newString = symbols.constLast().unquotedLexem();
+                         newString += input.mid(lexem - begin + 1, data - lexem - 2);
+                         newString.prepend('\"');
+                         newString.append('\"');
+-                        symbols.last() = Symbol(symbols.last().lineNum,
++                        symbols.last() = Symbol(symbols.constLast().lineNum,
+                                                 STRING_LITERAL,
+                                                 newString);
+                         continue;
+@@ -682,7 +682,7 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
+                 if (s.token == WHITESPACE)
+                     continue;
+ 
+-                while (expansion.size() && expansion.last().token == PP_WHITESPACE)
++                while (expansion.size() && expansion.constLast().token == PP_WHITESPACE)
+                     expansion.pop_back();
+ 
+                 Symbol next = s;
+@@ -695,8 +695,8 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
+                     next = arg.at(0);
+                 }
+ 
+-                if (!expansion.isEmpty() && expansion.last().token == s.token) {
+-                    Symbol last = expansion.last();
++                if (!expansion.isEmpty() && expansion.constLast().token == s.token) {
++                    Symbol last = expansion.constLast();
+                     expansion.pop_back();
+ 
+                     if (last.token == STRING_LITERAL || s.token == STRING_LITERAL)
+@@ -1130,12 +1130,12 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
+             }
+             // remove trailing whitespace
+             while (!macro.symbols.isEmpty() &&
+-                   (macro.symbols.last().token == PP_WHITESPACE || macro.symbols.last().token == WHITESPACE))
++                   (macro.symbols.constLast().token == PP_WHITESPACE || macro.symbols.constLast().token == WHITESPACE))
+                 macro.symbols.pop_back();
+ 
+             if (!macro.symbols.isEmpty()) {
+-                if (macro.symbols.first().token == PP_HASHHASH ||
+-                    macro.symbols.last().token == PP_HASHHASH) {
++                if (macro.symbols.constFirst().token == PP_HASHHASH ||
++                    macro.symbols.constLast().token == PP_HASHHASH) {
+                     error("'##' cannot appear at either end of a macro expansion");
+                 }
+             }
+-- 
+2.43.0
+


=====================================
contrib/src/qt/0021-Moc-use-QStringBuilder-more.patch
=====================================
@@ -0,0 +1,220 @@
+From 391d64e9c559bfd3a9542931902dc40ee775c8d8 Mon Sep 17 00:00:00 2001
+From: Anton Kudryavtsev <a.kudryavtsev at netris.ru>
+Date: Tue, 19 Apr 2016 10:04:12 +0300
+Subject: [PATCH 21/23] Moc: use QStringBuilder more
+
+Adding strings in a single expression gets mediated
+efficiently by QStringBuilder, where using += repeatedly
+forces premature consolidation.
+
+Change-Id: I6c1abb9c9801a016ce6c151cffdf8c7ac9502f4e
+Reviewed-by: Edward Welbourne <edward.welbourne at theqtcompany.com>
+Reviewed-by: Marc Mutz <marc.mutz at kdab.com>
+Backport-Of: bafe205d6a87c0672e1e6142160a60415c7f4533 (v5.7.0)
+---
+ src/tools/moc/generator.cpp    |  4 +-
+ src/tools/moc/moc.cpp          | 84 +++++++++++++++-------------------
+ src/tools/moc/preprocessor.cpp | 14 +++---
+ 3 files changed, 44 insertions(+), 58 deletions(-)
+
+diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
+index dcb7de00bcf..2055a1be1bb 100644
+--- a/src/tools/moc/generator.cpp
++++ b/src/tools/moc/generator.cpp
+@@ -1461,9 +1461,7 @@ void Generator::generateSignal(FunctionDef *def,int index)
+     const char *constQualifier = "";
+ 
+     if (def->isConst) {
+-        thisPtr = "const_cast< ";
+-        thisPtr += cdef->qualified;
+-        thisPtr += " *>(this)";
++        thisPtr = "const_cast< " + cdef->qualified + " *>(this)";
+         constQualifier = "const";
+     }
+ 
+diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
+index f7a2a07df70..1f7efc3d1fe 100644
+--- a/src/tools/moc/moc.cpp
++++ b/src/tools/moc/moc.cpp
+@@ -463,9 +463,8 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro)
+     }
+ 
+     if (scopedFunctionName) {
+-        QByteArray msg("Function declaration ");
+-        msg += def->name;
+-        msg += " contains extra qualification. Ignoring as signal or slot.";
++        const QByteArray msg = "Function declaration " + def->name
++                + " contains extra qualification. Ignoring as signal or slot.";
+         warning(msg.constData());
+         return false;
+     }
+@@ -536,9 +535,8 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
+     def->isConst = test(CONST);
+     if (scopedFunctionName
+         && (def->isSignal || def->isSlot || def->isInvokable)) {
+-        QByteArray msg("parsemaybe: Function declaration ");
+-        msg += def->name;
+-        msg += " contains extra qualification. Ignoring as signal or slot.";
++        const QByteArray msg = "parsemaybe: Function declaration " + def->name
++                + " contains extra qualification. Ignoring as signal or slot.";
+         warning(msg.constData());
+         return false;
+     }
+@@ -1126,25 +1124,19 @@ void Moc::createPropertyDef(PropertyDef &propDef)
+         }
+     }
+     if (propDef.read.isNull() && propDef.member.isNull()) {
+-        QByteArray msg;
+-        msg += "Property declaration ";
+-        msg += propDef.name;
+-        msg += " has no READ accessor function or associated MEMBER variable. The property will be invalid.";
++        const QByteArray msg = "Property declaration " + propDef.name
++                + " has no READ accessor function or associated MEMBER variable. The property will be invalid.";
+         warning(msg.constData());
+     }
+     if (propDef.constant && !propDef.write.isNull()) {
+-        QByteArray msg;
+-        msg += "Property declaration ";
+-        msg += propDef.name;
+-        msg += " is both WRITEable and CONSTANT. CONSTANT will be ignored.";
++        const QByteArray msg = "Property declaration " + propDef.name
++                + " is both WRITEable and CONSTANT. CONSTANT will be ignored.";
+         propDef.constant = false;
+         warning(msg.constData());
+     }
+     if (propDef.constant && !propDef.notify.isNull()) {
+-        QByteArray msg;
+-        msg += "Property declaration ";
+-        msg += propDef.name;
+-        msg += " is both NOTIFYable and CONSTANT. CONSTANT will be ignored.";
++        const QByteArray msg = "Property declaration " + propDef.name
++                + " is both NOTIFYable and CONSTANT. CONSTANT will be ignored.";
+         propDef.constant = false;
+         warning(msg.constData());
+     }
+@@ -1190,10 +1182,8 @@ void Moc::parsePluginData(ClassDef *def)
+                 }
+             }
+             if (!fi.exists()) {
+-                QByteArray msg;
+-                msg += "Plugin Metadata file ";
+-                msg += lexem();
+-                msg += " does not exist. Declaration will be ignored";
++                const QByteArray msg = "Plugin Metadata file " + lexem()
++                        + " does not exist. Declaration will be ignored";
+                 error(msg.constData());
+                 return;
+             }
+@@ -1206,10 +1196,8 @@ void Moc::parsePluginData(ClassDef *def)
+     if (!metaData.isEmpty()) {
+         def->pluginData.metaData = QJsonDocument::fromJson(metaData);
+         if (!def->pluginData.metaData.isObject()) {
+-            QByteArray msg;
+-            msg += "Plugin Metadata file ";
+-            msg += lexem();
+-            msg += " does not contain a valid JSON object. Declaration will be ignored";
++            const QByteArray msg = "Plugin Metadata file " + lexem()
++                    + " does not contain a valid JSON object. Declaration will be ignored";
+             warning(msg.constData());
+             def->pluginData.iid = QByteArray();
+             return;
+@@ -1506,12 +1494,12 @@ void Moc::checkSuperClasses(ClassDef *def)
+     if (!knownQObjectClasses.contains(firstSuperclass)) {
+         // enable once we /require/ include paths
+ #if 0
+-        QByteArray msg;
+-        msg += "Class ";
+-        msg += def->className;
+-        msg += " contains the Q_OBJECT macro and inherits from ";
+-        msg += def->superclassList.value(0);
+-        msg += " but that is not a known QObject subclass. You may get compilation errors.";
++        const QByteArray msg
++                = "Class "
++                + def->className
++                + " contains the Q_OBJECT macro and inherits from "
++                + def->superclassList.value(0)
++                + " but that is not a known QObject subclass. You may get compilation errors.";
+         warning(msg.constData());
+ #endif
+         return;
+@@ -1519,14 +1507,14 @@ void Moc::checkSuperClasses(ClassDef *def)
+     for (int i = 1; i < def->superclassList.count(); ++i) {
+         const QByteArray superClass = def->superclassList.at(i).first;
+         if (knownQObjectClasses.contains(superClass)) {
+-            QByteArray msg;
+-            msg += "Class ";
+-            msg += def->classname;
+-            msg += " inherits from two QObject subclasses ";
+-            msg += firstSuperclass;
+-            msg += " and ";
+-            msg += superClass;
+-            msg += ". This is not supported!";
++            const QByteArray msg
++                    = "Class "
++                    + def->classname
++                    + " inherits from two QObject subclasses "
++                    + firstSuperclass
++                    + " and "
++                    + superClass
++                    + ". This is not supported!";
+             warning(msg.constData());
+         }
+ 
+@@ -1539,14 +1527,14 @@ void Moc::checkSuperClasses(ClassDef *def)
+                 }
+ 
+             if (!registeredInterface) {
+-                QByteArray msg;
+-                msg += "Class ";
+-                msg += def->classname;
+-                msg += " implements the interface ";
+-                msg += superClass;
+-                msg += " but does not list it in Q_INTERFACES. qobject_cast to ";
+-                msg += superClass;
+-                msg += " will not work!";
++                const QByteArray msg
++                        = "Class "
++                        + def->classname
++                        + " implements the interface "
++                        + superClass
++                        + " but does not list it in Q_INTERFACES. qobject_cast to "
++                        + superClass
++                        + " will not work!";
+                 warning(msg.constData());
+             }
+         }
+diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
+index 9388992de2d..a79eb3706bf 100644
+--- a/src/tools/moc/preprocessor.cpp
++++ b/src/tools/moc/preprocessor.cpp
+@@ -210,10 +210,11 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
+                         && !symbols.isEmpty()
+                         && symbols.constLast().token == STRING_LITERAL) {
+ 
+-                        QByteArray newString = symbols.constLast().unquotedLexem();
+-                        newString += input.mid(lexem - begin + 1, data - lexem - 2);
+-                        newString.prepend('\"');
+-                        newString.append('\"');
++                        const QByteArray newString
++                                = '\"'
++                                + symbols.constLast().unquotedLexem()
++                                + input.mid(lexem - begin + 1, data - lexem - 2)
++                                + '\"';
+                         symbols.last() = Symbol(symbols.constLast().lineNum,
+                                                 STRING_LITERAL,
+                                                 newString);
+@@ -1037,9 +1038,8 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
+                     const int slashPos = include.indexOf('/');
+                     if (slashPos == -1)
+                         continue;
+-                    QByteArray frameworkCandidate = include.left(slashPos);
+-                    frameworkCandidate.append(".framework/Headers/");
+-                    fi.setFile(QString::fromLocal8Bit(QByteArray(p.path + '/' + frameworkCandidate).constData()), QString::fromLocal8Bit(include.mid(slashPos + 1).constData()));
++                    fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"),
++                               QString::fromLocal8Bit(include.mid(slashPos + 1).constData()));
+                 } else {
+                     fi.setFile(QString::fromLocal8Bit(p.path.constData()), QString::fromLocal8Bit(include.constData()));
+                 }
+-- 
+2.43.0
+


=====================================
contrib/src/qt/0022-Don-t-error-out-on-preprocessor-concatenation-of-two.patch
=====================================
@@ -0,0 +1,62 @@
+From 9cd7d7132615002135fc5de0771f28373d41d10f Mon Sep 17 00:00:00 2001
+From: Lars Knoll <lars.knoll at qt.io>
+Date: Tue, 5 Jul 2016 11:06:55 +0200
+Subject: [PATCH 22/23] Don't error out on preprocessor concatenation of two
+ strings
+
+"foo" ## "bar" doesn't make a lot of sense, but MSVC allows them
+(although gcc errors out on them). Simply ignore the ## in this case
+instead of aborting with an error.
+
+Fixes parsing of the Windows winsock2.h header.
+
+Task-number: QTBUG-54560
+Change-Id: I84cd5fbb56a006cf379430708c955cf0da475cff
+Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart at woboq.com>
+Reviewed-by: Edward Welbourne <edward.welbourne at qt.io>
+Backport-Of: c32ef0a725c7ac9d8a9ab053407389ef2fddc64e (v5.8.0)
+---
+ src/tools/moc/preprocessor.cpp   | 7 ++-----
+ tests/auto/tools/moc/tst_moc.cpp | 6 ++++++
+ 2 files changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
+index a79eb3706bf..43f165112fb 100644
+--- a/src/tools/moc/preprocessor.cpp
++++ b/src/tools/moc/preprocessor.cpp
+@@ -696,13 +696,10 @@ Symbols Preprocessor::macroExpandIdentifier(Preprocessor *that, SymbolStack &sym
+                     next = arg.at(0);
+                 }
+ 
+-                if (!expansion.isEmpty() && expansion.constLast().token == s.token) {
+-                    Symbol last = expansion.constLast();
++                Symbol last = expansion.constLast();
++                if (!expansion.isEmpty() && last.token == s.token && last.token != STRING_LITERAL) {
+                     expansion.pop_back();
+ 
+-                    if (last.token == STRING_LITERAL || s.token == STRING_LITERAL)
+-                        that->error("Can't concatenate non identifier tokens");
+-
+                     QByteArray lexem = last.lexem() + next.lexem();
+                     expansion += Symbol(lineNum, last.token, lexem);
+                 } else {
+diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
+index 7f73e8f23d7..d00a86a9e5a 100644
+--- a/tests/auto/tools/moc/tst_moc.cpp
++++ b/tests/auto/tools/moc/tst_moc.cpp
+@@ -75,6 +75,12 @@
+ #include "non-gadget-parent-class.h"
+ #include "grand-parent-gadget-class.h"
+ 
++#ifdef Q_MOC_RUN
++// check that moc can parse these constructs, they are being used in Windows winsock2.h header
++#define STRING_HASH_HASH(x) ("foo" ## x ## "bar")
++const char *string_hash_hash = STRING_HASH_HASH("baz");
++#endif
++
+ Q_DECLARE_METATYPE(const QMetaObject*);
+ 
+ 
+-- 
+2.43.0
+


=====================================
contrib/src/qt/0023-moc-get-the-system-defines-from-the-compiler-itself.patch
=====================================
@@ -0,0 +1,359 @@
+From 89074d0a7e4a038edef8aa0d05609ac33e83d32b Mon Sep 17 00:00:00 2001
+From: Thiago Macieira <thiago.macieira at intel.com>
+Date: Fri, 21 Aug 2015 17:08:19 -0700
+Subject: [PATCH 23/23] moc: get the system #defines from the compiler itself
+
+In order for moc to properly parse #ifdefs and family, we've had
+QMAKE_COMPILER_DEFINES as a list of pre-defined macros from the
+compiler. That list is woefully incomplete.
+
+Instead, let's simply ask the compiler for the list. With GCC and
+family, we use the -dM flag while preprocessing. With ICC on Windows,
+the flag gains an extra "Q" but is otherwise the same. For MSVC, it
+requires using some undocumented switches and parsing environment
+variables (I've tested MSVC 2012, 2013 and 2015).
+
+The new moc option is called --include to be similar to GCC's -include
+option. It does more than just parse a list of pre-defined macros and
+can be used to insert any sort of code that moc needs to parse prior to
+the main file.
+
+Change-Id: I7de033f80b0e4431b7f1ffff13fca02dbb60a0a6
+Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart at woboq.com>
+Backport-Of: 36d524e6a3b64a8c35805c1b868d6d67ccae765c (v5.8.0)
+---
+ mkspecs/features/moc.prf                   | 29 +++++++++--
+ qmake/main.cpp                             | 37 ++++++++++++++
+ src/tools/moc/main.cpp                     | 17 ++++++-
+ src/tools/moc/preprocessor.cpp             | 58 ++++++++++++----------
+ src/tools/moc/preprocessor.h               |  1 +
+ tests/auto/tools/moc/subdir/extradefines.h |  1 +
+ tests/auto/tools/moc/tst_moc.cpp           | 42 ++++++++++++++++
+ 7 files changed, 155 insertions(+), 30 deletions(-)
+ create mode 100644 tests/auto/tools/moc/subdir/extradefines.h
+
+diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf
+index 9cc2bf3b76d..75eafc2a01b 100644
+--- a/mkspecs/features/moc.prf
++++ b/mkspecs/features/moc.prf
+@@ -24,8 +24,23 @@ win32:count(MOC_INCLUDEPATH, 40, >) {
+     write_file($$absolute_path($$WIN_INCLUDETEMP, $$OUT_PWD), WIN_INCLUDETEMP_CONT)|error("Aborting.")
+ }
+ 
++# QNX's compiler sets "gcc" config, but does not support the -dM option;
++# iOS builds are multi-arch, so this feature cannot possibly work.
++if(gcc|intel_icl|msvc):!rim_qcc:!ios {
++    moc_predefs.CONFIG = no_link
++    gcc:            moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -dM -E -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
++    else:intel_icl: moc_predefs.commands = $$QMAKE_CXX $$QMAKE_CXXFLAGS -QdM -P -Fi${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
++    else:msvc {
++        moc_predefs.commands += $$QMAKE_CXX -Bx$$shell_path($$[QT_INSTALL_BINS/get]/qmake) $$QMAKE_CXXFLAGS -E ${QMAKE_FILE_IN} 2>NUL >${QMAKE_FILE_OUT}
++    } else:         error("Oops, I messed up")
++    moc_predefs.output = $$MOC_DIR/moc_predefs.h
++    moc_predefs.input = MOC_PREDEF_FILE
++    silent: moc_predefs.commands = @echo generating $$moc_predefs.output$$escape_expand(\n\t)@$$moc_predefs.commands
++    QMAKE_EXTRA_COMPILERS += moc_predefs
++    MOC_PREDEF_FILE = $$[QT_HOST_DATA/src]/mkspecs/features/data/dummy.cpp
++}
++
+ defineReplace(mocCmdBase) {
+-    RET =
+     !isEmpty(WIN_INCLUDETEMP) {
+         incvar = @$$WIN_INCLUDETEMP
+     } else {
+@@ -34,7 +49,13 @@ defineReplace(mocCmdBase) {
+             incvar += -I$$shell_quote($$inc)
+         incvar += $$QMAKE_FRAMEWORKPATH_FLAGS
+     }
+-    RET += $$QMAKE_MOC $(DEFINES) $$join(QMAKE_COMPILER_DEFINES, " -D", -D) $$incvar $$QMAKE_MOC_OPTIONS
++
++    RET = $$QMAKE_MOC $(DEFINES)
++
++    isEmpty(MOC_PREDEF_FILE): RET += $$join(QMAKE_COMPILER_DEFINES, " -D", -D)
++    else: RET += --include $$moc_predefs.output
++
++    RET += $$incvar $$QMAKE_MOC_OPTIONS
+     return($$RET)
+ }
+ 
+@@ -46,7 +67,7 @@ moc_header.output = $$MOC_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAK
+ moc_header.input = HEADERS
+ moc_header.variable_out = SOURCES
+ moc_header.name = MOC ${QMAKE_FILE_IN}
+-moc_header.depends += $$WIN_INCLUDETEMP
++moc_header.depends += $$WIN_INCLUDETEMP $$moc_predefs.output
+ silent:moc_header.commands = @echo moc ${QMAKE_FILE_IN} && $$moc_header.commands
+ QMAKE_EXTRA_COMPILERS += moc_header
+ INCREDIBUILD_XGE += moc_header
+@@ -58,7 +79,7 @@ moc_source.commands = ${QMAKE_FUNC_mocCmdBase} ${QMAKE_FILE_IN} -o ${QMAKE_FILE_
+ moc_source.output = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC}
+ moc_source.input = SOURCES
+ moc_source.name = MOC ${QMAKE_FILE_IN}
+-moc_source.depends += $$WIN_INCLUDETEMP
++moc_source.depends += $$WIN_INCLUDETEMP $$moc_predefs.output
+ silent:moc_source.commands = @echo moc ${QMAKE_FILE_IN} && $$moc_source.commands
+ QMAKE_EXTRA_COMPILERS += moc_source
+ INCREDIBUILD_XGE += moc_source
+diff --git a/qmake/main.cpp b/qmake/main.cpp
+index 96cb758e262..5ac513a43bc 100644
+--- a/qmake/main.cpp
++++ b/qmake/main.cpp
+@@ -47,6 +47,10 @@
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ 
++#ifdef Q_OS_WIN
++#  include <qt_windows.h>
++#endif
++
+ QT_BEGIN_NAMESPACE
+ 
+ #ifdef Q_OS_WIN
+@@ -246,6 +250,30 @@ static int doInstall(int argc, char **argv)
+     return 3;
+ }
+ 
++static int dumpMacros(const wchar_t *cmdline)
++{
++    // from http://stackoverflow.com/questions/3665537/how-to-find-out-cl-exes-built-in-macros
++    int argc;
++    wchar_t **argv = CommandLineToArgvW(cmdline, &argc);
++    if (!argv)
++        return 2;
++    for (int i = 0; i < argc; ++i) {
++        if (argv[i][0] != L'-' || argv[i][1] != 'D')
++            continue;
++
++        wchar_t *value = wcschr(argv[i], L'=');
++        if (value) {
++            *value = 0;
++            ++value;
++        } else {
++            // point to the NUL at the end, so we don't print anything
++            value = argv[i] + wcslen(argv[i]);
++        }
++        wprintf(L"#define %Ls %Ls\n", argv[i] + 2, value);
++    }
++    return 0;
++}
++
+ #endif // Q_OS_WIN
+ 
+ /* This is to work around lame implementation on Darwin. It has been noted that the getpwd(3) function
+@@ -280,6 +308,15 @@ int runQMake(int argc, char **argv)
+     // Workaround for inferior/missing command line tools on Windows: make our own!
+     if (argc >= 2 && !strcmp(argv[1], "-install"))
+         return doInstall(argc - 2, argv + 2);
++
++    {
++        // Support running as Visual C++'s compiler
++        const wchar_t *cmdline = _wgetenv(L"MSC_CMD_FLAGS");
++        if (!cmdline || !*cmdline)
++            cmdline = _wgetenv(L"MSC_IDE_FLAGS");
++        if (cmdline && *cmdline)
++            return dumpMacros(cmdline);
++    }
+ #endif
+ 
+     QMakeVfs vfs;
+diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
+index 9292a6cf748..1c20fd41df7 100644
+--- a/src/tools/moc/main.cpp
++++ b/src/tools/moc/main.cpp
+@@ -259,6 +259,11 @@ int runMoc(int argc, char **argv)
+     prependIncludeOption.setValueName(QStringLiteral("file"));
+     parser.addOption(prependIncludeOption);
+ 
++    QCommandLineOption includeOption(QStringLiteral("include"));
++    includeOption.setDescription(QStringLiteral("Parse <file> as an #include before the main source(s)."));
++    includeOption.setValueName(QStringLiteral("file"));
++    parser.addOption(includeOption);
++
+     QCommandLineOption noNotesWarningsCompatOption(QStringLiteral("n"));
+     noNotesWarningsCompatOption.setDescription(QStringLiteral("Do not display notes (-nn) or warnings (-nw). Compatibility option."));
+     noNotesWarningsCompatOption.setValueName(QStringLiteral("which"));
+@@ -408,7 +413,17 @@ int runMoc(int argc, char **argv)
+     moc.includes = pp.includes;
+ 
+     // 1. preprocess
+-    moc.symbols = pp.preprocessed(moc.filename, &in);
++    const auto includeFiles = parser.values(includeOption);
++    for (const QString &includeName : includeFiles) {
++        QByteArray rawName = pp.resolveInclude(QFile::encodeName(includeName), moc.filename);
++        QFile f(QFile::decodeName(rawName));
++        if (f.open(QIODevice::ReadOnly)) {
++            moc.symbols += Symbol(0, MOC_INCLUDE_BEGIN, rawName);
++            moc.symbols += pp.preprocessed(rawName, &f);
++            moc.symbols += Symbol(0, MOC_INCLUDE_END, rawName);
++        }
++    }
++    moc.symbols += pp.preprocessed(moc.filename, &in);
+ 
+     if (!pp.preprocessOnly) {
+         // 2. parse
+diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
+index 43f165112fb..43ea6c485bc 100644
+--- a/src/tools/moc/preprocessor.cpp
++++ b/src/tools/moc/preprocessor.cpp
+@@ -1005,6 +1005,36 @@ static void mergeStringLiterals(Symbols *_symbols)
+     }
+ }
+ 
++QByteArray Preprocessor::resolveInclude(const QByteArray &include, const QByteArray &relativeTo)
++{
++    // #### stringery
++    QFileInfo fi;
++    if (!relativeTo.isEmpty())
++        fi.setFile(QFileInfo(QString::fromLocal8Bit(relativeTo.constData())).dir(), QString::fromLocal8Bit(include.constData()));
++    for (int j = 0; j < Preprocessor::includes.size() && !fi.exists(); ++j) {
++        const IncludePath &p = Preprocessor::includes.at(j);
++        if (p.isFrameworkPath) {
++            const int slashPos = include.indexOf('/');
++            if (slashPos == -1)
++                continue;
++            fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"),
++                       QString::fromLocal8Bit(include.mid(slashPos + 1).constData()));
++        } else {
++            fi.setFile(QString::fromLocal8Bit(p.path.constData()), QString::fromLocal8Bit(include.constData()));
++        }
++        // try again, maybe there's a file later in the include paths with the same name
++        // (186067)
++        if (fi.isDir()) {
++            fi = QFileInfo();
++            continue;
++        }
++    }
++
++    if (!fi.exists() || fi.isDir())
++        return QByteArray();
++    return fi.canonicalFilePath().toLocal8Bit();
++}
++
+ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
+ {
+     currentFilenames.push(filename);
+@@ -1025,32 +1055,9 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
+                 continue;
+             until(PP_NEWLINE);
+ 
+-            // #### stringery
+-            QFileInfo fi;
+-            if (local)
+-                fi.setFile(QFileInfo(QString::fromLocal8Bit(filename.constData())).dir(), QString::fromLocal8Bit(include.constData()));
+-            for (int j = 0; j < Preprocessor::includes.size() && !fi.exists(); ++j) {
+-                const IncludePath &p = Preprocessor::includes.at(j);
+-                if (p.isFrameworkPath) {
+-                    const int slashPos = include.indexOf('/');
+-                    if (slashPos == -1)
+-                        continue;
+-                    fi.setFile(QString::fromLocal8Bit(p.path + '/' + include.left(slashPos) + ".framework/Headers/"),
+-                               QString::fromLocal8Bit(include.mid(slashPos + 1).constData()));
+-                } else {
+-                    fi.setFile(QString::fromLocal8Bit(p.path.constData()), QString::fromLocal8Bit(include.constData()));
+-                }
+-                // try again, maybe there's a file later in the include paths with the same name
+-                // (186067)
+-                if (fi.isDir()) {
+-                    fi = QFileInfo();
+-                    continue;
+-                }
+-            }
+-
+-            if (!fi.exists() || fi.isDir())
++            include = resolveInclude(include, local ? filename : QByteArray());
++            if (include.isNull())
+                 continue;
+-            include = fi.canonicalFilePath().toLocal8Bit();
+ 
+             if (Preprocessor::preprocessedIncludes.contains(include))
+                 continue;
+@@ -1205,6 +1212,7 @@ Symbols Preprocessor::preprocessed(const QByteArray &filename, QFile *file)
+     input = cleaned(input);
+ 
+     // phase 2: tokenize for the preprocessor
++    index = 0;
+     symbols = tokenize(input);
+ 
+ #if 0
+diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
+index 9c81f86f9c4..d876caf7297 100644
+--- a/src/tools/moc/preprocessor.h
++++ b/src/tools/moc/preprocessor.h
+@@ -67,6 +67,7 @@ public:
+     QList<QByteArray> frameworks;
+     QSet<QByteArray> preprocessedIncludes;
+     Macros macros;
++    QByteArray resolveInclude(const QByteArray &filename, const QByteArray &relativeTo);
+     Symbols preprocessed(const QByteArray &filename, QFile *device);
+ 
+     void parseDefineArguments(Macro *m);
+diff --git a/tests/auto/tools/moc/subdir/extradefines.h b/tests/auto/tools/moc/subdir/extradefines.h
+new file mode 100644
+index 00000000000..e7888ce80de
+--- /dev/null
++++ b/tests/auto/tools/moc/subdir/extradefines.h
+@@ -0,0 +1 @@
++#define FOO     1
+diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
+index d00a86a9e5a..e2c87e923a4 100644
+--- a/tests/auto/tools/moc/tst_moc.cpp
++++ b/tests/auto/tools/moc/tst_moc.cpp
+@@ -587,6 +587,8 @@ private slots:
+     void frameworkSearchPath();
+     void cstyleEnums();
+     void defineMacroViaCmdline();
++    void defineMacroViaForcedInclude();
++    void defineMacroViaForcedIncludeRelative();
+     void specifyMetaTagsFromCmdline();
+     void invokable();
+     void singleFunctionKeywordSignalAndSlot();
+@@ -1264,6 +1266,46 @@ void tst_Moc::defineMacroViaCmdline()
+ #endif
+ }
+ 
++void tst_Moc::defineMacroViaForcedInclude()
++{
++#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
++    QProcess proc;
++
++    QStringList args;
++    args << "--include" << m_sourceDirectory + QLatin1String("/subdir/extradefines.h");
++    args << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
++
++    proc.start(m_moc, args);
++    QVERIFY(proc.waitForFinished());
++    QCOMPARE(proc.exitCode(), 0);
++    QCOMPARE(proc.readAllStandardError(), QByteArray());
++    QByteArray mocOut = proc.readAllStandardOutput();
++    QVERIFY(!mocOut.isEmpty());
++#else
++    QSKIP("Only tested on linux/gcc");
++#endif
++}
++
++void tst_Moc::defineMacroViaForcedIncludeRelative()
++{
++#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS)
++    QProcess proc;
++
++    QStringList args;
++    args << "--include" << QStringLiteral("extradefines.h") << "-I" + m_sourceDirectory + "/subdir";
++    args << m_sourceDirectory + QStringLiteral("/macro-on-cmdline.h");
++
++    proc.start(m_moc, args);
++    QVERIFY(proc.waitForFinished());
++    QCOMPARE(proc.exitCode(), 0);
++    QCOMPARE(proc.readAllStandardError(), QByteArray());
++    QByteArray mocOut = proc.readAllStandardOutput();
++    QVERIFY(!mocOut.isEmpty());
++#else
++    QSKIP("Only tested on linux/gcc");
++#endif
++}
++
+ // tst_Moc::specifyMetaTagsFromCmdline()
+ // plugin_metadata.h contains a plugin which we register here. Since we're not building this
+ // application as a plugin, we need top copy some of the initializer code found in qplugin.h:
+-- 
+2.43.0
+


=====================================
contrib/src/qt/rules.mak
=====================================
@@ -41,6 +41,10 @@ qt: qt-$(QT_VERSION).tar.xz .sum-qt
 	$(APPLY) $(SRC)/qt/0017-Rename-QtPrivate-is_-un-signed-to-QtPrivate-Is-Un-si.patch
 	$(APPLY) $(SRC)/qt/0018-Remove-qtypetraits.h-s-contents-altogether.patch
 	$(APPLY) $(SRC)/qt/0019-QFileSystemEngine-only-define-FILE_ID_INFO-for-build.patch
+	$(APPLY) $(SRC)/qt/0020-Moc-use-const-and-const-APIs-more.patch
+	$(APPLY) $(SRC)/qt/0021-Moc-use-QStringBuilder-more.patch
+	$(APPLY) $(SRC)/qt/0022-Don-t-error-out-on-preprocessor-concatenation-of-two.patch
+	$(APPLY) $(SRC)/qt/0023-moc-get-the-system-defines-from-the-compiler-itself.patch
 	$(APPLY) $(SRC)/qt/systray-no-sound.patch
 	# fix forcing the WINVER/_WIN32_WINNT version without NTDDI_VERSION
 	sed -i.orig -e "s/DEFINES += WINVER/DEFINES += NTDDI_VERSION=0x06000000 WINVER/" "$(UNPACK_DIR)/src/network/kernel/kernel.pri"



View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/d312dcf73c9986866b2eafcd2a6f2dda0faedaca

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/d312dcf73c9986866b2eafcd2a6f2dda0faedaca
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the vlc-commits mailing list