diff --git a/gui/test/main.cpp b/gui/test/main.cpp index fc17d81f0..9ba262892 100644 --- a/gui/test/main.cpp +++ b/gui/test/main.cpp @@ -20,6 +20,8 @@ #include #include "testtranslationhandler.h" #include "testxmlreport.h" +#include "testxmlreportv1.h" +#include "testxmlreportv2.h" int main(int argc, char *argv[]) { @@ -31,5 +33,11 @@ int main(int argc, char *argv[]) TestXmlReport testXmlReport; QTest::qExec(&testXmlReport); + TestXmlReportV1 testXmlReportV1; + QTest::qExec(&testXmlReportV1); + + TestXmlReportV2 testXmlReportV2; + QTest::qExec(&testXmlReportV2); + return a.exec(); } diff --git a/gui/test/test.pro b/gui/test/test.pro index 892ded31d..917d4364f 100644 --- a/gui/test/test.pro +++ b/gui/test/test.pro @@ -2,21 +2,37 @@ TEMPLATE = app TARGET = test CONFIG += qtestlib DEPENDPATH += . .. -INCLUDEPATH += . .. +INCLUDEPATH += . .. ../../lib + +LIBS += -L../../externals -lpcre +INCLUDEPATH += ../../externals + +BASEPATH = ../../lib/ +include($$PWD/../../lib/lib.pri) # tests SOURCES += main.cpp \ testtranslationhandler.cpp \ - testxmlreport.cpp + testxmlreport.cpp \ + testxmlreportv1.cpp \ + testxmlreportv2.cpp HEADERS += testtranslationhandler.h \ - testxmlreport.h + testxmlreport.h \ + testxmlreportv1.h \ + testxmlreportv2.h # GUI -SOURCES += report.cpp \ +SOURCES += ../erroritem.cpp \ + ../report.cpp \ ../translationhandler.cpp \ - ../xmlreport.cpp + ../xmlreport.cpp \ + ../xmlreportv1.cpp \ + ../xmlreportv2.cpp -HEADERS += report.h \ +HEADERS += ../erroritem.h \ + ../report.h \ ../translationhandler.h \ - ../xmlreport.h + ../xmlreport.h \ + ../xmlreportv1.h \ + ../xmlreportv2.h diff --git a/gui/test/testxmlreport.cpp b/gui/test/testxmlreport.cpp index 291b07065..03eb937e5 100644 --- a/gui/test/testxmlreport.cpp +++ b/gui/test/testxmlreport.cpp @@ -25,13 +25,24 @@ void TestXmlReport::testQuoteMessage() { const QString toQuote("abcdefgh&\"'<>12345"); const QString quoted("abcdefgh&"'<>12345"); - QCOMPARE(quoted, XmlReport::quoteMessage(toQuote)); + QCOMPARE(XmlReport::quoteMessage(toQuote), quoted); } void TestXmlReport::testUnquoteMessage() { const QString toQuote("abcdefgh&\"'<>12345"); const QString quoted("abcdefgh&"'<>12345"); - QCOMPARE(toQuote, XmlReport::unquoteMessage(quoted)); + QCOMPARE(XmlReport::unquoteMessage(quoted), toQuote); } +void TestXmlReport::testGetVersion1() +{ + const QString filepath("xmlfiles/xmlreport_v1.xml"); + QCOMPARE(XmlReport::determineVersion(filepath), 1); +} + +void TestXmlReport::testGetVersion2() +{ + const QString filepath("xmlfiles/xmlreport_v2.xml"); + QCOMPARE(XmlReport::determineVersion(filepath), 2); +} diff --git a/gui/test/testxmlreport.h b/gui/test/testxmlreport.h index 2304c5252..8036aaa31 100644 --- a/gui/test/testxmlreport.h +++ b/gui/test/testxmlreport.h @@ -26,4 +26,6 @@ class TestXmlReport: public QObject private slots: void testQuoteMessage(); void testUnquoteMessage(); + void testGetVersion1(); + void testGetVersion2(); }; diff --git a/gui/test/testxmlreportv1.cpp b/gui/test/testxmlreportv1.cpp new file mode 100644 index 000000000..1c0ad3187 --- /dev/null +++ b/gui/test/testxmlreportv1.cpp @@ -0,0 +1,40 @@ +/* + * 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 "testxmlreportv1.h" +#include "xmlreportv1.h" +#include "erroritem.h" + +void TestXmlReportV1::readXml() +{ + const QString filepath("xmlfiles/xmlreport_v1.xml"); + XmlReportV1 report(filepath); + QVERIFY(report.Open()); + QList errors = report.Read(); + QCOMPARE(6, errors.size()); + + ErrorItem item = errors[0]; + QCOMPARE(item.file, QString("test.cxx")); + QCOMPARE(item.lines[0], (unsigned int)11); + QCOMPARE(item.id, QString("unreadVariable")); + QCOMPARE(item.severity, QString("Style")); + QCOMPARE(item.summary, QString("Variable 'a' is assigned a value that is never used")); + QCOMPARE(item.message, QString("Variable 'a' is assigned a value that is never used")); +} diff --git a/gui/test/testxmlreportv1.h b/gui/test/testxmlreportv1.h new file mode 100644 index 000000000..ada1bc640 --- /dev/null +++ b/gui/test/testxmlreportv1.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 TestXmlReportV1: public QObject +{ + Q_OBJECT + +private slots: + void readXml(); +}; diff --git a/gui/test/testxmlreportv2.cpp b/gui/test/testxmlreportv2.cpp new file mode 100644 index 000000000..164061852 --- /dev/null +++ b/gui/test/testxmlreportv2.cpp @@ -0,0 +1,56 @@ +/* + * 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 "testxmlreportv2.h" +#include "xmlreportv2.h" +#include "erroritem.h" + +void TestXmlReportV2::readXml() +{ + const QString filepath("xmlfiles/xmlreport_v2.xml"); + XmlReportV2 report(filepath); + QVERIFY(report.Open()); + QList errors = report.Read(); + QCOMPARE(6, errors.size()); + + ErrorItem item = errors[0]; + QCOMPARE(item.file, QString("test.cxx")); + QCOMPARE(item.files.size(), 1); + QCOMPARE(item.lines.size(), 1); + QCOMPARE(item.files[0], QString("test.cxx")); + QCOMPARE(item.lines[0], (unsigned int)11); + QCOMPARE(item.id, QString("unreadVariable")); + QCOMPARE(item.severity, QString("style")); + QCOMPARE(item.summary, QString("Variable 'a' is assigned a value that is never used")); + QCOMPARE(item.message, QString("Variable 'a' is assigned a value that is never used")); + + ErrorItem item2 = errors[3]; + QCOMPARE(item2.file, QString("test.cxx")); + QCOMPARE(item2.files.size(), 2); + QCOMPARE(item2.lines.size(), 2); + QCOMPARE(item2.files[0], QString("test.cxx")); + QCOMPARE(item2.lines[0], (unsigned int)32); + QCOMPARE(item2.files[1], QString("test.cxx")); + QCOMPARE(item2.lines[1], (unsigned int)16); + QCOMPARE(item2.id, QString("mismatchAllocDealloc")); + QCOMPARE(item2.severity, QString("error")); + QCOMPARE(item2.summary, QString("Mismatching allocation and deallocation: k")); + QCOMPARE(item2.message, QString("Mismatching allocation and deallocation: k")); +} diff --git a/gui/test/testxmlreportv2.h b/gui/test/testxmlreportv2.h new file mode 100644 index 000000000..d3c43f750 --- /dev/null +++ b/gui/test/testxmlreportv2.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 TestXmlReportV2: public QObject +{ + Q_OBJECT + +private slots: + void readXml(); +}; diff --git a/gui/test/xmlfiles/xmlreport_v1.xml b/gui/test/xmlfiles/xmlreport_v1.xml new file mode 100644 index 000000000..21426899e --- /dev/null +++ b/gui/test/xmlfiles/xmlreport_v1.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/gui/test/xmlfiles/xmlreport_v2.xml b/gui/test/xmlfiles/xmlreport_v2.xml new file mode 100644 index 000000000..81ed96496 --- /dev/null +++ b/gui/test/xmlfiles/xmlreport_v2.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gui/xmlreportv2.h b/gui/xmlreportv2.h index 6b1a2841c..47b5a5775 100644 --- a/gui/xmlreportv2.h +++ b/gui/xmlreportv2.h @@ -26,6 +26,7 @@ #include #include #include "report.h" +#include "xmlreport.h" /// @addtogroup GUI /// @{ diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 3ee0d272d..864b4a71c 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -583,7 +583,7 @@ bool SymbolDatabase::isFunction(const Token *tok, const Token **funcStart, const // regular function? else if (Token::Match(tok, "%var% (") && (Token::Match(tok->next()->link(), ") const| ;|{|=") || - Token::Match(tok->next()->link(), ") : %var% ("))) + Token::Match(tok->next()->link(), ") : %var% (|::"))) { *funcStart = tok; *argStart = tok->next(); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 37c6281a9..3ec631385 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -246,6 +246,36 @@ void Tokenizer::insertTokens(Token *dest, const Token *src, unsigned int n) } //--------------------------------------------------------------------------- +Token *Tokenizer::copyTokens(Token *dest, const Token *first, const Token *last) +{ + std::stack links; + Token *tok2 = dest; + for (const Token *tok = first; tok != last->next(); tok = tok->next()) + { + tok2->insertToken(tok->str()); + tok2 = tok2->next(); + tok2->fileIndex(dest->fileIndex()); + tok2->linenr(dest->linenr()); + tok2->isUnsigned(tok->isUnsigned()); + tok2->isSigned(tok->isSigned()); + tok2->isLong(tok->isLong()); + + // Check for links and fix them up + if (tok2->str() == "(" || tok2->str() == "[" || tok2->str() == "{") + links.push(tok2); + else if (tok2->str() == ")" || tok2->str() == "]" || tok2->str() == "}") + { + Token * link = links.top(); + + tok2->link(link); + link->link(tok2); + + links.pop(); + } + } + return tok2; +} + //--------------------------------------------------------------------------- // Tokenize - tokenizes a given file. //--------------------------------------------------------------------------- @@ -1412,26 +1442,7 @@ void Tokenizer::simplifyTypedef() // start substituting at the typedef name by replacing it with the type tok2->str(typeStart->str()); - Token * nextToken; - std::stack links; - for (nextToken = typeStart->next(); nextToken != typeEnd->next(); nextToken = nextToken->next()) - { - tok2->insertToken(nextToken->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - links.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") - { - Token * link = links.top(); - - tok2->link(link); - link->link(tok2); - - links.pop(); - } - } + tok2 = copyTokens(tok2, typeStart->next(), typeEnd); if (!pointers.empty()) { @@ -1448,25 +1459,7 @@ void Tokenizer::simplifyTypedef() tok2->insertToken("("); tok2 = tok2->next(); Token *tok3 = tok2; - Token *nextTok; - for (nextTok = funcStart; nextTok != funcEnd->next(); nextTok = nextTok->next()) - { - tok2->insertToken(nextTok->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - links.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") - { - Token * link = links.top(); - - tok2->link(link); - link->link(tok2); - - links.pop(); - } - } + tok2 = copyTokens(tok2, funcStart, funcEnd); if (!inCast) { @@ -1517,30 +1510,7 @@ void Tokenizer::simplifyTypedef() tok2 = tok2->next(); Token::createMutualLinks(tok2, tok3); - tok2->insertToken("("); - tok2 = tok2->next(); - tok3 = tok2; - for (nextTok = argStart->next(); nextTok != argEnd; nextTok = nextTok->next()) - { - tok2->insertToken(nextTok->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - links.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") - { - Token * link = links.top(); - - tok2->link(link); - link->link(tok2); - - links.pop(); - } - } - tok2->insertToken(")"); - tok2 = tok2->next(); - Token::createMutualLinks(tok2, tok3); + tok2 = copyTokens(tok2, argStart, argEnd); if (specStart) { @@ -1652,32 +1622,7 @@ void Tokenizer::simplifyTypedef() Token::createMutualLinks(tok2, tok3); } - tok2->insertToken("("); - tok2 = tok2->next(); - tok3 = tok2; - Token * nextArgTok; - std::stack argLinks; - for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next()) - { - tok2->insertToken(nextArgTok->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - argLinks.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") - { - Token * link = argLinks.top(); - - tok2->link(link); - link->link(tok2); - - argLinks.pop(); - } - } - tok2->insertToken(")"); - tok2 = tok2->next(); - Token::createMutualLinks(tok2, tok3); + tok2 = copyTokens(tok2, argStart, argEnd); if (inTemplate) tok2 = tok2->next(); @@ -1727,64 +1672,13 @@ void Tokenizer::simplifyTypedef() Token::createMutualLinks(tok2, tok4); } - tok2->insertToken("("); - tok2 = tok2->next(); - Token *tok5 = tok2; - - Token *nextArgTok; - std::stack argLinks; - for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next()) - { - tok2->insertToken(nextArgTok->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - argLinks.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") - { - Token * link = argLinks.top(); - - tok2->link(link); - link->link(tok2); - - argLinks.pop(); - } - } - tok2->insertToken(")"); - tok2 = tok2->next(); - Token::createMutualLinks(tok2, tok5); + tok2 = copyTokens(tok2, argStart, argEnd); tok2->insertToken(")"); tok2 = tok2->next(); Token::createMutualLinks(tok2, tok3); - tok2->insertToken("("); - tok2 = tok2->next(); - Token *tok6 = tok2; - - for (nextArgTok = argFuncRetStart->next(); nextArgTok != argFuncRetEnd; nextArgTok = nextArgTok->next()) - { - tok2->insertToken(nextArgTok->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - argLinks.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") - { - Token * link = argLinks.top(); - - tok2->link(link); - link->link(tok2); - - argLinks.pop(); - } - } - - tok2->insertToken(")"); - tok2 = tok2->next(); - Token::createMutualLinks(tok2, tok6); + tok2 = copyTokens(tok2, argFuncRetStart, argFuncRetEnd); } else if (ptrToArray || refToArray) { @@ -1857,33 +1751,7 @@ void Tokenizer::simplifyTypedef() } else if (typeOf) { - tok2->insertToken("("); - tok2 = tok2->next(); - Token *tok3 = tok2; - Token *nextArgTok; - std::stack argLinks; - for (nextArgTok = argStart->next(); nextArgTok != argEnd; nextArgTok = nextArgTok->next()) - { - tok2->insertToken(nextArgTok->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - argLinks.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") - { - Token * link = argLinks.top(); - - tok2->link(link); - link->link(tok2); - - argLinks.pop(); - } - } - tok2->insertToken(")"); - tok2 = tok2->next(); - Token::createMutualLinks(tok2, tok3); - + tok2 = copyTokens(tok2, argStart, argEnd); } else if (tok2->tokAt(2) && tok2->tokAt(2)->str() == "[") { @@ -1897,27 +1765,7 @@ void Tokenizer::simplifyTypedef() { if (!inCast && !inSizeof) tok2 = tok2->next(); - Token * nextArrTok; - std::stack arrLinks; - for (nextArrTok = arrayStart; nextArrTok != arrayEnd->next(); nextArrTok = nextArrTok->next()) - { - tok2->insertToken(nextArrTok->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[") - arrLinks.push(tok2); - if (tok2->str() == ")" || tok2->str() == "]") - { - Token * link = arrLinks.top(); - - tok2->link(link); - link->link(tok2); - - arrLinks.pop(); - } - } - + tok2 = copyTokens(tok2, arrayStart, arrayEnd); tok2 = tok2->next(); if (tok2->str() == "=") @@ -7691,26 +7539,8 @@ void Tokenizer::simplifyEnum() if (lastEnumValueStart && lastEnumValueEnd) { // previous value was an expression - Token * valueStart = tok1; - std::stack links; - for (Token *tok2 = lastEnumValueStart; tok2 != lastEnumValueEnd->next(); tok2 = tok2->next()) - { - tok1->insertToken(tok2->str()); - tok1 = tok1->next(); - - // Check for links and fix them up - if (tok1->str() == "(" || tok1->str() == "[" || tok1->str() == "{") - links.push(tok1); - else if (tok1->str() == ")" || tok1->str() == "]" || tok1->str() == "}") - { - Token * link = links.top(); - - tok1->link(link); - link->link(tok1); - - links.pop(); - } - } + Token *valueStart = tok1; + tok1 = copyTokens(tok1, lastEnumValueStart, lastEnumValueEnd); // value is previous expression + 1 tok1->insertToken("+"); @@ -7852,29 +7682,9 @@ void Tokenizer::simplifyEnum() tok2->str(enumValue->str()); else { - std::stack links; - tok2->str(enumValueStart->str()); - if (tok2->str() == "(" || tok2->str() == "[" || tok2->str() == "{") - links.push(tok2); - Token * nextToken = enumValueStart->next(); - for (; nextToken != enumValueEnd->next(); nextToken = nextToken->next()) - { - tok2->insertToken(nextToken->str()); - tok2 = tok2->next(); - - // Check for links and fix them up - if (tok2->str() == "(" || tok2->str() == "[" || tok2->str() == "{") - links.push(tok2); - else if (tok2->str() == ")" || tok2->str() == "]" || tok2->str() == "}") - { - Token * link = links.top(); - - tok2->link(link); - link->link(tok2); - - links.pop(); - } - } + tok2 = tok2->previous(); + tok2->deleteNext(); + tok2 = copyTokens(tok2, enumValueStart, enumValueEnd); } if (hasClass) diff --git a/lib/tokenize.h b/lib/tokenize.h index e9a280698..c98e46456 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -450,6 +450,15 @@ public: void insertTokens(Token *dest, const Token *src, unsigned int n); + /** + * Copy tokens. + * @param dest destination token where copied tokens will be inserted after + * @param first first token to copy + * @param last last token to copy + * @return new location of last token copied + */ + Token *copyTokens(Token *dest, const Token *first, const Token *last); + /** * Send error message to error logger about internal bug. * @param tok the token that this bug concerns. diff --git a/test/testconstructors.cpp b/test/testconstructors.cpp index 2be7e5672..cd40067bc 100644 --- a/test/testconstructors.cpp +++ b/test/testconstructors.cpp @@ -60,6 +60,7 @@ private: TEST_CASE(simple2); TEST_CASE(simple3); TEST_CASE(simple4); + TEST_CASE(simple5); // ticket #2560 TEST_CASE(initvar_with_this); // BUG 2190300 TEST_CASE(initvar_if); // BUG 2190290 @@ -258,6 +259,23 @@ private: ASSERT_EQUALS("[test.cpp:7]: (warning) Member variable 'Fred::i' is not initialised in the constructor.\n", errout.str()); } + void simple5() // ticket #2560 + { + check("namespace Nsp\n" + "{\n" + " class B { };\n" + "}\n" + "class Altren : public Nsp::B\n" + "{\n" + "public:\n" + " Altren () : Nsp::B(), mValue(0)\n" + " {\n" + " }\n" + "private:\n" + " int mValue;\n" + "};"); + ASSERT_EQUALS("", errout.str()); + } void initvar_with_this() { diff --git a/tools/dmake.cpp b/tools/dmake.cpp index 572e389eb..34cbadacd 100644 --- a/tools/dmake.cpp +++ b/tools/dmake.cpp @@ -26,7 +26,7 @@ #include #if defined(_WIN32) -#include "../cli/fileLister_win32.h" +#include "../cli/filelister_win32.h" #else // POSIX-style system #include "../cli/filelister_unix.h" #endif