Partial fix for #5555. Add const,pure attributes to library.
This commit is contained in:
parent
8c993c1363
commit
8d8913a168
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue