diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 3b175eabf..45f0b3c70 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -705,7 +705,7 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const varmap[varname] = value; } - simplifyCondition(varmap, def); + simplifyCondition(varmap, def, false); } if (! deflist.empty() && line.find("#elif ") == 0) @@ -917,7 +917,7 @@ std::list Preprocessor::getcfgs(const std::string &filedata, const } -void Preprocessor::simplifyCondition(const std::map &variables, std::string &condition) +void Preprocessor::simplifyCondition(const std::map &variables, std::string &condition, bool match) { Tokenizer tokenizer; std::istringstream istr(("(" + condition + ")").c_str()); @@ -931,10 +931,12 @@ void Preprocessor::simplifyCondition(const std::map &v if (Token::Match(tok, "defined ( %var% )")) { - if (variables.find(tok->strAt(2)) == variables.end()) + if (variables.find(tok->strAt(2)) != variables.end()) + tok->str("1"); + else if (match) tok->str("0"); else - tok->str("1"); + continue; tok->deleteNext(); tok->deleteNext(); tok->deleteNext(); @@ -943,10 +945,12 @@ void Preprocessor::simplifyCondition(const std::map &v if (Token::Match(tok, "defined %var%")) { - if (variables.find(tok->strAt(1)) == variables.end()) + if (variables.find(tok->strAt(1)) != variables.end()) + tok->str("1"); + else if (match) tok->str("0"); else - tok->str("1"); + continue; tok->deleteNext(); continue; } @@ -990,7 +994,7 @@ bool Preprocessor::match_cfg_def(const std::map &cfg, //std::cout << "cfg: \"" << cfg << "\" "; //std::cout << "def: \"" << def << "\""; - simplifyCondition(cfg, def); + simplifyCondition(cfg, def, true); if (cfg.find(def) != cfg.end()) return true; diff --git a/lib/preprocessor.h b/lib/preprocessor.h index 12a46b514..be98fa6ca 100644 --- a/lib/preprocessor.h +++ b/lib/preprocessor.h @@ -87,8 +87,9 @@ public: * simplify condition * @param variables Variable values * @param condition The condition to simplify + * @param match if true, 'defined(A)' is replaced with 0 if A is not defined */ - static void simplifyCondition(const std::map &variables, std::string &condition); + static void simplifyCondition(const std::map &variables, std::string &condition, bool match); protected: diff --git a/test/testcppcheck.cpp b/test/testcppcheck.cpp index 6971b48df..bf1f1fe51 100644 --- a/test/testcppcheck.cpp +++ b/test/testcppcheck.cpp @@ -67,7 +67,8 @@ private: check(filedata); // Compare results.. - ASSERT_EQUALS("[file.cpp:5]: (error) Dereferencing 'foo' after it is deallocated / released\n", errout.str()); + ASSERT_EQUALS("Checking file.cpp...\n" + "[file.cpp:5]: (error) Dereferencing 'foo' after it is deallocated / released\n", errout.str()); } void linenumbers2() diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index ff3c59f50..0f61736c7 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -101,6 +101,8 @@ private: TEST_CASE(if_cond6); TEST_CASE(if_cond7); + TEST_CASE(if_or); + TEST_CASE(multiline1); TEST_CASE(multiline2); TEST_CASE(multiline3); @@ -834,6 +836,35 @@ private: } + void if_or() + { + const char filedata[] = "#if defined(DEF_10) || defined(DEF_11)\n" + "a1;\n" + "#endif\n"; + + errout.str(""); + + // Preprocess => actual result.. + std::istringstream istr(filedata); + std::map actual; + Settings settings; + settings._verbose = true; + settings._debug = true; + Preprocessor preprocessor(&settings, this); + preprocessor.preprocess(istr, actual, "file.c"); + + // Compare results.. + ASSERT_EQUALS(1, actual.size()); + ASSERT_EQUALS("\n\n\n", actual[""]); + + // the "defined(DEF_10) || defined(DEF_11)" are not handled correctly.. + ASSERT_EQUALS("unhandled configuration: defined(DEF_10)||defined(DEF_11)\n", errout.str()); + TODO_ASSERT_EQUALS(2, actual.size()); + TODO_ASSERT_EQUALS("\na1;\n\n", actual["DEF_10"]); + + } + + void multiline1() { const char filedata[] = "#define str \"abc\" \\\n" diff --git a/test/testsuite.cpp b/test/testsuite.cpp index 215eb210e..abb175618 100644 --- a/test/testsuite.cpp +++ b/test/testsuite.cpp @@ -180,9 +180,9 @@ size_t TestFixture::runTests(const char cmd[]) return fails_counter; } -void TestFixture::reportOut(const std::string & /*outmsg*/) +void TestFixture::reportOut(const std::string & outmsg) { - // These can probably be ignored + errout << outmsg << std::endl; } void TestFixture::reportErr(const ErrorLogger::ErrorMessage &msg)