diff options
author | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2014-02-06 23:18:18 +0200 |
---|---|---|
committer | Orgad Shaneh <orgads@gmail.com> | 2014-02-27 16:13:51 +0100 |
commit | 5d2cd2e56d507623a2970e91afacd2c26f458714 (patch) | |
tree | 935e405e9bdf2894f4b51ae9abbe21661f0fc1e1 | |
parent | 8ff63de72802af6111530fab834421b492c97137 (diff) | |
download | qt-creator-5d2cd2e56d507623a2970e91afacd2c26f458714.tar.gz |
C++: Fix handling of #undef
* If the macro is defined before, track its reference
* Synchronize environment line before calling remove, which
currently sets incorrect line
* Set macro offset
Task-number: QTCREATORBUG-10454
Change-Id: I480d16423a976a025bb8c71046610a46f9d7b0fd
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
-rw-r--r-- | src/libs/cplusplus/pp-engine.cpp | 13 | ||||
-rw-r--r-- | tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp | 41 |
2 files changed, 52 insertions, 2 deletions
diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 21440bc86c..41439ad790 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -1951,10 +1951,19 @@ void Preprocessor::handleUndefDirective(PPToken *tk) lex(tk); // consume "undef" token if (tk->is(T_IDENTIFIER)) { const ByteArrayRef macroName = tk->asByteArrayRef(); - const Macro *macro = m_env->remove(macroName); + const unsigned offset = tk->offset + m_state.m_offsetRef; + // Track macro use if previously defined + if (m_client) { + if (const Macro *existingMacro = m_env->resolve(macroName)) + m_client->notifyMacroReference(offset, tk->lineno, *existingMacro); + } + synchronizeOutputLines(*tk); + Macro *macro = m_env->remove(macroName); - if (m_client && macro) + if (m_client && macro) { + macro->setOffset(offset); m_client->macroAdded(*macro); + } lex(tk); // consume macro name #ifndef NO_DEBUG } else { diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index be153ab0ab..808bd75a00 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -374,6 +374,7 @@ private slots: void include_guard_data(); void empty_trailing_lines(); void empty_trailing_lines_data(); + void undef(); }; // Remove all #... lines, and 'simplify' string, to allow easily comparing the result @@ -1739,6 +1740,46 @@ void tst_Preprocessor::empty_trailing_lines_data() ); } +void tst_Preprocessor::undef() +{ + Environment env; + QByteArray output; + MockClient client(&env, &output); + Preprocessor preprocess(&client, &env); + QByteArray input = + "#define FOO\n" + "#define FOO2\n" + "#undef FOO\n" + "#undef BAR\n"; + preprocess.run(QLatin1String("<stdin>"), input); + QCOMPARE(env.macroCount(), 4U); + Macro *macro = env.macroAt(0); + QCOMPARE(macro->name(), QByteArray("FOO")); + QCOMPARE(macro->offset(), 8U); + QCOMPARE(macro->line(), 1U); + QVERIFY(!macro->isHidden()); + macro = env.macroAt(1); + QCOMPARE(macro->name(), QByteArray("FOO2")); + QCOMPARE(macro->offset(), 20U); + QCOMPARE(macro->line(), 2U); + QVERIFY(!macro->isHidden()); + macro = env.macroAt(2); + QCOMPARE(macro->name(), QByteArray("FOO")); + QCOMPARE(macro->offset(), 32U); + QCOMPARE(macro->line(), 3U); + QVERIFY(macro->isHidden()); + macro = env.macroAt(3); + QCOMPARE(macro->name(), QByteArray("BAR")); + QCOMPARE(macro->offset(), 43U); + QCOMPARE(macro->line(), 4U); + QVERIFY(macro->isHidden()); + QList<QByteArray> macros = client.definedMacros(); + QVERIFY(macros.contains("FOO")); + QVERIFY(macros.contains("FOO2")); + QCOMPARE(client.macroUsesLine()["FOO"], (QList<unsigned>() << 3U)); + QVERIFY(client.macroUsesLine()["BAR"].isEmpty()); +} + void tst_Preprocessor::compare_input_output(bool keepComments) { QFETCH(QByteArray, input); |