"Fossies" - the Fresh Open Source Software Archive

Member "cppcheck-1.89/test/testinternal.cpp" (1 Sep 2019, 21010 Bytes) of package /windows/misc/cppcheck-1.89.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "testinternal.cpp": 1.87_vs_1.88.

    1 /*
    2  * Cppcheck - A tool for static C/C++ code analysis
    3  * Copyright (C) 2007-2019 Cppcheck team.
    4  *
    5  * This program is free software: you can redistribute it and/or modify
    6  * it under the terms of the GNU General Public License as published by
    7  * the Free Software Foundation, either version 3 of the License, or
    8  * (at your option) any later version.
    9  *
   10  * This program is distributed in the hope that it will be useful,
   11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13  * GNU General Public License for more details.
   14  *
   15  * You should have received a copy of the GNU General Public License
   16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
   17  */
   18 
   19 #ifdef CHECK_INTERNAL
   20 
   21 #include "tokenize.h"
   22 #include "checkinternal.h"
   23 #include "testsuite.h"
   24 
   25 
   26 class TestInternal : public TestFixture {
   27 public:
   28     TestInternal() : TestFixture("TestInternal") {
   29     }
   30 
   31 private:
   32     Settings settings;
   33 
   34     void run() OVERRIDE {
   35         settings.addEnabled("internal");
   36 
   37         TEST_CASE(simplePatternInTokenMatch)
   38         TEST_CASE(complexPatternInTokenSimpleMatch)
   39         TEST_CASE(simplePatternSquareBrackets)
   40         TEST_CASE(simplePatternAlternatives)
   41         TEST_CASE(missingPercentCharacter)
   42         TEST_CASE(unknownPattern)
   43         TEST_CASE(redundantNextPrevious)
   44         TEST_CASE(internalError);
   45         TEST_CASE(orInComplexPattern);
   46         TEST_CASE(extraWhitespace);
   47         TEST_CASE(checkRedundantTokCheck);
   48     }
   49 
   50     void check(const char code[]) {
   51         // Clear the error buffer..
   52         errout.str("");
   53 
   54         // Tokenize..
   55         Tokenizer tokenizer(&settings, this);
   56         std::istringstream istr(code);
   57         tokenizer.tokenize(istr, "test.cpp");
   58 
   59         // Check..
   60         CheckInternal checkInternal;
   61         checkInternal.runChecks(&tokenizer, &settings, this);
   62     }
   63 
   64     void simplePatternInTokenMatch() {
   65         check("void f() {\n"
   66               "    const Token *tok;\n"
   67               "    Token::Match(tok, \";\");\n"
   68               "}");
   69         ASSERT_EQUALS("[test.cpp:3]: (warning) Found simple pattern inside Token::Match() call: \";\"\n", errout.str());
   70 
   71         check("void f() {\n"
   72               "    const Token *tok;\n"
   73               "    Token::Match(tok, \"%type%\");\n"
   74               "}");
   75         ASSERT_EQUALS("", errout.str());
   76 
   77         check("void f() {\n"
   78               "    const Token *tok;\n"
   79               "    Token::Match(tok, \"%or%\");\n"
   80               "}");
   81         ASSERT_EQUALS("[test.cpp:3]: (warning) Found simple pattern inside Token::Match() call: \"%or%\"\n", errout.str());
   82 
   83         check("void f() {\n"
   84               "    const Token *tok;\n"
   85               "    Token::findmatch(tok, \";\");\n"
   86               "}");
   87         ASSERT_EQUALS("[test.cpp:3]: (warning) Found simple pattern inside Token::findmatch() call: \";\"\n", errout.str());
   88     }
   89 
   90     void complexPatternInTokenSimpleMatch() {
   91         check("void f() {\n"
   92               "    const Token *tok;\n"
   93               "    Token::simpleMatch(tok, \"%type%\");\n"
   94               "}");
   95         ASSERT_EQUALS("[test.cpp:3]: (error) Found complex pattern inside Token::simpleMatch() call: \"%type%\"\n", errout.str());
   96 
   97         check("void f() {\n"
   98               "    const Token *tok;\n"
   99               "    Token::findsimplematch(tok, \"%type%\");\n"
  100               "}");
  101         ASSERT_EQUALS("[test.cpp:3]: (error) Found complex pattern inside Token::findsimplematch() call: \"%type%\"\n", errout.str());
  102 
  103         check("void f() {\n"
  104               "    const Token *tok;\n"
  105               "    Token::findsimplematch(tok, \"} !!else\");\n"
  106               "}");
  107         ASSERT_EQUALS("[test.cpp:3]: (error) Found complex pattern inside Token::findsimplematch() call: \"} !!else\"\n", errout.str());
  108 
  109         check("void f() {\n"
  110               "    const Token *tok;\n"
  111               "    Token::findsimplematch(tok, \"foobar\");\n"
  112               "}");
  113         ASSERT_EQUALS("", errout.str());
  114 
  115         check("void f() {\n"
  116               "    const Token *tok;\n"
  117               "    Token::findsimplematch(tok, \"%\");\n"
  118               "}");
  119         ASSERT_EQUALS("", errout.str());
  120     }
  121 
  122     void simplePatternSquareBrackets() {
  123         check("void f() {\n"
  124               "    const Token *tok;\n"
  125               "    Token::simpleMatch(tok, \"[\");\n"
  126               "}");
  127         ASSERT_EQUALS("", errout.str());
  128 
  129         check("void f() {\n"
  130               "    const Token *tok;\n"
  131               "    Token::simpleMatch(tok, \"[ ]\");\n"
  132               "}");
  133         ASSERT_EQUALS("", errout.str());
  134 
  135         check("void f() {\n"
  136               "    const Token *tok;\n"
  137               "    Token::simpleMatch(tok, \"[]\");\n"
  138               "}");
  139         ASSERT_EQUALS("[test.cpp:3]: (error) Found complex pattern inside Token::simpleMatch() call: \"[]\"\n", errout.str());
  140 
  141         check("void f() {\n"
  142               "    const Token *tok;\n"
  143               "    Token::simpleMatch(tok, \"] [\");\n"
  144               "}");
  145         ASSERT_EQUALS("", errout.str());
  146 
  147         check("void f() {\n"
  148               "    const Token *tok;\n"
  149               "    Token::simpleMatch(tok, \"] [ [abc]\");\n"
  150               "}");
  151         ASSERT_EQUALS("[test.cpp:3]: (error) Found complex pattern inside Token::simpleMatch() call: \"] [ [abc]\"\n", errout.str());
  152 
  153         check("void f() {\n"
  154               "    const Token *tok;\n"
  155               "    Token::simpleMatch(tok, \"[.,;]\");\n"
  156               "}");
  157         ASSERT_EQUALS("[test.cpp:3]: (error) Found complex pattern inside Token::simpleMatch() call: \"[.,;]\"\n", errout.str());
  158     }
  159 
  160     void simplePatternAlternatives() {
  161         check("void f() {\n"
  162               "    const Token *tok;\n"
  163               "    Token::simpleMatch(tok, \"||\");\n"
  164               "}");
  165         ASSERT_EQUALS("", errout.str());
  166 
  167         check("void f() {\n"
  168               "    const Token *tok;\n"
  169               "    Token::simpleMatch(tok, \"|\");\n"
  170               "}");
  171         ASSERT_EQUALS("", errout.str());
  172 
  173         check("void f() {\n"
  174               "    const Token *tok;\n"
  175               "    Token::simpleMatch(tok, \"a|b\");\n"
  176               "}");
  177         ASSERT_EQUALS("[test.cpp:3]: (error) Found complex pattern inside Token::simpleMatch() call: \"a|b\"\n", errout.str());
  178 
  179         check("void f() {\n"
  180               "    const Token *tok;\n"
  181               "    Token::simpleMatch(tok, \"|= 0\");\n"
  182               "}");
  183         ASSERT_EQUALS("", errout.str());
  184 
  185         check("void f() {\n"
  186               "    const Token *tok;\n"
  187               "    Token::simpleMatch(tok, \"| 0 )\");\n"
  188               "}");
  189         ASSERT_EQUALS("", errout.str());
  190     }
  191 
  192     void missingPercentCharacter() {
  193         check("void f() {\n"
  194               "    const Token *tok;\n"
  195               "    Token::Match(tok, \"%type%\");\n"
  196               "}");
  197         ASSERT_EQUALS("", errout.str());
  198 
  199         check("void f() {\n"
  200               "    const Token *tok;\n"
  201               "    Token::Match(tok, \"foo %type% bar\");\n"
  202               "}");
  203         ASSERT_EQUALS("", errout.str());
  204 
  205         // Missing % at the end of string
  206         check("void f() {\n"
  207               "    const Token *tok;\n"
  208               "    Token::Match(tok, \"%type\");\n"
  209               "}");
  210         ASSERT_EQUALS("[test.cpp:3]: (error) Missing percent end character in Token::Match() pattern: \"%type\"\n", errout.str());
  211 
  212         // Missing % in the middle of a pattern
  213         check("void f() {\n"
  214               "    const Token *tok;\n"
  215               "    Token::Match(tok, \"foo %type bar\");\n"
  216               "}");
  217         ASSERT_EQUALS("[test.cpp:3]: (error) Missing percent end character in Token::Match() pattern: \"foo %type bar\"\n", errout.str());
  218 
  219         // Bei quiet on single %
  220         check("void f() {\n"
  221               "    const Token *tok;\n"
  222               "    Token::Match(tok, \"foo % %type% bar\");\n"
  223               "}");
  224         ASSERT_EQUALS("", errout.str());
  225 
  226         check("void f() {\n"
  227               "    const Token *tok;\n"
  228               "    Token::Match(tok, \"foo % %type % bar\");\n"
  229               "}");
  230         ASSERT_EQUALS("[test.cpp:3]: (error) Missing percent end character in Token::Match() pattern: \"foo % %type % bar\"\n"
  231                       "[test.cpp:3]: (error) Unknown pattern used: \"%type %\"\n", errout.str());
  232 
  233         // Find missing % also in 'alternatives' pattern
  234         check("void f() {\n"
  235               "    const Token *tok;\n"
  236               "    Token::Match(tok, \"foo|%type|bar\");\n"
  237               "}");
  238         ASSERT_EQUALS("[test.cpp:3]: (error) Missing percent end character in Token::Match() pattern: \"foo|%type|bar\"\n"
  239                       , errout.str());
  240 
  241         // Make sure we don't take %or% for a broken %oror%
  242         check("void f() {\n"
  243               "    const Token *tok;\n"
  244               "    Token::Match(tok, \"foo|%oror%|bar\");\n"
  245               "}");
  246         ASSERT_EQUALS("", errout.str());
  247     }
  248 
  249     void unknownPattern() {
  250         check("void f() {\n"
  251               "    Token::Match(tok, \"%typ%\");\n"
  252               "}");
  253         ASSERT_EQUALS("[test.cpp:2]: (error) Unknown pattern used: \"%typ%\"\n", errout.str());
  254 
  255         // Make sure we don't take %or% for a broken %oror%
  256         check("void f() {\n"
  257               "    Token::Match(tok, \"%type%\");\n"
  258               "}");
  259         ASSERT_EQUALS("", errout.str());
  260     }
  261 
  262     void redundantNextPrevious() {
  263         check("void f() {\n"
  264               "    return tok->next()->previous();\n"
  265               "}");
  266         ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::previous()' can be simplified.\n", errout.str());
  267 
  268         check("void f() {\n"
  269               "    return tok->tokAt(5)->previous();\n"
  270               "}");
  271         ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::tokAt()' followed by 'Token::previous()' can be simplified.\n", errout.str());
  272 
  273         check("void f() {\n"
  274               "    return tok->previous()->linkAt(5);\n"
  275               "}");
  276         ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::previous()' followed by 'Token::linkAt()' can be simplified.\n", errout.str());
  277 
  278         check("void f() {\n"
  279               "    tok->next()->previous(foo);\n"
  280               "}");
  281         ASSERT_EQUALS("", errout.str());
  282 
  283         check("void f() {\n"
  284               "    return tok->next()->next();\n" // Simplification won't make code much shorter/readable
  285               "}");
  286         ASSERT_EQUALS("", errout.str());
  287 
  288         check("void f() {\n"
  289               "    return tok->previous()->previous();\n" // Simplification won't make code much shorter/readable
  290               "}");
  291         ASSERT_EQUALS("", errout.str());
  292 
  293         check("void f() {\n"
  294               "    return tok->tokAt(foo+bar)->tokAt();\n"
  295               "}");
  296         ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::tokAt()' followed by 'Token::tokAt()' can be simplified.\n", errout.str());
  297 
  298         check("void f() {\n"
  299               "    return tok->tokAt(foo+bar)->link();\n"
  300               "}");
  301         ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::tokAt()' followed by 'Token::link()' can be simplified.\n", errout.str());
  302 
  303         check("void f() {\n"
  304               "    tok->tokAt(foo+bar)->link(foo);\n"
  305               "}");
  306         ASSERT_EQUALS("", errout.str());
  307 
  308         check("void f() {\n"
  309               "    return tok->next()->next()->str();\n"
  310               "}");
  311         ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::next()' followed by 'Token::str()' can be simplified.\n", errout.str());
  312 
  313         check("void f() {\n"
  314               "    return tok->previous()->next()->str();\n"
  315               "}");
  316         ASSERT_EQUALS("[test.cpp:2]: (style) Call to 'Token::previous()' followed by 'Token::next()' can be simplified.\n", errout.str());
  317 
  318     }
  319 
  320     void internalError() {
  321         // Make sure cppcheck does not raise an internal error of Token::Match ( Ticket #3727 )
  322         check("class DELPHICLASS X;\n"
  323               "class Y {\n"
  324               "private:\n"
  325               "   X* x;\n"
  326               "};\n"
  327               "class Z {\n"
  328               "   char z[1];\n"
  329               "   Z(){\n"
  330               "      z[0] = 0;\n"
  331               "   }\n"
  332               "};");
  333         ASSERT_EQUALS("", errout.str());
  334     }
  335 
  336     void orInComplexPattern() {
  337         check("void f() {\n"
  338               "    Token::Match(tok, \"||\");\n"
  339               "}");
  340         ASSERT_EQUALS("[test.cpp:2]: (error) Token::Match() pattern \"||\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".\n", errout.str());
  341 
  342         check("void f() {\n"
  343               "    Token::Match(tok, \"|\");\n"
  344               "}");
  345         ASSERT_EQUALS("[test.cpp:2]: (error) Token::Match() pattern \"|\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".\n", errout.str());
  346 
  347         check("void f() {\n"
  348               "    Token::Match(tok, \"[|+-]\");\n"
  349               "}");
  350         ASSERT_EQUALS("", errout.str());
  351 
  352         check("void f() {\n"
  353               "    Token::Match(tok, \"foo | bar\");\n"
  354               "}");
  355         ASSERT_EQUALS("[test.cpp:2]: (error) Token::Match() pattern \"foo | bar\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".\n", errout.str());
  356 
  357         check("void f() {\n"
  358               "    Token::Match(tok, \"foo |\");\n"
  359               "}");
  360         ASSERT_EQUALS("[test.cpp:2]: (error) Token::Match() pattern \"foo |\" contains \"||\" or \"|\". Replace it by \"%oror%\" or \"%or%\".\n", errout.str());
  361 
  362         check("void f() {\n"
  363               "    Token::Match(tok, \"bar foo|\");\n"
  364               "}");
  365         ASSERT_EQUALS("", errout.str());
  366     }
  367 
  368     void extraWhitespace() {
  369         // whitespace at the end
  370         check("void f() {\n"
  371               "    const Token *tok;\n"
  372               "    Token::Match(tok, \"%str% \");\n"
  373               "}");
  374         ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::Match() call: \"%str% \"\n", errout.str());
  375 
  376         // whitespace at the begin
  377         check("void f() {\n"
  378               "    const Token *tok;\n"
  379               "    Token::Match(tok, \" %str%\");\n"
  380               "}");
  381         ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::Match() call: \" %str%\"\n", errout.str());
  382 
  383         // two whitespaces or more
  384         check("void f() {\n"
  385               "    const Token *tok;\n"
  386               "    Token::Match(tok, \"%str%  bar\");\n"
  387               "}");
  388         ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::Match() call: \"%str%  bar\"\n", errout.str());
  389 
  390         // test simpleMatch
  391         check("void f() {\n"
  392               "    const Token *tok;\n"
  393               "    Token::simpleMatch(tok, \"foobar \");\n"
  394               "}");
  395         ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::simpleMatch() call: \"foobar \"\n", errout.str());
  396 
  397         // test findmatch
  398         check("void f() {\n"
  399               "    const Token *tok;\n"
  400               "    Token::findmatch(tok, \"%str% \");\n"
  401               "}");
  402         ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::findmatch() call: \"%str% \"\n", errout.str());
  403 
  404         // test findsimplematch
  405         check("void f() {\n"
  406               "    const Token *tok;\n"
  407               "    Token::findsimplematch(tok, \"foobar \");\n"
  408               "}");
  409         ASSERT_EQUALS("[test.cpp:3]: (warning) Found extra whitespace inside Token::findsimplematch() call: \"foobar \"\n", errout.str());
  410     }
  411 
  412     void checkRedundantTokCheck() {
  413         // findsimplematch
  414         check("void f() {\n"
  415               "    const Token *tok;\n"
  416               "    if(tok && Token::findsimplematch(tok, \"foobar\")) {};\n"
  417               "}");
  418         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  419 
  420         // findmatch
  421         check("void f() {\n"
  422               "    const Token *tok;\n"
  423               "    if(tok && Token::findmatch(tok, \"%str% foobar\")) {};\n"
  424               "}");
  425         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  426 
  427         // Match
  428         check("void f() {\n"
  429               "    const Token *tok;\n"
  430               "    if(tok && Token::Match(tok, \"5str% foobar\")) {};\n"
  431               "}");
  432         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  433 
  434         check("void f() {\n"
  435               "    const Token *tok;\n"
  436               "    if(a && tok && Token::Match(tok, \"5str% foobar\")) {};\n"
  437               "}");
  438         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  439 
  440         check("void f() {\n"
  441               "    const Token *tok;\n"
  442               "    if(a && b && tok && Token::Match(tok, \"5str% foobar\")) {};\n"
  443               "}");
  444         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  445 
  446         check("void f() {\n"
  447               "    const Token *tok;\n"
  448               "    if(a && b && && c && tok && Token::Match(tok, \"5str% foobar\")) {};\n"
  449               "}");
  450         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  451 
  452         check("void f() {\n"
  453               "    const Token *tok;\n"
  454               "    if(a && b && && c && tok && d && Token::Match(tok, \"5str% foobar\")) {};\n"
  455               "}");
  456         ASSERT_EQUALS("", errout.str());
  457 
  458         // simpleMatch
  459         check("void f() {\n"
  460               "    const Token *tok;\n"
  461               "    if(tok && Token::simpleMatch(tok, \"foobar\")) {};\n"
  462               "}");
  463         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  464 
  465         // Match
  466         check("void f() {\n"
  467               "    const Token *tok;\n"
  468               "    if(tok->previous() && Token::Match(tok->previous(), \"5str% foobar\")) {};\n"
  469               "}");
  470         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok->previous()\", match-function already checks if it is null.\n", errout.str());
  471 
  472         // don't report:
  473         // tok->previous() vs tok
  474         check("void f() {\n"
  475               "    const Token *tok;\n"
  476               "    if(tok->previous() && Token::Match(tok, \"5str% foobar\")) {};\n"
  477               "}");
  478         ASSERT_EQUALS("", errout.str());
  479 
  480         // tok vs tok->previous())
  481         check("void f() {\n"
  482               "    const Token *tok;\n"
  483               "    if(tok && Token::Match(tok->previous(), \"5str% foobar\")) {};\n"
  484               "}");
  485         ASSERT_EQUALS("", errout.str());
  486 
  487         // tok->previous() vs tok->previous()->previous())
  488         check("void f() {\n"
  489               "    const Token *tok;\n"
  490               "    if(tok->previous() && Token::Match(tok->previous()->previous(), \"5str% foobar\")) {};\n"
  491               "}");
  492         ASSERT_EQUALS("", errout.str());
  493 
  494         // if a && fn(a) triggers, make sure !a || !fn(a) triggers as well!
  495         check("void f() {\n"
  496               "    const Token *tok;\n"
  497               "    if(!tok || !Token::simpleMatch(tok, \"foobar\")) {};\n"
  498               "}");
  499         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  500 
  501         check("void f() {\n"
  502               "    const Token *tok;\n"
  503               "    if(a || !tok || !Token::simpleMatch(tok, \"foobar\")) {};\n"
  504               "}");
  505         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok\", match-function already checks if it is null.\n", errout.str());
  506 
  507         // if tok || !Token::simpleMatch...
  508         check("void f() {\n"
  509               "    const Token *tok;\n"
  510               "    if(tok || !Token::simpleMatch(tok, \"foobar\")) {};\n"
  511               "}");
  512         ASSERT_EQUALS("", errout.str());
  513 
  514         // if !tok || Token::simpleMatch...
  515         check("void f() {\n"
  516               "    const Token *tok;\n"
  517               "    if(!tok || Token::simpleMatch(tok, \"foobar\")) {};\n"
  518               "}");
  519         ASSERT_EQUALS("", errout.str());
  520 
  521         // something more complex
  522         check("void f() {\n"
  523               "    const Token *tok;\n"
  524               "    if(!tok->previous()->previous() || !Token::simpleMatch(tok->previous()->previous(), \"foobar\")) {};\n"
  525               "}");
  526         ASSERT_EQUALS("[test.cpp:3]: (style) Unnecessary check of \"tok->previous()->previous()\", match-function already checks if it is null.\n", errout.str());
  527     }
  528 };
  529 
  530 REGISTER_TEST(TestInternal)
  531 
  532 #endif // #ifdef CHECK_INTERNAL