summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2024-04-12 12:49:18 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2024-04-17 04:38:22 +0200
commit62d02c1d509780eca7d3a4c35ac64a0d475d0fe7 (patch)
tree13b6b2a5f0328b46c3389d1364fa8886d5911228
parent001d88ae38435a2d108178c5d396839986985bc4 (diff)
moc: Treat number + characters as Identifier, not Number
While <DIGIT>+<Character> is not a valid identifier by itself in the C++ language, it might become one when using it with the token pasting operator. This risks confusing some number literals with suffix as Identifiers, but those are currently not supported anyway, so this shouldn't break anything that is currently working. Fixes: QTBUG-87219 Fixes: QTBUG-124288 Pick-to: 6.7 Change-Id: If73255cc0e6649bc90c52b1d177aac8ff975ae69 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io> Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
-rw-r--r--src/tools/moc/preprocessor.cpp13
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp30
2 files changed, 41 insertions, 2 deletions
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index f0a61ce621..11ea8d417e 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -214,7 +214,9 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
data -= 2;
break;
case DIGIT:
- while (isAsciiDigit(*data) || *data == '\'')
+ {
+ bool hasSeenTokenSeparator = false;;
+ while (isAsciiDigit(*data) || (hasSeenTokenSeparator = *data == '\''))
++data;
if (!*data || *data != '.') {
token = INTEGER_LITERAL;
@@ -223,15 +225,22 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
|| *data == 'b' || *data == 'B')
&& *lexem == '0') {
++data;
- while (isHexDigit(*data) || *data == '\'')
+ while (isHexDigit(*data) || (hasSeenTokenSeparator = *data == '\''))
++data;
} else if (*data == 'L') // TODO: handle other suffixes
++data;
+ if (!hasSeenTokenSeparator) {
+ while (is_ident_char(*data)) {
+ ++data;
+ token = IDENTIFIER;
+ }
+ }
break;
}
token = FLOATING_LITERAL;
++data;
Q_FALLTHROUGH();
+ }
case FLOATING_LITERAL:
while (isAsciiDigit(*data) || *data == '\'')
++data;
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index f450cc5696..d24dfa11f7 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -85,6 +85,26 @@ namespace A {
}
#endif
+
+namespace TokenStartingWithNumber
+{
+Q_NAMESPACE
+
+#define FOR_EACH_ITEM( CALL ) \
+ CALL( EXAMPLE ) \
+ CALL( 123_EXAMPLE ) \
+ CALL( OTHER_EXAMPLE )
+
+enum FooItems
+{
+
+#define ENUM_ITEM(NAME, ...) FOO ## NAME,
+ FOR_EACH_ITEM( ENUM_ITEM )
+};
+
+Q_ENUM_NS(FooItems)
+}
+
Q_DECLARE_METATYPE(const QMetaObject*);
#define TESTEXPORTMACRO Q_DECL_EXPORT
@@ -852,6 +872,7 @@ private slots:
void readWriteThroughBindable();
void invokableCtors();
void virtualInlineTaggedSlot();
+ void tokenStartingWithNumber();
signals:
void sigWithUnsignedArg(unsigned foo);
@@ -4673,6 +4694,15 @@ void tst_Moc::virtualInlineTaggedSlot()
QCOMPARE(method.returnMetaType(), QMetaType::fromType<int>());
}
+void tst_Moc::tokenStartingWithNumber()
+{
+ auto *mo = &TokenStartingWithNumber::staticMetaObject;
+ int index = mo->indexOfEnumerator("FooItems");
+ QMetaEnum metaEnum = mo->enumerator(index);
+ QVERIFY(metaEnum.isValid());
+ QCOMPARE(metaEnum.keyCount(), 3);
+}
+
QTEST_MAIN(tst_Moc)
// the generated code must compile with QT_NO_KEYWORDS