Merge branch 'master' of http://github.com/danmar/cppcheck
This commit is contained in:
commit
8ad863d650
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
# This file is generated by tools/dmake, do not edit.
|
||||
|
||||
ifndef CXXFLAGS
|
||||
CXXFLAGS=-Wall -Wextra -Wshadow -pedantic -Wno-long-long -Wfloat-equal -Wcast-qual -Wsign-conversion -g
|
||||
CXXFLAGS=-DHAVE_DEPENDENCIES -Wall -Wextra -Wshadow -pedantic -Wno-long-long -Wfloat-equal -Wcast-qual -Wsign-conversion -g
|
||||
endif
|
||||
|
||||
ifndef CXX
|
||||
|
|
|
@ -5,6 +5,7 @@ INCLUDEPATH += . ../lib
|
|||
OBJECTS_DIR = temp
|
||||
CONFIG += warn_on
|
||||
CONFIG -= qt app_bundle
|
||||
DEFINES += HAVE_DEPENDENCIES
|
||||
|
||||
BASEPATH = ../externals/tinyxml/
|
||||
include($$PWD/../externals/tinyxml/tinyxml.pri)
|
||||
|
|
|
@ -28,8 +28,10 @@
|
|||
#include "path.h"
|
||||
#include "filelister.h"
|
||||
|
||||
#ifdef HAVE_DEPENDENCIES
|
||||
// xml is used in rules
|
||||
#include <tinyxml.h>
|
||||
#endif
|
||||
|
||||
static void AddFilesToList(const std::string& FileList, std::vector<std::string>& PathNames)
|
||||
{
|
||||
|
@ -503,6 +505,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
|||
_settings->_showtime = SHOWTIME_NONE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DEPENDENCIES
|
||||
// Rule given at command line
|
||||
else if (strncmp(argv[i], "--rule=", 7) == 0)
|
||||
{
|
||||
|
@ -549,6 +552,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Print help
|
||||
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
|
||||
|
|
|
@ -213,14 +213,11 @@ void MainWindow::DoCheckFiles(const QStringList &files)
|
|||
QDir inf(mCurrentDirectory);
|
||||
const QString checkPath = inf.canonicalPath();
|
||||
mSettings->setValue(SETTINGS_CHECK_PATH, checkPath);
|
||||
EnableCheckButtons(false);
|
||||
mUI.mActionSettings->setEnabled(false);
|
||||
mUI.mActionOpenXML->setEnabled(false);
|
||||
mUI.mResults->SetCheckDirectory(checkPath);
|
||||
|
||||
CheckLockDownUI(); // lock UI while checking
|
||||
|
||||
mUI.mResults->SetCheckDirectory(checkPath);
|
||||
Settings checkSettings = GetCppcheckSettings();
|
||||
EnableProjectActions(false);
|
||||
EnableProjectOpenActions(false);
|
||||
mThread->Check(checkSettings, false);
|
||||
}
|
||||
|
||||
|
@ -400,6 +397,15 @@ void MainWindow::CheckDone()
|
|||
QApplication::alert(this, 3000);
|
||||
}
|
||||
|
||||
void MainWindow::CheckLockDownUI()
|
||||
{
|
||||
EnableCheckButtons(false);
|
||||
mUI.mActionSettings->setEnabled(false);
|
||||
mUI.mActionOpenXML->setEnabled(false);
|
||||
EnableProjectActions(false);
|
||||
EnableProjectOpenActions(false);
|
||||
}
|
||||
|
||||
void MainWindow::ProgramSettings()
|
||||
{
|
||||
SettingsDialog dialog(mSettings, mApplications, mTranslation, this);
|
||||
|
@ -418,7 +424,7 @@ void MainWindow::ProgramSettings()
|
|||
void MainWindow::ReCheck()
|
||||
{
|
||||
ClearResults();
|
||||
EnableCheckButtons(false);
|
||||
CheckLockDownUI(); // lock UI while checking
|
||||
|
||||
const int filesCount = mThread->GetPreviousFilesCount();
|
||||
Q_ASSERT(filesCount > 0); // If no files should not be able to recheck
|
||||
|
|
|
@ -206,6 +206,12 @@ protected slots:
|
|||
*/
|
||||
void CheckDone();
|
||||
|
||||
/**
|
||||
* @brief Lock down UI while checking
|
||||
*
|
||||
*/
|
||||
void CheckLockDownUI();
|
||||
|
||||
/**
|
||||
* @brief Slot for enabling save and clear button
|
||||
*
|
||||
|
|
|
@ -87,8 +87,9 @@ QStandardItem *ResultsTree::CreateNormalItem(const QString &name)
|
|||
|
||||
QStandardItem *ResultsTree::CreateLineNumberItem(const QString &linenumber)
|
||||
{
|
||||
QStandardItem *item = new QStandardItem(linenumber);
|
||||
item->setData(linenumber, Qt::ToolTipRole);
|
||||
QStandardItem *item = new QStandardItem();
|
||||
item->setData(QVariant(linenumber.toULongLong()), Qt::DisplayRole);
|
||||
item->setToolTip(linenumber);
|
||||
item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
|
||||
item->setEditable(false);
|
||||
return item;
|
||||
|
|
|
@ -464,6 +464,11 @@ void CheckBufferOverrun::parse_for_body(const Token *tok2, const ArrayInfo &arra
|
|||
break;
|
||||
}
|
||||
|
||||
// TODO: try to reduce false negatives. This is just a quick fix
|
||||
// for TestBufferOverrun::array_index_for_question
|
||||
if (tok2->str() == "?")
|
||||
break;
|
||||
|
||||
if (Token::Match(tok2, "if|switch"))
|
||||
{
|
||||
if (bailoutIfSwitch(tok2, arrayInfo.varid))
|
||||
|
|
|
@ -610,7 +610,9 @@ void CheckClass::privateFunctions()
|
|||
if (!func->hasBody)
|
||||
{
|
||||
// empty private copy constructors and assignment operators are OK
|
||||
if ((func->type == Function::eCopyConstructor || func->type == Function::eOperatorEqual) && func->access == Private)
|
||||
if ((func->type == Function::eCopyConstructor ||
|
||||
func->type == Function::eOperatorEqual) &&
|
||||
func->access == Private)
|
||||
continue;
|
||||
|
||||
whole = false;
|
||||
|
@ -630,98 +632,37 @@ void CheckClass::privateFunctions()
|
|||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func)
|
||||
{
|
||||
// Get private functions..
|
||||
if (func->type == Function::eFunction &&
|
||||
func->access == Private && func->hasBody)
|
||||
if (func->type == Function::eFunction && func->access == Private)
|
||||
FuncList.push_back(func->tokenDef);
|
||||
}
|
||||
}
|
||||
|
||||
// Check that all private functions are used..
|
||||
bool HasFuncImpl = false;
|
||||
bool inclass = false;
|
||||
int indent_level = 0;
|
||||
for (const Token *ftok = _tokenizer->tokens(); ftok; ftok = ftok->next())
|
||||
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func)
|
||||
{
|
||||
if (ftok->str() == "{")
|
||||
++indent_level;
|
||||
else if (ftok->str() == "}")
|
||||
{
|
||||
if (indent_level > 0)
|
||||
--indent_level;
|
||||
if (indent_level == 0)
|
||||
inclass = false;
|
||||
}
|
||||
const Token *ftok = func->arg->link()->next();
|
||||
while (ftok->str() != "{")
|
||||
ftok = ftok->next();
|
||||
const Token *etok = ftok->link();
|
||||
|
||||
else if (ftok->str() == "class" &&
|
||||
ftok->next()->str() == classname &&
|
||||
Token::Match(ftok->tokAt(2), ":|{"))
|
||||
for (; ftok != etok; ftok = ftok->next())
|
||||
{
|
||||
indent_level = 0;
|
||||
inclass = true;
|
||||
}
|
||||
|
||||
// Check member class functions to see what functions are used..
|
||||
else if ((inclass && indent_level == 1 && Token::Match(ftok, "%var% (")) ||
|
||||
(ftok->str() == classname && Token::Match(ftok->next(), ":: ~| %var% (")))
|
||||
{
|
||||
while (ftok && ftok->str() != ")")
|
||||
ftok = ftok->next();
|
||||
if (!ftok)
|
||||
break;
|
||||
if (Token::Match(ftok, ") : %var% ("))
|
||||
if (Token::Match(ftok, "%var% ("))
|
||||
{
|
||||
while (!Token::Match(ftok->next(), "[{};]"))
|
||||
// Remove function from FuncList
|
||||
std::list<const Token *>::iterator it = FuncList.begin();
|
||||
while (it != FuncList.end())
|
||||
{
|
||||
if (Token::Match(ftok, "::|,|( %var% ,|)"))
|
||||
{
|
||||
// Remove function from FuncList
|
||||
std::list<const Token *>::iterator it = FuncList.begin();
|
||||
while (it != FuncList.end())
|
||||
{
|
||||
if (ftok->next()->str() == (*it)->str())
|
||||
FuncList.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
ftok = ftok->next();
|
||||
}
|
||||
}
|
||||
if (!Token::Match(ftok, ") const| {"))
|
||||
continue;
|
||||
|
||||
if (ftok->fileIndex() == 0)
|
||||
HasFuncImpl = true;
|
||||
|
||||
// Parse function..
|
||||
int indentlevel2 = 0;
|
||||
for (const Token *tok2 = ftok; tok2; tok2 = tok2->next())
|
||||
{
|
||||
if (tok2->str() == "{")
|
||||
++indentlevel2;
|
||||
else if (tok2->str() == "}")
|
||||
{
|
||||
--indentlevel2;
|
||||
if (indentlevel2 < 1)
|
||||
break;
|
||||
}
|
||||
else if (Token::Match(tok2, "%var% ("))
|
||||
{
|
||||
// Remove function from FuncList
|
||||
std::list<const Token *>::iterator it = FuncList.begin();
|
||||
while (it != FuncList.end())
|
||||
{
|
||||
if (tok2->str() == (*it)->str())
|
||||
FuncList.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
if (ftok->str() == (*it)->str())
|
||||
FuncList.erase(it++);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (HasFuncImpl && !FuncList.empty())
|
||||
while (!FuncList.empty())
|
||||
{
|
||||
// Final check; check if the function pointer is used somewhere..
|
||||
const std::string _pattern("return|(|)|,|= " + FuncList.front()->str());
|
||||
|
|
|
@ -34,6 +34,38 @@ CheckOther instance;
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void CheckOther::checkIncrementBoolean()
|
||||
{
|
||||
if (!_settings->_checkCodingStyle)
|
||||
return;
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok, "%var% ++"))
|
||||
{
|
||||
if (tok->varId())
|
||||
{
|
||||
const Token *declTok = Token::findmatch(_tokenizer->tokens(), "bool %varid%", tok->varId());
|
||||
if (declTok)
|
||||
incrementBooleanError(tok);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckOther::incrementBooleanError(const Token *tok)
|
||||
{
|
||||
reportError(
|
||||
tok,
|
||||
Severity::style,
|
||||
"incrementboolean",
|
||||
"The use of a variable of type bool with the ++ postfix operator is always true and deprecated by the C++ Standard.\n"
|
||||
"The operand of a postfix increment operator may be of type bool but it is deprecated by C++ Standard (Annex D-1) and the operand is always set to true\n"
|
||||
);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
void CheckOther::clarifyCalculation()
|
||||
{
|
||||
|
|
|
@ -88,6 +88,7 @@ public:
|
|||
checkOther.checkCatchExceptionByValue();
|
||||
checkOther.checkMemsetZeroBytes();
|
||||
checkOther.checkIncorrectStringCompare();
|
||||
checkOther.checkIncrementBoolean();
|
||||
}
|
||||
|
||||
/** @brief Clarify calculation for ".. a * b ? .." */
|
||||
|
@ -184,6 +185,9 @@ public:
|
|||
/** @brief %Check for using bad usage of strncmp and substr */
|
||||
void checkIncorrectStringCompare();
|
||||
|
||||
/** @brief %Check for using postfix increment on bool */
|
||||
void checkIncrementBoolean();
|
||||
|
||||
// Error messages..
|
||||
void cstyleCastError(const Token *tok);
|
||||
void dangerousUsageStrtolError(const Token *tok);
|
||||
|
@ -209,6 +213,7 @@ public:
|
|||
void memsetZeroBytesError(const Token *tok, const std::string &varname);
|
||||
void sizeofForArrayParameterError(const Token *tok);
|
||||
void incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string, const std::string &len);
|
||||
void incrementBooleanError(const Token *tok);
|
||||
|
||||
void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings)
|
||||
{
|
||||
|
@ -249,6 +254,7 @@ public:
|
|||
c.memsetZeroBytesError(0, "varname");
|
||||
c.clarifyCalculationError(0);
|
||||
c.incorrectStringCompareError(0, "substr", "\"Hello World\"", "12");
|
||||
c.incrementBooleanError(0);
|
||||
}
|
||||
|
||||
std::string myName() const
|
||||
|
@ -289,6 +295,7 @@ public:
|
|||
"* mutual exclusion over || always evaluating to true\n"
|
||||
"* exception caught by value instead of by reference\n"
|
||||
"* Clarify calculation with parantheses\n"
|
||||
"* using increment on boolean\n"
|
||||
|
||||
// optimisations
|
||||
"* optimisation: detect post increment/decrement\n";
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <ctime>
|
||||
#include "timer.h"
|
||||
|
||||
#ifndef __BORLANDC__
|
||||
#ifdef HAVE_DEPENDENCIES
|
||||
#define PCRE_STATIC
|
||||
#include <pcre.h>
|
||||
#endif
|
||||
|
@ -309,7 +309,7 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
|||
(*it)->runSimplifiedChecks(&_tokenizer, &_settings, this);
|
||||
}
|
||||
|
||||
#ifndef __BORLANDC__
|
||||
#ifdef HAVE_DEPENDENCIES
|
||||
// Are there extra rules?
|
||||
if (!_settings.rules.empty())
|
||||
{
|
||||
|
|
|
@ -109,39 +109,19 @@ static std::string join(const std::list<std::string> &list, char separator)
|
|||
/** Just read the code into a string. Perform simple cleanup of the code */
|
||||
std::string Preprocessor::read(std::istream &istr, const std::string &filename, Settings *settings)
|
||||
{
|
||||
// Get filedata from stream..
|
||||
bool ignoreSpace = true;
|
||||
|
||||
// need space.. #if( => #if (
|
||||
bool needSpace = false;
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
//
|
||||
// handling <backspace><newline>
|
||||
// when this is encountered the <backspace><newline> will be "skipped".
|
||||
// on the next <newline>, extra newlines will be added
|
||||
unsigned int newlines = 0;
|
||||
|
||||
std::ostringstream code;
|
||||
unsigned int newlines = 0;
|
||||
for (unsigned char ch = readChar(istr); istr.good(); ch = readChar(istr))
|
||||
{
|
||||
// Replace assorted special chars with spaces..
|
||||
if (((ch & 0x80) == 0) && (ch != '\n') && (std::isspace(ch) || std::iscntrl(ch)))
|
||||
ch = ' ';
|
||||
|
||||
// Skip spaces after ' ' and after '#'
|
||||
if (ch == ' ' && ignoreSpace)
|
||||
continue;
|
||||
ignoreSpace = bool(ch == ' ' || ch == '#' || ch == '\n');
|
||||
|
||||
if (needSpace)
|
||||
{
|
||||
if (ch == '(' || ch == '!')
|
||||
code << " ";
|
||||
else if (!std::isalpha(ch))
|
||||
needSpace = false;
|
||||
}
|
||||
if (ch == '#')
|
||||
needSpace = true;
|
||||
|
||||
// <backspace><newline>..
|
||||
// for gcc-compatibility the trailing spaces should be ignored
|
||||
// for vs-compatibility the trailing spaces should be kept
|
||||
|
@ -178,8 +158,6 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename,
|
|||
else
|
||||
code << "\\";
|
||||
}
|
||||
|
||||
// Just some code..
|
||||
else
|
||||
{
|
||||
code << char(ch);
|
||||
|
@ -192,8 +170,124 @@ std::string Preprocessor::read(std::istream &istr, const std::string &filename,
|
|||
}
|
||||
}
|
||||
}
|
||||
std::string result = code.str();
|
||||
code.str("");
|
||||
|
||||
return removeParantheses(removeComments(code.str(), filename, settings));
|
||||
// ------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Remove all comments..
|
||||
result = removeComments(result, filename, settings);
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Clean up all preprocessor statements
|
||||
result = preprocessCleanupDirectives(result);
|
||||
|
||||
// ------------------------------------------------------------------------------------------
|
||||
//
|
||||
// Clean up preprocessor #if statements with Parantheses
|
||||
result = removeParantheses(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Preprocessor::preprocessCleanupDirectives(const std::string &processedFile) const
|
||||
{
|
||||
std::ostringstream code;
|
||||
std::istringstream sstr(processedFile);
|
||||
|
||||
std::string line;
|
||||
while (std::getline(sstr, line))
|
||||
{
|
||||
// Trim lines..
|
||||
if (!line.empty() && line[0] == ' ')
|
||||
line.erase(0, line.find_first_not_of(" "));
|
||||
if (!line.empty() && line[line.size()-1] == ' ')
|
||||
line.erase(line.find_last_not_of(" ") + 1);
|
||||
|
||||
// Preprocessor
|
||||
if (!line.empty() && line[0] == '#')
|
||||
{
|
||||
enum
|
||||
{
|
||||
ESC_NONE,
|
||||
ESC_SINGLE,
|
||||
ESC_DOUBLE
|
||||
} escapeStatus = ESC_NONE;
|
||||
|
||||
char prev = ' '; // hack to make it skip spaces between # and the directive
|
||||
code << "#";
|
||||
std::string::const_iterator i = line.begin();
|
||||
i++;
|
||||
|
||||
// need space.. #if( => #if (
|
||||
bool needSpace = true;
|
||||
while (i != line.end())
|
||||
{
|
||||
// disable esc-mode
|
||||
if (escapeStatus != ESC_NONE)
|
||||
{
|
||||
if (prev != '\\' && escapeStatus == ESC_SINGLE && *i == '\'')
|
||||
{
|
||||
escapeStatus = ESC_NONE;
|
||||
}
|
||||
if (prev != '\\' && escapeStatus == ESC_DOUBLE && *i == '"')
|
||||
{
|
||||
escapeStatus = ESC_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// enable esc-mode
|
||||
if (escapeStatus == ESC_NONE && *i == '"')
|
||||
escapeStatus = ESC_DOUBLE;
|
||||
if (escapeStatus == ESC_NONE && *i == '\'')
|
||||
escapeStatus = ESC_SINGLE;
|
||||
}
|
||||
// skip double whitespace between arguments
|
||||
if (escapeStatus == ESC_NONE && prev == ' ' && *i == ' ')
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
// Convert #if( to "#if ("
|
||||
if (escapeStatus == ESC_NONE)
|
||||
{
|
||||
if (needSpace)
|
||||
{
|
||||
if (*i == '(' || *i == '!')
|
||||
code << " ";
|
||||
else if (!std::isalpha(*i))
|
||||
needSpace = false;
|
||||
}
|
||||
if (*i == '#')
|
||||
needSpace = true;
|
||||
}
|
||||
code << *i;
|
||||
if (escapeStatus != ESC_NONE && prev == '\\' && *i == '\\')
|
||||
{
|
||||
prev = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = *i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (escapeStatus != ESC_NONE)
|
||||
{
|
||||
// unmatched quotes.. compiler should probably complain about this..
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not mess with regular code..
|
||||
code << line;
|
||||
}
|
||||
code << (sstr.eof()?"":"\n");
|
||||
}
|
||||
|
||||
return code.str();
|
||||
}
|
||||
|
||||
static bool hasbom(const std::string &str)
|
||||
|
@ -668,9 +762,6 @@ void Preprocessor::preprocess(std::istream &srcCodeStream, std::string &processe
|
|||
|
||||
processedFile = read(srcCodeStream, filename, _settings);
|
||||
|
||||
// normalize the whitespaces of the file
|
||||
preprocessWhitespaces(processedFile);
|
||||
|
||||
// Remove asm(...)
|
||||
removeAsm(processedFile);
|
||||
|
||||
|
@ -1460,7 +1551,8 @@ std::string Preprocessor::getcode(const std::string &filedata, std::string cfg,
|
|||
return "";
|
||||
}
|
||||
|
||||
if (!match && line.compare(0, 8, "#define ") == 0)
|
||||
if (!match && (line.compare(0, 8, "#define ") == 0 ||
|
||||
line.compare(0, 6, "#undef") == 0))
|
||||
{
|
||||
// Remove define that is not part of this configuration
|
||||
line = "";
|
||||
|
@ -1635,15 +1727,7 @@ void Preprocessor::handleIncludes(std::string &code, const std::string &filePath
|
|||
|
||||
if (!processedFile.empty())
|
||||
{
|
||||
// Replace all tabs with spaces..
|
||||
std::replace(processedFile.begin(), processedFile.end(), '\t', ' ');
|
||||
|
||||
// Remove all indentation..
|
||||
if (!processedFile.empty() && processedFile[0] == ' ')
|
||||
processedFile.erase(0, processedFile.find_first_not_of(" "));
|
||||
|
||||
// Remove space characters that are after or before new line character
|
||||
processedFile = removeSpaceNearNL(processedFile);
|
||||
processedFile = "#file \"" + filename + "\"\n" + processedFile + "\n#endfile";
|
||||
code.insert(pos, processedFile);
|
||||
|
||||
|
@ -2048,12 +2132,14 @@ public:
|
|||
|
||||
else if (_params.empty())
|
||||
{
|
||||
std::string::size_type pos = _macro.find(" ");
|
||||
std::string::size_type pos = _macro.find_first_of(" \"");
|
||||
if (pos == std::string::npos)
|
||||
macrocode = "";
|
||||
else
|
||||
{
|
||||
macrocode = _macro.substr(pos + 1);
|
||||
if (_macro[pos] == ' ')
|
||||
pos++;
|
||||
macrocode = _macro.substr(pos);
|
||||
if ((pos = macrocode.find_first_of("\r\n")) != std::string::npos)
|
||||
macrocode.erase(pos);
|
||||
}
|
||||
|
|
|
@ -106,7 +106,6 @@ public:
|
|||
* @param processedFile The data to be processed
|
||||
*/
|
||||
static void preprocessWhitespaces(std::string &processedFile);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
@ -152,6 +151,12 @@ protected:
|
|||
*/
|
||||
static std::string removeParantheses(const std::string &str);
|
||||
|
||||
/**
|
||||
* clean up #-preprocessor lines (only)
|
||||
* @param processedFile The data to be processed
|
||||
*/
|
||||
std::string preprocessCleanupDirectives(const std::string &processedFile) const;
|
||||
|
||||
/**
|
||||
* Returns the string between double quote characters or \< \> characters.
|
||||
* @param str e.g. \code#include "menu.h"\endcode or \code#include <menu.h>\endcode
|
||||
|
|
966
lib/tokenize.cpp
966
lib/tokenize.cpp
File diff suppressed because it is too large
Load Diff
|
@ -308,6 +308,18 @@ public:
|
|||
*/
|
||||
bool simplifyKnownVariables();
|
||||
|
||||
/**
|
||||
* Utility function for simplifyKnownVariables. Get data about an
|
||||
* assigned variable.
|
||||
*/
|
||||
bool simplifyKnownVariablesGetData(unsigned int varid, Token **_tok2, Token **_tok3, std::string &value, unsigned int &valueVarId, bool &valueIsPointer, bool floatvar);
|
||||
|
||||
/**
|
||||
* utility function for simplifyKnownVariables. Perform simplification
|
||||
* of a given variable
|
||||
*/
|
||||
bool simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, bool pointeralias, int indentlevel);
|
||||
|
||||
/** Replace a "goto" with the statements */
|
||||
void simplifyGoto();
|
||||
|
||||
|
@ -574,7 +586,7 @@ public:
|
|||
*/
|
||||
void duplicateEnumError(const Token *tok1, const Token *tok2, const std::string & type);
|
||||
|
||||
bool duplicateTypedef(Token **tokPtr, const Token *name);
|
||||
bool duplicateTypedef(Token **tokPtr, const Token *name, const Token *typeDef);
|
||||
void duplicateTypedefError(const Token *tok1, const Token *tok2, const std::string & type);
|
||||
|
||||
/**
|
||||
|
|
|
@ -44,8 +44,11 @@ Compiling
|
|||
|
||||
g++ (for experts)
|
||||
=================
|
||||
If you just want to build Cppcheck then you can use this command:
|
||||
g++ -o cppcheck -lpcre -Ilib -Iexternals cli/*.cpp lib/*.cpp externals/tinyxml/*.cpp
|
||||
If you just want to build Cppcheck without dependencies then you can use this command:
|
||||
g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp
|
||||
|
||||
If you want to use --rule and --rule-file then dependencies are needed:
|
||||
g++ -o cppcheck -lpcre -DHAVE_DEPENDENCIES -Ilib -Iexternals cli/*.cpp lib/*.cpp externals/tinyxml/*.cpp
|
||||
mingw
|
||||
=====
|
||||
make LDFLAGS=-lshlwapi
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
#!/bin/bash
|
||||
ASTYLE_VERSION="Artistic Style Version 2.01"
|
||||
if [ "`astyle --version 2>&1`" != "${ASTYLE_VERSION}" ]; then
|
||||
echo "You should use: ${ASTYLE_VERSION}";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
style="--style=ansi --lineend=linux --min-conditional-indent=0"
|
||||
options="--pad-header --unpad-paren --suffix=none"
|
||||
|
|
|
@ -116,6 +116,7 @@ private:
|
|||
TEST_CASE(array_index_for_break); // FP: for,break
|
||||
TEST_CASE(array_index_for); // FN: for,if
|
||||
TEST_CASE(array_index_for_neq); // #2211: Using != in condition
|
||||
TEST_CASE(array_index_for_question); // #2561: for, ?:
|
||||
|
||||
TEST_CASE(buffer_overrun_1);
|
||||
TEST_CASE(buffer_overrun_2);
|
||||
|
@ -133,6 +134,7 @@ private:
|
|||
TEST_CASE(buffer_overrun_14);
|
||||
TEST_CASE(buffer_overrun_15); // ticket #1787
|
||||
TEST_CASE(buffer_overrun_16);
|
||||
TEST_CASE(buffer_overrun_17); // ticket #2548
|
||||
TEST_CASE(buffer_overrun_bailoutIfSwitch); // ticket #2378 : bailoutIfSwitch
|
||||
|
||||
// It is undefined behaviour to point out of bounds of an array
|
||||
|
@ -886,8 +888,8 @@ private:
|
|||
" a[-1] = 0;\n" // negative index
|
||||
" a[256] = 0;\n" // 256 > CHAR_MAX
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Array 'a[256]' index -1 out of bounds\n"
|
||||
"[test.cpp:4]: (error) Array 'a[256]' index 256 out of bounds\n", errout.str());
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[256]' index 256 out of bounds\n"
|
||||
"[test.cpp:3]: (error) Array 'a[256]' index -1 out of bounds\n", errout.str());
|
||||
}
|
||||
|
||||
check("void f(signed char n) {\n"
|
||||
|
@ -1380,6 +1382,18 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:4]: (error) Buffer access out-of-bounds: a\n", errout.str());
|
||||
}
|
||||
|
||||
void array_index_for_question()
|
||||
{
|
||||
// Ticket #2561 - using ?: inside for loop
|
||||
check("void f() {\n"
|
||||
" int a[10];\n"
|
||||
" for (int i = 0; i != 10; ++i) {\n"
|
||||
" i == 0 ? 0 : a[i-1];\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void buffer_overrun_1()
|
||||
{
|
||||
check("void f()\n"
|
||||
|
@ -1860,6 +1874,15 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void buffer_overrun_17() // ticket #2548
|
||||
{
|
||||
check("void f() {\n"
|
||||
" char t[8];\n"
|
||||
" sprintf(t, \"%s\", \"foo bar\");\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) Buffer access out-of-bounds\n", errout.str());
|
||||
}
|
||||
|
||||
void buffer_overrun_bailoutIfSwitch()
|
||||
{
|
||||
// No false positive
|
||||
|
|
|
@ -104,6 +104,8 @@ private:
|
|||
TEST_CASE(clarifyCalculation);
|
||||
|
||||
TEST_CASE(incorrectStringCompare);
|
||||
|
||||
TEST_CASE(incrementBoolean);
|
||||
}
|
||||
|
||||
void check(const char code[], const char *filename = NULL)
|
||||
|
@ -141,6 +143,7 @@ private:
|
|||
checkOther.checkMemsetZeroBytes();
|
||||
checkOther.clarifyCalculation();
|
||||
checkOther.checkIncorrectStringCompare();
|
||||
checkOther.checkIncrementBoolean();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1892,6 +1895,23 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
||||
void incrementBoolean()
|
||||
{
|
||||
check("bool bValue = true;\n"
|
||||
"bValue++;\n");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) The use of a variable of type bool with the ++ postfix operator is always true and deprecated by the C++ Standard.\n", errout.str());
|
||||
|
||||
check("void f(bool test){\n"
|
||||
" test++;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) The use of a variable of type bool with the ++ postfix operator is always true and deprecated by the C++ Standard.\n", errout.str());
|
||||
|
||||
check("void f(int test){\n"
|
||||
" test++;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestOther)
|
||||
|
|
|
@ -148,6 +148,8 @@ private:
|
|||
TEST_CASE(macro_simple11);
|
||||
TEST_CASE(macro_simple12);
|
||||
TEST_CASE(macro_simple13);
|
||||
TEST_CASE(macro_simple14);
|
||||
TEST_CASE(macro_simple15);
|
||||
TEST_CASE(macroInMacro);
|
||||
TEST_CASE(macro_mismatch);
|
||||
TEST_CASE(macro_linenumbers);
|
||||
|
@ -198,6 +200,11 @@ private:
|
|||
TEST_CASE(endfile);
|
||||
|
||||
TEST_CASE(redundant_config);
|
||||
|
||||
TEST_CASE(testPreprocessorRead1);
|
||||
TEST_CASE(testPreprocessorRead2);
|
||||
TEST_CASE(testPreprocessorRead3);
|
||||
TEST_CASE(testPreprocessorRead4);
|
||||
}
|
||||
|
||||
|
||||
|
@ -209,7 +216,7 @@ private:
|
|||
Preprocessor preprocessor(&settings, this);
|
||||
std::istringstream istr(code);
|
||||
std::string codestr(preprocessor.read(istr,"test.c",0));
|
||||
ASSERT_EQUALS("a \n#aa b \n", codestr);
|
||||
ASSERT_EQUALS("a\n#aa b\n", codestr);
|
||||
}
|
||||
|
||||
void readCode2()
|
||||
|
@ -323,7 +330,7 @@ private:
|
|||
preprocessor.preprocess(istr, actual, "file.c");
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS("\n\" #ifdef WIN32\"\n\n\n\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\" # ifdef WIN32\"\n\n\n\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\n\nqwerty\n\n", actual["WIN32"]);
|
||||
ASSERT_EQUALS(2, static_cast<unsigned int>(actual.size()));
|
||||
}
|
||||
|
@ -1363,7 +1370,7 @@ private:
|
|||
std::istringstream istr(filedata);
|
||||
Settings settings;
|
||||
Preprocessor preprocessor(&settings, this);
|
||||
ASSERT_EQUALS("#define str \"abc\" \"def\" \n\nabcdef = str;\n", preprocessor.read(istr, "test.c", 0));
|
||||
ASSERT_EQUALS("#define str \"abc\" \"def\"\n\nabcdef = str;\n", preprocessor.read(istr, "test.c", 0));
|
||||
}
|
||||
|
||||
void multiline2()
|
||||
|
@ -1576,6 +1583,20 @@ private:
|
|||
ASSERT_EQUALS("\n\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple14()
|
||||
{
|
||||
const char filedata[] = "#define A \" a \"\n"
|
||||
"printf(A);\n";
|
||||
ASSERT_EQUALS("\nprintf(\" a \");\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple15()
|
||||
{
|
||||
const char filedata[] = "#define FOO\"foo\"\n"
|
||||
"FOO\n";
|
||||
ASSERT_EQUALS("\n\"foo\"\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macroInMacro()
|
||||
{
|
||||
{
|
||||
|
@ -2462,6 +2483,25 @@ private:
|
|||
ASSERT_EQUALS("\n\n1\n\n", actual[""]);
|
||||
ASSERT_EQUALS(1, (int)actual.size());
|
||||
}
|
||||
|
||||
{
|
||||
const char filedata[] = "#define A 1\n"
|
||||
"#if 0\n"
|
||||
"#undef A\n"
|
||||
"#endif\n"
|
||||
"A\n";
|
||||
|
||||
// Preprocess => actual result..
|
||||
std::istringstream istr(filedata);
|
||||
std::map<std::string, std::string> actual;
|
||||
Settings settings;
|
||||
Preprocessor preprocessor(&settings, this);
|
||||
preprocessor.preprocess(istr, actual, "file.c");
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS("\n\n\n\n1\n", actual[""]);
|
||||
ASSERT_EQUALS(1, (int)actual.size());
|
||||
}
|
||||
}
|
||||
|
||||
void define_ifndef1()
|
||||
|
@ -2591,6 +2631,63 @@ private:
|
|||
ASSERT_EQUALS("A;A;B is NOT checked", "A;A;B is NOT checked");
|
||||
}
|
||||
}
|
||||
|
||||
void testPreprocessorRead1()
|
||||
{
|
||||
const std::string filedata("/*\n*/ # /*\n*/ defi\\\nne FO\\\nO 10\\\n20");
|
||||
std::istringstream istr(filedata.c_str());
|
||||
Settings settings;
|
||||
Preprocessor preprocessor(&settings, this);
|
||||
ASSERT_EQUALS("#define FOO 1020", preprocessor.read(istr, "test.cpp", 0));
|
||||
}
|
||||
|
||||
void testPreprocessorRead2()
|
||||
{
|
||||
const std::string filedata("\"foo\\\\\nbar\"");
|
||||
std::istringstream istr(filedata.c_str());
|
||||
Settings settings;
|
||||
Preprocessor preprocessor(&settings, this);
|
||||
ASSERT_EQUALS("\"foo\\bar\"", preprocessor.read(istr, "test.cpp", 0));
|
||||
}
|
||||
|
||||
void testPreprocessorRead3()
|
||||
{
|
||||
const std::string filedata("#define A \" a \"\n\" b\"");
|
||||
std::istringstream istr(filedata.c_str());
|
||||
Settings settings;
|
||||
Preprocessor preprocessor(&settings, this);
|
||||
ASSERT_EQUALS(filedata, preprocessor.read(istr, "test.cpp", 0));
|
||||
}
|
||||
|
||||
void testPreprocessorRead4()
|
||||
{
|
||||
{
|
||||
// test < \\> < > (unescaped)
|
||||
const std::string filedata("#define A \" \\\\\"/*space*/ \" \"");
|
||||
std::istringstream istr(filedata.c_str());
|
||||
Settings settings;
|
||||
Preprocessor preprocessor(&settings, this);
|
||||
ASSERT_EQUALS("#define A \" \\\\\" \" \"", preprocessor.read(istr, "test.cpp", 0));
|
||||
}
|
||||
|
||||
{
|
||||
// test <" \\\" "> (unescaped)
|
||||
const std::string filedata("#define A \" \\\\\\\" \"");
|
||||
std::istringstream istr(filedata.c_str());
|
||||
Settings settings;
|
||||
Preprocessor preprocessor(&settings, this);
|
||||
ASSERT_EQUALS("#define A \" \\\\\\\" \"", preprocessor.read(istr, "test.cpp", 0));
|
||||
}
|
||||
|
||||
{
|
||||
// test <" \\\\"> <" "> (unescaped)
|
||||
const std::string filedata("#define A \" \\\\\\\\\"/*space*/ \" \"");
|
||||
std::istringstream istr(filedata.c_str());
|
||||
Settings settings;
|
||||
Preprocessor preprocessor(&settings, this);
|
||||
ASSERT_EQUALS("#define A \" \\\\\\\\\" \" \"", preprocessor.read(istr, "test.cpp", 0));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestPreprocessor)
|
||||
|
|
|
@ -235,6 +235,7 @@ private:
|
|||
TEST_CASE(simplifyTypedef75); // ticket #2426
|
||||
TEST_CASE(simplifyTypedef76); // ticket #2453
|
||||
TEST_CASE(simplifyTypedef77); // ticket #2554
|
||||
TEST_CASE(simplifyTypedef78); // ticket #2568
|
||||
|
||||
TEST_CASE(simplifyTypedefFunction1);
|
||||
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
||||
|
@ -3941,7 +3942,7 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:1]: (style) Typedef 'A' hides typedef with same name\n"
|
||||
"[test.cpp:20] -> [test.cpp:1]: (style) Function parameter 'A' hides typedef with same name\n"
|
||||
"[test.cpp:21] -> [test.cpp:1]: (style) Variable 'A' hides typedef with same name\n"
|
||||
"[test.cpp:24] -> [test.cpp:1]: (style) Struct 'A' hides typedef with same name\n", errout.str());
|
||||
"[test.cpp:24] -> [test.cpp:1]: (style) Typedef 'A' hides typedef with same name\n", errout.str());
|
||||
}
|
||||
|
||||
void simplifyTypedef36()
|
||||
|
@ -4846,6 +4847,16 @@ private:
|
|||
ASSERT_EQUALS(expected, sizeof_(code));
|
||||
}
|
||||
|
||||
void simplifyTypedef78() // ticket #2568
|
||||
{
|
||||
const char code[] = "typedef struct A A_t;\n"
|
||||
"A_t a;\n"
|
||||
"typedef struct A { } A_t;\n"
|
||||
"A_t a1;\n";
|
||||
const std::string expected = "; struct A a ; struct A { } ; struct A a1 ;";
|
||||
ASSERT_EQUALS(expected, sizeof_(code));
|
||||
}
|
||||
|
||||
void simplifyTypedefFunction1()
|
||||
{
|
||||
{
|
||||
|
|
|
@ -65,6 +65,8 @@ private:
|
|||
TEST_CASE(testDoesNotIdentifyMethodAsFirstFunctionArgument); // #2480
|
||||
TEST_CASE(testDoesNotIdentifyMethodAsMiddleFunctionArgument);
|
||||
TEST_CASE(testDoesNotIdentifyMethodAsLastFunctionArgument);
|
||||
|
||||
TEST_CASE(multiFile);
|
||||
}
|
||||
|
||||
|
||||
|
@ -549,6 +551,26 @@ private:
|
|||
);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void multiFile() // ticket #2567
|
||||
{
|
||||
check("#file \"test.h\"\n"
|
||||
"struct Fred\n"
|
||||
"{\n"
|
||||
" Fred()\n"
|
||||
" {\n"
|
||||
" Init();\n"
|
||||
" }\n"
|
||||
"private:\n"
|
||||
" void Init();\n"
|
||||
"};\n"
|
||||
"#endfile\n"
|
||||
"void Fred::Init()\n"
|
||||
"{\n"
|
||||
"}\n");
|
||||
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestUnusedPrivateFunction)
|
||||
|
|
|
@ -225,7 +225,7 @@ int main(int argc, char **argv)
|
|||
// Makefile settings..
|
||||
if (release)
|
||||
{
|
||||
makeConditionalVariable(fout, "CXXFLAGS", "-O2 -DNDEBUG -Wall");
|
||||
makeConditionalVariable(fout, "CXXFLAGS", "-O2 -DNDEBUG -DHAVE_DEPENDENCIES -Wall");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -235,6 +235,7 @@ int main(int argc, char **argv)
|
|||
|
||||
// The _GLIBCXX_DEBUG doesn't work in cygwin
|
||||
makeConditionalVariable(fout, "CXXFLAGS",
|
||||
"-DHAVE_DEPENDENCIES "
|
||||
"-Wall "
|
||||
"-Wextra "
|
||||
"-Wshadow "
|
||||
|
@ -251,7 +252,7 @@ int main(int argc, char **argv)
|
|||
makeConditionalVariable(fout, "INCLUDE_FOR_LIB", "-Ilib");
|
||||
makeConditionalVariable(fout, "INCLUDE_FOR_CLI", "-Ilib -Iexternals -Iexternals/tinyxml");
|
||||
makeConditionalVariable(fout, "INCLUDE_FOR_TEST", "-Ilib -Icli -Iexternals -Iexternals/tinyxml");
|
||||
|
||||
|
||||
fout << "BIN=$(DESTDIR)$(PREFIX)/bin\n\n";
|
||||
fout << "# For 'make man': sudo apt-get install xsltproc docbook-xsl docbook-xml on Linux\n";
|
||||
fout << "DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl\n";
|
||||
|
|
Loading…
Reference in New Issue