Fixed ticket #3389 '-U option doesn't supress include file handling for #include statements inside #ifdef code paths'

Signed-off-by: makulik <g-makulik@t-online.de>
This commit is contained in:
makulik 2011-12-09 21:57:06 +01:00
parent 8c04431b17
commit 0a777dcb52
2 changed files with 107 additions and 24 deletions

View File

@ -856,7 +856,7 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
processedFile = ostr.str(); processedFile = ostr.str();
} }
if (_settings && !_settings->userDefines.empty()) { if (_settings && (!_settings->userDefines.empty() || !_settings->userUndefs.empty())) {
std::map<std::string, std::string> defs; std::map<std::string, std::string> defs;
// TODO: break out this code. There is other similar code. // TODO: break out this code. There is other similar code.
@ -885,7 +885,11 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
} }
processedFile = handleIncludes(processedFile, filename, includePaths, defs); processedFile = handleIncludes(processedFile, filename, includePaths, defs);
if (_settings->userDefines.empty())
resultConfigurations = getcfgs(processedFile, filename);
} else { } else {
handleIncludes(processedFile, filename, includePaths); handleIncludes(processedFile, filename, includePaths);
processedFile = replaceIfDefined(processedFile); processedFile = replaceIfDefined(processedFile);
@ -1768,31 +1772,48 @@ std::string Preprocessor::handleIncludes(const std::string &code, const std::str
unsigned int linenr = 0; unsigned int linenr = 0;
std::set<std::string> undefs = _settings ? _settings->userUndefs : std::set<std::string>();
std::ostringstream ostr; std::ostringstream ostr;
std::istringstream istr(code); std::istringstream istr(code);
std::string line; std::string line;
bool suppressCurrentCodePath = false;
while (std::getline(istr,line)) { while (std::getline(istr,line)) {
++linenr; ++linenr;
if (line.compare(0,7,"#ifdef ") == 0) { if (line.compare(0,7,"#ifdef ") == 0) {
if (indent == indentmatch && defs.find(getdef(line,true)) != defs.end()) { if (indent == indentmatch) {
elseIsTrue = false; std::string tag = getdef(line,true);
indentmatch++; if (defs.find(tag) != defs.end()) {
elseIsTrue = false;
indentmatch++;
} else if (undefs.find(tag) != undefs.end()) {
elseIsTrue = true;
indentmatch++;
suppressCurrentCodePath = true;
}
} }
++indent; ++indent;
if (indent == indentmatch + 1) if (indent == indentmatch + 1)
elseIsTrue = true; elseIsTrue = true;
} else if (line.compare(0,8,"#ifndef ") == 0) { } else if (line.compare(0,8,"#ifndef ") == 0) {
if (indent == indentmatch && defs.find(getdef(line,false)) == defs.end()) { if (indent == indentmatch) {
elseIsTrue = false; std::string tag = getdef(line,false);
indentmatch++; if (defs.find(tag) == defs.end()) {
} elseIsTrue = false;
++indent; indentmatch++;
} else if (undefs.find(tag) != undefs.end()) {
elseIsTrue = false;
indentmatch++;
suppressCurrentCodePath = false;
}
++indent;
if (indent == indentmatch + 1) if (indent == indentmatch + 1)
elseIsTrue = true; elseIsTrue = true;
} else if (line.compare(0,4,"#if ") == 0) { }
} else if (!suppressCurrentCodePath && line.compare(0,4,"#if ") == 0) {
if (indent == indentmatch && match_cfg_def(defs, line.substr(4))) { if (indent == indentmatch && match_cfg_def(defs, line.substr(4))) {
elseIsTrue = false; elseIsTrue = false;
indentmatch++; indentmatch++;
@ -1803,46 +1824,58 @@ std::string Preprocessor::handleIncludes(const std::string &code, const std::str
elseIsTrue = true; elseIsTrue = true;
} else if (line.compare(0,6,"#elif ") == 0 || line.compare(0,5,"#else") == 0) { } else if (line.compare(0,6,"#elif ") == 0 || line.compare(0,5,"#else") == 0) {
if (!elseIsTrue) { if (!elseIsTrue) {
if (indentmatch == indent) if (indentmatch == indent) {
indentmatch = indent - 1; indentmatch = indent - 1;
}
} else { } else {
if (indentmatch == indent) if (indentmatch == indent) {
indentmatch = indent - 1; indentmatch = indent - 1;
else if (indentmatch == indent - 1) { } else if (indentmatch == indent - 1) {
if (line.compare(0,5,"#else")==0 || match_cfg_def(defs,line.substr(6))) { if (line.compare(0,5,"#else")==0 || match_cfg_def(defs,line.substr(6))) {
indentmatch = indent; indentmatch = indent;
elseIsTrue = false; elseIsTrue = false;
} }
} }
} }
if (suppressCurrentCodePath) {
suppressCurrentCodePath = false;
indentmatch = indent;
}
} else if (line == "#endif") { } else if (line == "#endif") {
--indent; --indent;
if (indentmatch > indent) { if (indentmatch > indent) {
indentmatch = indent; indentmatch = indent;
elseIsTrue = false; elseIsTrue = false;
suppressCurrentCodePath = false;
} }
} else if (indentmatch == indent) { } else if (indentmatch == indent) {
if (line.compare(0,8,"#define ")==0) { if (!suppressCurrentCodePath && line.compare(0,8,"#define ")==0) {
// no value // no value
std::string tag = line.substr(8);
if (line.find_first_of("( ", 8) == std::string::npos) if (line.find_first_of("( ", 8) == std::string::npos)
defs[line.substr(8)] = ""; defs[tag] = "";
// define value // define value
else if (line.find("(") == std::string::npos) { else if (line.find("(") == std::string::npos) {
const std::string::size_type pos = line.find(" ", 8); const std::string::size_type pos = line.find(" ", 8);
defs[line.substr(8,pos-8)] = line.substr(pos+1); tag = line.substr(8,pos-8);
defs[tag] = line.substr(pos+1);
}
if (undefs.find(tag) != undefs.end()) {
defs.erase(tag);
} }
} }
else if (line.compare(0,7,"#undef ") == 0) { else if (!suppressCurrentCodePath && line.compare(0,7,"#undef ") == 0) {
defs.erase(line.substr(7)); defs.erase(line.substr(7));
} }
else if (line.compare(0,7,"#error ") == 0) { else if (!suppressCurrentCodePath && line.compare(0,7,"#error ") == 0) {
error(filePath, linenr, line.substr(7)); error(filePath, linenr, line.substr(7));
} }
else if (line.compare(0,9,"#include ")==0) { else if (!suppressCurrentCodePath && line.compare(0,9,"#include ")==0) {
std::string filename(line.substr(9)); std::string filename(line.substr(9));
const HeaderTypes headerType = getHeaderFileName(filename); const HeaderTypes headerType = getHeaderFileName(filename);
@ -1883,7 +1916,8 @@ std::string Preprocessor::handleIncludes(const std::string &code, const std::str
continue; continue;
} }
ostr << line; if (!suppressCurrentCodePath)
ostr << line;
} }
// A line has been read.. // A line has been read..

View File

@ -244,6 +244,8 @@ private:
TEST_CASE(undef5); TEST_CASE(undef5);
TEST_CASE(undef6); TEST_CASE(undef6);
TEST_CASE(undef7); TEST_CASE(undef7);
TEST_CASE(undef8);
TEST_CASE(undef9);
} }
@ -3151,7 +3153,7 @@ private:
const char filedata[] = "#define X Y\n" const char filedata[] = "#define X Y\n"
"#ifdef X\n" "#ifdef X\n"
"Fred & Wilma\n" "Fred & Wilma\n"
"#else" "#else\n"
"Barney & Betty\n" "Barney & Betty\n"
"#endif\n"; "#endif\n";
@ -3165,7 +3167,7 @@ private:
// Compare results.. // Compare results..
ASSERT_EQUALS(1U, actual.size()); ASSERT_EQUALS(1U, actual.size());
TODO_ASSERT_EQUALS("\n\n\nBarney & Betty\n\n","\n\n\n\n\n", actual[""]); ASSERT_EQUALS("\n\n\n\nBarney & Betty\n\n", actual[""]);
} }
void undef7() { void undef7() {
@ -3186,6 +3188,53 @@ private:
ASSERT_EQUALS(1U, actual.size()); ASSERT_EQUALS(1U, actual.size());
TODO_ASSERT_EQUALS("\n;\n","\nXDefined;\n", actual[""]); TODO_ASSERT_EQUALS("\n;\n","\nXDefined;\n", actual[""]);
} }
void undef8() {
Settings settings;
const char filedata[] = "#ifdef HAVE_CONFIG_H\n"
"#include \"config.h\"\n"
"#endif\n"
"\n"
"void foo();\n";
// Preprocess => actual result..
std::istringstream istr(filedata);
std::map<std::string, std::string> actual;
settings.userUndefs.insert("X"); // User undefs should override internal defines
settings.checkConfiguration = true;
errout.str("");
Preprocessor preprocessor(&settings, this);
preprocessor.preprocess(istr, actual, "file.c");
// Compare results..
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("\n\n\n\nvoid foo();\n", actual[""]);
}
void undef9() {
Settings settings;
const char filedata[] = "#define X Y\n"
"#ifndef X\n"
"Fred & Wilma\n"
"#else\n"
"Barney & Betty\n"
"#endif\n";
// Preprocess => actual result..
std::istringstream istr(filedata);
std::map<std::string, std::string> actual;
settings.userUndefs.insert("X"); // User undefs should override internal defines
Preprocessor preprocessor(&settings, this);
preprocessor.preprocess(istr, actual, "file.c");
// Compare results..
ASSERT_EQUALS(1U, actual.size());
ASSERT_EQUALS("\n\nFred & Wilma\n\n\n\n", actual[""]);
}
}; };
REGISTER_TEST(TestPreprocessor) REGISTER_TEST(TestPreprocessor)