summaryrefslogtreecommitdiffstats
path: root/qmake/generators
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2022-06-13 17:10:44 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2022-06-17 00:05:53 +0200
commitcfcbf38f76e0073aa939be0d85b9787805c9332b (patch)
treea605afc9901bdf4bdd58b86af9d98d2d6d96b1b3 /qmake/generators
parent077eddb3e1aaba1517d67e7c83574c16e971dc67 (diff)
Teach qmake about digit-grouping apostrophes in numeric literals
It was previously understanding them as character literal delimiters, with unfortunate consequences if a numeric literal contained an odd number of them. Recognize that an apostrophe with a digit on each side of it isn't the opening quote of a character literal (unless the digit before it is preceded by a u). Extend the findMocs test to trigger the bug, prior to the fix; verified it passes with the fix. Fixes: QTBUG-98845 Change-Id: I5db3ac59aaeade7c2d6c1fb680ba97261ec0e8a9 Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'qmake/generators')
-rw-r--r--qmake/generators/makefiledeps.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp
index 0646d232ce..c8f4772dcb 100644
--- a/qmake/generators/makefiledeps.cpp
+++ b/qmake/generators/makefiledeps.cpp
@@ -365,13 +365,21 @@ static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start,
return true;
}
-/* Advance from an opening quote at buffer[offset] to the matching close quote. */
+/* Advance from an opening quote at buffer[offset] to the matching close quote.
+ If an apostrophe turns out to be a digit-separator in a numeric literal,
+ rather than the start of a character literal, treat it as both the open and
+ the close quote of the "string" that isn't there.
+*/
static int scanPastString(char *buffer, int buffer_len, int offset, int *lines)
{
// http://en.cppreference.com/w/cpp/language/string_literal
// It might be a C++11 raw string.
bool israw = false;
- if (buffer[offset] == '"' && offset > 0) {
+
+ Q_ASSERT(offset < buffer_len);
+ if (offset <= 0) {
+ // skip, neither of these special cases applies here
+ } else if (buffer[offset] == '"') {
int explore = offset - 1;
bool prefix = false; // One of L, U, u or u8 may appear before R
bool saw8 = false; // Partial scan of u8
@@ -415,6 +423,19 @@ static int scanPastString(char *buffer, int buffer_len, int offset, int *lines)
&& (isalnum(buffer[explore]) || buffer[explore] == '_')) {
israw = false;
}
+
+ } else {
+ // Is this apostrophe a digit separator rather than the start of a
+ // character literal ? If so, there was no string to scan past, so
+ // treat the apostrophe as both open and close.
+ Q_ASSERT(buffer[offset] == '\'' && offset > 0);
+ // Wrap std::isdigit() to package the casting to unsigned char.
+ const auto isDigit = [](unsigned char c) { return std::isdigit(c); };
+ if (isDigit(buffer[offset - 1]) && offset + 1 < buffer_len && isDigit(buffer[offset + 1])) {
+ // One exception: u8'0' is a perfectly good character literal.
+ if (offset < 2 || buffer[offset - 1] != '8' || buffer[offset - 2] != 'u')
+ return offset;
+ }
}
if (israw) {