From d11004fa3d92b49e47bf4afc5a2897695ef41393 Mon Sep 17 00:00:00 2001 From: Raphael Geissert Date: Fri, 19 Mar 2010 16:13:45 +0100 Subject: [PATCH] Fixed #1512 (incorrect handling of ndefs in the preprocessor) --- lib/preprocessor.cpp | 45 ++++++++++++++++++--- test/testpreprocessor.cpp | 85 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 6 deletions(-) diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 56ecd15f8..492b56761 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -628,7 +628,7 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const std::list ret; ret.push_back(""); - std::list deflist; + std::list deflist, ndeflist; // constants defined through "#define" in the code.. std::set defines; @@ -679,7 +679,17 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const if (includeguard) continue; - std::string def = getdef(line, true) + getdef(line, false); + bool from_negation = false; + + std::string def = getdef(line, true); + if (def.empty()) + { + def = getdef(line, false); + // sub conditionals of ndef blocks need to be + // constructed _without_ the negated define + if (!def.empty()) + from_negation = true; + } if (!def.empty()) { int par = 0; @@ -736,7 +746,7 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const { if (*it == "0") break; - if (*it == "1") + if (*it == "1" || *it == "!") continue; // don't add "T;T": @@ -748,19 +758,42 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const def += *it; } } + if (from_negation) + { + ndeflist.push_back(deflist.back()); + deflist.pop_back(); + std::string nmark("!"); + deflist.push_back(nmark); + } + if (std::find(ret.begin(), ret.end(), def) == ret.end()) + { ret.push_back(def); + } } else if (line.find("#else") == 0 && ! deflist.empty()) { - std::string def((deflist.back() == "1") ? "0" : "1"); - deflist.pop_back(); - deflist.push_back(def); + if (deflist.back() == "!") + { + deflist.pop_back(); + deflist.push_back(ndeflist.back()); + ndeflist.pop_back(); + } + else + { + std::string def((deflist.back() == "1") ? "0" : "1"); + deflist.pop_back(); + deflist.push_back(def); + } } else if (line.find("#endif") == 0 && ! deflist.empty()) + { + if (deflist.back() == "!") + ndeflist.pop_back(); deflist.pop_back(); + } } // Remove defined constants from ifdef configurations.. diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index f858fb3f0..0f15348f1 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -716,6 +716,91 @@ private: ASSERT_EQUALS("\n\n\n\n\n\n", actual[""]); ASSERT_EQUALS("\na\n\n\n\n\n", actual["A"]); ASSERT_EQUALS("\na\n\n\nab\n\n", actual["A;B"]); + if_cond2b(); + if_cond2c(); + if_cond2d(); + } + + void if_cond2b() + { + const char filedata[] = "#ifndef A\n" + "!a\n" + "#ifdef B\n" + "b\n" + "#endif\n" + "#else\n" + "a\n" + "#endif\n"; + + // Preprocess => actual result.. + std::istringstream istr(filedata); + std::map actual; + Preprocessor preprocessor; + preprocessor.preprocess(istr, actual, "file.c"); + + // Compare results.. + ASSERT_EQUALS(3, static_cast(actual.size())); + ASSERT_EQUALS("\n!a\n\n\n\n\n\n\n", actual[""]); + ASSERT_EQUALS("\n\n\n\n\n\na\n\n", actual["A"]); + ASSERT_EQUALS("\n!a\n\nb\n\n\n\n\n", actual["B"]); + } + + void if_cond2c() + { + const char filedata[] = "#ifndef A\n" + "!a\n" + "#ifdef B\n" + "b\n" + "#else\n" + "!b\n" + "#endif\n" + "#else\n" + "a\n" + "#endif\n"; + + // Preprocess => actual result.. + std::istringstream istr(filedata); + std::map actual; + Preprocessor preprocessor; + preprocessor.preprocess(istr, actual, "file.c"); + + // Compare results.. + ASSERT_EQUALS(3, static_cast(actual.size())); + ASSERT_EQUALS("\n!a\n\n\n\n!b\n\n\n\n\n", actual[""]); + ASSERT_EQUALS("\n\n\n\n\n\n\n\na\n\n", actual["A"]); + ASSERT_EQUALS("\n!a\n\nb\n\n\n\n\n\n\n", actual["B"]); + } + + void if_cond2d() + { + const char filedata[] = "#ifndef A\n" + "!a\n" + "#ifdef B\n" + "b\n" + "#else\n" + "!b\n" + "#endif\n" + "#else\n" + "a\n" + "#ifdef B\n" + "b\n" + "#else\n" + "!b\n" + "#endif\n" + "#endif\n"; + + // Preprocess => actual result.. + std::istringstream istr(filedata); + std::map actual; + Preprocessor preprocessor; + preprocessor.preprocess(istr, actual, "file.c"); + + // Compare results.. + ASSERT_EQUALS(4, static_cast(actual.size())); + ASSERT_EQUALS("\n!a\n\n\n\n!b\n\n\n\n\n\n\n\n\n\n", actual[""]); + ASSERT_EQUALS("\n\n\n\n\n\n\n\na\n\n\n\n!b\n\n\n", actual["A"]); + ASSERT_EQUALS("\n\n\n\n\n\n\n\na\n\nb\n\n\n\n\n", actual["A;B"]); + ASSERT_EQUALS("\n!a\n\nb\n\n\n\n\n\n\n\n\n\n\n\n", actual["B"]); } void if_cond3()