AssignIf: Added new check. Ticket: #2909
This commit is contained in:
parent
7f193fb7a1
commit
47f13860b7
8
Makefile
8
Makefile
|
@ -47,6 +47,7 @@ MAN_SOURCE=man/cppcheck.1.xml
|
|||
###### Object Files
|
||||
|
||||
LIBOBJ = lib/check64bit.o \
|
||||
lib/checkassignif.o \
|
||||
lib/checkautovariables.o \
|
||||
lib/checkbufferoverrun.o \
|
||||
lib/checkclass.o \
|
||||
|
@ -81,6 +82,7 @@ CLIOBJ = cli/cmdlineparser.o \
|
|||
|
||||
TESTOBJ = test/options.o \
|
||||
test/test64bit.o \
|
||||
test/testassignif.o \
|
||||
test/testautovariables.o \
|
||||
test/testbufferoverrun.o \
|
||||
test/testcharvar.o \
|
||||
|
@ -170,6 +172,9 @@ install: cppcheck
|
|||
lib/check64bit.o: lib/check64bit.cpp lib/check64bit.h lib/check.h lib/token.h lib/tokenize.h lib/settings.h lib/errorlogger.h lib/symboldatabase.h lib/mathlib.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_LIB} -c -o lib/check64bit.o lib/check64bit.cpp
|
||||
|
||||
lib/checkassignif.o: lib/checkassignif.cpp lib/checkassignif.h lib/check.h lib/token.h lib/tokenize.h lib/settings.h lib/errorlogger.h lib/symboldatabase.h lib/mathlib.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_LIB} -c -o lib/checkassignif.o lib/checkassignif.cpp
|
||||
|
||||
lib/checkautovariables.o: lib/checkautovariables.cpp lib/checkautovariables.h lib/check.h lib/token.h lib/tokenize.h lib/settings.h lib/errorlogger.h lib/symboldatabase.h lib/mathlib.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_LIB} -c -o lib/checkautovariables.o lib/checkautovariables.cpp
|
||||
|
||||
|
@ -266,6 +271,9 @@ test/options.o: test/options.cpp test/options.h
|
|||
test/test64bit.o: test/test64bit.cpp lib/tokenize.h lib/check64bit.h lib/check.h lib/token.h lib/settings.h lib/errorlogger.h test/testsuite.h test/redirect.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/test64bit.o test/test64bit.cpp
|
||||
|
||||
test/testassignif.o: test/testassignif.cpp lib/tokenize.h lib/checkassignif.h lib/check.h lib/token.h lib/settings.h lib/errorlogger.h test/testsuite.h test/redirect.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testassignif.o test/testassignif.cpp
|
||||
|
||||
test/testautovariables.o: test/testautovariables.cpp lib/tokenize.h lib/checkautovariables.h lib/check.h lib/token.h lib/settings.h lib/errorlogger.h test/testsuite.h test/redirect.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testautovariables.o test/testautovariables.cpp
|
||||
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2011 Daniel Marjamäki and Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Check for assignment / condition mismatches
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "checkassignif.h"
|
||||
#include "symboldatabase.h"
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
// Register this check class (by creating a static instance of it)
|
||||
namespace
|
||||
{
|
||||
CheckAssignIf instance;
|
||||
}
|
||||
|
||||
|
||||
void CheckAssignIf::check()
|
||||
{
|
||||
if (!_settings->_checkCodingStyle)
|
||||
return;
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if (tok->str() != "=")
|
||||
continue;
|
||||
|
||||
if (Token::Match(tok->tokAt(-2), "[;{}] %var% = %var% & %num% ;"))
|
||||
{
|
||||
const unsigned int varid(tok->previous()->varId());
|
||||
if (varid == 0)
|
||||
continue;
|
||||
|
||||
const MathLib::bigint num = MathLib::toLongNumber(tok->strAt(3));
|
||||
if (num < 0)
|
||||
continue;
|
||||
|
||||
for (const Token *tok2 = tok->tokAt(4); tok2; tok2 = tok2->next())
|
||||
{
|
||||
if (tok2->str() == "(" || tok2->str() == "}" || tok2->str() == "=")
|
||||
break;
|
||||
if (Token::Match(tok2,"if ( %varid% %any% %num% ) ", varid))
|
||||
{
|
||||
const std::string op(tok2->strAt(3));
|
||||
const MathLib::bigint num2 = MathLib::toLongNumber(tok2->strAt(4));
|
||||
if (op == "==" && (num & num2) != num2)
|
||||
mismatchError(tok2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckAssignIf::mismatchError(const Token *tok)
|
||||
{
|
||||
reportError(tok, Severity::style,
|
||||
"assignIfMismatchError",
|
||||
"Mismatching assignment and condition, condition is always false");
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2011 Daniel Marjamäki and Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
#ifndef checkassignifH
|
||||
#define checkassignifH
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
#include "check.h"
|
||||
|
||||
|
||||
/// @addtogroup Checks
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* @brief Check for assignment / condition mismatches
|
||||
*/
|
||||
|
||||
class CheckAssignIf : public Check
|
||||
{
|
||||
public:
|
||||
/** This constructor is used when registering the CheckAssignIf */
|
||||
CheckAssignIf() : Check(myName())
|
||||
{
|
||||
}
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckAssignIf(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{
|
||||
}
|
||||
|
||||
/** @brief Run checks against the simplified token list */
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
{
|
||||
CheckAssignIf checkAssignIf(tokenizer, settings, errorLogger);
|
||||
checkAssignIf.check();
|
||||
}
|
||||
|
||||
/** Check for obsolete functions */
|
||||
void check();
|
||||
|
||||
private:
|
||||
|
||||
void mismatchError(const Token *tok);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
|
||||
{
|
||||
CheckAssignIf c(0, settings, errorLogger);
|
||||
c.mismatchError(0);
|
||||
}
|
||||
|
||||
std::string myName() const
|
||||
{
|
||||
return "match assignment / conditions";
|
||||
}
|
||||
|
||||
std::string classInfo() const
|
||||
{
|
||||
return "Match assignments and conditions:\n"
|
||||
" mismatching assignment and condition";
|
||||
}
|
||||
};
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
#endif
|
||||
|
|
@ -4,6 +4,7 @@ LIBS += -L../externals -lpcre
|
|||
INCLUDEPATH += ../externals ../externals/tinyxml
|
||||
HEADERS += $${BASEPATH}check.h \
|
||||
$${BASEPATH}check64bit.h \
|
||||
$${BASEPATH}checkassignif.h \
|
||||
$${BASEPATH}checkautovariables.h \
|
||||
$${BASEPATH}checkbufferoverrun.h \
|
||||
$${BASEPATH}checkclass.h \
|
||||
|
@ -30,6 +31,7 @@ HEADERS += $${BASEPATH}check.h \
|
|||
$${BASEPATH}tokenize.h
|
||||
|
||||
SOURCES += $${BASEPATH}check64bit.cpp \
|
||||
$${BASEPATH}checkassignif.cpp \
|
||||
$${BASEPATH}checkautovariables.cpp \
|
||||
$${BASEPATH}checkbufferoverrun.cpp \
|
||||
$${BASEPATH}checkclass.cpp \
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Cppcheck - A tool for static C/C++ code analysis
|
||||
* Copyright (C) 2007-2011 Daniel Marjamäki and Cppcheck team.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "tokenize.h"
|
||||
#include "checkassignif.h"
|
||||
#include "testsuite.h"
|
||||
#include <sstream>
|
||||
|
||||
extern std::ostringstream errout;
|
||||
|
||||
class TestAssignIf : public TestFixture
|
||||
{
|
||||
public:
|
||||
TestAssignIf() : TestFixture("TestAssignIf")
|
||||
{ }
|
||||
|
||||
private:
|
||||
|
||||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE(testand);
|
||||
}
|
||||
|
||||
void check(const char code[])
|
||||
{
|
||||
// Clear the error buffer..
|
||||
errout.str("");
|
||||
|
||||
Settings settings;
|
||||
settings._checkCodingStyle = true;
|
||||
|
||||
// Tokenize..
|
||||
Tokenizer tokenizer(&settings, this);
|
||||
std::istringstream istr(code);
|
||||
tokenizer.tokenize(istr, "test.cpp");
|
||||
tokenizer.setVarId();
|
||||
tokenizer.simplifyTokenList();
|
||||
|
||||
// Check char variable usage..
|
||||
CheckAssignIf CheckAssignIf(&tokenizer, &settings, this);
|
||||
CheckAssignIf.check();
|
||||
}
|
||||
|
||||
void testand()
|
||||
{
|
||||
check("void foo(int x)\n"
|
||||
"{\n"
|
||||
" int y = x & 4;\n"
|
||||
" if (y == 3);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (style) Mismatching assignment and condition, condition is always false\n", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestAssignIf)
|
||||
|
Loading…
Reference in New Issue