Blame test/testincompletestatement.cpp

Packit 2035a7
/*
Packit 2035a7
 * Cppcheck - A tool for static C/C++ code analysis
Packit 2035a7
 * Copyright (C) 2007-2017 Cppcheck team.
Packit 2035a7
 *
Packit 2035a7
 * This program is free software: you can redistribute it and/or modify
Packit 2035a7
 * it under the terms of the GNU General Public License as published by
Packit 2035a7
 * the Free Software Foundation, either version 3 of the License, or
Packit 2035a7
 * (at your option) any later version.
Packit 2035a7
 *
Packit 2035a7
 * This program is distributed in the hope that it will be useful,
Packit 2035a7
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 2035a7
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 2035a7
 * GNU General Public License for more details.
Packit 2035a7
 *
Packit 2035a7
 * You should have received a copy of the GNU General Public License
Packit 2035a7
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
Packit 2035a7
 */
Packit 2035a7
Packit 2035a7
#include "checkother.h"
Packit 2035a7
#include "settings.h"
Packit 2035a7
#include "testsuite.h"
Packit 2035a7
#include "tokenize.h"
Packit 2035a7
Packit 2035a7
#include <simplecpp.h>
Packit 2035a7
#include <map>
Packit 2035a7
#include <vector>
Packit 2035a7
Packit 2035a7
class TestIncompleteStatement : public TestFixture {
Packit 2035a7
public:
Packit 2035a7
    TestIncompleteStatement() : TestFixture("TestIncompleteStatement") {
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
private:
Packit 2035a7
    Settings settings;
Packit 2035a7
Packit 2035a7
    void check(const char code[]) {
Packit 2035a7
        // Clear the error buffer..
Packit 2035a7
        errout.str("");
Packit 2035a7
Packit 2035a7
Packit 2035a7
        // Raw tokens..
Packit 2035a7
        std::vector<std::string> files;
Packit 2035a7
        files.push_back("test.cpp");
Packit 2035a7
        std::istringstream istr(code);
Packit 2035a7
        const simplecpp::TokenList tokens1(istr, files, files[0]);
Packit 2035a7
Packit 2035a7
        // Preprocess..
Packit 2035a7
        simplecpp::TokenList tokens2(files);
Packit 2035a7
        std::map<std::string, simplecpp::TokenList*> filedata;
Packit 2035a7
        simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
Packit 2035a7
Packit 2035a7
        // Tokenize..
Packit 2035a7
        Tokenizer tokenizer(&settings, this);
Packit 2035a7
        tokenizer.createTokens(&tokens2);
Packit 2035a7
        tokenizer.simplifyTokens1("");
Packit 2035a7
        tokenizer.simplifyTokenList2();
Packit 2035a7
Packit 2035a7
        // Check for incomplete statements..
Packit 2035a7
        CheckOther checkOther(&tokenizer, &settings, this);
Packit 2035a7
        checkOther.checkIncompleteStatement();
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void run() {
Packit 2035a7
        settings.addEnabled("warning");
Packit 2035a7
Packit 2035a7
        TEST_CASE(test1);
Packit 2035a7
        TEST_CASE(test2);
Packit 2035a7
        TEST_CASE(test3);
Packit 2035a7
        TEST_CASE(test4);
Packit 2035a7
        TEST_CASE(test5);
Packit 2035a7
        TEST_CASE(test6);
Packit 2035a7
        TEST_CASE(test_numeric);
Packit 2035a7
        TEST_CASE(void0); // #6327: No fp for statement "(void)0;"
Packit 2035a7
        TEST_CASE(intarray);
Packit 2035a7
        TEST_CASE(structarraynull);
Packit 2035a7
        TEST_CASE(structarray);
Packit 2035a7
        TEST_CASE(conditionalcall);     // ; 0==x ? X() : Y();
Packit 2035a7
        TEST_CASE(structinit);          // #2462 : ABC abc{1,2,3};
Packit 2035a7
        TEST_CASE(returnstruct);
Packit 2035a7
        TEST_CASE(cast);                // #3009 : (struct Foo *)123.a = 1;
Packit 2035a7
        TEST_CASE(increment);           // #3251 : FP for increment
Packit 2035a7
        TEST_CASE(cpp11init);           // #5493 : int i{1};
Packit 2035a7
        TEST_CASE(block);               // ({ do_something(); 0; })
Packit 2035a7
        TEST_CASE(mapindex);
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void test1() {
Packit 2035a7
        check("void foo()\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "    const char def[] =\n"
Packit 2035a7
              "    \"abc\";\n"
Packit 2035a7
              "}");
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void test2() {
Packit 2035a7
        check("void foo()\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "    \"abc\";\n"
Packit 2035a7
              "}");
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS("[test.cpp:3]: (warning) Redundant code: Found a statement that begins with string constant.\n", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void test3() {
Packit 2035a7
        check("void foo()\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "    const char *str[] = { \"abc\" };\n"
Packit 2035a7
              "}");
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void test4() {
Packit 2035a7
        check("void foo()\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "const char *a =\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "\"hello \"\n"
Packit 2035a7
              "\"more \"\n"
Packit 2035a7
              "\"world\"\n"
Packit 2035a7
              "};\n"
Packit 2035a7
              "}");
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void test5() {
Packit 2035a7
        check("void foo()\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "    50;\n"
Packit 2035a7
              "}");
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS("[test.cpp:3]: (warning) Redundant code: Found a statement that begins with numeric constant.\n", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void test6() {
Packit 2035a7
        // don't crash
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "  1 == (two + three);\n"
Packit 2035a7
              "  2 != (two + three);\n"
Packit 2035a7
              "  (one + two) != (two + three);\n"
Packit 2035a7
              "}");
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void test_numeric() {
Packit 2035a7
        check("struct P\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "double a;\n"
Packit 2035a7
              "double b;\n"
Packit 2035a7
              "};\n"
Packit 2035a7
              "void f()\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "const P values[2] =\n"
Packit 2035a7
              "{\n"
Packit 2035a7
              "{ 346.1,114.1 }, { 347.1,111.1 }\n"
Packit 2035a7
              "};\n"
Packit 2035a7
              "}");
Packit 2035a7
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void void0() { // #6327
Packit 2035a7
        check("void f() { (void*)0; }");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        check("#define X  0\n"
Packit 2035a7
              "void f() { X; }");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void intarray() {
Packit 2035a7
        check("int arr[] = { 100/2, 1*100 };");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void structarraynull() {
Packit 2035a7
        check("struct st arr[] = {\n"
Packit 2035a7
              "    { 100/2, 1*100 }\n"
Packit 2035a7
              "    { 90, 70 }\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void structarray() {
Packit 2035a7
        check("struct st arr[] = {\n"
Packit 2035a7
              "    { 100/2, 1*100 }\n"
Packit 2035a7
              "    { 90, 70 }\n"
Packit 2035a7
              "};");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void conditionalcall() {
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "    0==x ? X() : Y();\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void structinit() {
Packit 2035a7
        // #2462 - C++11 struct initialization
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "    ABC abc{1,2,3};\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // #6260 - C++11 array initialization
Packit 2035a7
        check("void foo() {\n"
Packit 2035a7
              "    static const char* a[][2] {\n"
Packit 2035a7
              "        {\"b\", \"\"},\n"
Packit 2035a7
              "    };\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // #2482 - false positive for empty struct
Packit 2035a7
        check("struct A {};");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // #4387 - C++11 initializer list
Packit 2035a7
        check("A::A() : abc{0} {}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // #5042 - C++11 initializer list
Packit 2035a7
        check("A::A() : abc::def<int>{0} {}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // #4503 - vector init
Packit 2035a7
        check("void f() { vector<int> v{1}; }");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void returnstruct() {
Packit 2035a7
        check("struct s foo() {\n"
Packit 2035a7
              "    return (struct s){0,0};\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        // #4754
Packit 2035a7
        check("unordered_map<string, string>  foo() {\n"
Packit 2035a7
              "    return {\n"
Packit 2035a7
              "        {\"hi\", \"there\"},\n"
Packit 2035a7
              "        {\"happy\", \"sad\"}\n"
Packit 2035a7
              "    };\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        check("struct s foo() {\n"
Packit 2035a7
              "  return (struct s){0};\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void cast() {
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "    ((struct foo *)(0x1234))->xy = 1;\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void increment() {
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "    int x = 1;\n"
Packit 2035a7
              "    x++, x++;\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void cpp11init() {
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "    int x{1};\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void block() {
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "    ({ do_something(); 0; });\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "out:\n"
Packit 2035a7
              "    ({ do_something(); 0; });\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
Packit 2035a7
    void mapindex() {
Packit 2035a7
        check("void f() {\n"
Packit 2035a7
              "  map[{\"1\",\"2\"}]=0;\n"
Packit 2035a7
              "}");
Packit 2035a7
        ASSERT_EQUALS("", errout.str());
Packit 2035a7
    }
Packit 2035a7
};
Packit 2035a7
Packit 2035a7
REGISTER_TEST(TestIncompleteStatement)