cppcheck/test/testincompletestatement.cpp

293 lines
7.9 KiB
C++
Raw Normal View History

2008-12-18 22:28:57 +01:00
/*
* Cppcheck - A tool for static C/C++ code analysis
2016-01-01 14:34:45 +01:00
* Copyright (C) 2007-2016 Cppcheck team.
2008-12-18 22:28:57 +01:00
*
* 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/>.
2008-12-18 22:28:57 +01:00
*/
2017-05-27 04:33:47 +02:00
#include "checkother.h"
#include "settings.h"
2008-12-18 22:28:57 +01:00
#include "testsuite.h"
2009-10-25 12:49:06 +01:00
#include "tokenize.h"
2017-05-27 04:33:47 +02:00
2017-05-18 21:52:31 +02:00
#include <simplecpp.h>
2017-05-27 04:33:47 +02:00
#include <map>
#include <vector>
2008-12-18 22:28:57 +01:00
2011-10-13 20:53:06 +02:00
class TestIncompleteStatement : public TestFixture {
2008-12-18 22:28:57 +01:00
public:
2014-11-20 14:20:09 +01:00
TestIncompleteStatement() : TestFixture("TestIncompleteStatement") {
}
2008-12-18 22:28:57 +01:00
private:
Settings settings;
2014-11-20 14:20:09 +01:00
void check(const char code[]) {
// Clear the error buffer..
errout.str("");
2017-05-18 21:52:31 +02:00
// Raw tokens..
std::vector<std::string> files;
files.push_back("test.cpp");
std::istringstream istr(code);
const simplecpp::TokenList tokens1(istr, files, files[0]);
// Preprocess..
simplecpp::TokenList tokens2(files);
std::map<std::string, simplecpp::TokenList*> filedata;
simplecpp::preprocess(tokens2, tokens1, files, filedata, simplecpp::DUI());
2008-12-18 22:28:57 +01:00
// Tokenize..
Tokenizer tokenizer(&settings, this);
2017-05-18 21:52:31 +02:00
tokenizer.createTokens(&tokens2);
tokenizer.simplifyTokens1("");
tokenizer.simplifyTokenList2();
2008-12-18 22:28:57 +01:00
// Check for incomplete statements..
2009-03-20 18:16:21 +01:00
CheckOther checkOther(&tokenizer, &settings, this);
checkOther.checkIncompleteStatement();
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void run() {
settings.addEnabled("warning");
TEST_CASE(test1);
TEST_CASE(test2);
2009-02-05 19:57:53 +01:00
TEST_CASE(test3);
TEST_CASE(test4);
TEST_CASE(test5);
2014-04-23 19:49:16 +02:00
TEST_CASE(test6);
TEST_CASE(test_numeric);
TEST_CASE(void0); // #6327: No fp for statement "(void)0;"
TEST_CASE(intarray);
TEST_CASE(structarraynull);
TEST_CASE(structarray);
TEST_CASE(conditionalcall); // ; 0==x ? X() : Y();
TEST_CASE(structinit); // #2462 : ABC abc{1,2,3};
TEST_CASE(returnstruct);
TEST_CASE(cast); // #3009 : (struct Foo *)123.a = 1;
TEST_CASE(increment); // #3251 : FP for increment
TEST_CASE(cpp11init); // #5493 : int i{1};
TEST_CASE(block); // ({ do_something(); 0; })
TEST_CASE(mapindex);
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void test1() {
check("void foo()\n"
"{\n"
" const char def[] =\n"
" \"abc\";\n"
"}");
ASSERT_EQUALS("", errout.str());
2008-12-18 22:28:57 +01:00
}
2014-11-20 14:20:09 +01:00
void test2() {
check("void foo()\n"
"{\n"
2009-02-05 19:57:53 +01:00
" \"abc\";\n"
"}");
2008-12-18 22:28:57 +01:00
ASSERT_EQUALS("[test.cpp:3]: (warning) Redundant code: Found a statement that begins with string constant.\n", errout.str());
2008-12-18 22:28:57 +01:00
}
2009-02-05 19:57:53 +01:00
2014-11-20 14:20:09 +01:00
void test3() {
2009-02-05 19:57:53 +01:00
check("void foo()\n"
"{\n"
" const char *str[] = { \"abc\" };\n"
"}");
2009-02-05 19:57:53 +01:00
ASSERT_EQUALS("", errout.str());
2009-02-05 19:57:53 +01:00
}
2014-11-20 14:20:09 +01:00
void test4() {
check("void foo()\n"
"{\n"
"const char *a =\n"
"{\n"
"\"hello \"\n"
"\"more \"\n"
"\"world\"\n"
"};\n"
"}");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void test5() {
check("void foo()\n"
"{\n"
" 50;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (warning) Redundant code: Found a statement that begins with numeric constant.\n", errout.str());
}
2014-11-20 14:20:09 +01:00
void test6() {
// don't crash
2014-04-23 19:49:16 +02:00
check("void f() {\n"
" 1 == (two + three);\n"
" 2 != (two + three);\n"
" (one + two) != (two + three);\n"
"}");
}
2014-11-20 14:20:09 +01:00
void test_numeric() {
check("struct P\n"
"{\n"
"double a;\n"
"double b;\n"
"};\n"
"void f()\n"
"{\n"
"const P values[2] =\n"
"{\n"
"{ 346.1,114.1 }, { 347.1,111.1 }\n"
"};\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void void0() { // #6327
check("void f() { (void*)0; }");
ASSERT_EQUALS("", errout.str());
2017-05-18 21:52:31 +02:00
check("#define X 0\n"
"void f() { X; }");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void intarray() {
check("int arr[] = { 100/2, 1*100 };");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void structarraynull() {
check("struct st arr[] = {\n"
" { 100/2, 1*100 }\n"
" { 90, 70 }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void structarray() {
check("struct st arr[] = {\n"
" { 100/2, 1*100 }\n"
" { 90, 70 }\n"
"};");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void conditionalcall() {
check("void f() {\n"
" 0==x ? X() : Y();\n"
"}");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void structinit() {
// #2462 - C++11 struct initialization
check("void f() {\n"
" ABC abc{1,2,3};\n"
"}");
ASSERT_EQUALS("", errout.str());
2011-01-19 20:41:46 +01:00
// #6260 - C++11 array initialization
check("void foo() {\n"
" static const char* a[][2] {\n"
" {\"b\", \"\"},\n"
" };\n"
"}");
ASSERT_EQUALS("", errout.str());
2011-01-19 20:41:46 +01:00
// #2482 - false positive for empty struct
check("struct A {};");
ASSERT_EQUALS("", errout.str());
// #4387 - C++11 initializer list
check("A::A() : abc{0} {}");
ASSERT_EQUALS("", errout.str());
// #5042 - C++11 initializer list
check("A::A() : abc::def<int>{0} {}");
ASSERT_EQUALS("", errout.str());
// #4503 - vector init
check("void f() { vector<int> v{1}; }");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void returnstruct() {
check("struct s foo() {\n"
" return (struct s){0,0};\n"
"}");
ASSERT_EQUALS("", errout.str());
// #4754
check("unordered_map<string, string> foo() {\n"
" return {\n"
" {\"hi\", \"there\"},\n"
" {\"happy\", \"sad\"}\n"
" };\n"
"}");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void cast() {
check("void f() {\n"
" ((struct foo *)(0x1234))->xy = 1;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void increment() {
check("void f() {\n"
" int x = 1;\n"
" x++, x++;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void cpp11init() {
check("void f() {\n"
" int x{1};\n"
"}");
ASSERT_EQUALS("", errout.str());
}
2014-11-20 14:20:09 +01:00
void block() {
check("void f() {\n"
" ({ do_something(); 0; });\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f() {\n"
"out:\n"
" ({ do_something(); 0; });\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void mapindex() {
check("void f() {\n"
" map[{\"1\",\"2\"}]=0;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
2008-12-18 22:28:57 +01:00
};
REGISTER_TEST(TestIncompleteStatement)