diff --git a/Makefile b/Makefile index 794e7c5d1..ea8a3a46e 100644 --- a/Makefile +++ b/Makefile @@ -92,12 +92,16 @@ TESTOBJ = test/options.o \ test/testunusedprivfunc.o \ test/testunusedvar.o -EXTOBJ = externals/tinyxml/tinystr.o \ +#ifndef TINYXML + TINYXML = externals/tinyxml/tinystr.o \ externals/tinyxml/tinyxml.o \ externals/tinyxml/tinyxmlerror.o \ externals/tinyxml/tinyxmlparser.o +#endif +EXTOBJ += $(TINYXML) + ###### Targets cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ) diff --git a/gui/test/main.cpp b/gui/test/main.cpp new file mode 100644 index 000000000..fc17d81f0 --- /dev/null +++ b/gui/test/main.cpp @@ -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 . + */ + +#include +#include +#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(); +} diff --git a/gui/test/test.pro b/gui/test/test.pro new file mode 100644 index 000000000..892ded31d --- /dev/null +++ b/gui/test/test.pro @@ -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 diff --git a/gui/test/testtranslationhandler.cpp b/gui/test/testtranslationhandler.cpp new file mode 100644 index 000000000..dc0b17f3d --- /dev/null +++ b/gui/test/testtranslationhandler.cpp @@ -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 . + */ + +#include +#include +#include "testtranslationhandler.h" +#include "translationhandler.h" + +void TestTranslationHandler::construct() +{ + TranslationHandler handler; + QCOMPARE(10, handler.GetNames().size()); + QCOMPARE(QString("en"), handler.GetCurrentLanguage()); +} diff --git a/gui/test/testtranslationhandler.h b/gui/test/testtranslationhandler.h new file mode 100644 index 000000000..6f4235889 --- /dev/null +++ b/gui/test/testtranslationhandler.h @@ -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 . + */ + +#include +#include + +class TestTranslationHandler: public QObject +{ + Q_OBJECT + +private slots: + void construct(); +}; diff --git a/gui/test/testxmlreport.cpp b/gui/test/testxmlreport.cpp new file mode 100644 index 000000000..291b07065 --- /dev/null +++ b/gui/test/testxmlreport.cpp @@ -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 . + */ + +#include +#include +#include "testxmlreport.h" +#include "xmlreport.h" + +void TestXmlReport::testQuoteMessage() +{ + const QString toQuote("abcdefgh&\"'<>12345"); + const QString quoted("abcdefgh&"'<>12345"); + QCOMPARE(quoted, XmlReport::quoteMessage(toQuote)); +} + +void TestXmlReport::testUnquoteMessage() +{ + const QString toQuote("abcdefgh&\"'<>12345"); + const QString quoted("abcdefgh&"'<>12345"); + QCOMPARE(toQuote, XmlReport::unquoteMessage(quoted)); +} + diff --git a/gui/test/testxmlreport.h b/gui/test/testxmlreport.h new file mode 100644 index 000000000..2304c5252 --- /dev/null +++ b/gui/test/testxmlreport.h @@ -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 . + */ + +#include +#include + +class TestXmlReport: public QObject +{ + Q_OBJECT + +private slots: + void testQuoteMessage(); + void testUnquoteMessage(); +}; diff --git a/gui/translationhandler.h b/gui/translationhandler.h index 8640b7ea3..2d396c579 100644 --- a/gui/translationhandler.h +++ b/gui/translationhandler.h @@ -63,7 +63,7 @@ class TranslationHandler : QObject { Q_OBJECT public: - TranslationHandler(QObject *parent); + TranslationHandler(QObject *parent = 0); virtual ~TranslationHandler(); /** diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 891502d6e..1e94d1b33 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -1912,8 +1912,6 @@ void CheckOther::functionVariableUsage() variables.use(tok->next()->varId()); // use = read + write else if (Token::Match(tok, "[;{}] %var% >>")) variables.use(tok->next()->varId()); // use = read + write - else if (Token::Match(tok, "[{,] %var% [,}]")) - variables.read(tok->next()->varId()); // function parameter else if (Token::Match(tok, "[(,] %var% [")) @@ -1932,6 +1930,9 @@ void CheckOther::functionVariableUsage() variables.read(tok->tokAt(2)->varId()); } + else if (Token::Match(tok, "[{,] %var% [,}]")) + variables.read(tok->next()->varId()); + else if (Token::Match(tok, "%var% .")) variables.use(tok->varId()); // use = read + write diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index b74eb6793..37c6281a9 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -209,7 +209,7 @@ unsigned int Tokenizer::sizeOfType(const Token *type) const if (type->str()[0] == '"') return static_cast(Token::getStrLength(type) + 1); - std::map::const_iterator it = _typeSize.find(type->strAt(0)); + std::map::const_iterator it = _typeSize.find(type->str()); if (it == _typeSize.end()) return 0; else if (type->isLong()) @@ -804,7 +804,7 @@ static Token *splitDefinitionFromTypedef(Token *tok) tok1->insertToken("const"); 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->insertToken(name.c_str()); tok->deleteThis(); @@ -1382,13 +1382,14 @@ void Tokenizer::simplifyTypedef() bool inCast = false; bool inTemplate = false; bool inOperator = false; + bool inSizeof = false; // check for derived class: class A : some_typedef { isDerived = Token::Match(tok2->previous(), "public|protected|private %type% {|,"); // check for cast: (some_typedef) A or static_cast(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(), "> ("))) inCast = true; @@ -1397,6 +1398,9 @@ void Tokenizer::simplifyTypedef() Token::Match(tok2->next(), "&|*| &|*| >|,")) inTemplate = true; + else if (Token::Match(tok2->tokAt(-2), "sizeof ( %type% )")) + inSizeof = true; + // check for operator if (Token::simpleMatch(tok2->previous(), "operator") || Token::simpleMatch(tok2->tokAt(-2), "operator const")) @@ -1447,7 +1451,7 @@ void Tokenizer::simplifyTypedef() Token *nextTok; for (nextTok = funcStart; nextTok != funcEnd->next(); nextTok = nextTok->next()) { - tok2->insertToken(nextTok->strAt(0)); + tok2->insertToken(nextTok->str()); tok2 = tok2->next(); // Check for links and fix them up @@ -1518,7 +1522,7 @@ void Tokenizer::simplifyTypedef() tok3 = tok2; for (nextTok = argStart->next(); nextTok != argEnd; nextTok = nextTok->next()) { - tok2->insertToken(nextTok->strAt(0)); + tok2->insertToken(nextTok->str()); tok2 = tok2->next(); // Check for links and fix them up @@ -1655,7 +1659,7 @@ void Tokenizer::simplifyTypedef() std::stack argLinks; for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next()) { - tok2->insertToken(nextArgTok->strAt(0)); + tok2->insertToken(nextArgTok->str()); tok2 = tok2->next(); // Check for links and fix them up @@ -1860,7 +1864,7 @@ void Tokenizer::simplifyTypedef() std::stack argLinks; for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next()) { - tok2->insertToken(nextArgTok->strAt(0)); + tok2->insertToken(nextArgTok->str()); tok2 = tok2->next(); // Check for links and fix them up @@ -1891,12 +1895,13 @@ void Tokenizer::simplifyTypedef() { do { - tok2 = tok2->next(); + if (!inCast && !inSizeof) + tok2 = tok2->next(); Token * nextArrTok; std::stack arrLinks; for (nextArrTok = arrayStart; nextArrTok != arrayEnd->next(); nextArrTok = nextArrTok->next()) { - tok2->insertToken(nextArrTok->strAt(0)); + tok2->insertToken(nextArrTok->str()); tok2 = tok2->next(); // Check for links and fix them up @@ -4059,6 +4064,13 @@ void Tokenizer::simplifySizeof() 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(MathLib::toLongNumber(tok->strAt(4))); + } if (sz > 0) { @@ -5889,7 +5901,7 @@ void Tokenizer::simplifyIfAssign() for (tok2 = tok2->next(); tok2 && tok2 != tok; tok2 = tok2->previous()) { - tok3->insertToken(tok2->strAt(0)); + tok3->insertToken(tok2->str()); Token *newTok = tok3->next(); newTok->fileIndex(tok2->fileIndex()); @@ -7837,11 +7849,11 @@ void Tokenizer::simplifyEnum() if (simplify) { if (enumValue) - tok2->str(enumValue->strAt(0)); + tok2->str(enumValue->str()); else { std::stack links; - tok2->str(enumValueStart->strAt(0)); + tok2->str(enumValueStart->str()); if (tok2->str() == "(" || tok2->str() == "[" || tok2->str() == "{") links.push(tok2); Token * nextToken = enumValueStart->next(); diff --git a/readme.txt b/readme.txt index bb5e677c3..170559978 100644 --- a/readme.txt +++ b/readme.txt @@ -45,8 +45,7 @@ Compiling g++ (for experts) ================= 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 ===== make LDFLAGS=-lshlwapi diff --git a/runastyle b/runastyle index 00f2807cb..4da7b7866 100755 --- a/runastyle +++ b/runastyle @@ -1,12 +1,14 @@ #!/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" astyle $style $options cli/*.cpp astyle $style $options cli/*.h astyle $style $options gui/*.cpp 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/*.h astyle $style $options test/*.cpp diff --git a/runastyle.bat b/runastyle.bat index 3f3c46527..bf7b73202 100644 --- a/runastyle.bat +++ b/runastyle.bat @@ -1,12 +1,14 @@ 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 astyle %STYLE% %OPTIONS% cli/*.cpp astyle %STYLE% %OPTIONS% cli/*.h astyle %STYLE% %OPTIONS% gui/*.cpp 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/*.h astyle %STYLE% %OPTIONS% test/*.cpp diff --git a/test/testsimplifytokens.cpp b/test/testsimplifytokens.cpp index 0de4ff250..fe8d2b8a9 100644 --- a/test/testsimplifytokens.cpp +++ b/test/testsimplifytokens.cpp @@ -234,6 +234,7 @@ private: TEST_CASE(simplifyTypedef74); // ticket #2414 TEST_CASE(simplifyTypedef75); // ticket #2426 TEST_CASE(simplifyTypedef76); // ticket #2453 + TEST_CASE(simplifyTypedef77); // ticket #2554 TEST_CASE(simplifyTypedefFunction1); TEST_CASE(simplifyTypedefFunction2); // ticket #1685 @@ -4838,6 +4839,13 @@ private: 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() { { diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index a417ccf5f..c782364f2 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -82,6 +82,7 @@ private: TEST_CASE(localvar32); // ticket #2330 TEST_CASE(localvar33); // ticket #2346 TEST_CASE(localvar34); // ticket #2368 + TEST_CASE(localvar35); // ticket #2535 TEST_CASE(localvaralias1); TEST_CASE(localvaralias2); // ticket #1637 TEST_CASE(localvaralias3); // ticket #1639 @@ -1372,6 +1373,15 @@ private: 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() { functionVariableUsage("void foo()\n" diff --git a/tools/dmake.cpp b/tools/dmake.cpp index 7e688f33c..572e389eb 100644 --- a/tools/dmake.cpp +++ b/tools/dmake.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #if defined(_WIN32) #include "../cli/fileLister_win32.h" @@ -107,6 +108,52 @@ static void makeConditionalVariable(std::ostream &os, const std::string &variabl << "\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 &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) { @@ -220,11 +267,8 @@ int main(int argc, char **argv) for (unsigned int i = 1; i < testfiles.size(); ++i) fout << " \\" << std::endl << std::string(14, ' ') << objfile(testfiles[i]); 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 << "cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ)\n";