From 5d2cd2e56d507623a2970e91afacd2c26f458714 Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Thu, 6 Feb 2014 23:18:18 +0200 Subject: 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 --- src/libs/cplusplus/pp-engine.cpp | 13 +++++-- .../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(""), 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 macros = client.definedMacros(); + QVERIFY(macros.contains("FOO")); + QVERIFY(macros.contains("FOO2")); + QCOMPARE(client.macroUsesLine()["FOO"], (QList() << 3U)); + QVERIFY(client.macroUsesLine()["BAR"].isEmpty()); +} + void tst_Preprocessor::compare_input_output(bool keepComments) { QFETCH(QByteArray, input); -- cgit v1.2.1