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
|
###### Object Files
|
||||||
|
|
||||||
LIBOBJ = lib/check64bit.o \
|
LIBOBJ = lib/check64bit.o \
|
||||||
|
lib/checkassignif.o \
|
||||||
lib/checkautovariables.o \
|
lib/checkautovariables.o \
|
||||||
lib/checkbufferoverrun.o \
|
lib/checkbufferoverrun.o \
|
||||||
lib/checkclass.o \
|
lib/checkclass.o \
|
||||||
|
@ -81,6 +82,7 @@ CLIOBJ = cli/cmdlineparser.o \
|
||||||
|
|
||||||
TESTOBJ = test/options.o \
|
TESTOBJ = test/options.o \
|
||||||
test/test64bit.o \
|
test/test64bit.o \
|
||||||
|
test/testassignif.o \
|
||||||
test/testautovariables.o \
|
test/testautovariables.o \
|
||||||
test/testbufferoverrun.o \
|
test/testbufferoverrun.o \
|
||||||
test/testcharvar.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
|
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
|
$(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
|
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
|
$(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
|
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
|
$(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
|
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
|
$(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
|
INCLUDEPATH += ../externals ../externals/tinyxml
|
||||||
HEADERS += $${BASEPATH}check.h \
|
HEADERS += $${BASEPATH}check.h \
|
||||||
$${BASEPATH}check64bit.h \
|
$${BASEPATH}check64bit.h \
|
||||||
|
$${BASEPATH}checkassignif.h \
|
||||||
$${BASEPATH}checkautovariables.h \
|
$${BASEPATH}checkautovariables.h \
|
||||||
$${BASEPATH}checkbufferoverrun.h \
|
$${BASEPATH}checkbufferoverrun.h \
|
||||||
$${BASEPATH}checkclass.h \
|
$${BASEPATH}checkclass.h \
|
||||||
|
@ -30,6 +31,7 @@ HEADERS += $${BASEPATH}check.h \
|
||||||
$${BASEPATH}tokenize.h
|
$${BASEPATH}tokenize.h
|
||||||
|
|
||||||
SOURCES += $${BASEPATH}check64bit.cpp \
|
SOURCES += $${BASEPATH}check64bit.cpp \
|
||||||
|
$${BASEPATH}checkassignif.cpp \
|
||||||
$${BASEPATH}checkautovariables.cpp \
|
$${BASEPATH}checkautovariables.cpp \
|
||||||
$${BASEPATH}checkbufferoverrun.cpp \
|
$${BASEPATH}checkbufferoverrun.cpp \
|
||||||
$${BASEPATH}checkclass.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