Fixed #982 (Preprocessor: detects and remove conditions which always true)
This commit is contained in:
parent
38a6c41730
commit
092f64b77a
|
@ -832,6 +832,22 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Replace defined constants
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string> varmap;
|
||||||
|
for (std::set<std::string>::const_iterator it = defines.begin(); it != defines.end(); ++it)
|
||||||
|
{
|
||||||
|
std::string::size_type pos = (*it).find("=");
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
continue;
|
||||||
|
const std::string varname((*it).substr(0, pos));
|
||||||
|
const std::string value((*it).substr(pos + 1));
|
||||||
|
varmap[varname] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
simplifyCondition(varmap, def);
|
||||||
|
}
|
||||||
|
|
||||||
if (! deflist.empty() && line.find("#elif ") == 0)
|
if (! deflist.empty() && line.find("#elif ") == 0)
|
||||||
deflist.pop_back();
|
deflist.pop_back();
|
||||||
deflist.push_back(def);
|
deflist.push_back(def);
|
||||||
|
@ -999,12 +1015,53 @@ std::list<std::string> Preprocessor::getcfgs(const std::string &filedata, const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Preprocessor::simplifyCondition(const std::map<std::string, std::string> &variables, std::string &condition)
|
||||||
|
{
|
||||||
|
Tokenizer tokenizer;
|
||||||
|
std::istringstream istr(condition.c_str());
|
||||||
|
tokenizer.tokenize(istr, "");
|
||||||
|
|
||||||
|
// replace variable names with values..
|
||||||
|
for (Token *tok = const_cast<Token *>(tokenizer.tokens()); tok; tok = tok->next())
|
||||||
|
{
|
||||||
|
const std::map<std::string, std::string>::const_iterator it = variables.find(tok->str());
|
||||||
|
if (it != variables.end())
|
||||||
|
tok->str(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
// simplify calculations..
|
||||||
|
tokenizer.simplifyCalculations();
|
||||||
|
|
||||||
|
if (!tokenizer.tokens()->tokAt(3) && Token::Match(tokenizer.tokens(), "%num% ==|!=|<=|>=|<|> %num%"))
|
||||||
|
{
|
||||||
|
const std::string op1(tokenizer.tokens()->str());
|
||||||
|
const std::string cmp(tokenizer.tokens()->strAt(1));
|
||||||
|
const std::string op2(tokenizer.tokens()->strAt(2));
|
||||||
|
if (cmp == "==")
|
||||||
|
condition = (op1 == op2) ? "1" : "0";
|
||||||
|
else if (cmp == "!=")
|
||||||
|
condition = (op1 != op2) ? "1" : "0";
|
||||||
|
else if (cmp == "<=")
|
||||||
|
condition = (op1 <= op2) ? "1" : "0";
|
||||||
|
else if (cmp == ">=")
|
||||||
|
condition = (op1 >= op2) ? "1" : "0";
|
||||||
|
else if (cmp == "<")
|
||||||
|
condition = (op1 < op2) ? "1" : "0";
|
||||||
|
else if (cmp == ">")
|
||||||
|
condition = (op1 > op2) ? "1" : "0";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg, std::string def)
|
bool Preprocessor::match_cfg_def(const std::map<std::string, std::string> &cfg, std::string def)
|
||||||
{
|
{
|
||||||
//std::cout << "cfg: \"" << cfg << "\" ";
|
//std::cout << "cfg: \"" << cfg << "\" ";
|
||||||
//std::cout << "def: \"" << def << "\"";
|
//std::cout << "def: \"" << def << "\"";
|
||||||
|
|
||||||
|
simplifyCondition(cfg, def);
|
||||||
|
|
||||||
if (cfg.find(def) != cfg.end())
|
if (cfg.find(def) != cfg.end())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,13 @@ public:
|
||||||
*/
|
*/
|
||||||
static std::string getcode(const std::string &filedata, std::string cfg, const std::string &filename, ErrorLogger *errorLogger);
|
static std::string getcode(const std::string &filedata, std::string cfg, const std::string &filename, ErrorLogger *errorLogger);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* simplify condition
|
||||||
|
* @param variables Variable values
|
||||||
|
* @param condition The condition to simplify
|
||||||
|
*/
|
||||||
|
static void simplifyCondition(const std::map<std::string, std::string> &variables, std::string &condition);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
static void writeError(const std::string &fileName, const std::string &code, size_t pos, ErrorLogger *errorLogger, const std::string &errorType, const std::string &errorText);
|
static void writeError(const std::string &fileName, const std::string &code, size_t pos, ErrorLogger *errorLogger, const std::string &errorType, const std::string &errorText);
|
||||||
|
|
|
@ -126,6 +126,13 @@ public:
|
||||||
*/
|
*/
|
||||||
std::map<std::string, ClassInfo> _classInfoList;
|
std::map<std::string, ClassInfo> _classInfoList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simplify constant calculations such as "1+2" => "3"
|
||||||
|
* @return true if modifications to token-list are done.
|
||||||
|
* false if no modifications are done.
|
||||||
|
*/
|
||||||
|
bool simplifyCalculations();
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
private:
|
private:
|
||||||
#endif
|
#endif
|
||||||
|
@ -272,13 +279,6 @@ private:
|
||||||
*/
|
*/
|
||||||
bool simplifyRedundantParanthesis();
|
bool simplifyRedundantParanthesis();
|
||||||
|
|
||||||
/**
|
|
||||||
* Simplify constant calculations such as "1+2" => "3"
|
|
||||||
* @return true if modifications to token-list are done.
|
|
||||||
* false if no modifications are done.
|
|
||||||
*/
|
|
||||||
bool simplifyCalculations();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplify functions like "void f(x) int x; {"
|
* Simplify functions like "void f(x) int x; {"
|
||||||
* into "void f(int x) {"
|
* into "void f(int x) {"
|
||||||
|
|
|
@ -99,6 +99,7 @@ private:
|
||||||
TEST_CASE(if_cond4);
|
TEST_CASE(if_cond4);
|
||||||
TEST_CASE(if_cond5);
|
TEST_CASE(if_cond5);
|
||||||
TEST_CASE(if_cond6);
|
TEST_CASE(if_cond6);
|
||||||
|
TEST_CASE(if_cond7);
|
||||||
|
|
||||||
TEST_CASE(multiline1);
|
TEST_CASE(multiline1);
|
||||||
TEST_CASE(multiline2);
|
TEST_CASE(multiline2);
|
||||||
|
@ -606,8 +607,8 @@ private:
|
||||||
cfg["A"] = "1";
|
cfg["A"] = "1";
|
||||||
cfg["B"] = "2";
|
cfg["B"] = "2";
|
||||||
|
|
||||||
TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A==1"));
|
ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A==1"));
|
||||||
TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A<2"));
|
ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A<2"));
|
||||||
ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "A==2"));
|
ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "A==2"));
|
||||||
ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "A<1"));
|
ASSERT_EQUALS(false, Preprocessor::match_cfg_def(cfg, "A<1"));
|
||||||
TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A>=1&&B<=A"));
|
TODO_ASSERT_EQUALS(true, Preprocessor::match_cfg_def(cfg, "A>=1&&B<=A"));
|
||||||
|
@ -798,6 +799,25 @@ private:
|
||||||
ASSERT_EQUALS("[file.c:2]: (error) mismatching number of '(' and ')' in this line: defined(A)&&defined(B))\n", errout.str());
|
ASSERT_EQUALS("[file.c:2]: (error) mismatching number of '(' and ')' in this line: defined(A)&&defined(B))\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void if_cond7()
|
||||||
|
{
|
||||||
|
const char filedata[] = "#define A 1\n"
|
||||||
|
"#if A==1\n"
|
||||||
|
"a1;\n"
|
||||||
|
"#endif\n";
|
||||||
|
|
||||||
|
// Preprocess => actual result..
|
||||||
|
std::istringstream istr(filedata);
|
||||||
|
std::map<std::string, std::string> actual;
|
||||||
|
const Settings settings;
|
||||||
|
Preprocessor preprocessor(&settings, this);
|
||||||
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
|
// Compare results..
|
||||||
|
ASSERT_EQUALS(1, actual.size());
|
||||||
|
ASSERT_EQUALS("\n\na1;\n\n", actual[""]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void multiline1()
|
void multiline1()
|
||||||
{
|
{
|
||||||
|
@ -1657,8 +1677,8 @@ private:
|
||||||
preprocessor.preprocess(istr, actual, "file.c");
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
TODO_ASSERT_EQUALS("\n\n1\n\n", actual[""]);
|
ASSERT_EQUALS("\n\n1\n\n", actual[""]);
|
||||||
TODO_ASSERT_EQUALS(1, actual.size());
|
ASSERT_EQUALS(1, actual.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1674,8 +1694,8 @@ private:
|
||||||
preprocessor.preprocess(istr, actual, "file.c");
|
preprocessor.preprocess(istr, actual, "file.c");
|
||||||
|
|
||||||
// Compare results..
|
// Compare results..
|
||||||
TODO_ASSERT_EQUALS("\n\n1\n\n", actual[""]);
|
ASSERT_EQUALS("\n\n1\n\n", actual[""]);
|
||||||
TODO_ASSERT_EQUALS(1, actual.size());
|
ASSERT_EQUALS(1, actual.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue