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>
This commit is contained in:
parent
077eddb3e1
commit
cfcbf38f76
@ -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) {
|
||||
|
8
tests/auto/tools/qmake/testdata/findMocs/digitseparated.h
vendored
Normal file
8
tests/auto/tools/qmake/testdata/findMocs/digitseparated.h
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
#include <QObject>
|
||||
|
||||
class AfterDigitSeparator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AfterDigitSeparator() : QObject(nullptr) {}
|
||||
};
|
@ -1,5 +1,6 @@
|
||||
DESTDIR = ./
|
||||
|
||||
HEADERS += object1.h object2.h object3.h object4.h \
|
||||
object5.h object6.h object7.h object8.h object9.h
|
||||
object5.h object6.h object7.h object8.h object9.h \
|
||||
digitseparated.h
|
||||
SOURCES += main.cpp
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Copyright (C) 2016 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
|
||||
|
||||
|
||||
#include <moc_object1.cpp>
|
||||
#include <moc_object2.cpp>
|
||||
#include <moc_object3.cpp>
|
||||
@ -12,4 +11,9 @@
|
||||
#include "object8.h"
|
||||
#include <moc_object9.cpp>
|
||||
|
||||
int main() { return 0; }
|
||||
int main() { return 0'000; }
|
||||
/* Included *after* the use of a numeric literal with an *odd* number of digit
|
||||
separator tick marks in it (and no subsequent apostrophe to end the
|
||||
"single-quoted character literal" that the old parser though it was thus left
|
||||
in). */
|
||||
#include <moc_digitseparated.cpp>
|
||||
|
Loading…
x
Reference in New Issue
Block a user