From 64ab4de4b0abb19fad18e009dfd094f1ae6a78c1 Mon Sep 17 00:00:00 2001 From: Edward Welbourne <edward.welbourne@theqtcompany.com> Date: Wed, 25 Nov 2015 11:57:36 +0100 Subject: [PATCH] Teach qmake's #include parser to recognize C++11 Raw strings. Can't sensibly test unless the compiler does support raw strings, since any test that would catch qmake's (prior) inability to parse raw strings would necessarily confuse the C++ compiler in the same way. This even applies (in test app code) to any #if-ery around the raw string, since tokenization happens before preprocessor directives are resolved. So the #if-ery on Q_COMPILER_RAW_STRINGS has to be in tst_qmake.cpp, not the test app it builds. Change-Id: I4a461f515adff288b54fb273fd9996f9b906d11c Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> --- qmake/generators/makefiledeps.cpp | 47 +++++++++++++++---- .../tools/qmake/testdata/rawString/main.cpp | 37 +++++++++++++++ .../tools/qmake/testdata/rawString/object1.h | 41 ++++++++++++++++ .../qmake/testdata/rawString/rawString.pro | 4 ++ tests/auto/tools/qmake/tst_qmake.cpp | 19 ++++++++ 5 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 tests/auto/tools/qmake/testdata/rawString/main.cpp create mode 100644 tests/auto/tools/qmake/testdata/rawString/object1.h create mode 100644 tests/auto/tools/qmake/testdata/rawString/rawString.pro diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 0f11745f4c3..b939a9c9d4d 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -555,15 +555,44 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) // quoted strings if (buffer[x] == '\'' || buffer[x] == '"') { - const char term = buffer[x]; - while (++x < buffer_len) { - if (buffer[x] == term) { - ++x; - break; - } else if (buffer[x] == '\\') { - ++x; - } else if (qmake_endOfLine(buffer[x])) { - ++line_count; + // It might be a C++11 raw string. + bool israw = false; + if (buffer[x] == '"' && x > 0) { + int y = x; + while (--y > 0 && (buffer[y] == '8' || buffer[y] == 'u' || buffer[y] == 'U')) {} // skip + israw = (buffer[y] == 'R'); + } + if (israw) { + x++; + const char *const delim = buffer + x; + while (x < buffer_len && buffer[x] != '(') + x++; + /* + Not checking correctness (trust real compiler to do that): + - no controls, spaces, '(', ')', '\\' or (presumably) '"' in delim; + - at most 16 bytes in delim + */ + + const int delimlen = buffer + x - delim; + while (++x < buffer_len + && (buffer[x] != ')' + || (delimlen > 0 && + strncmp(buffer + x + 1, delim, delimlen)) + || buffer[x + 1 + delimlen] != '"')) {} // skip + // buffer[x] is ')' + x += 1 + delimlen; // 1 for ')', then delim + // buffer[x] is '"' + } else { + const char term = buffer[x]; + while (++x < buffer_len) { + if (buffer[x] == term) { + ++x; + break; + } else if (buffer[x] == '\\') { + ++x; + } else if (qmake_endOfLine(buffer[x])) { + ++line_count; + } } } } diff --git a/tests/auto/tools/qmake/testdata/rawString/main.cpp b/tests/auto/tools/qmake/testdata/rawString/main.cpp new file mode 100644 index 00000000000..fb7008a1a92 --- /dev/null +++ b/tests/auto/tools/qmake/testdata/rawString/main.cpp @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +static const char raw[] = R"blah(lorem " ipsum /*)blah"; +#include <moc_object1.cpp> + +int main () { return 0; } diff --git a/tests/auto/tools/qmake/testdata/rawString/object1.h b/tests/auto/tools/qmake/testdata/rawString/object1.h new file mode 100644 index 00000000000..07af4229fb1 --- /dev/null +++ b/tests/auto/tools/qmake/testdata/rawString/object1.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QObject> + +class Object1 : public QObject +{ + Q_OBJECT +}; + diff --git a/tests/auto/tools/qmake/testdata/rawString/rawString.pro b/tests/auto/tools/qmake/testdata/rawString/rawString.pro new file mode 100644 index 00000000000..d2d8132ceb4 --- /dev/null +++ b/tests/auto/tools/qmake/testdata/rawString/rawString.pro @@ -0,0 +1,4 @@ +DESTDIR = ./ + +HEADERS += object1.h +SOURCES += main.cpp diff --git a/tests/auto/tools/qmake/tst_qmake.cpp b/tests/auto/tools/qmake/tst_qmake.cpp index ac94d1a2b9b..d216a54575b 100644 --- a/tests/auto/tools/qmake/tst_qmake.cpp +++ b/tests/auto/tools/qmake/tst_qmake.cpp @@ -79,6 +79,7 @@ private slots: void one_space(); void findMocs(); void findDeps(); + void rawString(); #if defined(Q_OS_MAC) void bundle_spaces(); #endif @@ -406,6 +407,24 @@ void tst_qmake::findDeps() QVERIFY( test_compiler.removeMakefile(workDir) ); } +void tst_qmake::rawString() +{ +#ifdef Q_COMPILER_RAW_STRINGS + QString workDir = base_path + "/testdata/rawString"; + + QVERIFY( test_compiler.qmake(workDir, "rawString") ); + QVERIFY( test_compiler.make(workDir) ); + QVERIFY( test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) ); + QVERIFY( test_compiler.makeClean(workDir) ); + QVERIFY( test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) ); + QVERIFY( test_compiler.makeDistClean(workDir ) ); + QVERIFY( !test_compiler.exists(workDir, "rawString", Exe, "1.0.0" ) ); + QVERIFY( test_compiler.removeMakefile(workDir) ); +#else + QSKIP("Test for C++11 raw strings depends on compiler support for them"); +#endif +} + struct TempFile : QFile { -- GitLab