Fixed #1512 (incorrect handling of ndefs in the preprocessor)

This commit is contained in:
Raphael Geissert 2010-03-19 16:13:45 +01:00 committed by Daniel Marjamäki
parent c7bd437d7d
commit d11004fa3d
2 changed files with 124 additions and 6 deletions

View File

@ -628,7 +628,7 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
std::list<std::string> ret;
ret.push_back("");
std::list<std::string> deflist;
std::list<std::string> deflist, ndeflist;
// constants defined through "#define" in the code..
std::set<std::string> defines;
@ -679,7 +679,17 @@ std::list<std::string> 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<std::string> 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<std::string> 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..

View File

@ -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<std::string, std::string> actual;
Preprocessor preprocessor;
preprocessor.preprocess(istr, actual, "file.c");
// Compare results..
ASSERT_EQUALS(3, static_cast<unsigned int>(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<std::string, std::string> actual;
Preprocessor preprocessor;
preprocessor.preprocess(istr, actual, "file.c");
// Compare results..
ASSERT_EQUALS(3, static_cast<unsigned int>(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<std::string, std::string> actual;
Preprocessor preprocessor;
preprocessor.preprocess(istr, actual, "file.c");
// Compare results..
ASSERT_EQUALS(4, static_cast<unsigned int>(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()