summaryrefslogtreecommitdiffstats
path: root/qmake/generators
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2016-09-06 19:21:50 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2017-08-24 14:27:50 +0000
commit515b9051505d61af6be0eba87616c7281ee4ce62 (patch)
tree69bea4769022c2003f6ddf1cd1c8e1699e4b7f9e /qmake/generators
parent797530c3f81b6c5fb8e25e431105fdcd22d8775a (diff)
Adapt qmake's raw-string parser to avoid confusion by macros
A macro name ending in R might expand to a string; if this precedes a string constant, we're juxtaposing the strings. My first parser for raw strings would mistake it for a raw string instead, ignoring the part of the identifier before R. Re-worked the exploration of what came before the string to catch these cases, too. The backwards parsing would also allow any messy jumble of [RLUu8]* as prefix for the string; but in fact R must (if present) be last in the prefix and *it* can have at most one prefix, [LUu] or u8. Anything else is an identifier that happens to precede the string. Reworked the parsing to allow only one prefix and not treat R specially unless it's immediately (modulo BSNL) before the string's open-quotes. Add link to the cppreference page about string literals, on which the grammar now parsed is based. Added a test for the issue this addresses. Verified that this fails on 5.6, dev and 5.9 without the fix. Expanded the existing test to cover R-with-prefix cases. Task-number: QTBUG-55633 Change-Id: I541486c2ec909cfb42050907c84bee83ead4a2f4 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Diffstat (limited to 'qmake/generators')
-rw-r--r--qmake/generators/makefiledeps.cpp42
1 files changed, 35 insertions, 7 deletions
diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp
index 3140b045a1..c68eeb13d6 100644
--- a/qmake/generators/makefiledeps.cpp
+++ b/qmake/generators/makefiledeps.cpp
@@ -422,25 +422,53 @@ static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start,
/* Advance from an opening quote at buffer[offset] to the matching close quote. */
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) {
int explore = offset - 1;
- while (explore > 0 && buffer[explore] != 'R') {
- if (buffer[explore] == '8' || buffer[explore] == 'u' || buffer[explore] == 'U') {
- explore--;
- } else if (explore > 1 && qmake_endOfLine(buffer[explore])
- && buffer[explore - 1] == '\\') {
+ bool prefix = false; // One of L, U, u or u8 may appear before R
+ bool saw8 = false; // Partial scan of u8
+ while (explore >= 0) {
+ // Cope with backslash-newline interruptions of the prefix:
+ if (explore > 0
+ && qmake_endOfLine(buffer[explore])
+ && buffer[explore - 1] == '\\') {
explore -= 2;
- } else if (explore > 2 && buffer[explore] == '\n'
+ } else if (explore > 1
+ && buffer[explore] == '\n'
&& buffer[explore - 1] == '\r'
&& buffer[explore - 2] == '\\') {
explore -= 3;
+ // Remaining cases can only decrement explore by one at a time:
+ } else if (saw8 && buffer[explore] == 'u') {
+ explore--;
+ saw8 = false;
+ prefix = true;
+ } else if (saw8 || prefix) {
+ break;
+ } else if (explore > 1 && buffer[explore] == '8') {
+ explore--;
+ saw8 = true;
+ } else if (buffer[explore] == 'L'
+ || buffer[explore] == 'U'
+ || buffer[explore] == 'u') {
+ explore--;
+ prefix = true;
+ } else if (buffer[explore] == 'R') {
+ if (israw)
+ break;
+ explore--;
+ israw = true;
} else {
break;
}
}
- israw = (buffer[explore] == 'R');
+ // Check the R (with possible prefix) isn't just part of an identifier:
+ if (israw && explore >= 0
+ && (isalnum(buffer[explore]) || buffer[explore] == '_')) {
+ israw = false;
+ }
}
if (israw) {