From c2e5f1c819776ea607f5d5c203aa86185db0c4c3 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 12 Sep 2014 10:49:23 +0200 Subject: [PATCH] C++: Pass on the byte offsets of macro arguments ...to the Document/Block. Change-Id: I1a96dc70ac93254e6030326b36a5df9a2cdc2bd8 Reviewed-by: Christian Stenger Reviewed-by: Nikolai Kosjar --- src/libs/cplusplus/CppDocument.cpp | 4 +- src/libs/cplusplus/PreprocessorClient.h | 16 +++- src/libs/cplusplus/pp-engine.cpp | 3 + .../preprocessor/tst_preprocessor.cpp | 76 ++++++++++++++++++- 4 files changed, 95 insertions(+), 4 deletions(-) diff --git a/src/libs/cplusplus/CppDocument.cpp b/src/libs/cplusplus/CppDocument.cpp index 8e6bc66a5de..40d91baf4c2 100644 --- a/src/libs/cplusplus/CppDocument.cpp +++ b/src/libs/cplusplus/CppDocument.cpp @@ -378,7 +378,9 @@ void Document::addMacroUse(const Macro ¯o, beginLine); foreach (const MacroArgumentReference &actual, actuals) { - const Block arg(0, 0, actual.utf16charsOffset(), + const Block arg(actual.bytesOffset(), + actual.bytesOffset() + actual.bytesLength(), + actual.utf16charsOffset(), actual.utf16charsOffset() + actual.utf16charsLength()); use.addArgument(arg); } diff --git a/src/libs/cplusplus/PreprocessorClient.h b/src/libs/cplusplus/PreprocessorClient.h index 3680770dc2f..1e722550fbc 100644 --- a/src/libs/cplusplus/PreprocessorClient.h +++ b/src/libs/cplusplus/PreprocessorClient.h @@ -46,14 +46,26 @@ class Macro; class CPLUSPLUS_EXPORT MacroArgumentReference { + unsigned _bytesOffset; + unsigned _bytesLength; unsigned _utf16charsOffset; unsigned _utf16charsLength; public: - explicit MacroArgumentReference(unsigned utf16charsOffset = 0, unsigned utf16charsLength = 0) - : _utf16charsOffset(utf16charsOffset), _utf16charsLength(utf16charsLength) + explicit MacroArgumentReference(unsigned bytesOffset = 0, unsigned bytesLength = 0, + unsigned utf16charsOffset = 0, unsigned utf16charsLength = 0) + : _bytesOffset(bytesOffset) + , _bytesLength(bytesLength) + , _utf16charsOffset(utf16charsOffset) + , _utf16charsLength(utf16charsLength) { } + unsigned bytesOffset() const + { return _bytesOffset; } + + unsigned bytesLength() const + { return _bytesLength; } + unsigned utf16charsOffset() const { return _utf16charsOffset; } diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 6c883307f4b..3c21bf3389a 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1034,6 +1034,9 @@ bool Preprocessor::handleIdentifier(PPToken *tk) } else { argRefs.push_back(MacroArgumentReference( + m_state.m_bytesOffsetRef + argTks.first().bytesBegin(), + argTks.last().bytesBegin() + argTks.last().bytes() + - argTks.first().bytesBegin(), m_state.m_utf16charsOffsetRef + argTks.first().utf16charsBegin(), argTks.last().utf16charsBegin() + argTks.last().utf16chars() - argTks.first().utf16charsBegin())); diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index 6b8dad64886..258a1f8e7d3 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -27,8 +27,8 @@ ** ****************************************************************************/ +#include "../cplusplus_global.h" #include - #include #include #include @@ -149,6 +149,7 @@ public: m_expandedMacrosOffset.append(bytesOffset); m_macroUsesLine[macro.name()].append(line); m_macroArgsCount.append(actuals.size()); + m_usedMacros.insert(macro.name(), actuals); } virtual void stopExpandingMacro(unsigned /*offset*/, const Macro &/*macro*/) {} @@ -273,6 +274,9 @@ public: const QList macroArgsCount() const { return m_macroArgsCount; } + const QMap> usedMacros() const + { return m_usedMacros; } + private: Environment *m_env; QByteArray *m_output; @@ -290,6 +294,7 @@ private: QHash > m_definitionsResolvedFromLines; QSet m_unresolvedDefines; QList m_macroArgsCount; + QMap> m_usedMacros; }; QT_BEGIN_NAMESPACE @@ -352,6 +357,8 @@ private slots: void defined_usage(); void empty_macro_args(); void macro_args_count(); + void macro_args_offsets(); + void macro_args_offsets_data(); void invalid_param_count(); void objmacro_expanding_as_fnmacro_notification(); void macro_uses(); @@ -515,6 +522,73 @@ void tst_Preprocessor::macro_args_count() } +void tst_Preprocessor::macro_args_offsets() +{ + QFETCH(QString, fileName); + QFETCH(QByteArray, source); + QFETCH(QByteArray, macroName); + QFETCH(unsigned, bytesOffset); + QFETCH(unsigned, bytesLength); + QFETCH(unsigned, utf16charsOffset); + QFETCH(unsigned, utf16charsLength); + + Environment env; + QByteArray output; + MockClient client(&env, &output); + Preprocessor preprocess(&client, &env); + preprocess.run(fileName, source, true, false); + + QMap> usedMacros = client.usedMacros(); + QCOMPARE(usedMacros.size(), 1); + QVERIFY(usedMacros.contains(macroName)); + MacroArgumentReference argRef = usedMacros.value(macroName).at(0); + QCOMPARE(argRef.bytesOffset(), bytesOffset); + QCOMPARE(argRef.bytesLength(), bytesLength); + QCOMPARE(argRef.utf16charsOffset(), utf16charsOffset); + QCOMPARE(argRef.utf16charsLength(), utf16charsLength); + + +} + +void tst_Preprocessor::macro_args_offsets_data() +{ + QTest::addColumn("fileName"); + QTest::addColumn("source"); + QTest::addColumn("macroName"); + QTest::addColumn("bytesOffset"); + QTest::addColumn("bytesLength"); + QTest::addColumn("utf16charsOffset"); + QTest::addColumn("utf16charsLength"); + + QString fN = QLatin1String(""); + QByteArray src = QByteArray("#define SQR(a) ( a * a )\n" + "void f(){\n" + "int i = 10;\n" + "int j = SQR(10);\n" + "}"); + QTest::newRow("ascii_only_before_ref") << fN << src << QByteArray("SQR") + << 59u << 2u << 59u << 2u; + src.replace("int i", "int äöü"); + QTest::newRow("ascii_with_umlauts_before_ref") << fN << src << QByteArray("SQR") + << 64u << 2u << 61u << 2u; + src.clear(); + src.append("#define OUT(format, ...) printf(\"%s %d: \" format, __FILE__, __LINE__)\n" + "void f(){\n" + "OUT(\"Hei verden!\\n\");\n" + "}\n"); + QTest::newRow("arg_ascii_only") << fN << src << QByteArray("OUT") + << 84u << 15u << 84u << 15u; + src.replace("Hei verden", UC_U00FC); + QTest::newRow("arg_ascii_with_unicode_00fc") << fN << src << QByteArray("OUT") + << 84u << 7u << 84u << 6u; + src.replace(UC_U00FC, UC_U4E8C); + QTest::newRow("arg_ascii_with_unicode_4e8c") << fN << src << QByteArray("OUT") + << 84u << 8u << 84u << 6u; + src.replace(UC_U4E8C, UC_U10302); + QTest::newRow("arg_ascii_with_unicode_10302") << fN << src << QByteArray("OUT") + << 84u << 9u << 84u << 7u; +} + void tst_Preprocessor::invalid_param_count() { Environment env;