diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 40bb1b753..d3d5ec5d6 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -856,7 +856,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 defs; // 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); + if (_settings->userDefines.empty()) + resultConfigurations = getcfgs(processedFile, filename); + } else { + handleIncludes(processedFile, filename, includePaths); processedFile = replaceIfDefined(processedFile); @@ -1768,31 +1772,48 @@ std::string Preprocessor::handleIncludes(const std::string &code, const std::str unsigned int linenr = 0; + std::set undefs = _settings ? _settings->userUndefs : std::set(); + 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++; @@ -1803,46 +1824,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); @@ -1883,7 +1916,8 @@ std::string Preprocessor::handleIncludes(const std::string &code, const std::str continue; } - ostr << line; + if (!suppressCurrentCodePath) + ostr << line; } // A line has been read.. diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index 7cf434d12..b8032856c 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -244,6 +244,8 @@ private: TEST_CASE(undef5); TEST_CASE(undef6); TEST_CASE(undef7); + TEST_CASE(undef8); + TEST_CASE(undef9); } @@ -3151,7 +3153,7 @@ private: const char filedata[] = "#define X Y\n" "#ifdef X\n" "Fred & Wilma\n" - "#else" + "#else\n" "Barney & Betty\n" "#endif\n"; @@ -3165,7 +3167,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() { @@ -3186,6 +3188,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 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 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)