diff options
author | Ahmad Samir <a.samirh78@gmail.com> | 2023-05-14 15:44:01 +0300 |
---|---|---|
committer | Ahmad Samir <a.samirh78@gmail.com> | 2023-05-15 19:20:21 +0300 |
commit | d2242c353fac9b76437b2c3bc521c0e6e415f3b1 (patch) | |
tree | 75d7554bb1451877bb682699215d30ab1ba59d76 | |
parent | 328680b34bc9d37bbfb42e188d9f943c07b5d5d0 (diff) | |
download | qtbase-d2242c353fac9b76437b2c3bc521c0e6e415f3b1.tar.gz |
MOC: pass the erroneous Symbol as an arg to Parser::error() overload
We already know the Symbol while parsing, passing a reference to it to
error() makes it simpler to construct the error message.
This fixes an issue where reporting an error about "NONSENSE" in e.g.:
Q_PROPERTY(Foo* foo NONSENSE foo)
would be off-by-one and the error message would say:
path/to/file.h:11:1: error: Parse error at "foo"
instead of 'at "NONSENSE"', which is where the parser actually found an
unexpected attribute.
Fixes: QTBUG-36367
Pick-to: 6.5
Change-Id: Ief70e544af41f7575fbeea9b936fa8197c3ef43d
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/tools/moc/moc.cpp | 27 | ||||
-rw-r--r-- | src/tools/moc/parser.cpp | 17 | ||||
-rw-r--r-- | src/tools/moc/parser.h | 2 | ||||
-rw-r--r-- | tests/auto/tools/moc/tst_moc.cpp | 9 |
4 files changed, 36 insertions, 19 deletions
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 743742ba97..c71f2cec53 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -1300,7 +1300,8 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) }; while (test(IDENTIFIER)) { - const QByteArray l = lexem(); + const Symbol &lsym = symbol(); + const QByteArray l = lsym.lexem(); if (l[0] == 'C' && l == "CONSTANT") { propDef.constant = true; continue; @@ -1327,11 +1328,11 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) } else if (test(INTEGER_LITERAL)) { v = lexem(); if (l != "REVISION") - error(1); + error(lsym); } else if (test(DEFAULT)) { v = lexem(); if (l != "READ" && l != "WRITE") - error(1); + error(lsym); } else { next(IDENTIFIER); v = lexem(); @@ -1345,7 +1346,7 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) if (l == "MEMBER") propDef.member = v; else - error(2); + error(lsym); break; case 'R': if (l == "READ") @@ -1356,10 +1357,10 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) bool ok = false; const int minor = v.toInt(&ok); if (!ok || !QTypeRevision::isValidSegment(minor)) - error(1); + error(lsym); propDef.revision = QTypeRevision::fromMinorVersion(minor).toEncodedVersion<int>(); } else - error(2); + error(lsym); break; case 'S': if (l == "SCRIPTABLE") { @@ -1369,27 +1370,27 @@ void Moc::parsePropertyAttributes(PropertyDef &propDef) propDef.stored = v + v2; checkIsFunction(propDef.stored, "STORED"); } else - error(2); + error(lsym); break; - case 'W': if (l != "WRITE") error(2); + case 'W': if (l != "WRITE") error(lsym); propDef.write = v; break; - case 'B': if (l != "BINDABLE") error(2); + case 'B': if (l != "BINDABLE") error(lsym); propDef.bind = v; break; - case 'D': if (l != "DESIGNABLE") error(2); + case 'D': if (l != "DESIGNABLE") error(lsym); propDef.designable = v + v2; checkIsFunction(propDef.designable, "DESIGNABLE"); break; - case 'N': if (l != "NOTIFY") error(2); + case 'N': if (l != "NOTIFY") error(lsym); propDef.notify = v; break; - case 'U': if (l != "USER") error(2); + case 'U': if (l != "USER") error(lsym); propDef.user = v + v2; checkIsFunction(propDef.user, "USER"); break; default: - error(2); + error(lsym); } } if (propDef.constant && !propDef.write.isNull()) { diff --git a/src/tools/moc/parser.cpp b/src/tools/moc/parser.cpp index 6fa0e645d3..6b0308fc15 100644 --- a/src/tools/moc/parser.cpp +++ b/src/tools/moc/parser.cpp @@ -20,17 +20,24 @@ static const char *error_msg = nullptr; #define ErrorFormatString "%s:%d:%d: " #endif -void Parser::error(int rollback) { - index -= rollback; - error(); +static void defaultErrorMsg(const QByteArray &fileName, const Symbol &sym) +{ + fprintf(stderr, ErrorFormatString "error: Parse error at \"%s\"\n", + fileName.constData(), sym.lineNum, 1, sym.lexem().data()); } + +void Parser::error(const Symbol &sym) +{ + defaultErrorMsg(currentFilenames.top(), sym); + exit(EXIT_FAILURE); +} + void Parser::error(const char *msg) { if (msg || error_msg) fprintf(stderr, ErrorFormatString "error: %s\n", currentFilenames.top().constData(), symbol().lineNum, 1, msg?msg:error_msg); else - fprintf(stderr, ErrorFormatString "error: Parse error at \"%s\"\n", - currentFilenames.top().constData(), symbol().lineNum, 1, symbol().lexem().data()); + defaultErrorMsg(currentFilenames.top(), symbol()); exit(EXIT_FAILURE); } diff --git a/src/tools/moc/parser.h b/src/tools/moc/parser.h index 5f754d9b19..dc86cdec73 100644 --- a/src/tools/moc/parser.h +++ b/src/tools/moc/parser.h @@ -44,7 +44,7 @@ public: inline QByteArray unquotedLexem() { return symbols.at(index-1).unquotedLexem();} inline const Symbol &symbol() { return symbols.at(index-1);} - Q_NORETURN void error(int rollback); + Q_NORETURN void error(const Symbol &symbol); Q_NORETURN void error(const char *msg = nullptr); void warning(const char * = nullptr); void note(const char * = nullptr); diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 40d42a662b..b0cc42c6b6 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -62,6 +62,8 @@ #include "qmlmacro.h" +using namespace Qt::StringLiterals; + #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") @@ -2371,6 +2373,13 @@ void tst_Moc::warnings_data() << QString() << QString("standard input:3:1: error: Parse error at \"decltype\""); + QTest::newRow("QTBUG-36367: report correct error location") + << "class X { \n Q_PROPERTY(Foo* foo NONSENSE foo) \n };"_ba + << QStringList() + << 1 + << QString() + << u"standard input:2:1: error: Parse error at \"NONSENSE\""_s; + #ifdef Q_OS_UNIX // Limit to Unix because the error message is platform-dependent QTest::newRow("Q_PLUGIN_METADATA: unreadable file") << QByteArray("class X { \n Q_PLUGIN_METADATA(FILE \".\") \n };") |