Partial fix for #5555. Add const,pure attributes to library.

This commit is contained in:
Daniel Marjamäki 2014-03-14 06:38:45 +01:00
parent 8c993c1363
commit 8d8913a168
5 changed files with 28 additions and 14 deletions

View File

@ -40,7 +40,7 @@
<function name="strchr"> <noreturn>false</noreturn> <leak-ignore/> <arg nr="1"><not-null/><not-uninit/></arg> </function>
<function name="strcoll"> <noreturn>false</noreturn> <leak-ignore/> <arg nr="1"><not-null/><not-uninit/></arg> <arg nr="2"><not-null/><not-uninit/></arg> </function>
<function name="strcpy"> <noreturn>false</noreturn> <leak-ignore/> <arg nr="1"><not-null/></arg> <arg nr="2"><not-null/><not-uninit/></arg> </function>
<function name="strcmp"> <noreturn>false</noreturn> <leak-ignore/> <arg nr="1"><not-null/><not-uninit/></arg> <arg nr="2"><not-null/><not-uninit/></arg> </function>
<function name="strcmp"> <noreturn>false</noreturn> <const/> <pure/> <leak-ignore/> <arg nr="1"><not-null/><not-uninit/></arg> <arg nr="2"><not-null/><not-uninit/></arg> </function>
<function name="strdup"> <noreturn>false</noreturn> <leak-ignore/> <arg nr="1"><not-null/><not-uninit/></arg> </function>
<function name="strlen"> <noreturn>false</noreturn> <leak-ignore/> <arg nr="1"><not-null/><not-uninit/></arg> </function>
<function name="strncat"> <noreturn>false</noreturn> <leak-ignore/> <arg nr="1"><not-null/><not-uninit/></arg> <arg nr="2"><not-null/><not-uninit/></arg> <arg nr="3"><not-bool/><valid>0-</valid></arg> </function>

View File

@ -73,9 +73,9 @@ static bool isSameExpression(const Token *tok1, const Token *tok2, const std::se
if (tok1->isExpandedMacro() || tok2->isExpandedMacro())
return false;
if (tok1->isName() && tok1->next()->str() == "(") {
if (!tok1->function() && !Token::Match(tok1->previous(), ".|::") && constFunctions.find(tok1->str()) == constFunctions.end())
if (!tok1->function() && !Token::Match(tok1->previous(), ".|::") && constFunctions.find(tok1->str()) == constFunctions.end() && !tok1->isAttributeConst() && !tok1->isAttributePure())
return false;
else if (tok1->function() && !tok1->function()->isConst)
else if (tok1->function() && !tok1->function()->isConst && !tok1->function()->isAttributeConst() && !tok1->function()->isAttributePure())
return false;
}
// templates/casts
@ -2868,27 +2868,24 @@ void CheckOther::checkDuplicateExpression()
if (scope->type != Scope::eFunction)
continue;
std::set<std::string> constStandardFunctions;
constStandardFunctions.insert("strcmp");
// Experimental implementation
// TODO: check for duplicate separated expressions: (a==1 || a==2 || a==1)
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
if (tok->isOp() && tok->astOperand1() && !Token::Match(tok, "+|-|*|/|%|=|<<|>>")) {
if (Token::Match(tok, "==|!=|-") && astIsFloat(tok->astOperand1()))
continue;
if (isSameExpression(tok->astOperand1(), tok->astOperand2(), constStandardFunctions))
if (isSameExpression(tok->astOperand1(), tok->astOperand2(), _settings->library.functionconst))
duplicateExpressionError(tok, tok, tok->str());
else if (tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(tok->astOperand2(), tok->astOperand1()->astOperand2(), constStandardFunctions))
else if (tok->astOperand2() && tok->str() == tok->astOperand1()->str() && isSameExpression(tok->astOperand2(), tok->astOperand1()->astOperand2(), _settings->library.functionconst))
duplicateExpressionError(tok->astOperand2(), tok->astOperand2(), tok->str());
else if (tok->astOperand2()) {
const Token *ast1 = tok->astOperand1();
while (ast1 && tok->str() == ast1->str()) {
if (isSameExpression(ast1->astOperand1(), tok->astOperand2(), constStandardFunctions))
if (isSameExpression(ast1->astOperand1(), tok->astOperand2(), _settings->library.functionconst))
duplicateExpressionError(ast1->astOperand1(), tok->astOperand2(), tok->str());
else if (isSameExpression(ast1->astOperand2(), tok->astOperand2(), constStandardFunctions))
else if (isSameExpression(ast1->astOperand2(), tok->astOperand2(), _settings->library.functionconst))
duplicateExpressionError(ast1->astOperand2(), tok->astOperand2(), tok->str());
if (!isConstExpression(ast1->astOperand2(), constStandardFunctions))
if (!isConstExpression(ast1->astOperand2(), _settings->library.functionconst))
break;
ast1 = ast1->astOperand1();
}

View File

@ -134,6 +134,10 @@ bool Library::load(const tinyxml2::XMLDocument &doc)
for (const tinyxml2::XMLElement *functionnode = node->FirstChildElement(); functionnode; functionnode = functionnode->NextSiblingElement()) {
if (strcmp(functionnode->Name(),"noreturn")==0)
_noreturn[name] = (strcmp(functionnode->GetText(), "true") == 0);
else if (strcmp(functionnode->Name(), "pure") == 0)
functionpure.insert(name);
else if (strcmp(functionnode->Name(), "const") == 0)
functionconst.insert(name);
else if (strcmp(functionnode->Name(),"leak-ignore")==0)
leakignore.insert(name);
else if (strcmp(functionnode->Name(), "arg") == 0 && functionnode->Attribute("nr") != nullptr) {

View File

@ -98,6 +98,8 @@ public:
std::set<std::string> use;
std::set<std::string> leakignore;
std::set<std::string> functionconst;
std::set<std::string> functionpure;
bool isnoreturn(const std::string &name) const {
std::map<std::string, bool>::const_iterator it = _noreturn.find(name);

View File

@ -4825,10 +4825,21 @@ private:
"}");
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"
" if ((strcmp(a, b) == 0) || (strcmp(a, b) == 0)) {}\n"
{
LOAD_LIB("std.cfg");
Settings settings;
settings.library = _lib;
check("void foo() {\n"
" if ((strcmp(a, b) == 0) || (strcmp(a, b) == 0)) {}\n"
"}", "test.cpp", false, false, false, true, &settings);
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Same expression on both sides of '||'.\n", errout.str());
}
check("void GetValue() __attribute__((const)) { return X; }\n"
"void foo() {\n"
" if ((GetValue() == 0) || (GetValue() == 0)) { dostuff(); }\n"
"}");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:2]: (style) Same expression on both sides of '||'.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:3]: (style) Same expression on both sides of '||'.\n", errout.str());
check("void foo() {\n"
" if (str == \"(\" || str == \"(\") {}\n"