Merge pull request #67 from makulik/master

Fixed ticket #3389 '-U option doesn't supress include file handling for #include statements inside #ifdef code paths'
This commit is contained in:
Daniel Marjamäki 2011-12-10 02:44:01 -08:00
commit 8624c0b9fd
2 changed files with 107 additions and 24 deletions

View File

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

View File

@ -243,6 +243,8 @@ private:
TEST_CASE(undef5);
TEST_CASE(undef6);
TEST_CASE(undef7);
TEST_CASE(undef8);
TEST_CASE(undef9);
}
@ -3150,7 +3152,7 @@ private:
const char filedata[] = "#define X Y\n"
"#ifdef X\n"
"Fred & Wilma\n"
"#else"
"#else\n"
"Barney & Betty\n"
"#endif\n";
@ -3164,7 +3166,7 @@ private:
// Compare results..
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() {
@ -3185,6 +3187,53 @@ private:
ASSERT_EQUALS(1U, actual.size());
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)