summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2014-02-06 23:18:18 +0200
committerOrgad Shaneh <orgads@gmail.com>2014-02-27 16:13:51 +0100
commit5d2cd2e56d507623a2970e91afacd2c26f458714 (patch)
tree935e405e9bdf2894f4b51ae9abbe21661f0fc1e1
parent8ff63de72802af6111530fab834421b492c97137 (diff)
downloadqt-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.cpp13
-rw-r--r--tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp41
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);