Skip to content

Commit

Permalink
Fixed danmar#3834 (Preprocessor: -U doesn't work)
Browse files Browse the repository at this point in the history
  • Loading branch information
danmar committed Jul 18, 2012
1 parent 17c27f5 commit dc6c322
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 5 deletions.
37 changes: 33 additions & 4 deletions lib/preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
processedFile = ostr.str();
}

if (_settings && (!_settings->userDefines.empty() || !_settings->userUndefs.empty())) {
if (_settings && !_settings->userDefines.empty()) {
std::map<std::string, std::string> defs;

// TODO: break out this code. There is other similar code.
Expand Down Expand Up @@ -849,12 +849,41 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
processedFile = replaceIfDefined(processedFile);

// Get all possible configurations..
if (!_settings || (_settings && _settings->userDefines.empty()))
resultConfigurations = getcfgs(processedFile, filename);
resultConfigurations = getcfgs(processedFile, filename);

// Remove configurations that are disabled by -U
handleUndef(resultConfigurations);
}
}


void Preprocessor::handleUndef(std::list<std::string> &configurations) const
{
if (_settings && !_settings->userUndefs.empty()) {
for (std::list<std::string>::iterator cfg = configurations.begin(); cfg != configurations.end();) {
const std::string strcfg(*cfg);
bool undef = false;
for (std::set<std::string>::const_iterator it = _settings->userUndefs.begin(); it != _settings->userUndefs.end(); ++it) {
if (*it == *cfg)
undef = true;
else if (cfg->compare(0,it->length(),*it)==0 && cfg->find_first_of(";=") == it->length())
undef = true;
else if (cfg->find(";" + *it) == std::string::npos)
;
else if (cfg->find(";" + *it + ";") != std::string::npos)
undef = true;
else if (cfg->find(";" + *it + "=") != std::string::npos)
undef = true;
else if (cfg->find(";" + *it) + it->size() + 1U == cfg->size())
undef = true;
}

if (undef)
configurations.erase(cfg++);
else
cfg++;
}
}
}

// Get the DEF in this line: "#ifdef DEF"
std::string Preprocessor::getdef(std::string line, bool def)
Expand Down
2 changes: 2 additions & 0 deletions lib/preprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ class CPPCHECKLIB Preprocessor {
bool validateCfg(const std::string &code, const std::string &cfg);
void validateCfgError(const std::string &cfg);

void handleUndef(std::list<std::string> &configurations) const;

protected:

/**
Expand Down
57 changes: 56 additions & 1 deletion test/testpreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,9 @@ class TestPreprocessor : public TestFixture {
TEST_CASE(undef7);
TEST_CASE(undef8);
TEST_CASE(undef9);
TEST_CASE(undef10);

TEST_CASE(handleUndef);

TEST_CASE(macroChar);

Expand Down Expand Up @@ -3502,7 +3505,7 @@ class TestPreprocessor : public TestFixture {
preprocessor.preprocess(istr, actual, "file.c");

// Compare results..
ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("[file.c:2]: (information) Include file: \"config.h\" not found.\n", errout.str());
ASSERT_EQUALS("\n\n\n\nvoid foo();\n", actual[""]);
}

Expand All @@ -3529,6 +3532,58 @@ class TestPreprocessor : public TestFixture {
ASSERT_EQUALS("\n\nFred & Wilma\n\n\n\n", actual[""]);
}

void undef10() {
Settings settings;

const char filedata[] = "#ifndef X\n"
"#endif\n"
"#ifndef Y\n"
"#endif\n";

// Preprocess => actual result..
std::istringstream istr(filedata);
settings.userUndefs.insert("X"); // User undefs should override internal defines

Preprocessor preprocessor(&settings, this);

std::string processedFile;
std::list<std::string> resultConfigurations;
const std::list<std::string> includePaths;
preprocessor.preprocess(istr, processedFile, resultConfigurations, "file.c", includePaths);


// Compare results. Two configurations "" and "Y". No "X".
ASSERT_EQUALS(2U, resultConfigurations.size());
ASSERT_EQUALS("", resultConfigurations.front());
ASSERT_EQUALS("Y", resultConfigurations.back());
}

void handleUndef() {
Settings settings;
settings.userUndefs.insert("X");
const Preprocessor preprocessor(&settings, this);
std::list<std::string> configurations;

// configurations to keep
configurations.clear();
configurations.push_back("XY;");
configurations.push_back("AX;");
configurations.push_back("A;XY");
preprocessor.handleUndef(configurations);
ASSERT_EQUALS(3U, configurations.size());

// configurations to remove
configurations.clear();
configurations.push_back("X;Y");
configurations.push_back("X=1;Y");
configurations.push_back("A;X;B");
configurations.push_back("A;X=1;B");
configurations.push_back("A;X");
configurations.push_back("A;X=1");
preprocessor.handleUndef(configurations);
ASSERT_EQUALS(0U, configurations.size());
}

void macroChar() {
const char filedata[] = "#define X 1\nX\n";
ASSERT_EQUALS("\n$1\n", OurPreprocessor::expandMacros(filedata,NULL));
Expand Down

0 comments on commit dc6c322

Please sign in to comment.