Merge branch 'master' of http://github.com/danmar/cppcheck
This commit is contained in:
commit
78498d4888
14
Makefile
14
Makefile
|
@ -52,6 +52,7 @@ CLIOBJ = cli/cmdlineparser.o \
|
|||
cli/filelister_unix.o \
|
||||
cli/filelister_win32.o \
|
||||
cli/main.o \
|
||||
cli/pathmatch.o \
|
||||
cli/threadexecutor.o
|
||||
|
||||
TESTOBJ = test/options.o \
|
||||
|
@ -74,6 +75,7 @@ TESTOBJ = test/options.o \
|
|||
test/testoptions.o \
|
||||
test/testother.o \
|
||||
test/testpath.o \
|
||||
test/testpathmatch.o \
|
||||
test/testpostfixoperator.o \
|
||||
test/testpreprocessor.o \
|
||||
test/testrunner.o \
|
||||
|
@ -103,8 +105,8 @@ cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)
|
|||
|
||||
all: cppcheck testrunner
|
||||
|
||||
testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o $(LDFLAGS)
|
||||
testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o $(LDFLAGS)
|
||||
|
||||
test: all
|
||||
./testrunner
|
||||
|
@ -206,7 +208,7 @@ lib/tokenize.o: lib/tokenize.cpp lib/tokenize.h lib/token.h lib/mathlib.h lib/se
|
|||
cli/cmdlineparser.o: cli/cmdlineparser.cpp lib/cppcheck.h lib/settings.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/timer.h cli/cmdlineparser.h lib/path.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/cmdlineparser.o cli/cmdlineparser.cpp
|
||||
|
||||
cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h cli/threadexecutor.h cli/cmdlineparser.h cli/filelister.h lib/path.h
|
||||
cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h cli/threadexecutor.h cli/cmdlineparser.h cli/filelister.h lib/path.h cli/pathmatch.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/cppcheckexecutor.o cli/cppcheckexecutor.cpp
|
||||
|
||||
cli/filelister.o: cli/filelister.cpp cli/filelister.h cli/filelister_win32.h cli/filelister_unix.h
|
||||
|
@ -221,6 +223,9 @@ cli/filelister_win32.o: cli/filelister_win32.cpp cli/filelister.h cli/filelister
|
|||
cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/settings.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/main.o cli/main.cpp
|
||||
|
||||
cli/pathmatch.o: cli/pathmatch.cpp cli/pathmatch.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/pathmatch.o cli/pathmatch.cpp
|
||||
|
||||
cli/threadexecutor.o: cli/threadexecutor.cpp cli/threadexecutor.h lib/settings.h lib/errorlogger.h lib/cppcheck.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Iexternals -c -o cli/threadexecutor.o cli/threadexecutor.cpp
|
||||
|
||||
|
@ -284,6 +289,9 @@ test/testother.o: test/testother.cpp lib/tokenize.h lib/checkother.h lib/check.h
|
|||
test/testpath.o: test/testpath.cpp test/testsuite.h lib/errorlogger.h test/redirect.h lib/path.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpath.o test/testpath.cpp
|
||||
|
||||
test/testpathmatch.o: test/testpathmatch.cpp test/testsuite.h lib/errorlogger.h test/redirect.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpathmatch.o test/testpathmatch.cpp
|
||||
|
||||
test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/tokenize.h lib/checkpostfixoperator.h lib/check.h lib/token.h lib/settings.h lib/errorlogger.h test/testsuite.h test/redirect.h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -Ilib -Icli -Iexternals -c -o test/testpostfixoperator.o test/testpostfixoperator.cpp
|
||||
|
||||
|
|
|
@ -17,12 +17,15 @@ SOURCES += main.cpp \
|
|||
filelister.cpp \
|
||||
filelister_unix.cpp \
|
||||
filelister_win32.cpp \
|
||||
pathmatch.cpp \
|
||||
threadexecutor.cpp
|
||||
|
||||
HEADERS += cppcheckexecutor.h \
|
||||
cmdlineparser.h \
|
||||
filelister.h \
|
||||
filelister_unix.h \
|
||||
filelister_win32.h \
|
||||
pathmatch.h \
|
||||
threadexecutor.h
|
||||
|
||||
CONFIG(release, debug|release) {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "settings.h"
|
||||
#include "cmdlineparser.h"
|
||||
#include "path.h"
|
||||
#include "filelister.h"
|
||||
|
||||
// xml is used in rules
|
||||
#include "tinyxml/tinyxml.h"
|
||||
|
@ -210,11 +211,28 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
|||
else if (strcmp(argv[i], "--xml") == 0)
|
||||
_settings->_xml = true;
|
||||
|
||||
// Write results in xml2 format
|
||||
else if (strcmp(argv[i], "--xml-version=2") == 0)
|
||||
// Define the XML file version (and enable XML output)
|
||||
else if (strncmp(argv[i], "--xml-version=", 14) == 0)
|
||||
{
|
||||
std::string numberString(argv[i]);
|
||||
numberString = numberString.substr(14);
|
||||
|
||||
std::istringstream iss(numberString);
|
||||
if (!(iss >> _settings->_xml_version))
|
||||
{
|
||||
PrintMessage("cppcheck: argument to '--xml-version' is not a number");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_settings->_xml_version < 0 || _settings->_xml_version > 2)
|
||||
{
|
||||
// We only have xml versions 1 and 2
|
||||
PrintMessage("cppcheck: --xml-version can only be 1 or 2.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable also XML if version is set
|
||||
_settings->_xml = true;
|
||||
_settings->_xml_version = 2;
|
||||
}
|
||||
|
||||
// Only print something when there are errors
|
||||
|
@ -327,6 +345,44 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
|||
AddFilesToList(12 + argv[i], _pathnames);
|
||||
}
|
||||
|
||||
// Ignored paths
|
||||
else if (strncmp(argv[i], "-i", 2) == 0)
|
||||
{
|
||||
std::string path;
|
||||
|
||||
// "-i path/"
|
||||
if (strcmp(argv[i], "-i") == 0)
|
||||
{
|
||||
++i;
|
||||
if (i >= argc)
|
||||
{
|
||||
PrintMessage("cppcheck: argument to '-i' is missing");
|
||||
return false;
|
||||
}
|
||||
path = argv[i];
|
||||
}
|
||||
|
||||
// "-ipath/"
|
||||
else
|
||||
{
|
||||
path = 2 + argv[i];
|
||||
}
|
||||
|
||||
if (!path.empty())
|
||||
{
|
||||
path = Path::fromNativeSeparators(path);
|
||||
|
||||
// If not "known" filename extension then assume it is path
|
||||
if (!FileLister::acceptFile(path))
|
||||
{
|
||||
// If path doesn't end with / or \, add it
|
||||
if (path[path.length()-1] != '/')
|
||||
path += '/';
|
||||
}
|
||||
_ignoredPaths.push_back(path);
|
||||
}
|
||||
}
|
||||
|
||||
// Report progress
|
||||
else if (strcmp(argv[i], "--report-progress") == 0)
|
||||
{
|
||||
|
@ -461,18 +517,18 @@ bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[])
|
|||
TiXmlDocument doc;
|
||||
if (doc.LoadFile(12+argv[i]))
|
||||
{
|
||||
TiXmlElement *root = doc.FirstChildElement();
|
||||
if (root && root->ValueStr() == "rule")
|
||||
TiXmlElement *node = doc.FirstChildElement();
|
||||
for (; node && node->ValueStr() == "rule"; node = node->NextSiblingElement())
|
||||
{
|
||||
Settings::Rule rule;
|
||||
|
||||
TiXmlElement *pattern = root->FirstChildElement("pattern");
|
||||
TiXmlElement *pattern = node->FirstChildElement("pattern");
|
||||
if (pattern)
|
||||
{
|
||||
rule.pattern = pattern->GetText();
|
||||
}
|
||||
|
||||
TiXmlElement *message = root->FirstChildElement("message");
|
||||
TiXmlElement *message = node->FirstChildElement("message");
|
||||
if (message)
|
||||
{
|
||||
TiXmlElement *severity = message->FirstChildElement("severity");
|
||||
|
@ -589,6 +645,10 @@ void CmdLineParser::PrintHelp()
|
|||
" -I [dir] Give include path. Give several -I parameters to give\n"
|
||||
" several paths. First given path is checked first. If\n"
|
||||
" paths are relative to source files, this is not needed\n"
|
||||
" -i [dir] Give path to ignore. Give several -i parameters to ignore\n"
|
||||
" several paths. Give directory name or filename with path\n"
|
||||
" as parameter. Directory name is matched to all parts of the\n"
|
||||
" path."
|
||||
" --inline-suppr Enable inline suppressions. Use them by placing one or\n"
|
||||
" more comments, like: // cppcheck-suppress warningId\n"
|
||||
" on the lines before the warning to suppress.\n"
|
||||
|
@ -608,6 +668,9 @@ void CmdLineParser::PrintHelp()
|
|||
" -v, --verbose More detailed error reports\n"
|
||||
" --version Print out version number\n"
|
||||
" --xml Write results in xml to error stream.\n"
|
||||
" --xml-version=[version]\n"
|
||||
" Select the XML file version. Currently versions 1 and 2\n"
|
||||
" are available. The default version is 1."
|
||||
"\n"
|
||||
"Example usage:\n"
|
||||
" # Recursively check the current folder. Print the progress on the screen and\n"
|
||||
|
|
|
@ -92,6 +92,14 @@ public:
|
|||
return _exitAfterPrint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of paths user wants to ignore.
|
||||
*/
|
||||
std::vector<std::string> GetIgnoredPaths() const
|
||||
{
|
||||
return _ignoredPaths;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
|
@ -111,6 +119,7 @@ private:
|
|||
bool _showErrorMessages;
|
||||
bool _exitAfterPrint;
|
||||
std::vector<std::string> _pathnames;
|
||||
std::vector<std::string> _ignoredPaths;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="cppcheck"
|
||||
ProjectGUID="{7E69D6C6-32B2-32E1-BF56-A5BFBAF5E61F}"
|
||||
ProjectGUID="{56B0F403-02CE-3F89-9A1B-E03F21240A63}"
|
||||
Keyword="Qt4VSv1.0">
|
||||
<Platforms>
|
||||
<Platform
|
||||
|
@ -169,6 +169,8 @@
|
|||
RelativePath="..\lib\mathlib.cpp" />
|
||||
<File
|
||||
RelativePath="..\lib\path.cpp" />
|
||||
<File
|
||||
RelativePath="pathmatch.cpp" />
|
||||
<File
|
||||
RelativePath="..\lib\preprocessor.cpp" />
|
||||
<File
|
||||
|
@ -242,6 +244,8 @@
|
|||
RelativePath="..\lib\mathlib.h" />
|
||||
<File
|
||||
RelativePath="..\lib\path.h" />
|
||||
<File
|
||||
RelativePath="pathmatch.h" />
|
||||
<File
|
||||
RelativePath="..\lib\preprocessor.h" />
|
||||
<File
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{42BC0E8E-9175-3B2D-B8B3-9EC5C36EF49A}</ProjectGuid>
|
||||
<ProjectGuid>{A6DACC3F-847F-3498-9415-164FBC746D6B}</ProjectGuid>
|
||||
<RootNamespace>cppcheck</RootNamespace>
|
||||
<Keyword>Qt4VSv1.0</Keyword>
|
||||
</PropertyGroup>
|
||||
|
@ -140,6 +140,7 @@
|
|||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="..\lib\mathlib.cpp" />
|
||||
<ClCompile Include="..\lib\path.cpp" />
|
||||
<ClCompile Include="pathmatch.cpp" />
|
||||
<ClCompile Include="..\lib\preprocessor.cpp" />
|
||||
<ClCompile Include="..\lib\settings.cpp" />
|
||||
<ClCompile Include="..\lib\symboldatabase.cpp" />
|
||||
|
@ -176,6 +177,7 @@
|
|||
<ClInclude Include="filelister_win32.h" />
|
||||
<ClInclude Include="..\lib\mathlib.h" />
|
||||
<ClInclude Include="..\lib\path.h" />
|
||||
<ClInclude Include="pathmatch.h" />
|
||||
<ClInclude Include="..\lib\preprocessor.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="..\lib\settings.h" />
|
||||
|
|
|
@ -84,6 +84,9 @@
|
|||
<ClCompile Include="..\lib\path.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pathmatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\preprocessor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -188,6 +191,9 @@
|
|||
<ClInclude Include="..\lib\path.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pathmatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\lib\preprocessor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "cmdlineparser.h"
|
||||
#include "filelister.h"
|
||||
#include "path.h"
|
||||
#include "pathmatch.h"
|
||||
|
||||
CppCheckExecutor::CppCheckExecutor()
|
||||
{
|
||||
|
@ -55,7 +56,7 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
|
|||
errorlist = true;
|
||||
std::cout << ErrorLogger::ErrorMessage::getXMLHeader(_settings._xml_version);
|
||||
cppcheck->getErrorMessages();
|
||||
std::cout << ErrorLogger::ErrorMessage::getXMLFooter() << std::endl;
|
||||
std::cout << ErrorLogger::ErrorMessage::getXMLFooter(_settings._xml_version) << std::endl;
|
||||
}
|
||||
|
||||
if (parser.ExitAfterPrinting())
|
||||
|
@ -87,19 +88,36 @@ bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* c
|
|||
std::vector<std::string>::const_iterator iter;
|
||||
for (iter = pathnames.begin(); iter != pathnames.end(); ++iter)
|
||||
getFileLister()->recursiveAddFiles(filenames, Path::toNativeSeparators(iter->c_str()));
|
||||
|
||||
for (iter = filenames.begin(); iter != filenames.end(); ++iter)
|
||||
cppcheck->addFile(*iter);
|
||||
}
|
||||
|
||||
if (filenames.empty())
|
||||
if (!filenames.empty())
|
||||
{
|
||||
PathMatch matcher(parser.GetIgnoredPaths());
|
||||
std::vector<std::string>::iterator iterBegin = filenames.begin();
|
||||
for (int i = (int)filenames.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (matcher.Match(filenames[i]))
|
||||
filenames.erase(iterBegin + i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "cppcheck: error: could not find or open any of the paths given." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!filenames.empty())
|
||||
{
|
||||
std::vector<std::string>::iterator iter;
|
||||
for (iter = filenames.begin(); iter != filenames.end(); ++iter)
|
||||
cppcheck->addFile(*iter);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
std::cout << "cppcheck: error: no files to check - all paths ignored." << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,7 +159,7 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
|
|||
|
||||
if (_settings._xml)
|
||||
{
|
||||
reportErr(ErrorLogger::ErrorMessage::getXMLFooter());
|
||||
reportErr(ErrorLogger::ErrorMessage::getXMLFooter(_settings._xml_version));
|
||||
}
|
||||
|
||||
if (returnValue)
|
||||
|
|
|
@ -55,7 +55,7 @@ public:
|
|||
* @param filename filename to check
|
||||
* @return returns true if the file extension indicates it should be checked
|
||||
*/
|
||||
virtual bool acceptFile(const std::string &filename);
|
||||
static bool acceptFile(const std::string &filename);
|
||||
|
||||
/**
|
||||
* @brief Is given path a directory?
|
||||
|
|
|
@ -72,7 +72,7 @@ void FileListerUnix::recursiveAddFiles2(std::vector<std::string> &relative,
|
|||
continue;
|
||||
}
|
||||
|
||||
if (Path::sameFileName(path,filename) || FileListerUnix::acceptFile(filename))
|
||||
if (Path::sameFileName(path,filename) || FileLister::acceptFile(filename))
|
||||
{
|
||||
relative.push_back(filename);
|
||||
absolute.push_back(fname);
|
||||
|
|
|
@ -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 "pathmatch.h"
|
||||
|
||||
PathMatch::PathMatch(const std::vector<std::string> &masks)
|
||||
: _masks(masks)
|
||||
{
|
||||
}
|
||||
|
||||
bool PathMatch::Match(const std::string &path)
|
||||
{
|
||||
if (path.empty())
|
||||
return false;
|
||||
|
||||
std::vector<std::string>::const_iterator iterMask;
|
||||
for (iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask)
|
||||
{
|
||||
// Filtering directory name
|
||||
if ((*iterMask)[(*iterMask).length() - 1] == '/')
|
||||
{
|
||||
std::string findpath(path);
|
||||
if (findpath[findpath.length() - 1] != '/')
|
||||
findpath = RemoveFilename(findpath);
|
||||
|
||||
if ((*iterMask).length() > findpath.length())
|
||||
continue;
|
||||
// Match relative paths starting with mask
|
||||
// -isrc matches src/foo.cpp
|
||||
if (findpath.compare(0, (*iterMask).size(), *iterMask) == 0)
|
||||
return true;
|
||||
// Match only full directory name in middle or end of the path
|
||||
// -isrc matches myproject/src/ but does not match
|
||||
// myproject/srcfiles/ or myproject/mysrc/
|
||||
if (findpath.find("/" + *iterMask) != std::string::npos)
|
||||
return true;
|
||||
}
|
||||
// Filtering filename
|
||||
else
|
||||
{
|
||||
if ((*iterMask).length() > path.length())
|
||||
continue;
|
||||
// Check if path ends with mask
|
||||
// -ifoo.cpp matches (./)foo.c, src/foo.cpp and proj/src/foo.cpp
|
||||
// -isrc/file.cpp matches src/foo.cpp and proj/src/foo.cpp
|
||||
if (path.compare(path.size() - (*iterMask).size(), path.size(), *iterMask) == 0)
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string PathMatch::RemoveFilename(const std::string &path)
|
||||
{
|
||||
const size_t ind = path.find_last_of('/');
|
||||
return path.substr(0, ind + 1);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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 PATHMATCH_H
|
||||
#define PATHMATCH_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/// @addtogroup CLI
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* @brief Simple path matching for ignoring paths in CLI.
|
||||
*/
|
||||
class PathMatch
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* The constructor.
|
||||
* @param masks List of masks.
|
||||
*/
|
||||
PathMatch(const std::vector<std::string> &masks);
|
||||
|
||||
/**
|
||||
* @brief Match path against list of masks.
|
||||
* @param path Path to match.
|
||||
* @return true if any of the masks match the path, false otherwise.
|
||||
*/
|
||||
bool Match(const std::string &path);
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* @brief Remove filename part from the path.
|
||||
* @param path Path to edit.
|
||||
* @return path without filename part.
|
||||
*/
|
||||
std::string RemoveFilename(const std::string &path);
|
||||
|
||||
private:
|
||||
std::vector<std::string> _masks;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
#endif // PATHMATCH_H
|
|
@ -7,6 +7,8 @@
|
|||
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<link rel="alternate" type="application/atom+xml" title="Recent Commits to cppcheck:master"
|
||||
href="https://github.com/danmar/cppcheck/commits/master.atom" />
|
||||
<link rel="alternate" type="application/atom+xml" title="Trac Timeline"
|
||||
href="http://sourceforge.net/apps/trac/cppcheck/timeline?changeset=on&ticket=on&milestone=on&wiki=on&max=50&daysback=90&format=rss" />
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script>
|
||||
<script src="/site/js/github.js" type="text/javascript"></script>
|
||||
<script type="text/javascript">
|
||||
|
@ -44,6 +46,23 @@ cppcheck git repository</a>. To download it, run the following command:</p>
|
|||
the latest sources in a zip or tgz archive</a> from the github website.</p>
|
||||
<h3>Recent Commits</h3>
|
||||
<div id="github-commits"><a href="https://github.com/danmar/cppcheck/commits/master">View recent commits…</a></div>
|
||||
<p><a href="https://github.com/danmar/cppcheck/commits/master">View all commits…</a></p>
|
||||
<h2>Trac Timeline</h2>
|
||||
<?php
|
||||
require '../site/simplepie/simplepie.inc';
|
||||
|
||||
$feed = new SimplePie();
|
||||
$feed->set_feed_url('http://sourceforge.net/apps/trac/cppcheck/timeline?changeset=on&ticket=on&milestone=on&wiki=on&max=10&daysback=90&format=rss');
|
||||
$feed->set_cache_location('./site/simplepie/cache');
|
||||
$feed->init();
|
||||
print("<ul class=\"rssfeeditems\">\n");
|
||||
foreach ($feed->get_items() as $item) { //for the last timeline items...
|
||||
$author = $item->get_author();
|
||||
print(" <li><a href=\"".$item->get_link()."\">".$item->get_title()."</a> by <strong>".$author->get_name()."</strong><em>".$item->get_date('Y-m-d')."</em></li>\n");
|
||||
}
|
||||
print("</ul>\n");
|
||||
?>
|
||||
<p><a href="http://sourceforge.net/apps/trac/cppcheck/timeline">View complete Trac timeline…</a></p>
|
||||
<h2>Doxygen</h2>
|
||||
<ul>
|
||||
<li><a href="/doxyoutput/">Output</a></li>
|
||||
|
|
|
@ -81,6 +81,10 @@ Cppcheck as an external tool.</p>
|
|||
?>
|
||||
<p><a href="http://sourceforge.net/news/?group_id=195752">View all news…</a></p>
|
||||
|
||||
<h2>Documentation</h2>
|
||||
<p>You can read the <a href="manual.pdf">manual</a> or download some
|
||||
<a href="http://sourceforge.net/projects/cppcheck/files/Articles/">articles</a>.</p>
|
||||
|
||||
<h2>Support</h2>
|
||||
<ul>
|
||||
<li>Use <a href="http://sourceforge.net/apps/trac/cppcheck/">Trac</a> to report
|
||||
|
|
42
lib/check.h
42
lib/check.h
|
@ -39,16 +39,11 @@ class Check
|
|||
{
|
||||
public:
|
||||
/** This constructor is used when registering the CheckClass */
|
||||
Check()
|
||||
: _tokenizer(0), _settings(0), _errorLogger(0)
|
||||
{
|
||||
instances().push_back(this);
|
||||
instances().sort();
|
||||
}
|
||||
Check(const std::string &aname);
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
Check(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: _tokenizer(tokenizer), _settings(settings), _errorLogger(errorLogger)
|
||||
Check(const std::string &aname, const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: _name(aname), _tokenizer(tokenizer), _settings(settings), _errorLogger(errorLogger)
|
||||
{ }
|
||||
|
||||
virtual ~Check()
|
||||
|
@ -98,7 +93,10 @@ public:
|
|||
virtual void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) = 0;
|
||||
|
||||
/** class name, used to generate documentation */
|
||||
virtual std::string name() const = 0;
|
||||
std::string name() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
/** get information about this class, used to generate documentation */
|
||||
virtual std::string classInfo() const = 0;
|
||||
|
@ -114,6 +112,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
const std::string _name;
|
||||
const Tokenizer * const _tokenizer;
|
||||
const Settings * const _settings;
|
||||
ErrorLogger * const _errorLogger;
|
||||
|
@ -155,17 +154,30 @@ protected:
|
|||
|
||||
|
||||
private:
|
||||
/** compare the names of Check classes, used when sorting the Check descendants */
|
||||
bool operator<(const Check *other) const
|
||||
{
|
||||
return (name() < other->name());
|
||||
}
|
||||
|
||||
/** disabled assignment operator */
|
||||
void operator=(const Check &);
|
||||
|
||||
};
|
||||
|
||||
namespace std
|
||||
{
|
||||
/** compare the names of Check classes, used when sorting the Check descendants */
|
||||
template <> struct less<Check *>
|
||||
{
|
||||
bool operator()(const Check *p1, const Check *p2) const
|
||||
{
|
||||
return (p1->name() < p2->name());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
inline Check::Check(const std::string &aname)
|
||||
: _name(aname), _tokenizer(0), _settings(0), _errorLogger(0)
|
||||
{
|
||||
instances().push_back(this);
|
||||
instances().sort(std::less<Check *>());
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -448,7 +448,7 @@ void CheckAutoVariables::returncstr()
|
|||
}
|
||||
|
||||
// have we reached a function that returns a reference?
|
||||
if (Token::Match(tok, "const char *"))
|
||||
if (Token::simpleMatch(tok, "const char *"))
|
||||
{
|
||||
// go to the '('
|
||||
const Token *tok2 = tok->tokAt(3);
|
||||
|
|
|
@ -34,12 +34,12 @@ class CheckAutoVariables : public Check
|
|||
{
|
||||
public:
|
||||
/** This constructor is used when registering the CheckClass */
|
||||
CheckAutoVariables() : Check()
|
||||
CheckAutoVariables() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckAutoVariables(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
|
@ -98,7 +98,7 @@ private:
|
|||
c.errorReturnTempPointer(0);
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Auto Variables";
|
||||
}
|
||||
|
|
|
@ -766,7 +766,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
|
|||
|
||||
const unsigned char varc(static_cast<unsigned char>(varname.empty() ? 0U : (varname.size() - 1) * 2U));
|
||||
|
||||
if (Token::Match(tok, "return"))
|
||||
if (Token::simpleMatch(tok, "return"))
|
||||
{
|
||||
tok = tok->next();
|
||||
if (!tok)
|
||||
|
@ -828,7 +828,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
|
|||
const MathLib::bigint index = MathLib::toLongNumber(tok->strAt(3));
|
||||
if (index < 0 || index >= size)
|
||||
{
|
||||
if (index > size || !Token::Match(tok->previous(), "& ("))
|
||||
if (index > size || !Token::simpleMatch(tok->previous(), "& ("))
|
||||
{
|
||||
arrayIndexOutOfBounds(tok->next(), size, index);
|
||||
}
|
||||
|
|
|
@ -50,12 +50,12 @@ class CheckBufferOverrun : public Check
|
|||
public:
|
||||
|
||||
/** This constructor is used when registering the CheckClass */
|
||||
CheckBufferOverrun() : Check()
|
||||
CheckBufferOverrun() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckBufferOverrun(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
|
@ -209,7 +209,7 @@ public:
|
|||
c.pointerOutOfBounds(0, "array");
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Bounds checking";
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ CheckClass instance;
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
CheckClass::CheckClass(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger),
|
||||
: Check(myName(), tokenizer, settings, errorLogger),
|
||||
symbolDatabase(NULL)
|
||||
{
|
||||
|
||||
|
@ -931,7 +931,7 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co
|
|||
// check of *this is returned
|
||||
else if (!(Token::Match(tok->tokAt(1), "(| * this ;|=") ||
|
||||
Token::Match(tok->tokAt(1), "(| * this +=") ||
|
||||
Token::Match(tok->tokAt(1), "operator= (")))
|
||||
Token::simpleMatch(tok->tokAt(1), "operator= (")))
|
||||
operatorEqRetRefThisError(func->token);
|
||||
}
|
||||
}
|
||||
|
@ -1132,7 +1132,7 @@ bool CheckClass::hasAssignSelf(const Token *first, const Token *last, const Toke
|
|||
{
|
||||
for (const Token *tok = first; tok && tok != last; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok, "if ("))
|
||||
if (Token::simpleMatch(tok, "if ("))
|
||||
{
|
||||
const Token *tok1 = tok->tokAt(2);
|
||||
const Token *tok2 = tok->tokAt(1)->link();
|
||||
|
@ -1412,7 +1412,7 @@ bool CheckClass::isMemberVar(const Scope *scope, const Token *tok)
|
|||
|
||||
while (tok->previous() && !Token::Match(tok->previous(), "}|{|;|public:|protected:|private:|return|:|?"))
|
||||
{
|
||||
if (Token::Match(tok->previous(), "* this"))
|
||||
if (Token::simpleMatch(tok->previous(), "* this"))
|
||||
return true;
|
||||
|
||||
tok = tok->previous();
|
||||
|
|
|
@ -36,7 +36,7 @@ class CheckClass : public Check
|
|||
{
|
||||
public:
|
||||
/** @brief This constructor is used when registering the CheckClass */
|
||||
CheckClass() : Check(), symbolDatabase(NULL)
|
||||
CheckClass() : Check(myName()), symbolDatabase(NULL)
|
||||
{ }
|
||||
|
||||
/** @brief This constructor is used when running checks. */
|
||||
|
@ -144,7 +144,7 @@ private:
|
|||
c.checkConstError(0, "class", "function");
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Class";
|
||||
}
|
||||
|
|
|
@ -43,12 +43,12 @@ class CheckExceptionSafety : public Check
|
|||
{
|
||||
public:
|
||||
/** This constructor is used when registering the CheckClass */
|
||||
CheckExceptionSafety() : Check()
|
||||
CheckExceptionSafety() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckExceptionSafety(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
/** Checks that uses the simplified token list */
|
||||
|
@ -86,7 +86,7 @@ private:
|
|||
}
|
||||
|
||||
/** Short description of class (for --doc) */
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Exception Safety";
|
||||
}
|
||||
|
|
|
@ -223,7 +223,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok
|
|||
return gMalloc;
|
||||
|
||||
if (Token::Match(tok, "fclose ( %varid% )", varid) ||
|
||||
Token::Match(tok, "fcloseall ( )"))
|
||||
Token::simpleMatch(tok, "fcloseall ( )"))
|
||||
return File;
|
||||
|
||||
if (Token::Match(tok, "close ( %varid% )", varid))
|
||||
|
@ -1445,7 +1445,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
|
|||
// Assignment..
|
||||
if (varid)
|
||||
{
|
||||
if (Token::Match(tok, "= {"))
|
||||
if (Token::simpleMatch(tok, "= {"))
|
||||
{
|
||||
unsigned int indentlevel2 = 0;
|
||||
bool use = false;
|
||||
|
@ -1754,7 +1754,7 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok)
|
|||
}
|
||||
}
|
||||
|
||||
if (Token::Match(tok2, "while1 { if { dealloc ; return ; } }"))
|
||||
if (Token::simpleMatch(tok2, "while1 { if { dealloc ; return ; } }"))
|
||||
{
|
||||
tok2->str(";");
|
||||
Token::eraseTokens(tok2, tok2->tokAt(4));
|
||||
|
@ -1820,7 +1820,7 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok)
|
|||
}
|
||||
|
||||
// Reduce "if continue ; if continue ;" => "if continue ;"
|
||||
else if (Token::Match(tok2->next(), "if continue ; if continue ;"))
|
||||
else if (Token::simpleMatch(tok2->next(), "if continue ; if continue ;"))
|
||||
{
|
||||
Token::eraseTokens(tok2, tok2->tokAt(4));
|
||||
done = false;
|
||||
|
|
|
@ -172,12 +172,12 @@ class CheckMemoryLeakInFunction : private Check, public CheckMemoryLeak
|
|||
{
|
||||
public:
|
||||
/** @brief This constructor is used when registering this class */
|
||||
CheckMemoryLeakInFunction() : Check(), CheckMemoryLeak(0, 0), symbolDatabase(NULL)
|
||||
CheckMemoryLeakInFunction() : Check(myName()), CheckMemoryLeak(0, 0), symbolDatabase(NULL)
|
||||
{ }
|
||||
|
||||
/** @brief This constructor is used when running checks */
|
||||
CheckMemoryLeakInFunction(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
||||
: Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
|
||||
: Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
|
||||
{
|
||||
// get the symbol database
|
||||
if (tokenizr)
|
||||
|
@ -329,7 +329,7 @@ public:
|
|||
* Get name of class (--doc)
|
||||
* @return name of class
|
||||
*/
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Memory leaks (function variables)";
|
||||
}
|
||||
|
@ -364,11 +364,11 @@ public:
|
|||
class CheckMemoryLeakInClass : private Check, private CheckMemoryLeak
|
||||
{
|
||||
public:
|
||||
CheckMemoryLeakInClass() : Check(), CheckMemoryLeak(0, 0)
|
||||
CheckMemoryLeakInClass() : Check(myName()), CheckMemoryLeak(0, 0)
|
||||
{ }
|
||||
|
||||
CheckMemoryLeakInClass(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
||||
: Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
|
||||
: Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
|
||||
{ }
|
||||
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
||||
|
@ -396,7 +396,7 @@ private:
|
|||
void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/)
|
||||
{ }
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Memory leaks (class variables)";
|
||||
}
|
||||
|
@ -414,11 +414,11 @@ private:
|
|||
class CheckMemoryLeakStructMember : private Check, private CheckMemoryLeak
|
||||
{
|
||||
public:
|
||||
CheckMemoryLeakStructMember() : Check(), CheckMemoryLeak(0, 0)
|
||||
CheckMemoryLeakStructMember() : Check(myName()), CheckMemoryLeak(0, 0)
|
||||
{ }
|
||||
|
||||
CheckMemoryLeakStructMember(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
||||
: Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
|
||||
: Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
|
||||
{ }
|
||||
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
||||
|
@ -434,7 +434,7 @@ private:
|
|||
void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/)
|
||||
{ }
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Memory leaks (struct members)";
|
||||
}
|
||||
|
@ -452,11 +452,11 @@ private:
|
|||
class CheckMemoryLeakNoVar : private Check, private CheckMemoryLeak
|
||||
{
|
||||
public:
|
||||
CheckMemoryLeakNoVar() : Check(), CheckMemoryLeak(0, 0)
|
||||
CheckMemoryLeakNoVar() : Check(myName()), CheckMemoryLeak(0, 0)
|
||||
{ }
|
||||
|
||||
CheckMemoryLeakNoVar(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
||||
: Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
|
||||
: Check(myName(), tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog)
|
||||
{ }
|
||||
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog)
|
||||
|
@ -474,7 +474,7 @@ private:
|
|||
void getErrorMessages(ErrorLogger * /*errorLogger*/, const Settings * /*settings*/)
|
||||
{ }
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Memory leaks (address not taken)";
|
||||
}
|
||||
|
|
|
@ -71,7 +71,6 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list<const Token
|
|||
functionNames1.insert("strstr");
|
||||
functionNames1.insert("fclose");
|
||||
functionNames1.insert("feof");
|
||||
functionNames1.insert("fread");
|
||||
functionNames1.insert("fwrite");
|
||||
functionNames1.insert("fseek");
|
||||
functionNames1.insert("ftell");
|
||||
|
@ -544,7 +543,7 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
|||
if (Token::Match(tok, "* %var% [;,)=]"))
|
||||
pointerVariables.insert(tok->next()->varId());
|
||||
|
||||
else if (Token::Match(tok, "if ("))
|
||||
else if (Token::simpleMatch(tok, "if ("))
|
||||
{
|
||||
// TODO: investigate false negatives:
|
||||
// - handle "while"?
|
||||
|
@ -617,7 +616,7 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
|||
if (null && indentlevel == 0)
|
||||
{
|
||||
// skip all "else" blocks because they are not executed in this execution path
|
||||
while (Token::Match(tok2, "} else {"))
|
||||
while (Token::simpleMatch(tok2, "} else {"))
|
||||
tok2 = tok2->tokAt(2)->link();
|
||||
null = false;
|
||||
}
|
||||
|
|
|
@ -37,12 +37,12 @@ class CheckNullPointer : public Check
|
|||
{
|
||||
public:
|
||||
/** @brief This constructor is used when registering the CheckNullPointer */
|
||||
CheckNullPointer() : Check()
|
||||
CheckNullPointer() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** @brief This constructor is used when running checks. */
|
||||
CheckNullPointer(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
/** @brief Run checks against the normal token list */
|
||||
|
@ -112,7 +112,7 @@ public:
|
|||
}
|
||||
|
||||
/** Name of check */
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Null pointer";
|
||||
}
|
||||
|
|
|
@ -38,14 +38,14 @@ class CheckObsoleteFunctions : public Check
|
|||
{
|
||||
public:
|
||||
/** This constructor is used when registering the CheckObsoleteFunctions */
|
||||
CheckObsoleteFunctions() : Check()
|
||||
CheckObsoleteFunctions() : Check(myName())
|
||||
{
|
||||
initObsoleteFunctions();
|
||||
}
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckObsoleteFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{
|
||||
initObsoleteFunctions();
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Obsolete functions";
|
||||
}
|
||||
|
|
|
@ -1491,7 +1491,7 @@ void CheckOther::functionVariableUsage()
|
|||
variables.read(nametok->tokAt(2)->varId());
|
||||
|
||||
// look at initializers
|
||||
if (Token::Match(nametok->tokAt(4), "= {"))
|
||||
if (Token::simpleMatch(nametok->tokAt(4), "= {"))
|
||||
{
|
||||
tok = nametok->tokAt(6);
|
||||
while (tok->str() != "}")
|
||||
|
@ -2705,7 +2705,7 @@ void CheckOther::checkMisusedScopedObject()
|
|||
}
|
||||
|
||||
if (Token::Match(tok, "[;{}] %var% (")
|
||||
&& Token::Match(tok->tokAt(2)->link(), ") ;")
|
||||
&& Token::simpleMatch(tok->tokAt(2)->link(), ") ;")
|
||||
&& symbolDatabase->isClassOrStruct(tok->next()->str())
|
||||
)
|
||||
{
|
||||
|
@ -2834,8 +2834,11 @@ void CheckOther::sizeofsizeof()
|
|||
return;
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if (Token::simpleMatch(tok, "sizeof sizeof"))
|
||||
if (Token::Match(tok, "sizeof (| sizeof"))
|
||||
{
|
||||
sizeofsizeofError(tok);
|
||||
tok = tok->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@ class CheckOther : public Check
|
|||
{
|
||||
public:
|
||||
/** @brief This constructor is used when registering the CheckClass */
|
||||
CheckOther() : Check()
|
||||
CheckOther() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** @brief This constructor is used when running checks. */
|
||||
CheckOther(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
/** @brief Run checks against the normal token list */
|
||||
|
@ -245,7 +245,7 @@ public:
|
|||
c.clarifyCalculationError(0);
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Other";
|
||||
}
|
||||
|
|
|
@ -35,12 +35,12 @@ class CheckPostfixOperator : public Check
|
|||
{
|
||||
public:
|
||||
/** This constructor is used when registering the CheckPostfixOperator */
|
||||
CheckPostfixOperator() : Check()
|
||||
CheckPostfixOperator() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckPostfixOperator(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
void runSimplifiedChecks(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
|
@ -62,7 +62,7 @@ private:
|
|||
c.postfixOperatorError(0);
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Using postfix operators";
|
||||
}
|
||||
|
|
|
@ -572,7 +572,7 @@ void CheckStl::pushback()
|
|||
}
|
||||
|
||||
// Using push_back or push_front inside a loop..
|
||||
if (Token::Match(tok2, "for ("))
|
||||
if (Token::simpleMatch(tok2, "for ("))
|
||||
{
|
||||
tok2 = tok2->tokAt(2);
|
||||
}
|
||||
|
@ -1038,7 +1038,7 @@ void CheckStl::string_c_str()
|
|||
string_c_strError(tok);
|
||||
}
|
||||
else if (Token::Match(tok, "[;{}] %var% = %var% (") &&
|
||||
Token::Match(tok->tokAt(4)->link(), ") . c_str ( ) ;") &&
|
||||
Token::simpleMatch(tok->tokAt(4)->link(), ") . c_str ( ) ;") &&
|
||||
tok->next()->varId() > 0 &&
|
||||
pointers.find(tok->next()->varId()) != pointers.end() &&
|
||||
Token::findmatch(_tokenizer->tokens(), ("std :: string " + tok->strAt(3) + " (").c_str()))
|
||||
|
|
|
@ -35,12 +35,12 @@ class CheckStl : public Check
|
|||
{
|
||||
public:
|
||||
/** This constructor is used when registering the CheckClass */
|
||||
CheckStl() : Check()
|
||||
CheckStl() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** This constructor is used when running checks. */
|
||||
CheckStl(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
/** Simplified checks. The token list is simplified. */
|
||||
|
@ -173,7 +173,7 @@ private:
|
|||
c.redundantIfRemoveError(0);
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "STL usage";
|
||||
}
|
||||
|
|
|
@ -37,12 +37,12 @@ class CheckUninitVar : public Check
|
|||
{
|
||||
public:
|
||||
/** @brief This constructor is used when registering the CheckUninitVar */
|
||||
CheckUninitVar() : Check()
|
||||
CheckUninitVar() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** @brief This constructor is used when running checks. */
|
||||
CheckUninitVar(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
/** @brief Run checks against the normal token list */
|
||||
|
@ -87,7 +87,7 @@ public:
|
|||
c.uninitvarError(0, "varname");
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Uninitialized variables";
|
||||
}
|
||||
|
|
|
@ -33,12 +33,12 @@ class CheckUnusedFunctions: public Check
|
|||
{
|
||||
public:
|
||||
/** @brief This constructor is used when registering the CheckUnusedFunctions */
|
||||
CheckUnusedFunctions() : Check()
|
||||
CheckUnusedFunctions() : Check(myName())
|
||||
{ }
|
||||
|
||||
/** @brief This constructor is used when running checks. */
|
||||
CheckUnusedFunctions(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger)
|
||||
: Check(tokenizer, settings, errorLogger)
|
||||
: Check(myName(), tokenizer, settings, errorLogger)
|
||||
{ }
|
||||
|
||||
// Parse current tokens and determine..
|
||||
|
@ -69,7 +69,7 @@ private:
|
|||
|
||||
}
|
||||
|
||||
std::string name() const
|
||||
std::string myName() const
|
||||
{
|
||||
return "Unused functions";
|
||||
}
|
||||
|
|
|
@ -335,15 +335,19 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
|||
|
||||
reportErr(errmsg);
|
||||
}
|
||||
if (re)
|
||||
{
|
||||
if (!re)
|
||||
continue;
|
||||
|
||||
int pos = 0;
|
||||
int ovector[30];
|
||||
if (0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30))
|
||||
while (0 <= pcre_exec(re, NULL, str.c_str(), (int)str.size(), pos, 0, ovector, 30))
|
||||
{
|
||||
unsigned int pos1 = (unsigned int)ovector[0];
|
||||
unsigned int pos2 = (unsigned int)ovector[1];
|
||||
|
||||
// jump to the end of the match for the next pcre_exec
|
||||
pos = pos2;
|
||||
|
||||
// determine location..
|
||||
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||
loc.setfile(_tokenizer.getFiles()->front());
|
||||
|
@ -378,7 +382,6 @@ void CppCheck::checkFile(const std::string &code, const char FileName[])
|
|||
pcre_free(re);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -162,15 +162,16 @@ std::string ErrorLogger::ErrorMessage::getXMLHeader(int xml_version)
|
|||
else
|
||||
{
|
||||
ostr << "<results version=\"" << xml_version << "\">\n";
|
||||
ostr << " <cppcheck version=\"" << CppCheck::version() << "\"/>";
|
||||
ostr << " <cppcheck version=\"" << CppCheck::version() << "\"/>\n";
|
||||
ostr << " <errors>";
|
||||
}
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
std::string ErrorLogger::ErrorMessage::getXMLFooter()
|
||||
std::string ErrorLogger::ErrorMessage::getXMLFooter(int xml_version)
|
||||
{
|
||||
return "</results>";
|
||||
return (xml_version<=1) ? "</results>" : " </errors>\n</results>";
|
||||
}
|
||||
|
||||
static std::string stringToXml(std::string s)
|
||||
|
|
|
@ -137,7 +137,7 @@ public:
|
|||
std::string toXML(bool verbose, int ver) const;
|
||||
|
||||
static std::string getXMLHeader(int xml_version);
|
||||
static std::string getXMLFooter();
|
||||
static std::string getXMLFooter(int xml_version);
|
||||
|
||||
/**
|
||||
* Format the error message into a string.
|
||||
|
|
|
@ -348,7 +348,7 @@ void ExecutionPath::checkScope(const Token *tok, std::list<ExecutionPath *> &che
|
|||
}
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "= {"))
|
||||
if (Token::simpleMatch(tok, "= {"))
|
||||
{
|
||||
// GCC struct initialization.. bail out
|
||||
if (Token::Match(tok->tokAt(2), ". %var% ="))
|
||||
|
|
|
@ -2142,7 +2142,7 @@ public:
|
|||
if (Token::Match(tok, "%var% %var%") ||
|
||||
Token::Match(tok, "%var% %num%") ||
|
||||
Token::Match(tok, "%num% %var%") ||
|
||||
Token::Match(tok, "> >"))
|
||||
Token::simpleMatch(tok, "> >"))
|
||||
macrocode += " ";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,9 +254,19 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
|
|||
}
|
||||
}
|
||||
|
||||
// nested class function?
|
||||
// nested class or friend function?
|
||||
else if (tok->previous()->str() == "::" && isFunction(tok, &funcStart, &argStart))
|
||||
{
|
||||
/** @todo check entire qualification for match */
|
||||
Scope * nested = scope->findInNestedListRecursive(tok->strAt(-2));
|
||||
|
||||
if (nested)
|
||||
addFunction(&scope, &tok, argStart);
|
||||
else
|
||||
{
|
||||
/** @todo handle friend functions */
|
||||
}
|
||||
}
|
||||
|
||||
// friend class declaration?
|
||||
else if (Token::Match(tok, "friend class| %any% ;"))
|
||||
|
@ -1398,6 +1408,26 @@ Scope * Scope::findInNestedList(const std::string & name)
|
|||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
Scope * Scope::findInNestedListRecursive(const std::string & name)
|
||||
{
|
||||
std::list<Scope *>::iterator it;
|
||||
|
||||
for (it = nestedList.begin(); it != nestedList.end(); ++it)
|
||||
{
|
||||
if ((*it)->className == name)
|
||||
return (*it);
|
||||
}
|
||||
|
||||
for (it = nestedList.begin(); it != nestedList.end(); ++it)
|
||||
{
|
||||
Scope *child = (*it)->findInNestedListRecursive(name);
|
||||
return child;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
const Function *Scope::getDestructor() const
|
||||
{
|
||||
std::list<Function>::const_iterator it;
|
||||
|
|
|
@ -311,6 +311,12 @@ public:
|
|||
*/
|
||||
Scope * findInNestedList(const std::string & name);
|
||||
|
||||
/**
|
||||
* @brief find if name is in nested list
|
||||
* @param name name of nested scope
|
||||
*/
|
||||
Scope * findInNestedListRecursive(const std::string & name);
|
||||
|
||||
void addVariable(const Token *token_, AccessControl access_, bool mutable_, bool static_, bool const_, bool class_, const Scope *type_)
|
||||
{
|
||||
varlist.push_back(Variable(token_, varlist.size(), access_, mutable_, static_, const_, class_, type_));
|
||||
|
|
152
lib/tokenize.cpp
152
lib/tokenize.cpp
|
@ -552,7 +552,7 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name)
|
|||
|
||||
if (end)
|
||||
{
|
||||
if (Token::Match(end, ") {")) // function parameter ?
|
||||
if (Token::simpleMatch(end, ") {")) // function parameter ?
|
||||
{
|
||||
// look backwards
|
||||
if (Token::Match(tok->previous(), "%type%") &&
|
||||
|
@ -588,7 +588,7 @@ bool Tokenizer::duplicateTypedef(Token **tokPtr, const Token *name)
|
|||
(tok->previous()->str() == "*" && tok->next()->str() != "(") ||
|
||||
(Token::Match(tok->previous(), "%type%") &&
|
||||
(!Token::Match(tok->previous(), "return|new|const|friend|public|private|protected|throw|extern") &&
|
||||
!Token::Match(tok->tokAt(-2), "friend class"))))
|
||||
!Token::simpleMatch(tok->tokAt(-2), "friend class"))))
|
||||
{
|
||||
// scan backwards for the end of the previous statement
|
||||
int level = (tok->previous()->str() == "}") ? 1 : 0;
|
||||
|
@ -824,7 +824,8 @@ void Tokenizer::simplifyTypedef()
|
|||
if (_errorLogger && !_files.empty())
|
||||
_errorLogger->reportProgress(_files[0], "Tokenize (typedef)", tok->progressValue());
|
||||
|
||||
if (Token::Match(tok, "class|struct|namespace %any%"))
|
||||
if (Token::Match(tok, "class|struct|namespace %any%") &&
|
||||
(!tok->previous() || (tok->previous() && tok->previous()->str() != "enum")))
|
||||
{
|
||||
isNamespace = (tok->str() == "namespace");
|
||||
hasClass = true;
|
||||
|
@ -926,7 +927,7 @@ void Tokenizer::simplifyTypedef()
|
|||
Token *namespaceStart = 0;
|
||||
Token *namespaceEnd = 0;
|
||||
|
||||
if (Token::Match(tok->next(), "::") ||
|
||||
if (Token::simpleMatch(tok->next(), "::") ||
|
||||
Token::Match(tok->next(), "%type%"))
|
||||
{
|
||||
typeStart = tok->next();
|
||||
|
@ -940,13 +941,13 @@ void Tokenizer::simplifyTypedef()
|
|||
bool atEnd = false;
|
||||
while (!atEnd)
|
||||
{
|
||||
if (Token::Match(tok->tokAt(offset), "::"))
|
||||
if (Token::simpleMatch(tok->tokAt(offset), "::"))
|
||||
typeEnd = tok->tokAt(offset++);
|
||||
|
||||
if (Token::Match(tok->tokAt(offset), "%type%") &&
|
||||
tok->tokAt(offset + 1) && !Token::Match(tok->tokAt(offset + 1), "[|;|,|("))
|
||||
typeEnd = tok->tokAt(offset++);
|
||||
else if (Token::Match(tok->tokAt(offset), "const ("))
|
||||
else if (Token::simpleMatch(tok->tokAt(offset), "const ("))
|
||||
{
|
||||
typeEnd = tok->tokAt(offset++);
|
||||
atEnd = true;
|
||||
|
@ -1040,7 +1041,7 @@ void Tokenizer::simplifyTypedef()
|
|||
tok = tok->tokAt(offset);
|
||||
|
||||
// or a function typedef
|
||||
else if (Token::Match(tok->tokAt(offset), "("))
|
||||
else if (Token::simpleMatch(tok->tokAt(offset), "("))
|
||||
{
|
||||
// unhandled typedef, skip it and continue
|
||||
if (typeName->str() == "void")
|
||||
|
@ -1143,7 +1144,7 @@ void Tokenizer::simplifyTypedef()
|
|||
|
||||
// function returning pointer to function
|
||||
else if (Token::Match(tok->tokAt(offset), "( * %type% (") &&
|
||||
Token::Match(tok->tokAt(offset + 3)->link(), ") ) ("))
|
||||
Token::simpleMatch(tok->tokAt(offset + 3)->link(), ") ) ("))
|
||||
{
|
||||
functionRetFuncPtr = true;
|
||||
|
||||
|
@ -1397,8 +1398,8 @@ void Tokenizer::simplifyTypedef()
|
|||
inTemplate = true;
|
||||
|
||||
// check for operator
|
||||
if (Token::Match(tok2->previous(), "operator") ||
|
||||
Token::Match(tok2->tokAt(-2), "operator const"))
|
||||
if (Token::simpleMatch(tok2->previous(), "operator") ||
|
||||
Token::simpleMatch(tok2->tokAt(-2), "operator const"))
|
||||
inOperator = true;
|
||||
|
||||
// skip over class or struct in derived class declaration
|
||||
|
@ -2382,6 +2383,9 @@ bool Tokenizer::tokenize(std::istream &code,
|
|||
// remove __attribute__((?))
|
||||
simplifyAttribute();
|
||||
|
||||
// remove unnecessary member qualification..
|
||||
removeUnnecessaryQualification();
|
||||
|
||||
// remove Microsoft MFC..
|
||||
simplifyMicrosoftMFC();
|
||||
|
||||
|
@ -2714,7 +2718,7 @@ void Tokenizer::simplifyTemplates()
|
|||
ostr << " ";
|
||||
ostr << tok3->str();
|
||||
}
|
||||
if (!Token::Match(tok3, "> ("))
|
||||
if (!Token::simpleMatch(tok3, "> ("))
|
||||
continue;
|
||||
s = ostr.str();
|
||||
}
|
||||
|
@ -3996,7 +4000,7 @@ void Tokenizer::simplifySizeof()
|
|||
tok->next()->deleteNext();
|
||||
}
|
||||
|
||||
if (Token::Match(tok->next(), "( * )"))
|
||||
if (Token::simpleMatch(tok->next(), "( * )"))
|
||||
{
|
||||
tok->str(MathLib::toString<unsigned long>(sizeOfType(tok->tokAt(2))));
|
||||
Token::eraseTokens(tok, tok->tokAt(4));
|
||||
|
@ -4708,9 +4712,9 @@ void Tokenizer::simplifyIfAddBraces()
|
|||
if (!innerIf)
|
||||
break;
|
||||
|
||||
if (Token::Match(tempToken, "; else if"))
|
||||
if (Token::simpleMatch(tempToken, "; else if"))
|
||||
;
|
||||
else if (Token::Match(tempToken, "; else"))
|
||||
else if (Token::simpleMatch(tempToken, "; else"))
|
||||
innerIf = false;
|
||||
else
|
||||
break;
|
||||
|
@ -4751,7 +4755,7 @@ bool Tokenizer::simplifyDoWhileAddBracesHelper(Token *tok)
|
|||
tok2 = tok3;
|
||||
break;
|
||||
}
|
||||
else if (Token::Match(tok3, "do {"))
|
||||
else if (Token::simpleMatch(tok3, "do {"))
|
||||
{
|
||||
// Skip do{}while inside the current "do"
|
||||
tok3 = tok3->next()->link();
|
||||
|
@ -5755,37 +5759,37 @@ void Tokenizer::simplifyStdType()
|
|||
tok->isSigned(!isUnsigned);
|
||||
}
|
||||
|
||||
if (Token::Match(tok, "__int8"))
|
||||
if (Token::simpleMatch(tok, "__int8"))
|
||||
tok->str("char");
|
||||
else if (Token::Match(tok, "__int16"))
|
||||
else if (Token::simpleMatch(tok, "__int16"))
|
||||
tok->str("short");
|
||||
else if (Token::Match(tok, "__int32"))
|
||||
else if (Token::simpleMatch(tok, "__int32"))
|
||||
tok->str("int");
|
||||
else if (Token::Match(tok, "__int64"))
|
||||
else if (Token::simpleMatch(tok, "__int64"))
|
||||
{
|
||||
tok->str("long");
|
||||
tok->isLong(true);
|
||||
}
|
||||
else if (Token::Match(tok, "long"))
|
||||
else if (Token::simpleMatch(tok, "long"))
|
||||
{
|
||||
if (Token::Match(tok->next(), "long"))
|
||||
if (Token::simpleMatch(tok->next(), "long"))
|
||||
{
|
||||
tok->isLong(true);
|
||||
tok->deleteNext();
|
||||
}
|
||||
|
||||
if (Token::Match(tok->next(), "int"))
|
||||
if (Token::simpleMatch(tok->next(), "int"))
|
||||
tok->deleteNext();
|
||||
else if (Token::Match(tok->next(), "double"))
|
||||
else if (Token::simpleMatch(tok->next(), "double"))
|
||||
{
|
||||
tok->str("double");
|
||||
tok->isLong(true);
|
||||
tok->deleteNext();
|
||||
}
|
||||
}
|
||||
else if (Token::Match(tok, "short"))
|
||||
else if (Token::simpleMatch(tok, "short"))
|
||||
{
|
||||
if (Token::Match(tok->next(), "int"))
|
||||
if (Token::simpleMatch(tok->next(), "int"))
|
||||
tok->deleteNext();
|
||||
}
|
||||
}
|
||||
|
@ -7489,7 +7493,7 @@ bool Tokenizer::duplicateDefinition(Token ** tokPtr, const Token * name)
|
|||
|
||||
if (end)
|
||||
{
|
||||
if (Token::Match(end, ") {")) // function parameter ?
|
||||
if (Token::simpleMatch(end, ") {")) // function parameter ?
|
||||
{
|
||||
// look backwards
|
||||
if (tok->previous()->str() == "enum" ||
|
||||
|
@ -7546,7 +7550,8 @@ void Tokenizer::simplifyEnum()
|
|||
int classLevel = 0;
|
||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok, "class|struct|namespace %any%"))
|
||||
if (Token::Match(tok, "class|struct|namespace %any%") &&
|
||||
(!tok->previous() || (tok->previous() && tok->previous()->str() != "enum")))
|
||||
{
|
||||
className = tok->next()->str();
|
||||
classLevel = 0;
|
||||
|
@ -7566,7 +7571,7 @@ void Tokenizer::simplifyEnum()
|
|||
continue;
|
||||
}
|
||||
else if (Token::Match(tok, "enum class|struct| {|:") ||
|
||||
Token::Match(tok, "enum class|struct| %type% {|:"))
|
||||
Token::Match(tok, "enum class|struct| %type% {|:|;"))
|
||||
{
|
||||
Token *tok1;
|
||||
Token *start = tok;
|
||||
|
@ -7587,12 +7592,19 @@ void Tokenizer::simplifyEnum()
|
|||
offset = 3;
|
||||
|
||||
// check for forward declaration
|
||||
/** @todo start substitution check at forward declaration */
|
||||
const Token *temp = tok->tokAt(offset);
|
||||
while (!Token::Match(temp, "{|;"))
|
||||
temp = temp->next();
|
||||
if (temp->str() == ";")
|
||||
{
|
||||
/** @todo start substitution check at forward declaration */
|
||||
// delete forward declaration
|
||||
tok->deleteThis();
|
||||
tok->deleteThis();
|
||||
tok->deleteThis();
|
||||
tok->deleteThis();
|
||||
continue;
|
||||
}
|
||||
|
||||
typeTokenStart = tok->tokAt(offset);
|
||||
typeTokenEnd = typeTokenStart;
|
||||
|
@ -7606,6 +7618,16 @@ void Tokenizer::simplifyEnum()
|
|||
}
|
||||
}
|
||||
|
||||
// check for forward declaration
|
||||
else if (Token::Match(tok->next(), "%type% ;"))
|
||||
{
|
||||
/** @todo start substitution check at forward declaration */
|
||||
// delete forward declaration
|
||||
tok->deleteThis();
|
||||
tok->deleteThis();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tok->tokAt(1)->str() == "{")
|
||||
tok1 = tok->tokAt(2);
|
||||
else if (tok->tokAt(1)->str() == ":")
|
||||
|
@ -7905,7 +7927,7 @@ void Tokenizer::simplifyEnum()
|
|||
}
|
||||
else if (tok2->str() == "{")
|
||||
++level;
|
||||
else if (!pattern.empty() && ((Token::Match(tok2, "enum") && Token::Match(tok2->next(), pattern.c_str())) || Token::Match(tok2, pattern.c_str())))
|
||||
else if (!pattern.empty() && ((Token::simpleMatch(tok2, "enum") && Token::Match(tok2->next(), pattern.c_str())) || Token::Match(tok2, pattern.c_str())))
|
||||
{
|
||||
simplify = true;
|
||||
hasClass = true;
|
||||
|
@ -8240,7 +8262,7 @@ void Tokenizer::simplifyComma()
|
|||
|
||||
// We must not accept just any keyword, e.g. accepting int
|
||||
// would cause function parameters to corrupt.
|
||||
if (Token::Match(tok->next(), "delete"))
|
||||
if (Token::simpleMatch(tok->next(), "delete"))
|
||||
{
|
||||
// Handle "delete a, delete b;"
|
||||
tok->str(";");
|
||||
|
@ -8248,7 +8270,7 @@ void Tokenizer::simplifyComma()
|
|||
|
||||
if (tok->previous() && tok->previous()->previous())
|
||||
{
|
||||
if (Token::Match(tok->previous()->previous(), "delete") &&
|
||||
if (Token::simpleMatch(tok->previous()->previous(), "delete") &&
|
||||
tok->next()->varId() != 0)
|
||||
{
|
||||
// Handle "delete a, b;"
|
||||
|
@ -8563,7 +8585,7 @@ void Tokenizer::simplifyStructInit()
|
|||
if (Token::simpleMatch(tok2, ", ."))
|
||||
tok2 = tok2->next();
|
||||
}
|
||||
if (!Token::Match(tok2, "} ;"))
|
||||
if (!Token::simpleMatch(tok2, "} ;"))
|
||||
continue;
|
||||
|
||||
// Known expression format => Perform simplification
|
||||
|
@ -9251,6 +9273,12 @@ void Tokenizer::simplifyQtSignalsSlots()
|
|||
Token *tok = _tokens;
|
||||
while ((tok = const_cast<Token *>(Token::findmatch(tok, "class %var% :"))))
|
||||
{
|
||||
if (tok->previous() && tok->previous()->str() == "enum")
|
||||
{
|
||||
tok = tok->tokAt(2);
|
||||
continue;
|
||||
}
|
||||
|
||||
// count { and } for tok2
|
||||
unsigned int indentlevel = 0;
|
||||
for (Token *tok2 = tok; tok2; tok2 = tok2->next())
|
||||
|
@ -9325,3 +9353,61 @@ void Tokenizer::simplifyOperatorName()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// remove unnecessary member qualification..
|
||||
struct ClassInfo
|
||||
{
|
||||
std::string className;
|
||||
Token *end;
|
||||
};
|
||||
|
||||
void Tokenizer::removeUnnecessaryQualification()
|
||||
{
|
||||
std::stack<ClassInfo> classInfo;
|
||||
for (Token *tok = _tokens; tok; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok, "class|struct %type% :|{") &&
|
||||
(!tok->previous() || (tok->previous() && tok->previous()->str() != "enum")))
|
||||
{
|
||||
tok = tok->next();
|
||||
ClassInfo info;
|
||||
info.className = tok->str();
|
||||
tok = tok->next();
|
||||
while (tok && tok->str() != "{")
|
||||
tok = tok->next();
|
||||
if (!tok)
|
||||
return;
|
||||
info.end = tok->link();
|
||||
classInfo.push(info);
|
||||
}
|
||||
else if (!classInfo.empty())
|
||||
{
|
||||
if (tok == classInfo.top().end)
|
||||
classInfo.pop();
|
||||
else if (tok->str() == classInfo.top().className &&
|
||||
Token::Match(tok, "%type% :: %type% (") &&
|
||||
Token::Match(tok->tokAt(3)->link(), ") const| {|;"))
|
||||
{
|
||||
std::list<ErrorLogger::ErrorMessage::FileLocation> locationList;
|
||||
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||
loc.line = tok->linenr();
|
||||
loc.setfile(file(tok));
|
||||
locationList.push_back(loc);
|
||||
|
||||
const ErrorLogger::ErrorMessage errmsg(locationList,
|
||||
Severity::portability,
|
||||
"Extra qualification \'" + tok->str() + "::\' unnecessary and considered an error by many compilers.",
|
||||
"portability");
|
||||
|
||||
if (_errorLogger)
|
||||
_errorLogger->reportErr(errmsg);
|
||||
else
|
||||
Check::reportError(errmsg);
|
||||
|
||||
tok->deleteThis();
|
||||
tok->deleteThis();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -519,6 +519,11 @@ public:
|
|||
*/
|
||||
void simplifyBuiltinExpect();
|
||||
|
||||
/**
|
||||
* Remove unnecessary member qualification
|
||||
*/
|
||||
void removeUnnecessaryQualification();
|
||||
|
||||
/**
|
||||
* Remove Microsoft MFC 'DECLARE_MESSAGE_MAP()'
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<rule version="1">
|
||||
<pattern>Severity :: fromString \( "\w+" \)</pattern>
|
||||
<message>
|
||||
<id>ConstantSeverityFromString</id>
|
||||
<severity>style</severity>
|
||||
<summary>Constant severity lookups should be done via
|
||||
Severity::constant.</summary>
|
||||
</message>
|
||||
</rule>
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0"?>
|
||||
<rule version="1">
|
||||
<!-- This should ideally be checked by lib/checkstl.cpp -->
|
||||
<pattern> \. find \( "[^"]+?" \) == \d+ </pattern>
|
||||
<message>
|
||||
<id>UselessSTDStringFind</id>
|
||||
<severity>performance</severity>
|
||||
<summary>When looking for a string at a fixed position compare
|
||||
is faster.</summary>
|
||||
</message>
|
||||
</rule>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0"?>
|
||||
<rule version="1">
|
||||
<pattern>Token :: (?:findm|(?:simple|)M)atch \([^,]+,\s+"(?:\s+|[^"]+?\s+")</pattern>
|
||||
<message>
|
||||
<id>TokenMatchSpacing</id>
|
||||
<severity>style</severity>
|
||||
<summary>Useless extra spacing for Token::*Match.</summary>
|
||||
</message>
|
||||
</rule>
|
||||
<rule version="1">
|
||||
<pattern>(?U)Token :: Match \([^,]+,\s+"[^%|!\[\]]+"</pattern>
|
||||
<message>
|
||||
<id>UseTokensimpleMatch</id>
|
||||
<severity>error</severity>
|
||||
<summary>Token::simpleMatch should be used to match tokens
|
||||
without special pattern requirements.</summary>
|
||||
</message>
|
||||
</rule>
|
||||
<rule version="1">
|
||||
<pattern>\b[\w_]+ \. tokAt \( 0 \)</pattern>
|
||||
<message>
|
||||
<id>TokentokAt0</id>
|
||||
<severity>error</severity>
|
||||
<summary>tok->tokAt(0) is a slow way to say tok.</summary>
|
||||
</message>
|
||||
</rule>
|
||||
<rule version="1">
|
||||
<pattern>\b[\w_]+ \. strAt \( 0 \)</pattern>
|
||||
<message>
|
||||
<id>TokenstrAt0</id>
|
||||
<severity>error</severity>
|
||||
<summary>tok->strAt(0) is a slow way to say tok->str()</summary>
|
||||
</message>
|
||||
</rule>
|
|
@ -21,15 +21,25 @@ SOURCES += ../cli/cmdlineparser.cpp \
|
|||
../cli/filelister.cpp \
|
||||
../cli/filelister_unix.cpp \
|
||||
../cli/filelister_win32.cpp \
|
||||
../cli/threadexecutor.cpp
|
||||
../cli/pathmatch.cpp \
|
||||
../cli/threadexecutor.cpp \
|
||||
testpathmatch.cpp
|
||||
HEADERS += ../cli/cmdlineparser.h \
|
||||
../cli/cppcheckexecutor.h \
|
||||
../cli/filelister.h \
|
||||
../cli/filelister_unix.h \
|
||||
../cli/filelister_win32.h \
|
||||
../cli/pathmatch.h \
|
||||
../cli/threadexecutor.h
|
||||
|
||||
# test/*
|
||||
|
||||
# Note:
|
||||
# testfilelister_unix.cpp omitted since there is test fail when run in QtCreator
|
||||
# Test assumes the test (executable) is built from the test directory (or
|
||||
# directory containing source files). But QtCreator builds to separate build
|
||||
# directory. Hence the test does not find the source files.
|
||||
|
||||
HEADERS += options.h redirect.h testsuite.h
|
||||
SOURCES += options.cpp \
|
||||
testautovariables.cpp \
|
||||
|
@ -50,6 +60,7 @@ SOURCES += options.cpp \
|
|||
testoptions.cpp \
|
||||
testother.cpp \
|
||||
testpath.cpp \
|
||||
testpathmatch.cpp \
|
||||
testpostfixoperator.cpp \
|
||||
testpreprocessor.cpp \
|
||||
testrunner.cpp \
|
||||
|
@ -57,6 +68,7 @@ SOURCES += options.cpp \
|
|||
testsimplifytokens.cpp \
|
||||
teststl.cpp \
|
||||
testsuite.cpp \
|
||||
testsymboldatabase.cpp \
|
||||
testthreadexecutor.cpp \
|
||||
testtoken.cpp \
|
||||
testtokenize.cpp \
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
ProjectType="Visual C++"
|
||||
Version="9,00"
|
||||
Name="test"
|
||||
ProjectGUID="{48110A35-C2BB-3F1C-A741-C15295041A2D}"
|
||||
ProjectGUID="{5B7869EA-A1CB-3E73-8569-5B385608779E}"
|
||||
Keyword="Qt4VSv1.0">
|
||||
<Platforms>
|
||||
<Platform
|
||||
|
@ -72,7 +72,7 @@
|
|||
UseOfMfc="0">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories="".","..\cli","..\lib","..\externals",c:\Qt\VS4.7.0\mkspecs\win32-msvc2008"
|
||||
AdditionalIncludeDirectories="".","..\cli","..\lib","..\externals",..\..\..\..\Qt\qt-everywhere-opensource-src-4.7.1-vs2008-x86\mkspecs\win32-msvc2008"
|
||||
AdditionalOptions="-Zm200 -w34100 -w34189"
|
||||
AssemblerListingLocation="temp\"
|
||||
BufferSecurityCheck="false"
|
||||
|
@ -169,6 +169,8 @@
|
|||
RelativePath="options.cpp" />
|
||||
<File
|
||||
RelativePath="..\lib\path.cpp" />
|
||||
<File
|
||||
RelativePath="..\cli\pathmatch.cpp" />
|
||||
<File
|
||||
RelativePath="..\lib\preprocessor.cpp" />
|
||||
<File
|
||||
|
@ -211,6 +213,8 @@
|
|||
RelativePath="testother.cpp" />
|
||||
<File
|
||||
RelativePath="testpath.cpp" />
|
||||
<File
|
||||
RelativePath="testpathmatch.cpp" />
|
||||
<File
|
||||
RelativePath="testpostfixoperator.cpp" />
|
||||
<File
|
||||
|
@ -225,6 +229,8 @@
|
|||
RelativePath="teststl.cpp" />
|
||||
<File
|
||||
RelativePath="testsuite.cpp" />
|
||||
<File
|
||||
RelativePath="testsymboldatabase.cpp" />
|
||||
<File
|
||||
RelativePath="testthreadexecutor.cpp" />
|
||||
<File
|
||||
|
@ -308,6 +314,8 @@
|
|||
RelativePath="options.h" />
|
||||
<File
|
||||
RelativePath="..\lib\path.h" />
|
||||
<File
|
||||
RelativePath="..\cli\pathmatch.h" />
|
||||
<File
|
||||
RelativePath="..\lib\preprocessor.h" />
|
||||
<File
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{081168BA-E630-3D82-8EDB-A19028999479}</ProjectGuid>
|
||||
<ProjectGuid>{D0001948-3B19-3314-8BEE-3B92350BC5B5}</ProjectGuid>
|
||||
<RootNamespace>test</RootNamespace>
|
||||
<Keyword>Qt4VSv1.0</Keyword>
|
||||
</PropertyGroup>
|
||||
|
@ -140,6 +140,7 @@
|
|||
<ClCompile Include="..\lib\mathlib.cpp" />
|
||||
<ClCompile Include="options.cpp" />
|
||||
<ClCompile Include="..\lib\path.cpp" />
|
||||
<ClCompile Include="..\cli\pathmatch.cpp" />
|
||||
<ClCompile Include="..\lib\preprocessor.cpp" />
|
||||
<ClCompile Include="..\lib\settings.cpp" />
|
||||
<ClCompile Include="..\lib\symboldatabase.cpp" />
|
||||
|
@ -161,6 +162,7 @@
|
|||
<ClCompile Include="testoptions.cpp" />
|
||||
<ClCompile Include="testother.cpp" />
|
||||
<ClCompile Include="testpath.cpp" />
|
||||
<ClCompile Include="testpathmatch.cpp" />
|
||||
<ClCompile Include="testpostfixoperator.cpp" />
|
||||
<ClCompile Include="testpreprocessor.cpp" />
|
||||
<ClCompile Include="testrunner.cpp" />
|
||||
|
@ -168,6 +170,7 @@
|
|||
<ClCompile Include="testsimplifytokens.cpp" />
|
||||
<ClCompile Include="teststl.cpp" />
|
||||
<ClCompile Include="testsuite.cpp" />
|
||||
<ClCompile Include="testsymboldatabase.cpp" />
|
||||
<ClCompile Include="testthreadexecutor.cpp" />
|
||||
<ClCompile Include="testtoken.cpp" />
|
||||
<ClCompile Include="testtokenize.cpp" />
|
||||
|
@ -209,6 +212,7 @@
|
|||
<ClInclude Include="..\lib\mathlib.h" />
|
||||
<ClInclude Include="options.h" />
|
||||
<ClInclude Include="..\lib\path.h" />
|
||||
<ClInclude Include="..\cli\pathmatch.h" />
|
||||
<ClInclude Include="..\lib\preprocessor.h" />
|
||||
<ClInclude Include="redirect.h" />
|
||||
<ClInclude Include="..\lib\settings.h" />
|
||||
|
|
|
@ -80,6 +80,9 @@
|
|||
<ClCompile Include="..\lib\path.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\cli\pathmatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\lib\preprocessor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -143,6 +146,9 @@
|
|||
<ClCompile Include="testpath.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testpathmatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testpostfixoperator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -164,6 +170,9 @@
|
|||
<ClCompile Include="testsuite.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testsymboldatabase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="testthreadexecutor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -283,6 +292,9 @@
|
|||
<ClInclude Include="..\lib\path.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\cli\pathmatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\lib\preprocessor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
@ -188,6 +188,7 @@ private:
|
|||
TEST_CASE(symboldatabase7); // ticket #2230
|
||||
TEST_CASE(symboldatabase8); // ticket #2252
|
||||
TEST_CASE(symboldatabase9); // ticket #2525
|
||||
TEST_CASE(symboldatabase10); // ticket #2537
|
||||
}
|
||||
|
||||
// Check the operator Equal
|
||||
|
@ -5490,6 +5491,20 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void symboldatabase10()
|
||||
{
|
||||
// ticket #2537 - segmentation fault
|
||||
checkConst("class A {\n"
|
||||
"private:\n"
|
||||
" void f();\n"
|
||||
"};\n"
|
||||
"class B {\n"
|
||||
" friend void A::f();\n"
|
||||
"};\n");
|
||||
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestClass)
|
||||
|
|
|
@ -81,12 +81,22 @@ private:
|
|||
TEST_CASE(templatesGcc);
|
||||
TEST_CASE(templatesVs);
|
||||
TEST_CASE(xml);
|
||||
TEST_CASE(xmlver1);
|
||||
TEST_CASE(xmlver2);
|
||||
TEST_CASE(xmlver2both);
|
||||
TEST_CASE(xmlver2both2);
|
||||
TEST_CASE(xmlverunknown);
|
||||
TEST_CASE(xmlverinvalid);
|
||||
TEST_CASE(errorlist1);
|
||||
TEST_CASE(errorlistverbose1)
|
||||
TEST_CASE(errorlistverbose2)
|
||||
TEST_CASE(ignorepathsnopath)
|
||||
TEST_CASE(ignorepaths1)
|
||||
TEST_CASE(ignorepaths2)
|
||||
TEST_CASE(ignorepaths3)
|
||||
TEST_CASE(ignorepaths4)
|
||||
TEST_CASE(ignorefilepaths1)
|
||||
TEST_CASE(ignorefilepaths2)
|
||||
TEST_CASE(unknownParam);
|
||||
}
|
||||
|
||||
|
@ -585,6 +595,17 @@ private:
|
|||
ASSERT_EQUALS(1, settings._xml_version);
|
||||
}
|
||||
|
||||
void xmlver1()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "--xml-version=1", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(parser.ParseFromArgs(3, argv));
|
||||
ASSERT(settings._xml);
|
||||
ASSERT_EQUALS(1, settings._xml_version);
|
||||
}
|
||||
|
||||
void xmlver2()
|
||||
{
|
||||
REDIRECT;
|
||||
|
@ -618,6 +639,24 @@ private:
|
|||
ASSERT_EQUALS(2, settings._xml_version);
|
||||
}
|
||||
|
||||
void xmlverunknown()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "--xml", "--xml-version=3", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(!parser.ParseFromArgs(4, argv));
|
||||
}
|
||||
|
||||
void xmlverinvalid()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "--xml", "--xml-version=a", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(!parser.ParseFromArgs(4, argv));
|
||||
}
|
||||
|
||||
void errorlist1()
|
||||
{
|
||||
REDIRECT;
|
||||
|
@ -647,6 +686,84 @@ private:
|
|||
ASSERT(settings._verbose);
|
||||
}
|
||||
|
||||
void ignorepathsnopath()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "-i"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(!parser.ParseFromArgs(2, argv));
|
||||
ASSERT_EQUALS(0, parser.GetIgnoredPaths().size());
|
||||
}
|
||||
|
||||
void ignorepaths1()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "-isrc", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(parser.ParseFromArgs(3, argv));
|
||||
ASSERT_EQUALS(1, parser.GetIgnoredPaths().size());
|
||||
ASSERT_EQUALS("src/", parser.GetIgnoredPaths()[0]);
|
||||
}
|
||||
|
||||
void ignorepaths2()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "-i", "src", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(parser.ParseFromArgs(4, argv));
|
||||
ASSERT_EQUALS(1, parser.GetIgnoredPaths().size());
|
||||
ASSERT_EQUALS("src/", parser.GetIgnoredPaths()[0]);
|
||||
}
|
||||
|
||||
void ignorepaths3()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "-isrc", "-imodule", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(parser.ParseFromArgs(4, argv));
|
||||
ASSERT_EQUALS(2, parser.GetIgnoredPaths().size());
|
||||
ASSERT_EQUALS("src/", parser.GetIgnoredPaths()[0]);
|
||||
ASSERT_EQUALS("module/", parser.GetIgnoredPaths()[1]);
|
||||
}
|
||||
|
||||
void ignorepaths4()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "-i", "src", "-i", "module", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(parser.ParseFromArgs(6, argv));
|
||||
ASSERT_EQUALS(2, parser.GetIgnoredPaths().size());
|
||||
ASSERT_EQUALS("src/", parser.GetIgnoredPaths()[0]);
|
||||
ASSERT_EQUALS("module/", parser.GetIgnoredPaths()[1]);
|
||||
}
|
||||
|
||||
void ignorefilepaths1()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "-ifoo.cpp", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(parser.ParseFromArgs(3, argv));
|
||||
ASSERT_EQUALS(1, parser.GetIgnoredPaths().size());
|
||||
ASSERT_EQUALS("foo.cpp", parser.GetIgnoredPaths()[0]);
|
||||
}
|
||||
|
||||
void ignorefilepaths2()
|
||||
{
|
||||
REDIRECT;
|
||||
const char *argv[] = {"cppcheck", "-isrc/foo.cpp", "file.cpp"};
|
||||
Settings settings;
|
||||
CmdLineParser parser(&settings);
|
||||
ASSERT(parser.ParseFromArgs(3, argv));
|
||||
ASSERT_EQUALS(1, parser.GetIgnoredPaths().size());
|
||||
ASSERT_EQUALS("src/foo.cpp", parser.GetIgnoredPaths()[0]);
|
||||
}
|
||||
|
||||
void unknownParam()
|
||||
{
|
||||
REDIRECT;
|
||||
|
|
|
@ -66,9 +66,23 @@ private:
|
|||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE(instancesSorted);
|
||||
TEST_CASE(getErrorMessages);
|
||||
}
|
||||
|
||||
void instancesSorted()
|
||||
{
|
||||
for (std::list<Check *>::iterator i = Check::instances().begin(); i != Check::instances().end(); ++i)
|
||||
{
|
||||
std::list<Check *>::iterator j = i;
|
||||
++j;
|
||||
if (j != Check::instances().end())
|
||||
{
|
||||
ASSERT_EQUALS(true, (*i)->name() < (*j)->name());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getErrorMessages()
|
||||
{
|
||||
ErrorLogger2 errorLogger;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include <list>
|
||||
#include "cppcheck.h"
|
||||
#include "testsuite.h"
|
||||
#include "errorlogger.h"
|
||||
|
||||
|
@ -38,6 +39,7 @@ private:
|
|||
TEST_CASE(CustomFormat2);
|
||||
TEST_CASE(ToXml);
|
||||
TEST_CASE(ToVerboseXml);
|
||||
TEST_CASE(ToXmlV2);
|
||||
}
|
||||
|
||||
void FileLocationDefaults()
|
||||
|
@ -124,7 +126,7 @@ private:
|
|||
locs.push_back(loc);
|
||||
ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId");
|
||||
ASSERT_EQUALS("<?xml version=\"1.0\"?>\n<results>", ErrorLogger::ErrorMessage::getXMLHeader(1));
|
||||
ASSERT_EQUALS("</results>", ErrorLogger::ErrorMessage::getXMLFooter());
|
||||
ASSERT_EQUALS("</results>", ErrorLogger::ErrorMessage::getXMLFooter(1));
|
||||
ASSERT_EQUALS("<error file=\"foo.cpp\" line=\"5\" id=\"errorId\" severity=\"error\" msg=\"Programming error.\"/>", msg.toXML(false,1));
|
||||
}
|
||||
|
||||
|
@ -137,8 +139,28 @@ private:
|
|||
locs.push_back(loc);
|
||||
ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId");
|
||||
ASSERT_EQUALS("<?xml version=\"1.0\"?>\n<results>", ErrorLogger::ErrorMessage::getXMLHeader(1));
|
||||
ASSERT_EQUALS("</results>", ErrorLogger::ErrorMessage::getXMLFooter());
|
||||
ASSERT_EQUALS("</results>", ErrorLogger::ErrorMessage::getXMLFooter(1));
|
||||
ASSERT_EQUALS("<error file=\"foo.cpp\" line=\"5\" id=\"errorId\" severity=\"error\" msg=\"Verbose error\"/>", msg.toXML(true,1));
|
||||
}
|
||||
|
||||
void ToXmlV2()
|
||||
{
|
||||
ErrorLogger::ErrorMessage::FileLocation loc;
|
||||
loc.setfile("foo.cpp");
|
||||
loc.line = 5;
|
||||
std::list<ErrorLogger::ErrorMessage::FileLocation> locs;
|
||||
locs.push_back(loc);
|
||||
ErrorMessage msg(locs, Severity::error, "Programming error.\nVerbose error", "errorId");
|
||||
std::string header("<?xml version=\"1.0\"?>\n<results version=\"2\">\n");
|
||||
header += " <cppcheck version=\"";
|
||||
header += CppCheck::version();
|
||||
header += "\"/>\n <errors>";
|
||||
ASSERT_EQUALS(header, ErrorLogger::ErrorMessage::getXMLHeader(2));
|
||||
ASSERT_EQUALS(" </errors>\n</results>", ErrorLogger::ErrorMessage::getXMLFooter(2));
|
||||
std::string message(" <error id=\"errorId\" severity=\"error\"");
|
||||
message += " msg=\"Programming error.\" verbose=\"Verbose error\">\n";
|
||||
message += " <location file=\"foo.cpp\" line=\"5\"/>\n </error>";
|
||||
ASSERT_EQUALS(message, msg.toXML(false,2));
|
||||
}
|
||||
};
|
||||
REGISTER_TEST(TestErrorLogger)
|
||||
|
|
|
@ -961,6 +961,18 @@ private:
|
|||
" int i = sizeof sizeof char;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling sizeof for 'sizeof'.\n", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" int i = sizeof (sizeof long);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling sizeof for 'sizeof'.\n", errout.str());
|
||||
|
||||
check("void foo(long *p)\n"
|
||||
"{\n"
|
||||
" int i = sizeof (sizeof (p));\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (warning) Calling sizeof for 'sizeof'.\n", errout.str());
|
||||
}
|
||||
|
||||
void sizeofCalculation()
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
/*
|
||||
* 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 <string>
|
||||
#include <vector>
|
||||
#include "testsuite.h"
|
||||
#include "pathmatch.h"
|
||||
|
||||
class TestPathMatch : public TestFixture
|
||||
{
|
||||
public:
|
||||
TestPathMatch() : TestFixture("TestPathMatch")
|
||||
{ }
|
||||
|
||||
private:
|
||||
|
||||
void run()
|
||||
{
|
||||
TEST_CASE(emptymaskemptyfile);
|
||||
TEST_CASE(emptymaskpath1);
|
||||
TEST_CASE(emptymaskpath2);
|
||||
TEST_CASE(emptymaskpath3);
|
||||
TEST_CASE(onemaskemptypath);
|
||||
TEST_CASE(onemasksamepath);
|
||||
TEST_CASE(onemasksamepathwithfile);
|
||||
TEST_CASE(onemaskdifferentdir1);
|
||||
TEST_CASE(onemaskdifferentdir2);
|
||||
TEST_CASE(onemaskdifferentdir3);
|
||||
TEST_CASE(onemaskdifferentdir4);
|
||||
TEST_CASE(onemasklongerpath1);
|
||||
TEST_CASE(onemasklongerpath2);
|
||||
TEST_CASE(onemasklongerpath3);
|
||||
TEST_CASE(filemask1);
|
||||
TEST_CASE(filemask2);
|
||||
TEST_CASE(filemask3);
|
||||
TEST_CASE(filemaskpath1);
|
||||
TEST_CASE(filemaskpath2);
|
||||
TEST_CASE(filemaskpath3);
|
||||
TEST_CASE(filemaskpath4);
|
||||
}
|
||||
|
||||
void emptymaskemptyfile()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match(""));
|
||||
}
|
||||
|
||||
void emptymaskpath1()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("src/"));
|
||||
}
|
||||
|
||||
void emptymaskpath2()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("../src/"));
|
||||
}
|
||||
|
||||
void emptymaskpath3()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("/home/user/code/src/"));
|
||||
}
|
||||
|
||||
void onemaskemptypath()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match(""));
|
||||
}
|
||||
|
||||
void onemasksamepath()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("src/"));
|
||||
}
|
||||
|
||||
void onemasksamepathwithfile()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("src/file.txt"));
|
||||
}
|
||||
|
||||
void onemaskdifferentdir1()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("srcfiles/file.txt"));
|
||||
}
|
||||
|
||||
void onemaskdifferentdir2()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("proj/srcfiles/file.txt"));
|
||||
}
|
||||
|
||||
void onemaskdifferentdir3()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("proj/mysrc/file.txt"));
|
||||
}
|
||||
|
||||
void onemaskdifferentdir4()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("proj/mysrcfiles/file.txt"));
|
||||
}
|
||||
|
||||
void onemasklongerpath1()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("/tmp/src/"));
|
||||
}
|
||||
|
||||
void onemasklongerpath2()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("src/module/"));
|
||||
}
|
||||
|
||||
void onemasklongerpath3()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("project/src/module/"));
|
||||
}
|
||||
|
||||
void twomasklongerpath1()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
masks.push_back("module/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("project/"));
|
||||
}
|
||||
|
||||
void twomasklongerpath2()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
masks.push_back("module/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("project/src/"));
|
||||
}
|
||||
|
||||
void twomasklongerpath3()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
masks.push_back("module/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("project/module/"));
|
||||
}
|
||||
|
||||
void twomasklongerpath4()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/");
|
||||
masks.push_back("module/");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("project/src/module/"));
|
||||
}
|
||||
|
||||
void filemask1()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("foo.cpp");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("foo.cpp"));
|
||||
}
|
||||
|
||||
void filemask2()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("foo.cpp");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("../foo.cpp"));
|
||||
}
|
||||
|
||||
void filemask3()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("foo.cpp");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("src/foo.cpp"));
|
||||
}
|
||||
|
||||
void filemaskpath1()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/foo.cpp");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("src/foo.cpp"));
|
||||
}
|
||||
|
||||
void filemaskpath2()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/foo.cpp");
|
||||
PathMatch match(masks);
|
||||
ASSERT(match.Match("proj/src/foo.cpp"));
|
||||
}
|
||||
|
||||
void filemaskpath3()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/foo.cpp");
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("foo.cpp"));
|
||||
}
|
||||
|
||||
void filemaskpath4()
|
||||
{
|
||||
std::vector<std::string> masks;
|
||||
masks.push_back("src/foo.cpp");
|
||||
PathMatch match(masks);
|
||||
ASSERT(!match.Match("bar/foo.cpp"));
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestPathMatch)
|
|
@ -278,6 +278,7 @@ private:
|
|||
TEST_CASE(enum16); // ticket #1988
|
||||
TEST_CASE(enum17); // ticket #2381 (duplicate enums)
|
||||
TEST_CASE(enum18); // #2466 (array with same name as enum constant)
|
||||
TEST_CASE(enum19); // ticket #2536
|
||||
|
||||
// remove "std::" on some standard functions
|
||||
TEST_CASE(removestd);
|
||||
|
@ -315,6 +316,8 @@ private:
|
|||
TEST_CASE(redundant_semicolon);
|
||||
|
||||
TEST_CASE(simplifyFunctionReturn);
|
||||
|
||||
TEST_CASE(removeUnnecessaryQualification);
|
||||
}
|
||||
|
||||
std::string tok(const char code[], bool simplify = true)
|
||||
|
@ -6097,6 +6100,13 @@ private:
|
|||
ASSERT_EQUALS("; void f ( ) { a [ 0 ] ; }", tok(code, false));
|
||||
}
|
||||
|
||||
void enum19() // ticket #2536
|
||||
{
|
||||
const char code[] = "enum class E1;\n"
|
||||
"enum class E2 : int;\n";
|
||||
ASSERT_EQUALS(";", tok(code, false));
|
||||
}
|
||||
|
||||
void removestd()
|
||||
{
|
||||
ASSERT_EQUALS("; strcpy ( a , b ) ;", tok("; std::strcpy(a,b);"));
|
||||
|
@ -6408,6 +6418,14 @@ private:
|
|||
"} ;";
|
||||
ASSERT_EQUALS(expected, tok(code, false));
|
||||
}
|
||||
|
||||
void removeUnnecessaryQualification()
|
||||
{
|
||||
const char code[] = "class Fred { Fred::Fred() {} };";
|
||||
const char expected[] = "class Fred { Fred ( ) { } } ;";
|
||||
ASSERT_EQUALS(expected, tok(code, false));
|
||||
ASSERT_EQUALS("[test.cpp:1]: (portability) Extra qualification 'Fred::' unnecessary and considered an error by many compilers.\n", errout.str());
|
||||
}
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestSimplifyTokens)
|
||||
|
|
|
@ -1412,6 +1412,12 @@ private:
|
|||
" return cmd[0];\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkUninitVar("char fn(FILE *f) {\n"
|
||||
" char buf[10];\n"
|
||||
" fread(buf, 1, 10, f);\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void uninitvar_typeof()
|
||||
|
|
|
@ -230,8 +230,8 @@ int main(int argc, char **argv)
|
|||
fout << "cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)\n";
|
||||
fout << "\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o cppcheck $(CLIOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre $(LDFLAGS)\n\n";
|
||||
fout << "all:\tcppcheck testrunner\n\n";
|
||||
fout << "testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o\n";
|
||||
fout << "\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o $(LDFLAGS)\n\n";
|
||||
fout << "testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o\n";
|
||||
fout << "\t$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) -lpcre cli/threadexecutor.o cli/cmdlineparser.o cli/filelister.o cli/filelister_unix.o cli/pathmatch.o $(LDFLAGS)\n\n";
|
||||
fout << "test:\tall\n";
|
||||
fout << "\t./testrunner\n\n";
|
||||
fout << "check:\tall\n";
|
||||
|
|
Loading…
Reference in New Issue