This commit is contained in:
Sébastien Debrard 2011-02-09 20:46:08 +01:00
commit a8ca439b7a
16 changed files with 286 additions and 24 deletions

View File

@ -92,12 +92,16 @@ TESTOBJ = test/options.o \
test/testunusedprivfunc.o \ test/testunusedprivfunc.o \
test/testunusedvar.o test/testunusedvar.o
EXTOBJ = externals/tinyxml/tinystr.o \ #ifndef TINYXML
TINYXML = externals/tinyxml/tinystr.o \
externals/tinyxml/tinyxml.o \ externals/tinyxml/tinyxml.o \
externals/tinyxml/tinyxmlerror.o \ externals/tinyxml/tinyxmlerror.o \
externals/tinyxml/tinyxmlparser.o externals/tinyxml/tinyxmlparser.o
#endif
EXTOBJ += $(TINYXML)
###### Targets ###### Targets
cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ) cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)

35
gui/test/main.cpp Normal file
View File

@ -0,0 +1,35 @@
/*
* 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 <QCoreApplication>
#include <QtTest>
#include "testtranslationhandler.h"
#include "testxmlreport.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
TestTranslationHandler testTtranslationHandler;
QTest::qExec(&testTtranslationHandler);
TestXmlReport testXmlReport;
QTest::qExec(&testXmlReport);
return a.exec();
}

22
gui/test/test.pro Normal file
View File

@ -0,0 +1,22 @@
TEMPLATE = app
TARGET = test
CONFIG += qtestlib
DEPENDPATH += . ..
INCLUDEPATH += . ..
# tests
SOURCES += main.cpp \
testtranslationhandler.cpp \
testxmlreport.cpp
HEADERS += testtranslationhandler.h \
testxmlreport.h
# GUI
SOURCES += report.cpp \
../translationhandler.cpp \
../xmlreport.cpp
HEADERS += report.h \
../translationhandler.h \
../xmlreport.h

View File

@ -0,0 +1,29 @@
/*
* 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 <QtTest>
#include <QObject>
#include "testtranslationhandler.h"
#include "translationhandler.h"
void TestTranslationHandler::construct()
{
TranslationHandler handler;
QCOMPARE(10, handler.GetNames().size());
QCOMPARE(QString("en"), handler.GetCurrentLanguage());
}

View File

@ -0,0 +1,28 @@
/*
* 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 <QtTest>
#include <QObject>
class TestTranslationHandler: public QObject
{
Q_OBJECT
private slots:
void construct();
};

View File

@ -0,0 +1,37 @@
/*
* 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 <QtTest>
#include <QObject>
#include "testxmlreport.h"
#include "xmlreport.h"
void TestXmlReport::testQuoteMessage()
{
const QString toQuote("abcdefgh&\"'<>12345");
const QString quoted("abcdefgh&amp;&quot;&#039;&lt;&gt;12345");
QCOMPARE(quoted, XmlReport::quoteMessage(toQuote));
}
void TestXmlReport::testUnquoteMessage()
{
const QString toQuote("abcdefgh&\"'<>12345");
const QString quoted("abcdefgh&amp;&quot;&#039;&lt;&gt;12345");
QCOMPARE(toQuote, XmlReport::unquoteMessage(quoted));
}

29
gui/test/testxmlreport.h Normal file
View File

@ -0,0 +1,29 @@
/*
* 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 <QtTest>
#include <QObject>
class TestXmlReport: public QObject
{
Q_OBJECT
private slots:
void testQuoteMessage();
void testUnquoteMessage();
};

View File

@ -63,7 +63,7 @@ class TranslationHandler : QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
TranslationHandler(QObject *parent); TranslationHandler(QObject *parent = 0);
virtual ~TranslationHandler(); virtual ~TranslationHandler();
/** /**

View File

@ -1912,8 +1912,6 @@ void CheckOther::functionVariableUsage()
variables.use(tok->next()->varId()); // use = read + write variables.use(tok->next()->varId()); // use = read + write
else if (Token::Match(tok, "[;{}] %var% >>")) else if (Token::Match(tok, "[;{}] %var% >>"))
variables.use(tok->next()->varId()); // use = read + write variables.use(tok->next()->varId()); // use = read + write
else if (Token::Match(tok, "[{,] %var% [,}]"))
variables.read(tok->next()->varId());
// function parameter // function parameter
else if (Token::Match(tok, "[(,] %var% [")) else if (Token::Match(tok, "[(,] %var% ["))
@ -1932,6 +1930,9 @@ void CheckOther::functionVariableUsage()
variables.read(tok->tokAt(2)->varId()); variables.read(tok->tokAt(2)->varId());
} }
else if (Token::Match(tok, "[{,] %var% [,}]"))
variables.read(tok->next()->varId());
else if (Token::Match(tok, "%var% .")) else if (Token::Match(tok, "%var% ."))
variables.use(tok->varId()); // use = read + write variables.use(tok->varId()); // use = read + write

View File

@ -209,7 +209,7 @@ unsigned int Tokenizer::sizeOfType(const Token *type) const
if (type->str()[0] == '"') if (type->str()[0] == '"')
return static_cast<unsigned int>(Token::getStrLength(type) + 1); return static_cast<unsigned int>(Token::getStrLength(type) + 1);
std::map<std::string, unsigned int>::const_iterator it = _typeSize.find(type->strAt(0)); std::map<std::string, unsigned int>::const_iterator it = _typeSize.find(type->str());
if (it == _typeSize.end()) if (it == _typeSize.end())
return 0; return 0;
else if (type->isLong()) else if (type->isLong())
@ -804,7 +804,7 @@ static Token *splitDefinitionFromTypedef(Token *tok)
tok1->insertToken("const"); tok1->insertToken("const");
tok1 = tok1->next(); tok1 = tok1->next();
} }
tok1->insertToken(tok->next()->strAt(0)); // struct, union or enum tok1->insertToken(tok->next()->str()); // struct, union or enum
tok1 = tok1->next(); tok1 = tok1->next();
tok1->insertToken(name.c_str()); tok1->insertToken(name.c_str());
tok->deleteThis(); tok->deleteThis();
@ -1382,13 +1382,14 @@ void Tokenizer::simplifyTypedef()
bool inCast = false; bool inCast = false;
bool inTemplate = false; bool inTemplate = false;
bool inOperator = false; bool inOperator = false;
bool inSizeof = false;
// check for derived class: class A : some_typedef { // check for derived class: class A : some_typedef {
isDerived = Token::Match(tok2->previous(), "public|protected|private %type% {|,"); isDerived = Token::Match(tok2->previous(), "public|protected|private %type% {|,");
// check for cast: (some_typedef) A or static_cast<some_typedef>(A) // check for cast: (some_typedef) A or static_cast<some_typedef>(A)
// todo: check for more complicated casts like: (const some_typedef *)A // todo: check for more complicated casts like: (const some_typedef *)A
if ((tok2->previous()->str() == "(" && tok2->next()->str() == ")") || if ((tok2->previous()->str() == "(" && tok2->next()->str() == ")" && tok2->strAt(-2) != "sizeof") ||
(tok2->previous()->str() == "<" && Token::simpleMatch(tok2->next(), "> ("))) (tok2->previous()->str() == "<" && Token::simpleMatch(tok2->next(), "> (")))
inCast = true; inCast = true;
@ -1397,6 +1398,9 @@ void Tokenizer::simplifyTypedef()
Token::Match(tok2->next(), "&|*| &|*| >|,")) Token::Match(tok2->next(), "&|*| &|*| >|,"))
inTemplate = true; inTemplate = true;
else if (Token::Match(tok2->tokAt(-2), "sizeof ( %type% )"))
inSizeof = true;
// check for operator // check for operator
if (Token::simpleMatch(tok2->previous(), "operator") || if (Token::simpleMatch(tok2->previous(), "operator") ||
Token::simpleMatch(tok2->tokAt(-2), "operator const")) Token::simpleMatch(tok2->tokAt(-2), "operator const"))
@ -1447,7 +1451,7 @@ void Tokenizer::simplifyTypedef()
Token *nextTok; Token *nextTok;
for (nextTok = funcStart; nextTok != funcEnd->next(); nextTok = nextTok->next()) for (nextTok = funcStart; nextTok != funcEnd->next(); nextTok = nextTok->next())
{ {
tok2->insertToken(nextTok->strAt(0)); tok2->insertToken(nextTok->str());
tok2 = tok2->next(); tok2 = tok2->next();
// Check for links and fix them up // Check for links and fix them up
@ -1518,7 +1522,7 @@ void Tokenizer::simplifyTypedef()
tok3 = tok2; tok3 = tok2;
for (nextTok = argStart->next(); nextTok != argEnd; nextTok = nextTok->next()) for (nextTok = argStart->next(); nextTok != argEnd; nextTok = nextTok->next())
{ {
tok2->insertToken(nextTok->strAt(0)); tok2->insertToken(nextTok->str());
tok2 = tok2->next(); tok2 = tok2->next();
// Check for links and fix them up // Check for links and fix them up
@ -1655,7 +1659,7 @@ void Tokenizer::simplifyTypedef()
std::stack<Token *> argLinks; std::stack<Token *> argLinks;
for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next()) for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next())
{ {
tok2->insertToken(nextArgTok->strAt(0)); tok2->insertToken(nextArgTok->str());
tok2 = tok2->next(); tok2 = tok2->next();
// Check for links and fix them up // Check for links and fix them up
@ -1860,7 +1864,7 @@ void Tokenizer::simplifyTypedef()
std::stack<Token *> argLinks; std::stack<Token *> argLinks;
for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next()) for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next())
{ {
tok2->insertToken(nextArgTok->strAt(0)); tok2->insertToken(nextArgTok->str());
tok2 = tok2->next(); tok2 = tok2->next();
// Check for links and fix them up // Check for links and fix them up
@ -1891,12 +1895,13 @@ void Tokenizer::simplifyTypedef()
{ {
do do
{ {
tok2 = tok2->next(); if (!inCast && !inSizeof)
tok2 = tok2->next();
Token * nextArrTok; Token * nextArrTok;
std::stack<Token *> arrLinks; std::stack<Token *> arrLinks;
for (nextArrTok = arrayStart; nextArrTok != arrayEnd->next(); nextArrTok = nextArrTok->next()) for (nextArrTok = arrayStart; nextArrTok != arrayEnd->next(); nextArrTok = nextArrTok->next())
{ {
tok2->insertToken(nextArrTok->strAt(0)); tok2->insertToken(nextArrTok->str());
tok2 = tok2->next(); tok2 = tok2->next();
// Check for links and fix them up // Check for links and fix them up
@ -4059,6 +4064,13 @@ void Tokenizer::simplifySizeof()
sz = sizeOfType(decltok->tokAt(-2)); sz = sizeOfType(decltok->tokAt(-2));
} }
} }
else if (tok->strAt(3) == "[" && tok->tokAt(2)->isStandardType())
{
sz = sizeOfType(tok->tokAt(2));
if (sz == 0)
continue;
sz = sz * static_cast<unsigned long>(MathLib::toLongNumber(tok->strAt(4)));
}
if (sz > 0) if (sz > 0)
{ {
@ -5889,7 +5901,7 @@ void Tokenizer::simplifyIfAssign()
for (tok2 = tok2->next(); tok2 && tok2 != tok; tok2 = tok2->previous()) for (tok2 = tok2->next(); tok2 && tok2 != tok; tok2 = tok2->previous())
{ {
tok3->insertToken(tok2->strAt(0)); tok3->insertToken(tok2->str());
Token *newTok = tok3->next(); Token *newTok = tok3->next();
newTok->fileIndex(tok2->fileIndex()); newTok->fileIndex(tok2->fileIndex());
@ -7837,11 +7849,11 @@ void Tokenizer::simplifyEnum()
if (simplify) if (simplify)
{ {
if (enumValue) if (enumValue)
tok2->str(enumValue->strAt(0)); tok2->str(enumValue->str());
else else
{ {
std::stack<Token *> links; std::stack<Token *> links;
tok2->str(enumValueStart->strAt(0)); tok2->str(enumValueStart->str());
if (tok2->str() == "(" || tok2->str() == "[" || tok2->str() == "{") if (tok2->str() == "(" || tok2->str() == "[" || tok2->str() == "{")
links.push(tok2); links.push(tok2);
Token * nextToken = enumValueStart->next(); Token * nextToken = enumValueStart->next();

View File

@ -45,8 +45,7 @@ Compiling
g++ (for experts) g++ (for experts)
================= =================
If you just want to build Cppcheck then you can use this command: If you just want to build Cppcheck then you can use this command:
g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp g++ -o cppcheck -lpcre -Ilib -Iexternals cli/*.cpp lib/*.cpp externals/tinyxml/*.cpp
mingw mingw
===== =====
make LDFLAGS=-lshlwapi make LDFLAGS=-lshlwapi

View File

@ -1,12 +1,14 @@
#!/bin/bash #!/bin/bash
style="--style=ansi --min-conditional-indent=0" style="--style=ansi --lineend=linux --min-conditional-indent=0"
options="--pad-header --unpad-paren --suffix=none" options="--pad-header --unpad-paren --suffix=none"
astyle $style $options cli/*.cpp astyle $style $options cli/*.cpp
astyle $style $options cli/*.h astyle $style $options cli/*.h
astyle $style $options gui/*.cpp astyle $style $options gui/*.cpp
astyle $style $options gui/*.h astyle $style $options gui/*.h
astyle $style $options gui/test/*.cpp
astyle $style $options gui/test/*.h
astyle $style $options lib/*.cpp astyle $style $options lib/*.cpp
astyle $style $options lib/*.h astyle $style $options lib/*.h
astyle $style $options test/*.cpp astyle $style $options test/*.cpp

View File

@ -1,12 +1,14 @@
REM A script to run Astyle for the sources REM A script to run Astyle for the sources
SET STYLE=--style=ansi --min-conditional-indent=0 SET STYLE=--style=ansi --lineend=linux --min-conditional-indent=0
SET OPTIONS=--pad-header --unpad-paren --suffix=none SET OPTIONS=--pad-header --unpad-paren --suffix=none
astyle %STYLE% %OPTIONS% cli/*.cpp astyle %STYLE% %OPTIONS% cli/*.cpp
astyle %STYLE% %OPTIONS% cli/*.h astyle %STYLE% %OPTIONS% cli/*.h
astyle %STYLE% %OPTIONS% gui/*.cpp astyle %STYLE% %OPTIONS% gui/*.cpp
astyle %STYLE% %OPTIONS% gui/*.h astyle %STYLE% %OPTIONS% gui/*.h
astyle %STYLE% %OPTIONS% gui/test/*.cpp
astyle %STYLE% %OPTIONS% gui/test/*.h
astyle %STYLE% %OPTIONS% lib/*.cpp astyle %STYLE% %OPTIONS% lib/*.cpp
astyle %STYLE% %OPTIONS% lib/*.h astyle %STYLE% %OPTIONS% lib/*.h
astyle %STYLE% %OPTIONS% test/*.cpp astyle %STYLE% %OPTIONS% test/*.cpp

View File

@ -234,6 +234,7 @@ private:
TEST_CASE(simplifyTypedef74); // ticket #2414 TEST_CASE(simplifyTypedef74); // ticket #2414
TEST_CASE(simplifyTypedef75); // ticket #2426 TEST_CASE(simplifyTypedef75); // ticket #2426
TEST_CASE(simplifyTypedef76); // ticket #2453 TEST_CASE(simplifyTypedef76); // ticket #2453
TEST_CASE(simplifyTypedef77); // ticket #2554
TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction1);
TEST_CASE(simplifyTypedefFunction2); // ticket #1685 TEST_CASE(simplifyTypedefFunction2); // ticket #1685
@ -4838,6 +4839,13 @@ private:
ASSERT_EQUALS("[test.cpp:1]: (error) syntax error\n", errout.str()); ASSERT_EQUALS("[test.cpp:1]: (error) syntax error\n", errout.str());
} }
void simplifyTypedef77() // ticket #2554
{
const char code[] = "typedef char Str[10]; int x = sizeof(Str);\n";
const std::string expected = "; int x ; x = 10 ;";
ASSERT_EQUALS(expected, sizeof_(code));
}
void simplifyTypedefFunction1() void simplifyTypedefFunction1()
{ {
{ {

View File

@ -82,6 +82,7 @@ private:
TEST_CASE(localvar32); // ticket #2330 TEST_CASE(localvar32); // ticket #2330
TEST_CASE(localvar33); // ticket #2346 TEST_CASE(localvar33); // ticket #2346
TEST_CASE(localvar34); // ticket #2368 TEST_CASE(localvar34); // ticket #2368
TEST_CASE(localvar35); // ticket #2535
TEST_CASE(localvaralias1); TEST_CASE(localvaralias1);
TEST_CASE(localvaralias2); // ticket #1637 TEST_CASE(localvaralias2); // ticket #1637
TEST_CASE(localvaralias3); // ticket #1639 TEST_CASE(localvaralias3); // ticket #1639
@ -1372,6 +1373,15 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void localvar35() // ticket #2535
{
functionVariableUsage("void f() {\n"
" int a, b;\n"
" x(1,a,b);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void localvaralias1() void localvaralias1()
{ {
functionVariableUsage("void foo()\n" functionVariableUsage("void foo()\n"

View File

@ -23,6 +23,7 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector> #include <vector>
#include <sstream>
#if defined(_WIN32) #if defined(_WIN32)
#include "../cli/fileLister_win32.h" #include "../cli/fileLister_win32.h"
@ -107,6 +108,52 @@ static void makeConditionalVariable(std::ostream &os, const std::string &variabl
<< "\n"; << "\n";
} }
static std::string getLibName(const std::string &path)
{
// path can be e.g. "externals/foo/foo.cpp" then returned
// library name is "FOO".
std::string libName = path.substr(path.find('/')+1);
libName = libName.substr(0, libName.find('/'));
std::transform(libName.begin(), libName.end(),libName.begin(), ::toupper);
return libName;
}
static void makeExtObj(std::ostream &fout, const std::vector<std::string> &externalfiles)
{
bool start = true;
std::ostringstream libNames;
std::string libName;
for (unsigned int i = 0; i < externalfiles.size(); ++i)
{
if (start)
{
libName = getLibName(externalfiles[i]);
fout << "#ifndef " << libName << std::endl;
fout << " " << libName << " = " << objfile(externalfiles[i]);
libNames << "EXTOBJ += $(" << libName << ")" << std::endl;
start = false;
}
else
{
fout << std::string(14, ' ') << objfile(externalfiles[i]);
}
if (i+1 >= externalfiles.size() || libName != getLibName(externalfiles[i+1]))
{
// This was the last file for this library
fout << std::endl << "#endif" << std::endl;
fout << "\n\n";
start = true;
}
else
{
// There are more files for this library
fout << " \\" << std::endl;
}
}
fout << libNames.str();
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
@ -220,11 +267,8 @@ int main(int argc, char **argv)
for (unsigned int i = 1; i < testfiles.size(); ++i) for (unsigned int i = 1; i < testfiles.size(); ++i)
fout << " \\" << std::endl << std::string(14, ' ') << objfile(testfiles[i]); fout << " \\" << std::endl << std::string(14, ' ') << objfile(testfiles[i]);
fout << "\n\n"; fout << "\n\n";
fout << "EXTOBJ = " << objfile(externalfiles[0]);
for (unsigned int i = 1; i < externalfiles.size(); ++i)
fout << " \\" << std::endl << std::string(14, ' ') << objfile(externalfiles[i]);
fout << "\n\n";
makeExtObj(fout, externalfiles);
fout << "\n###### Targets\n\n"; fout << "\n###### Targets\n\n";
fout << "cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)\n"; fout << "cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)\n";