Merge branch 'master' of http://github.com/danmar/cppcheck
This commit is contained in:
commit
3b9b8784c8
1
AUTHORS
1
AUTHORS
|
@ -3,6 +3,7 @@ The cppcheck team, in alphabetical order:
|
||||||
Bill Egert
|
Bill Egert
|
||||||
Daniel Marjamäki
|
Daniel Marjamäki
|
||||||
Gianluca Scacco
|
Gianluca Scacco
|
||||||
|
Greg Hewgill
|
||||||
Hoang Tuan Su
|
Hoang Tuan Su
|
||||||
Kimmo Varis
|
Kimmo Varis
|
||||||
Leandro Penz
|
Leandro Penz
|
||||||
|
|
6
Makefile
6
Makefile
|
@ -1,7 +1,7 @@
|
||||||
# This file is generated by tools/dmake, do not edit.
|
# This file is generated by tools/dmake, do not edit.
|
||||||
|
|
||||||
ifndef CXXFLAGS
|
ifndef CXXFLAGS
|
||||||
CXXFLAGS=-DHAVE_DEPENDENCIES -Wall -Wextra -Wshadow -pedantic -Wno-long-long -Wfloat-equal -Wcast-qual -Wsign-conversion -g
|
CXXFLAGS=-DHAVE_RULES -Wall -Wextra -Wshadow -pedantic -Wno-long-long -Wfloat-equal -Wcast-qual -Wsign-conversion -g
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifndef CXX
|
ifndef CXX
|
||||||
|
@ -95,6 +95,7 @@ TESTOBJ = test/options.o \
|
||||||
test/testsimplifytokens.o \
|
test/testsimplifytokens.o \
|
||||||
test/teststl.o \
|
test/teststl.o \
|
||||||
test/testsuite.o \
|
test/testsuite.o \
|
||||||
|
test/testsuppressions.o \
|
||||||
test/testsymboldatabase.o \
|
test/testsymboldatabase.o \
|
||||||
test/testthreadexecutor.o \
|
test/testthreadexecutor.o \
|
||||||
test/testtoken.o \
|
test/testtoken.o \
|
||||||
|
@ -329,6 +330,9 @@ test/teststl.o: test/teststl.cpp lib/tokenize.h lib/checkstl.h lib/check.h lib/t
|
||||||
test/testsuite.o: test/testsuite.cpp test/testsuite.h lib/errorlogger.h test/redirect.h test/options.h
|
test/testsuite.o: test/testsuite.cpp test/testsuite.h lib/errorlogger.h test/redirect.h test/options.h
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testsuite.o test/testsuite.cpp
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testsuite.o test/testsuite.cpp
|
||||||
|
|
||||||
|
test/testsuppressions.o: test/testsuppressions.cpp test/testsuite.h lib/cppcheck.h lib/settings.h lib/errorlogger.h cli/threadexecutor.h
|
||||||
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testsuppressions.o test/testsuppressions.cpp
|
||||||
|
|
||||||
test/testsymboldatabase.o: test/testsymboldatabase.cpp test/testsuite.h lib/errorlogger.h test/redirect.h test/testutils.h lib/settings.h lib/tokenize.h lib/token.h lib/symboldatabase.h
|
test/testsymboldatabase.o: test/testsymboldatabase.cpp test/testsuite.h lib/errorlogger.h test/redirect.h test/testutils.h lib/settings.h lib/tokenize.h lib/token.h lib/symboldatabase.h
|
||||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testsymboldatabase.o test/testsymboldatabase.cpp
|
$(CXX) $(CPPFLAGS) $(CXXFLAGS) ${INCLUDE_FOR_TEST} -c -o test/testsymboldatabase.o test/testsymboldatabase.cpp
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ INCLUDEPATH += . ../lib
|
||||||
OBJECTS_DIR = temp
|
OBJECTS_DIR = temp
|
||||||
CONFIG += warn_on
|
CONFIG += warn_on
|
||||||
CONFIG -= qt app_bundle
|
CONFIG -= qt app_bundle
|
||||||
DEFINES += HAVE_DEPENDENCIES
|
DEFINES += HAVE_RULES
|
||||||
|
|
||||||
BASEPATH = ../externals/tinyxml/
|
BASEPATH = ../externals/tinyxml/
|
||||||
include($$PWD/../externals/tinyxml/tinyxml.pri)
|
include($$PWD/../externals/tinyxml/tinyxml.pri)
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
#include "filelister.h"
|
#include "filelister.h"
|
||||||
|
|
||||||
#ifdef HAVE_DEPENDENCIES
|
#ifdef HAVE_RULES
|
||||||
// xml is used in rules
|
// xml is used in rules
|
||||||
#include <tinyxml.h>
|
#include <tinyxml.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -505,7 +505,7 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
||||||
_settings->_showtime = SHOWTIME_NONE;
|
_settings->_showtime = SHOWTIME_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DEPENDENCIES
|
#ifdef HAVE_RULES
|
||||||
// Rule given at command line
|
// Rule given at command line
|
||||||
else if (strncmp(argv[i], "--rule=", 7) == 0)
|
else if (strncmp(argv[i], "--rule=", 7) == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -123,7 +123,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
|
||||||
|
|
||||||
int CppCheckExecutor::check(int argc, const char* const argv[])
|
int CppCheckExecutor::check(int argc, const char* const argv[])
|
||||||
{
|
{
|
||||||
CppCheck cppCheck(*this);
|
CppCheck cppCheck(*this, true);
|
||||||
if (!parseFromArgs(&cppCheck, argc, argv))
|
if (!parseFromArgs(&cppCheck, argc, argv))
|
||||||
{
|
{
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
@ -152,11 +152,13 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
|
||||||
{
|
{
|
||||||
// Multiple processes
|
// Multiple processes
|
||||||
const std::vector<std::string> &filenames = cppCheck.filenames();
|
const std::vector<std::string> &filenames = cppCheck.filenames();
|
||||||
Settings settings = cppCheck.settings();
|
Settings &settings = cppCheck.settings();
|
||||||
ThreadExecutor executor(filenames, settings, *this);
|
ThreadExecutor executor(filenames, settings, *this);
|
||||||
returnValue = executor.check();
|
returnValue = executor.check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions());
|
||||||
|
|
||||||
if (_settings._xml)
|
if (_settings._xml)
|
||||||
{
|
{
|
||||||
reportErr(ErrorLogger::ErrorMessage::getXMLFooter(_settings._xml_version));
|
reportErr(ErrorLogger::ErrorMessage::getXMLFooter(_settings._xml_version));
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &errorLogger)
|
ThreadExecutor::ThreadExecutor(const std::vector<std::string> &filenames, Settings &settings, ErrorLogger &errorLogger)
|
||||||
: _filenames(filenames), _settings(settings), _errorLogger(errorLogger), _fileCount(0)
|
: _filenames(filenames), _settings(settings), _errorLogger(errorLogger), _fileCount(0)
|
||||||
{
|
{
|
||||||
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
|
#if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__)
|
||||||
|
@ -95,6 +95,16 @@ int ThreadExecutor::handleRead(unsigned int &result)
|
||||||
ErrorLogger::ErrorMessage msg;
|
ErrorLogger::ErrorMessage msg;
|
||||||
msg.deserialize(buf);
|
msg.deserialize(buf);
|
||||||
|
|
||||||
|
std::string file;
|
||||||
|
unsigned int line(0);
|
||||||
|
if (!msg._callStack.empty())
|
||||||
|
{
|
||||||
|
file = msg._callStack.back().getfile(false);
|
||||||
|
line = msg._callStack.back().line;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_settings.nomsg.isSuppressed(msg._id, file, line))
|
||||||
|
{
|
||||||
// Alert only about unique errors
|
// Alert only about unique errors
|
||||||
std::string errmsg = msg.toString(_settings._verbose);
|
std::string errmsg = msg.toString(_settings._verbose);
|
||||||
if (std::find(_errorList.begin(), _errorList.end(), errmsg) == _errorList.end())
|
if (std::find(_errorList.begin(), _errorList.end(), errmsg) == _errorList.end())
|
||||||
|
@ -103,6 +113,7 @@ int ThreadExecutor::handleRead(unsigned int &result)
|
||||||
_errorLogger.reportErr(msg);
|
_errorLogger.reportErr(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (type == '3')
|
else if (type == '3')
|
||||||
{
|
{
|
||||||
_fileCount++;
|
_fileCount++;
|
||||||
|
@ -158,7 +169,7 @@ unsigned int ThreadExecutor::check()
|
||||||
}
|
}
|
||||||
else if (pid == 0)
|
else if (pid == 0)
|
||||||
{
|
{
|
||||||
CppCheck fileChecker(*this);
|
CppCheck fileChecker(*this, false);
|
||||||
fileChecker.settings(_settings);
|
fileChecker.settings(_settings);
|
||||||
|
|
||||||
if (_fileContents.size() > 0 && _fileContents.find(_filenames[i]) != _fileContents.end())
|
if (_fileContents.size() > 0 && _fileContents.find(_filenames[i]) != _fileContents.end())
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
class ThreadExecutor : public ErrorLogger
|
class ThreadExecutor : public ErrorLogger
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ThreadExecutor(const std::vector<std::string> &filenames, const Settings &settings, ErrorLogger &_errorLogger);
|
ThreadExecutor(const std::vector<std::string> &filenames, Settings &settings, ErrorLogger &_errorLogger);
|
||||||
virtual ~ThreadExecutor();
|
virtual ~ThreadExecutor();
|
||||||
unsigned int check();
|
unsigned int check();
|
||||||
virtual void reportOut(const std::string &outmsg);
|
virtual void reportOut(const std::string &outmsg);
|
||||||
|
@ -52,7 +52,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::vector<std::string> &_filenames;
|
const std::vector<std::string> &_filenames;
|
||||||
const Settings &_settings;
|
Settings &_settings;
|
||||||
ErrorLogger &_errorLogger;
|
ErrorLogger &_errorLogger;
|
||||||
unsigned int _fileCount;
|
unsigned int _fileCount;
|
||||||
|
|
||||||
|
|
|
@ -30,15 +30,15 @@
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
#ifdef HAVE_DEPENDENCIES
|
#ifdef HAVE_RULES
|
||||||
#define PCRE_STATIC
|
#define PCRE_STATIC
|
||||||
#include <pcre.h>
|
#include <pcre.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static TimerResults S_timerResults;
|
static TimerResults S_timerResults;
|
||||||
|
|
||||||
CppCheck::CppCheck(ErrorLogger &errorLogger)
|
CppCheck::CppCheck(ErrorLogger &errorLogger, bool useGlobalSuppressions)
|
||||||
: _errorLogger(errorLogger)
|
: _useGlobalSuppressions(useGlobalSuppressions), _errorLogger(errorLogger)
|
||||||
{
|
{
|
||||||
exitcode = 0;
|
exitcode = 0;
|
||||||
}
|
}
|
||||||
|
@ -197,6 +197,8 @@ unsigned int CppCheck::check()
|
||||||
_errorLogger.reportOut("Bailing out from checking " + fixedpath + ": " + e.what());
|
_errorLogger.reportOut("Bailing out from checking " + fixedpath + ": " + e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reportUnmatchedSuppressions(_settings.nomsg.getUnmatchedLocalSuppressions());
|
||||||
|
|
||||||
_errorLogger.reportStatus(c + 1, (unsigned int)_filenames.size());
|
_errorLogger.reportStatus(c + 1, (unsigned int)_filenames.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +311,7 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
||||||
(*it)->runSimplifiedChecks(&_tokenizer, &_settings, this);
|
(*it)->runSimplifiedChecks(&_tokenizer, &_settings, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DEPENDENCIES
|
#ifdef HAVE_RULES
|
||||||
// Are there extra rules?
|
// Are there extra rules?
|
||||||
if (!_settings.rules.empty())
|
if (!_settings.rules.empty())
|
||||||
{
|
{
|
||||||
|
@ -385,7 +387,7 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings CppCheck::settings() const
|
Settings &CppCheck::settings()
|
||||||
{
|
{
|
||||||
return _settings;
|
return _settings;
|
||||||
}
|
}
|
||||||
|
@ -408,8 +410,16 @@ void CppCheck::reportErr(const ErrorLogger::ErrorMessage &msg)
|
||||||
line = msg._callStack.back().line;
|
line = msg._callStack.back().line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_useGlobalSuppressions)
|
||||||
|
{
|
||||||
if (_settings.nomsg.isSuppressed(msg._id, file, line))
|
if (_settings.nomsg.isSuppressed(msg._id, file, line))
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_settings.nomsg.isSuppressedLocal(msg._id, file, line))
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_settings.nofail.isSuppressed(msg._id, file, line))
|
if (!_settings.nofail.isSuppressed(msg._id, file, line))
|
||||||
exitcode = 1;
|
exitcode = 1;
|
||||||
|
|
|
@ -43,7 +43,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* @brief Constructor.
|
* @brief Constructor.
|
||||||
*/
|
*/
|
||||||
CppCheck(ErrorLogger &errorLogger);
|
CppCheck(ErrorLogger &errorLogger, bool useGlobalSuppressions);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructor.
|
* @brief Destructor.
|
||||||
|
@ -66,10 +66,10 @@ public:
|
||||||
void settings(const Settings &settings);
|
void settings(const Settings &settings);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get copy of current settings.
|
* @brief Get reference to current settings.
|
||||||
* @return a copy of current settings
|
* @return a reference to current settings
|
||||||
*/
|
*/
|
||||||
Settings settings() const;
|
Settings &settings();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Add new file to be checked.
|
* @brief Add new file to be checked.
|
||||||
|
@ -147,6 +147,7 @@ private:
|
||||||
std::list<std::string> _errorList;
|
std::list<std::string> _errorList;
|
||||||
std::ostringstream _errout;
|
std::ostringstream _errout;
|
||||||
Settings _settings;
|
Settings _settings;
|
||||||
|
bool _useGlobalSuppressions;
|
||||||
std::vector<std::string> _filenames;
|
std::vector<std::string> _filenames;
|
||||||
|
|
||||||
void reportProgress(const std::string &filename, const char stage[], const unsigned int value);
|
void reportProgress(const std::string &filename, const char stage[], const unsigned int value);
|
||||||
|
|
|
@ -291,11 +291,26 @@ std::string ErrorLogger::ErrorMessage::toString(bool verbose, const std::string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ErrorLogger::reportUnmatchedSuppressions(const std::list<Settings::Suppressions::SuppressionEntry> &unmatched)
|
||||||
|
{
|
||||||
|
for (std::list<Settings::Suppressions::SuppressionEntry>::const_iterator i = unmatched.begin(); i != unmatched.end(); ++i)
|
||||||
|
{
|
||||||
|
std::list<ErrorLogger::ErrorMessage::FileLocation> callStack;
|
||||||
|
callStack.push_back(ErrorLogger::ErrorMessage::FileLocation(i->file, i->line));
|
||||||
|
reportErr(ErrorLogger::ErrorMessage(callStack, Severity::information, "Unmatched suppression: " + i->id, "unmatchedSuppression"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string ErrorLogger::callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack)
|
std::string ErrorLogger::callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack)
|
||||||
{
|
{
|
||||||
std::ostringstream ostr;
|
std::ostringstream ostr;
|
||||||
for (std::list<ErrorLogger::ErrorMessage::FileLocation>::const_iterator tok = callStack.begin(); tok != callStack.end(); ++tok)
|
for (std::list<ErrorLogger::ErrorMessage::FileLocation>::const_iterator tok = callStack.begin(); tok != callStack.end(); ++tok)
|
||||||
ostr << (tok == callStack.begin() ? "" : " -> ") << "[" << (*tok).getfile() << ":" << (*tok).line << "]";
|
{
|
||||||
|
ostr << (tok == callStack.begin() ? "" : " -> ") << "[" << (*tok).getfile();
|
||||||
|
if ((*tok).line != 0)
|
||||||
|
ostr << ":" << (*tok).line;
|
||||||
|
ostr << "]";
|
||||||
|
}
|
||||||
return ostr.str();
|
return ostr.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
class Token;
|
class Token;
|
||||||
class Tokenizer;
|
class Tokenizer;
|
||||||
|
|
||||||
|
@ -108,6 +110,11 @@ public:
|
||||||
line = 0;
|
line = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileLocation(const std::string &file, int aline)
|
||||||
|
: line(aline), _file(file)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the filename.
|
* Return the filename.
|
||||||
* @param convert If true convert path to native separators.
|
* @param convert If true convert path to native separators.
|
||||||
|
@ -230,6 +237,12 @@ public:
|
||||||
(void)value;
|
(void)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report list of unmatched suppressions
|
||||||
|
* @param unmatched list of unmatched suppressions (from Settings::Suppressions::getUnmatched(Local|Global)Suppressions)
|
||||||
|
*/
|
||||||
|
void reportUnmatchedSuppressions(const std::list<Settings::Suppressions::SuppressionEntry> &unmatched);
|
||||||
|
|
||||||
static std::string callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack);
|
static std::string callStackToString(const std::list<ErrorLogger::ErrorMessage::FileLocation> &callStack);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -218,7 +218,7 @@ std::string Preprocessor::preprocessCleanupDirectives(const std::string &process
|
||||||
char prev = ' '; // hack to make it skip spaces between # and the directive
|
char prev = ' '; // hack to make it skip spaces between # and the directive
|
||||||
code << "#";
|
code << "#";
|
||||||
std::string::const_iterator i = line.begin();
|
std::string::const_iterator i = line.begin();
|
||||||
i++;
|
++i;
|
||||||
|
|
||||||
// need space.. #if( => #if (
|
// need space.. #if( => #if (
|
||||||
bool needSpace = true;
|
bool needSpace = true;
|
||||||
|
@ -247,7 +247,7 @@ std::string Preprocessor::preprocessCleanupDirectives(const std::string &process
|
||||||
// skip double whitespace between arguments
|
// skip double whitespace between arguments
|
||||||
if (escapeStatus == ESC_NONE && prev == ' ' && *i == ' ')
|
if (escapeStatus == ESC_NONE && prev == ' ' && *i == ' ')
|
||||||
{
|
{
|
||||||
i++;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Convert #if( to "#if ("
|
// Convert #if( to "#if ("
|
||||||
|
@ -272,7 +272,7 @@ std::string Preprocessor::preprocessCleanupDirectives(const std::string &process
|
||||||
{
|
{
|
||||||
prev = *i;
|
prev = *i;
|
||||||
}
|
}
|
||||||
i++;
|
++i;
|
||||||
}
|
}
|
||||||
if (escapeStatus != ESC_NONE)
|
if (escapeStatus != ESC_NONE)
|
||||||
{
|
{
|
||||||
|
|
112
lib/settings.cpp
112
lib/settings.cpp
|
@ -70,6 +70,16 @@ std::string Settings::Suppressions::parseFile(std::istream &istr)
|
||||||
if (line.length() >= 2 && line[0] == '/' && line[1] == '/')
|
if (line.length() >= 2 && line[0] == '/' && line[1] == '/')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
const std::string errmsg(addSuppressionLine(line));
|
||||||
|
if (!errmsg.empty())
|
||||||
|
return errmsg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Settings::Suppressions::addSuppressionLine(const std::string &line)
|
||||||
|
{
|
||||||
std::istringstream lineStream(line);
|
std::istringstream lineStream(line);
|
||||||
std::string id;
|
std::string id;
|
||||||
std::string file;
|
std::string file;
|
||||||
|
@ -112,7 +122,6 @@ std::string Settings::Suppressions::parseFile(std::istream &istr)
|
||||||
const std::string errmsg(addSuppression(id, file, lineNumber));
|
const std::string errmsg(addSuppression(id, file, lineNumber));
|
||||||
if (!errmsg.empty())
|
if (!errmsg.empty())
|
||||||
return errmsg;
|
return errmsg;
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -205,47 +214,64 @@ std::string Settings::Suppressions::FileMatcher::addFile(const std::string &name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_globs[name].insert(line);
|
_globs[name][line] = false;
|
||||||
|
}
|
||||||
|
else if (name.empty())
|
||||||
|
{
|
||||||
|
_globs["*"][0U] = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_files[name].insert(line);
|
_files[name][line] = false;
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::Suppressions::FileMatcher::isSuppressed(const std::string &file, unsigned int line)
|
bool Settings::Suppressions::FileMatcher::isSuppressed(const std::string &file, unsigned int line)
|
||||||
{
|
{
|
||||||
// Check are all errors of this type filtered out
|
if (isSuppressedLocal(file, line))
|
||||||
if (_files.find("") != _files.end())
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
std::set<unsigned int> lineset;
|
for (std::map<std::string, std::map<unsigned int, bool> >::iterator g = _globs.begin(); g != _globs.end(); ++g)
|
||||||
|
|
||||||
std::map<std::string, std::set<unsigned int> >::const_iterator f = _files.find(file);
|
|
||||||
if (f != _files.end())
|
|
||||||
{
|
|
||||||
lineset.insert(f->second.begin(), f->second.end());
|
|
||||||
}
|
|
||||||
for (std::map<std::string, std::set<unsigned int> >::iterator g = _globs.begin(); g != _globs.end(); ++g)
|
|
||||||
{
|
{
|
||||||
if (match(g->first, file))
|
if (match(g->first, file))
|
||||||
{
|
{
|
||||||
lineset.insert(g->second.begin(), g->second.end());
|
if (g->second.find(0U) != g->second.end())
|
||||||
|
{
|
||||||
|
g->second[0U] = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
std::map<unsigned int, bool>::iterator l = g->second.find(line);
|
||||||
|
if (l != g->second.end())
|
||||||
|
{
|
||||||
|
l->second = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lineset.empty())
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check should all errors in this file be filtered out
|
bool Settings::Suppressions::FileMatcher::isSuppressedLocal(const std::string &file, unsigned int line)
|
||||||
if (lineset.find(0U) != lineset.end())
|
{
|
||||||
|
std::map<std::string, std::map<unsigned int, bool> >::iterator f = _files.find(file);
|
||||||
|
if (f != _files.end())
|
||||||
|
{
|
||||||
|
if (f->second.find(0U) != f->second.end())
|
||||||
|
{
|
||||||
|
f->second[0U] = true;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
std::map<unsigned int, bool>::iterator l = f->second.find(line);
|
||||||
|
if (l != f->second.end())
|
||||||
|
{
|
||||||
|
l->second = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (lineset.find(line) == lineset.end())
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Settings::Suppressions::addSuppression(const std::string &errorId, const std::string &file, unsigned int line)
|
std::string Settings::Suppressions::addSuppression(const std::string &errorId, const std::string &file, unsigned int line)
|
||||||
|
@ -278,6 +304,52 @@ bool Settings::Suppressions::isSuppressed(const std::string &errorId, const std:
|
||||||
return _suppressions[errorId].isSuppressed(file, line);
|
return _suppressions[errorId].isSuppressed(file, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Settings::Suppressions::isSuppressedLocal(const std::string &errorId, const std::string &file, unsigned int line)
|
||||||
|
{
|
||||||
|
if (_suppressions.find(errorId) == _suppressions.end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return _suppressions[errorId].isSuppressedLocal(file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<Settings::Suppressions::SuppressionEntry> Settings::Suppressions::getUnmatchedLocalSuppressions() const
|
||||||
|
{
|
||||||
|
std::list<SuppressionEntry> r;
|
||||||
|
for (std::map<std::string, FileMatcher>::const_iterator i = _suppressions.begin(); i != _suppressions.end(); ++i)
|
||||||
|
{
|
||||||
|
for (std::map<std::string, std::map<unsigned int, bool> >::const_iterator f = i->second._files.begin(); f != i->second._files.end(); ++f)
|
||||||
|
{
|
||||||
|
for (std::map<unsigned int, bool>::const_iterator l = f->second.begin(); l != f->second.end(); ++l)
|
||||||
|
{
|
||||||
|
if (!l->second)
|
||||||
|
{
|
||||||
|
r.push_back(SuppressionEntry(i->first, f->first, l->first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<Settings::Suppressions::SuppressionEntry> Settings::Suppressions::getUnmatchedGlobalSuppressions() const
|
||||||
|
{
|
||||||
|
std::list<SuppressionEntry> r;
|
||||||
|
for (std::map<std::string, FileMatcher>::const_iterator i = _suppressions.begin(); i != _suppressions.end(); ++i)
|
||||||
|
{
|
||||||
|
for (std::map<std::string, std::map<unsigned int, bool> >::const_iterator g = i->second._globs.begin(); g != i->second._globs.end(); ++g)
|
||||||
|
{
|
||||||
|
for (std::map<unsigned int, bool>::const_iterator l = g->second.begin(); l != g->second.end(); ++l)
|
||||||
|
{
|
||||||
|
if (!l->second)
|
||||||
|
{
|
||||||
|
r.push_back(SuppressionEntry(i->first, g->first, l->first));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Settings::addEnabled(const std::string &str)
|
std::string Settings::addEnabled(const std::string &str)
|
||||||
{
|
{
|
||||||
// Enable parameters may be comma separated...
|
// Enable parameters may be comma separated...
|
||||||
|
|
|
@ -138,11 +138,12 @@ public:
|
||||||
private:
|
private:
|
||||||
class FileMatcher
|
class FileMatcher
|
||||||
{
|
{
|
||||||
|
friend class Suppressions;
|
||||||
private:
|
private:
|
||||||
/** @brief List of filenames suppressed. */
|
/** @brief List of filenames suppressed, bool flag indicates whether suppression matched. */
|
||||||
std::map<std::string, std::set<unsigned int> > _files;
|
std::map<std::string, std::map<unsigned int, bool> > _files;
|
||||||
/** @brief List of globs suppressed. */
|
/** @brief List of globs suppressed, bool flag indicates whether suppression matched. */
|
||||||
std::map<std::string, std::set<unsigned int> > _globs;
|
std::map<std::string, std::map<unsigned int, bool> > _globs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Match a name against a glob pattern.
|
* @brief Match a name against a glob pattern.
|
||||||
|
@ -168,6 +169,14 @@ public:
|
||||||
* @return true if this filename/line matches
|
* @return true if this filename/line matches
|
||||||
*/
|
*/
|
||||||
bool isSuppressed(const std::string &file, unsigned int line);
|
bool isSuppressed(const std::string &file, unsigned int line);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if the file name matches a previously added file (only, not glob pattern).
|
||||||
|
* @param name File name to check
|
||||||
|
* @param line Line number
|
||||||
|
* @return true if this filename/line matches
|
||||||
|
*/
|
||||||
|
bool isSuppressedLocal(const std::string &file, unsigned int line);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief List of error which the user doesn't want to see. */
|
/** @brief List of error which the user doesn't want to see. */
|
||||||
|
@ -180,6 +189,13 @@ public:
|
||||||
*/
|
*/
|
||||||
std::string parseFile(std::istream &istr);
|
std::string parseFile(std::istream &istr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Don't show the given error.
|
||||||
|
* @param str Description of error to suppress (in id:file:line format).
|
||||||
|
* @return error message. empty upon success
|
||||||
|
*/
|
||||||
|
std::string addSuppressionLine(const std::string &line);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Don't show this error. If file and/or line are optional. In which case
|
* @brief Don't show this error. If file and/or line are optional. In which case
|
||||||
* the errorId alone is used for filtering.
|
* the errorId alone is used for filtering.
|
||||||
|
@ -198,6 +214,38 @@ public:
|
||||||
* @return true if this error is suppressed.
|
* @return true if this error is suppressed.
|
||||||
*/
|
*/
|
||||||
bool isSuppressed(const std::string &errorId, const std::string &file, unsigned int line);
|
bool isSuppressed(const std::string &errorId, const std::string &file, unsigned int line);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns true if this message should not be shown to the user (explicit files only, not glob patterns).
|
||||||
|
* @param errorId the id for the error, e.g. "arrayIndexOutOfBounds"
|
||||||
|
* @param file File name with the path, e.g. "src/main.cpp"
|
||||||
|
* @param line number, e.g. "123"
|
||||||
|
* @return true if this error is suppressed.
|
||||||
|
*/
|
||||||
|
bool isSuppressedLocal(const std::string &errorId, const std::string &file, unsigned int line);
|
||||||
|
|
||||||
|
struct SuppressionEntry
|
||||||
|
{
|
||||||
|
SuppressionEntry(const std::string &aid, const std::string &afile, const unsigned int &aline)
|
||||||
|
: id(aid), file(afile), line(aline)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
std::string id;
|
||||||
|
std::string file;
|
||||||
|
unsigned int line;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns list of unmatched local (per-file) suppressions.
|
||||||
|
* @return list of unmatched suppressions
|
||||||
|
*/
|
||||||
|
std::list<SuppressionEntry> getUnmatchedLocalSuppressions() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns list of unmatched global (glob pattern) suppressions.
|
||||||
|
* @return list of unmatched suppressions
|
||||||
|
*/
|
||||||
|
std::list<SuppressionEntry> getUnmatchedGlobalSuppressions() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @brief suppress message (--suppressions) */
|
/** @brief suppress message (--suppressions) */
|
||||||
|
|
|
@ -906,12 +906,14 @@ const Token *SymbolDatabase::initBaseInfo(Scope *scope, const Token *tok)
|
||||||
base.name += tok2->str();
|
base.name += tok2->str();
|
||||||
base.scope = 0;
|
base.scope = 0;
|
||||||
|
|
||||||
// don't add unhandled templates
|
// add unhandled templates
|
||||||
if (tok2->next()->str() == "<")
|
if (tok2->next()->str() == "<")
|
||||||
{
|
{
|
||||||
int level1 = 1;
|
int level1 = 1;
|
||||||
while (tok2->next())
|
while (tok2->next())
|
||||||
{
|
{
|
||||||
|
base.name += tok2->next()->str();
|
||||||
|
|
||||||
if (tok2->next()->str() == ">")
|
if (tok2->next()->str() == ">")
|
||||||
{
|
{
|
||||||
level1--;
|
level1--;
|
||||||
|
@ -926,11 +928,8 @@ const Token *SymbolDatabase::initBaseInfo(Scope *scope, const Token *tok)
|
||||||
}
|
}
|
||||||
|
|
||||||
// save pattern for base class name
|
// save pattern for base class name
|
||||||
else
|
|
||||||
{
|
|
||||||
scope->derivedFrom.push_back(base);
|
scope->derivedFrom.push_back(base);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
tok2 = tok2->next();
|
tok2 = tok2->next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -869,6 +869,8 @@ static Token *processFunc(Token *tok2, bool inOperator)
|
||||||
tok2 = tok2->tokAt(5)->link();
|
tok2 = tok2->tokAt(5)->link();
|
||||||
else if (Token::Match(tok2->next(), "* ( * %type% ) ("))
|
else if (Token::Match(tok2->next(), "* ( * %type% ) ("))
|
||||||
tok2 = tok2->tokAt(6)->link();
|
tok2 = tok2->tokAt(6)->link();
|
||||||
|
else if (Token::Match(tok2->next(), "* ( * %type% ) ;"))
|
||||||
|
tok2 = tok2->tokAt(5);
|
||||||
else if (Token::Match(tok2->next(), "* ( %type% [") &&
|
else if (Token::Match(tok2->next(), "* ( %type% [") &&
|
||||||
Token::Match(tok2->tokAt(4)->link(), "] ) ;|="))
|
Token::Match(tok2->tokAt(4)->link(), "] ) ;|="))
|
||||||
tok2 = tok2->tokAt(4)->link()->next();
|
tok2 = tok2->tokAt(4)->link()->next();
|
||||||
|
@ -6357,7 +6359,7 @@ bool Tokenizer::simplifyKnownVariablesGetData(unsigned int varid, Token **_tok2,
|
||||||
|
|
||||||
bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, bool pointeralias, int indentlevel)
|
bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsigned int varid, const std::string &structname, std::string &value, unsigned int valueVarId, bool valueIsPointer, bool pointeralias, int indentlevel)
|
||||||
{
|
{
|
||||||
bool ret = false;;
|
bool ret = false;
|
||||||
|
|
||||||
Token* bailOutFromLoop = 0;
|
Token* bailOutFromLoop = 0;
|
||||||
int indentlevel3 = indentlevel;
|
int indentlevel3 = indentlevel;
|
||||||
|
@ -6527,7 +6529,7 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
|
||||||
// Using the variable in condition..
|
// Using the variable in condition..
|
||||||
if (Token::Match(tok3->previous(), ("if ( " + structname + " %varid% ==|!=|<|<=|>|>=|)").c_str(), varid) ||
|
if (Token::Match(tok3->previous(), ("if ( " + structname + " %varid% ==|!=|<|<=|>|>=|)").c_str(), varid) ||
|
||||||
Token::Match(tok3, ("( " + structname + " %varid% ==|!=|<|<=|>|>=").c_str(), varid) ||
|
Token::Match(tok3, ("( " + structname + " %varid% ==|!=|<|<=|>|>=").c_str(), varid) ||
|
||||||
Token::Match(tok3, ("!|==|!=|<|<=|>|>= " + structname + " %varid% ==|!=|<|<=|>|>=|)").c_str(), varid) ||
|
Token::Match(tok3, ("!|==|!=|<|<=|>|>= " + structname + " %varid% ==|!=|<|<=|>|>=|)|;").c_str(), varid) ||
|
||||||
Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid))
|
Token::Match(tok3->previous(), "strlen|free ( %varid% )", varid))
|
||||||
{
|
{
|
||||||
if (!structname.empty())
|
if (!structname.empty())
|
||||||
|
@ -6618,10 +6620,10 @@ bool Tokenizer::simplifyKnownVariablesSimplify(Token **tok2, Token *tok3, unsign
|
||||||
|
|
||||||
// Variable is used in calculation..
|
// Variable is used in calculation..
|
||||||
if (((tok3->previous()->varId() > 0) && Token::Match(tok3, ("& " + structname + " %varid%").c_str(), varid)) ||
|
if (((tok3->previous()->varId() > 0) && Token::Match(tok3, ("& " + structname + " %varid%").c_str(), varid)) ||
|
||||||
Token::Match(tok3, ("[=+-*/[] " + structname + " %varid% [=?+-*/;])]").c_str(), varid) ||
|
Token::Match(tok3, ("[=+-*/%^|[] " + structname + " %varid% [=?+-*/%^|;])]").c_str(), varid) ||
|
||||||
Token::Match(tok3, ("[(=+-*/[] " + structname + " %varid% <<|>>").c_str(), varid) ||
|
Token::Match(tok3, ("[(=+-*/%^|[] " + structname + " %varid% <<|>>").c_str(), varid) ||
|
||||||
Token::Match(tok3, ("<<|>> " + structname + " %varid% [+-*/;])]").c_str(), varid) ||
|
Token::Match(tok3, ("<<|>> " + structname + " %varid% [+-*/%^|;])]").c_str(), varid) ||
|
||||||
Token::Match(tok3->previous(), ("[=+-*/[] ( " + structname + " %varid%").c_str(), varid))
|
Token::Match(tok3->previous(), ("[=+-*/%^|[] ( " + structname + " %varid%").c_str(), varid))
|
||||||
{
|
{
|
||||||
if (!structname.empty())
|
if (!structname.empty())
|
||||||
{
|
{
|
||||||
|
@ -7069,10 +7071,11 @@ bool Tokenizer::simplifyCalculations()
|
||||||
{
|
{
|
||||||
|
|
||||||
// (1-2)
|
// (1-2)
|
||||||
while (Token::Match(tok, "[[,(=<>+-*] %num% [+-*/] %num% [],);=<>+-*/]") ||
|
while (Token::Match(tok, "[[,(=<>+-*|&^] %num% [+-*/] %num% [],);=<>+-*/|&^]") ||
|
||||||
Token::Match(tok, "<< %num% [+-*/] %num% [],);=<>+-*/]") ||
|
Token::Match(tok, "<< %num% [+-*/] %num% [],);=<>+-*/|&^]") ||
|
||||||
Token::Match(tok, "[[,(=<>+-*] %num% [+-*/] %num% <<|>>") ||
|
Token::Match(tok, "[[,(=<>+-*|&^] %num% [+-*/] %num% <<|>>") ||
|
||||||
Token::Match(tok, "<< %num% [+-*/] %num% <<"))
|
Token::Match(tok, "<< %num% [+-*/] %num% <<") ||
|
||||||
|
Token::Match(tok, "[(,[] %num% [|&^] %num% [];,);]"))
|
||||||
{
|
{
|
||||||
tok = tok->next();
|
tok = tok->next();
|
||||||
|
|
||||||
|
@ -7080,6 +7083,29 @@ bool Tokenizer::simplifyCalculations()
|
||||||
if (Token::simpleMatch(tok->next(), "/ 0"))
|
if (Token::simpleMatch(tok->next(), "/ 0"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// & | ^
|
||||||
|
if (Token::Match(tok->next(), "[&|^]"))
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
const std::string first(tok->str());
|
||||||
|
const std::string second(tok->strAt(2));
|
||||||
|
const char op = tok->next()->str()[0];
|
||||||
|
if (op == '&')
|
||||||
|
result = MathLib::toString<MathLib::bigint>(MathLib::toLongNumber(first) & MathLib::toLongNumber(second));
|
||||||
|
else if (op == '|')
|
||||||
|
result = MathLib::toString<MathLib::bigint>(MathLib::toLongNumber(first) | MathLib::toLongNumber(second));
|
||||||
|
else if (op == '^')
|
||||||
|
result = MathLib::toString<MathLib::bigint>(MathLib::toLongNumber(first) ^ MathLib::toLongNumber(second));
|
||||||
|
|
||||||
|
if (!result.empty())
|
||||||
|
{
|
||||||
|
ret = true;
|
||||||
|
tok->str(result);
|
||||||
|
Token::eraseTokens(tok, tok->tokAt(3));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// + and - are calculated after * and /
|
// + and - are calculated after * and /
|
||||||
if (Token::Match(tok->next(), "[+-/]"))
|
if (Token::Match(tok->next(), "[+-/]"))
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,8 +18,8 @@ Compiling
|
||||||
|
|
||||||
To build the GUI, you need Qt.
|
To build the GUI, you need Qt.
|
||||||
|
|
||||||
To build the command line tool, PCRE is needed. More information about PCRE is found in
|
To build the command line tool, no dependencies are required. However for
|
||||||
build.txt
|
the handling of rules, PCRE is needed.
|
||||||
|
|
||||||
There are multiple compilation choices:
|
There are multiple compilation choices:
|
||||||
* qmake - cross platform build tool
|
* qmake - cross platform build tool
|
||||||
|
@ -48,7 +48,7 @@ Compiling
|
||||||
g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp
|
g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp
|
||||||
|
|
||||||
If you want to use --rule and --rule-file then dependencies are needed:
|
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
|
g++ -o cppcheck -lpcre -DHAVE_RULES -Ilib -Iexternals cli/*.cpp lib/*.cpp externals/tinyxml/*.cpp
|
||||||
mingw
|
mingw
|
||||||
=====
|
=====
|
||||||
make LDFLAGS=-lshlwapi
|
make LDFLAGS=-lshlwapi
|
||||||
|
|
|
@ -868,7 +868,7 @@ private:
|
||||||
" a[256] = 0;\n" // 256 > CHAR_MAX
|
" a[256] = 0;\n" // 256 > CHAR_MAX
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("[test.cpp:4]: (error) Array 'a[256]' index 256 out of bounds\n"
|
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());
|
"[test.cpp:3]: (error) Array index -1 out of bounds\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
check("void f(signed char n) {\n"
|
check("void f(signed char n) {\n"
|
||||||
|
@ -1875,6 +1875,20 @@ private:
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("class A {\n"
|
||||||
|
" void foo();\n"
|
||||||
|
" bool b[7];\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"void A::foo() {\n"
|
||||||
|
" for (int i=0; i<7; i++) {\n"
|
||||||
|
" b[i] = b[i+1];\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
TODO_ASSERT_EQUALS("error", // wanted result
|
||||||
|
"", // current result
|
||||||
|
errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_overrun_bailoutIfSwitch()
|
void buffer_overrun_bailoutIfSwitch()
|
||||||
|
|
|
@ -86,7 +86,7 @@ private:
|
||||||
void getErrorMessages()
|
void getErrorMessages()
|
||||||
{
|
{
|
||||||
ErrorLogger2 errorLogger;
|
ErrorLogger2 errorLogger;
|
||||||
CppCheck cppCheck(errorLogger);
|
CppCheck cppCheck(errorLogger, true);
|
||||||
cppCheck.getErrorMessages();
|
cppCheck.getErrorMessages();
|
||||||
ASSERT(!errorLogger.id.empty());
|
ASSERT(!errorLogger.id.empty());
|
||||||
|
|
||||||
|
|
|
@ -236,6 +236,7 @@ private:
|
||||||
TEST_CASE(simplifyTypedef76); // ticket #2453
|
TEST_CASE(simplifyTypedef76); // ticket #2453
|
||||||
TEST_CASE(simplifyTypedef77); // ticket #2554
|
TEST_CASE(simplifyTypedef77); // ticket #2554
|
||||||
TEST_CASE(simplifyTypedef78); // ticket #2568
|
TEST_CASE(simplifyTypedef78); // ticket #2568
|
||||||
|
TEST_CASE(simplifyTypedef79); // ticket #2348
|
||||||
|
|
||||||
TEST_CASE(simplifyTypedefFunction1);
|
TEST_CASE(simplifyTypedefFunction1);
|
||||||
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
TEST_CASE(simplifyTypedefFunction2); // ticket #1685
|
||||||
|
@ -2590,6 +2591,8 @@ private:
|
||||||
ASSERT_EQUALS("a [ 0 ]", tok(code));
|
ASSERT_EQUALS("a [ 0 ]", tok(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASSERT_EQUALS("a [ 4 ] ;", tok("a[1+3|4];"));
|
||||||
|
|
||||||
ASSERT_EQUALS("x = 1 + 2 * y ;", tok("x=1+2*y;"));
|
ASSERT_EQUALS("x = 1 + 2 * y ;", tok("x=1+2*y;"));
|
||||||
ASSERT_EQUALS("x = 7 ;", tok("x=1+2*3;"));
|
ASSERT_EQUALS("x = 7 ;", tok("x=1+2*3;"));
|
||||||
ASSERT_EQUALS("x = 47185 ;", tok("x=(65536*72/100);"));
|
ASSERT_EQUALS("x = 47185 ;", tok("x=(65536*72/100);"));
|
||||||
|
@ -4858,6 +4861,21 @@ private:
|
||||||
ASSERT_EQUALS(expected, sizeof_(code));
|
ASSERT_EQUALS(expected, sizeof_(code));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void simplifyTypedef79() // ticket #2348
|
||||||
|
{
|
||||||
|
const char code[] = "typedef int (Tcl_ObjCmdProc) (int x);\n"
|
||||||
|
"typedef struct LangVtab\n"
|
||||||
|
"{\n"
|
||||||
|
" Tcl_ObjCmdProc * (*V_LangOptionCommand);\n"
|
||||||
|
"} LangVtab;\n";
|
||||||
|
const std::string expected = "; "
|
||||||
|
"struct LangVtab "
|
||||||
|
"{ "
|
||||||
|
"int ( * ( * V_LangOptionCommand ) ) ( int x ) ; "
|
||||||
|
"} ;";
|
||||||
|
ASSERT_EQUALS(expected, sizeof_(code));
|
||||||
|
}
|
||||||
|
|
||||||
void simplifyTypedefFunction1()
|
void simplifyTypedefFunction1()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
* 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 "cppcheck.h"
|
||||||
|
#include "settings.h"
|
||||||
|
#include "testsuite.h"
|
||||||
|
#include "threadexecutor.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
extern std::ostringstream errout;
|
||||||
|
|
||||||
|
class TestSuppressions : public TestFixture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestSuppressions() : TestFixture("TestSuppressions")
|
||||||
|
{ }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
TEST_CASE(suppressionsSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the suppression
|
||||||
|
void checkSuppression(const char code[], const std::string &suppression = "")
|
||||||
|
{
|
||||||
|
// Clear the error log
|
||||||
|
errout.str("");
|
||||||
|
|
||||||
|
Settings settings;
|
||||||
|
settings._inlineSuppressions = true;
|
||||||
|
if (!suppression.empty())
|
||||||
|
settings.nomsg.addSuppressionLine(suppression);
|
||||||
|
|
||||||
|
CppCheck cppCheck(*this, true);
|
||||||
|
cppCheck.settings(settings);
|
||||||
|
cppCheck.addFile("test.cpp", code);
|
||||||
|
cppCheck.check();
|
||||||
|
|
||||||
|
reportUnmatchedSuppressions(cppCheck.settings().nomsg.getUnmatchedGlobalSuppressions());
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkSuppressionThreads(const char code[], const std::string &suppression = "")
|
||||||
|
{
|
||||||
|
errout.str("");
|
||||||
|
output.str("");
|
||||||
|
if (!ThreadExecutor::isEnabled())
|
||||||
|
{
|
||||||
|
// Skip this check on systems which don't use this feature
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> filenames;
|
||||||
|
filenames.push_back("test.cpp");
|
||||||
|
|
||||||
|
Settings settings;
|
||||||
|
settings._jobs = 1;
|
||||||
|
settings._inlineSuppressions = true;
|
||||||
|
if (!suppression.empty())
|
||||||
|
settings.nomsg.addSuppressionLine(suppression);
|
||||||
|
ThreadExecutor executor(filenames, settings, *this);
|
||||||
|
for (unsigned int i = 0; i < filenames.size(); ++i)
|
||||||
|
executor.addFileContent(filenames[i], code);
|
||||||
|
|
||||||
|
executor.check();
|
||||||
|
|
||||||
|
reportUnmatchedSuppressions(settings.nomsg.getUnmatchedGlobalSuppressions());
|
||||||
|
}
|
||||||
|
|
||||||
|
void runChecks(void (TestSuppressions::*check)(const char[], const std::string &))
|
||||||
|
{
|
||||||
|
// check to make sure the appropriate error is present
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" a++;\n"
|
||||||
|
"}\n",
|
||||||
|
"");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (error) Uninitialized variable: a\n", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar globally
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" a++;\n"
|
||||||
|
"}\n",
|
||||||
|
"uninitvar");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar globally, without error present
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" b++;\n"
|
||||||
|
"}\n",
|
||||||
|
"uninitvar");
|
||||||
|
ASSERT_EQUALS("[*]: (information) Unmatched suppression: uninitvar\n", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar for this file only
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" a++;\n"
|
||||||
|
"}\n",
|
||||||
|
"uninitvar:test.cpp");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar for this file only, without error present
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" b++;\n"
|
||||||
|
"}\n",
|
||||||
|
"uninitvar:test.cpp");
|
||||||
|
ASSERT_EQUALS("[test.cpp]: (information) Unmatched suppression: uninitvar\n", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar for this file and line
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" a++;\n"
|
||||||
|
"}\n",
|
||||||
|
"uninitvar:test.cpp:3");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar for this file and line, without error present
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" b++;\n"
|
||||||
|
"}\n",
|
||||||
|
"uninitvar:test.cpp:3");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (information) Unmatched suppression: uninitvar\n", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar inline
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" // cppcheck-suppress uninitvar\n"
|
||||||
|
" a++;\n"
|
||||||
|
"}\n",
|
||||||
|
"");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// suppress uninitvar inline, without error present
|
||||||
|
(this->*check)("void f() {\n"
|
||||||
|
" int a;\n"
|
||||||
|
" // cppcheck-suppress uninitvar\n"
|
||||||
|
" b++;\n"
|
||||||
|
"}\n",
|
||||||
|
"");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (information) Unmatched suppression: uninitvar\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void suppressionsSettings()
|
||||||
|
{
|
||||||
|
runChecks(&TestSuppressions::checkSuppression);
|
||||||
|
runChecks(&TestSuppressions::checkSuppressionThreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
REGISTER_TEST(TestSuppressions)
|
|
@ -1637,21 +1637,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h | i;\n"
|
" return h | i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: int foo ( int u@1 , int v@2 )\n"
|
"1: int foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4:\n"
|
"4:\n"
|
||||||
"5: return u@1 | v@2 ;\n"
|
"5: return u@1 | v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n"
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
"1: int foo ( int u@1 , int v@2 )\n"
|
|
||||||
"2: {\n"
|
|
||||||
"3: ;\n"
|
|
||||||
"4: int i@4 ; i@4 = v@2 ;\n"
|
|
||||||
"5: return u@1 | i@4 ;\n"
|
|
||||||
"6: }\n";
|
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1661,21 +1654,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h ^ i;\n"
|
" return h ^ i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: int foo ( int u@1 , int v@2 )\n"
|
"1: int foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4:\n"
|
"4:\n"
|
||||||
"5: return u@1 ^ v@2 ;\n"
|
"5: return u@1 ^ v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n"
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
"1: int foo ( int u@1 , int v@2 )\n"
|
|
||||||
"2: {\n"
|
|
||||||
"3: ;\n"
|
|
||||||
"4: int i@4 ; i@4 = v@2 ;\n"
|
|
||||||
"5: return u@1 ^ i@4 ;\n"
|
|
||||||
"6: }\n";
|
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1685,21 +1671,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h % i;\n"
|
" return h % i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: int foo ( int u@1 , int v@2 )\n"
|
"1: int foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4:\n"
|
"4:\n"
|
||||||
"5: return u@1 % v@2 ;\n"
|
"5: return u@1 % v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n"
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
"1: int foo ( int u@1 , int v@2 )\n"
|
|
||||||
"2: {\n"
|
|
||||||
"3: ;\n"
|
|
||||||
"4: int i@4 ; i@4 = v@2 ;\n"
|
|
||||||
"5: return u@1 % i@4 ;\n"
|
|
||||||
"6: }\n";
|
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1743,22 +1722,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h == i;\n"
|
" return h == i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: bool foo ( int u@1 , int v@2 )\n"
|
"1: bool foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4: ;\n"
|
"4:\n"
|
||||||
"5: return u@1 == v@2 ;\n"
|
"5: return u@1 == v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n"
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
"1: bool foo ( int u@1 , int v@2 )\n"
|
|
||||||
"2: {\n"
|
|
||||||
"3: ;\n"
|
|
||||||
"4: int i@4 ; i@4 = v@2 ;\n"
|
|
||||||
"5: return u@1 == i@4 ;\n"
|
|
||||||
"6: }\n";
|
|
||||||
|
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1768,21 +1739,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h != i;\n"
|
" return h != i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: bool foo ( int u@1 , int v@2 )\n"
|
"1: bool foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4: ;\n"
|
"4:\n"
|
||||||
"5: return u@1 != v@2 ;\n"
|
"5: return u@1 != v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n"
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
"1: bool foo ( int u@1 , int v@2 )\n"
|
|
||||||
"2: {\n"
|
|
||||||
"3: ;\n"
|
|
||||||
"4: int i@4 ; i@4 = v@2 ;\n"
|
|
||||||
"5: return u@1 != i@4 ;\n"
|
|
||||||
"6: }\n";
|
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1792,15 +1756,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h > i;\n"
|
" return h > i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: bool foo ( int u@1 , int v@2 )\n"
|
"1: bool foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4: ;\n"
|
"4:\n"
|
||||||
"5: return u@1 > v@2 ;\n"
|
"5: return u@1 > v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n1: bool foo ( int u@1 , int v@2 )\n2: {\n3: ;\n4: int i@4 ; i@4 = v@2 ;\n5: return u@1 > i@4 ;\n6: }\n";
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1810,15 +1773,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h >= i;\n"
|
" return h >= i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: bool foo ( int u@1 , int v@2 )\n"
|
"1: bool foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4: ;\n"
|
"4:\n"
|
||||||
"5: return u@1 >= v@2 ;\n"
|
"5: return u@1 >= v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n1: bool foo ( int u@1 , int v@2 )\n2: {\n3: ;\n4: int i@4 ; i@4 = v@2 ;\n5: return u@1 >= i@4 ;\n6: }\n";
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1828,15 +1790,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h < i;\n"
|
" return h < i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: bool foo ( int u@1 , int v@2 )\n"
|
"1: bool foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4: ;\n"
|
"4:\n"
|
||||||
"5: return u@1 < v@2 ;\n"
|
"5: return u@1 < v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n1: bool foo ( int u@1 , int v@2 )\n2: {\n3: ;\n4: int i@4 ; i@4 = v@2 ;\n5: return u@1 < i@4 ;\n6: }\n";
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1846,15 +1807,14 @@ private:
|
||||||
" int i = v;\n"
|
" int i = v;\n"
|
||||||
" return h <= i;\n"
|
" return h <= i;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
const char wanted[] = "\n\n##file 0\n"
|
const char expected[] = "\n\n##file 0\n"
|
||||||
"1: bool foo ( int u@1 , int v@2 )\n"
|
"1: bool foo ( int u@1 , int v@2 )\n"
|
||||||
"2: {\n"
|
"2: {\n"
|
||||||
"3: ;\n"
|
"3: ;\n"
|
||||||
"4: ;\n"
|
"4:\n"
|
||||||
"5: return u@1 <= v@2 ;\n"
|
"5: return u@1 <= v@2 ;\n"
|
||||||
"6: }\n";
|
"6: }\n";
|
||||||
const char current[] = "\n\n##file 0\n1: bool foo ( int u@1 , int v@2 )\n2: {\n3: ;\n4: int i@4 ; i@4 = v@2 ;\n5: return u@1 <= i@4 ;\n6: }\n";
|
ASSERT_EQUALS(expected, tokenizeDebugListing(code, true));
|
||||||
TODO_ASSERT_EQUALS(wanted, current, tokenizeDebugListing(code, true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,6 +67,7 @@ private:
|
||||||
TEST_CASE(testDoesNotIdentifyMethodAsLastFunctionArgument);
|
TEST_CASE(testDoesNotIdentifyMethodAsLastFunctionArgument);
|
||||||
|
|
||||||
TEST_CASE(multiFile);
|
TEST_CASE(multiFile);
|
||||||
|
TEST_CASE(unknownBaseTemplate); // ticket #2580
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -571,6 +572,20 @@ private:
|
||||||
|
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void unknownBaseTemplate() // ticket #2580
|
||||||
|
{
|
||||||
|
check("class Bla : public Base2<Base> {\n"
|
||||||
|
"public:\n"
|
||||||
|
" Bla() {}\n"
|
||||||
|
"private:\n"
|
||||||
|
" virtual void F() const;\n"
|
||||||
|
"};\n"
|
||||||
|
"void Bla::F() const { }");
|
||||||
|
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestUnusedPrivateFunction)
|
REGISTER_TEST(TestUnusedPrivateFunction)
|
||||||
|
|
|
@ -225,7 +225,7 @@ int main(int argc, char **argv)
|
||||||
// Makefile settings..
|
// Makefile settings..
|
||||||
if (release)
|
if (release)
|
||||||
{
|
{
|
||||||
makeConditionalVariable(fout, "CXXFLAGS", "-O2 -DNDEBUG -DHAVE_DEPENDENCIES -Wall");
|
makeConditionalVariable(fout, "CXXFLAGS", "-O2 -DNDEBUG -DHAVE_RULES -Wall");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -235,7 +235,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
// The _GLIBCXX_DEBUG doesn't work in cygwin
|
// The _GLIBCXX_DEBUG doesn't work in cygwin
|
||||||
makeConditionalVariable(fout, "CXXFLAGS",
|
makeConditionalVariable(fout, "CXXFLAGS",
|
||||||
"-DHAVE_DEPENDENCIES "
|
"-DHAVE_RULES "
|
||||||
"-Wall "
|
"-Wall "
|
||||||
"-Wextra "
|
"-Wextra "
|
||||||
"-Wshadow "
|
"-Wshadow "
|
||||||
|
|
Loading…
Reference in New Issue