"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "test/testother.cpp" between
cppcheck-1.86.tar.gz and cppcheck-1.87.tar.gz

About: Cppcheck is a static analysis tool for C/C++ code. It checks for memory leaks, mismatching allocation-deallocation, buffer overrun, and many more.

testother.cpp  (cppcheck-1.86):testother.cpp  (cppcheck-1.87)
/* /*
* Cppcheck - A tool for static C/C++ code analysis * Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2018 Cppcheck team. * Copyright (C) 2007-2019 Cppcheck team.
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
skipping to change at line 41 skipping to change at line 41
#include <vector> #include <vector>
class TestOther : public TestFixture { class TestOther : public TestFixture {
public: public:
TestOther() : TestFixture("TestOther") { TestOther() : TestFixture("TestOther") {
} }
private: private:
Settings _settings; Settings _settings;
void run() override { void run() OVERRIDE {
LOAD_LIB_2(_settings.library, "std.cfg"); LOAD_LIB_2(_settings.library, "std.cfg");
TEST_CASE(emptyBrackets); TEST_CASE(emptyBrackets);
TEST_CASE(zeroDiv1); TEST_CASE(zeroDiv1);
TEST_CASE(zeroDiv2); TEST_CASE(zeroDiv2);
TEST_CASE(zeroDiv3); TEST_CASE(zeroDiv3);
TEST_CASE(zeroDiv4); TEST_CASE(zeroDiv4);
TEST_CASE(zeroDiv5); TEST_CASE(zeroDiv5);
TEST_CASE(zeroDiv6); TEST_CASE(zeroDiv6);
skipping to change at line 223 skipping to change at line 223
TEST_CASE(moveAndAddressOf); TEST_CASE(moveAndAddressOf);
TEST_CASE(partiallyMoved); TEST_CASE(partiallyMoved);
TEST_CASE(moveAndLambda); TEST_CASE(moveAndLambda);
TEST_CASE(forwardAndUsed); TEST_CASE(forwardAndUsed);
TEST_CASE(funcArgNamesDifferent); TEST_CASE(funcArgNamesDifferent);
TEST_CASE(funcArgOrderDifferent); TEST_CASE(funcArgOrderDifferent);
TEST_CASE(cpp11FunctionArgInit); // #7846 - "void foo(int declaration = {}) {" TEST_CASE(cpp11FunctionArgInit); // #7846 - "void foo(int declaration = {}) {"
TEST_CASE(shadowVariables); TEST_CASE(shadowVariables);
TEST_CASE(constArgument);
} }
void check(const char code[], const char *filename = nullptr, bool experimen tal = false, bool inconclusive = true, bool runSimpleChecks=true, Settings* sett ings = 0) { void check(const char code[], const char *filename = nullptr, bool experimen tal = false, bool inconclusive = true, bool runSimpleChecks=true, bool verbose=f alse, Settings* settings = 0) {
// Clear the error buffer.. // Clear the error buffer..
errout.str(""); errout.str("");
if (!settings) { if (!settings) {
settings = &_settings; settings = &_settings;
} }
settings->addEnabled("style"); settings->addEnabled("style");
settings->addEnabled("warning"); settings->addEnabled("warning");
settings->addEnabled("portability"); settings->addEnabled("portability");
settings->addEnabled("performance"); settings->addEnabled("performance");
settings->standards.c = Standards::CLatest; settings->standards.c = Standards::CLatest;
settings->standards.cpp = Standards::CPPLatest; settings->standards.cpp = Standards::CPPLatest;
settings->inconclusive = inconclusive; settings->inconclusive = inconclusive;
settings->experimental = experimental; settings->experimental = experimental;
settings->verbose = verbose;
// Tokenize.. // Tokenize..
Tokenizer tokenizer(settings, this); Tokenizer tokenizer(settings, this);
std::istringstream istr(code); std::istringstream istr(code);
tokenizer.tokenize(istr, filename ? filename : "test.cpp"); tokenizer.tokenize(istr, filename ? filename : "test.cpp");
// Check.. // Check..
CheckOther checkOther(&tokenizer, settings, this); CheckOther checkOther(&tokenizer, settings, this);
checkOther.runChecks(&tokenizer, settings, this); checkOther.runChecks(&tokenizer, settings, this);
if (runSimpleChecks) { if (runSimpleChecks) {
tokenizer.simplifyTokenList2(); tokenizer.simplifyTokenList2();
checkOther.runSimplifiedChecks(&tokenizer, settings, this); checkOther.runSimplifiedChecks(&tokenizer, settings, this);
} }
} }
void check(const char code[], Settings *s) { void check(const char code[], Settings *s) {
check(code,"test.cpp",false,true,true,s); check(code,"test.cpp",false,true,true,false,s);
} }
void checkP(const char code[], const char *filename = "test.cpp") { void checkP(const char code[], const char *filename = "test.cpp") {
// Clear the error buffer.. // Clear the error buffer..
errout.str(""); errout.str("");
Settings* settings = &_settings; Settings* settings = &_settings;
settings->addEnabled("style"); settings->addEnabled("style");
settings->addEnabled("warning"); settings->addEnabled("warning");
settings->addEnabled("portability"); settings->addEnabled("portability");
skipping to change at line 306 skipping to change at line 308
void checkposix(const char code[]) { void checkposix(const char code[]) {
static Settings settings; static Settings settings;
settings.addEnabled("warning"); settings.addEnabled("warning");
settings.standards.posix = true; settings.standards.posix = true;
check(code, check(code,
nullptr, // filename nullptr, // filename
false, // experimental false, // experimental
false, // inconclusive false, // inconclusive
true, // runSimpleChecks true, // runSimpleChecks
false, // verbose
&settings); &settings);
} }
void checkInterlockedDecrement(const char code[]) { void checkInterlockedDecrement(const char code[]) {
static Settings settings; static Settings settings;
settings.platformType = Settings::Win32A; settings.platformType = Settings::Win32A;
check(code, nullptr, false, false, true, &settings); check(code, nullptr, false, false, true, false, &settings);
} }
void emptyBrackets() { void emptyBrackets() {
check("{\n" check("{\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void zeroDiv1() { // floating point division by zero => no error void zeroDiv1() { // floating point division by zero => no error
check("void foo() {\n" check("void foo() {\n"
skipping to change at line 560 skipping to change at line 563
" if (x != 0) {}\n" " if (x != 0) {}\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condit ion 'x!=0' is redundant or there is division by zero at line 2.\n", errout.str() ); ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condit ion 'x!=0' is redundant or there is division by zero at line 2.\n", errout.str() );
// function call // function call
check("void f1(int x, int y) { c=x/y; }\n" check("void f1(int x, int y) { c=x/y; }\n"
"void f2(unsigned int y) {\n" "void f2(unsigned int y) {\n"
" f1(123,y);\n" " f1(123,y);\n"
" if (y>0){}\n" " if (y>0){}\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (warning) Either the condit ion 'y>0' is redundant or there is division by zero at line 1.\n", errout.str()) ; TODO_ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (warning) Either the c ondition 'y>0' is redundant or there is division by zero at line 1.\n", "", erro ut.str());
// avoid false positives when variable is changed after division // avoid false positives when variable is changed after division
check("void f() {\n" check("void f() {\n"
" unsigned int x = do_something();\n" " unsigned int x = do_something();\n"
" int y = 17 / x;\n" " int y = 17 / x;\n"
" x = some+calculation;\n" " x = some+calculation;\n"
" if (x != 0) {}\n" " if (x != 0) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
skipping to change at line 649 skipping to change at line 652
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void nanInArithmeticExpression() { void nanInArithmeticExpression() {
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" double x = 3.0 / 0.0 + 1.0;\n" " double x = 3.0 / 0.0 + 1.0;\n"
" printf(\"%f\", x);\n" " printf(\"%f\", x);\n"
"}"); "}");
ASSERT_EQUALS( ASSERT_EQUALS("[test.cpp:3]: (style) Using NaN/Inf in a computation.\n",
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.st errout.str());
r());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" double x = 3.0 / 0.0 - 1.0;\n" " double x = 3.0 / 0.0 - 1.0;\n"
" printf(\"%f\", x);\n" " printf(\"%f\", x);\n"
"}"); "}");
ASSERT_EQUALS( ASSERT_EQUALS("[test.cpp:3]: (style) Using NaN/Inf in a computation.\n",
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.st errout.str());
r());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" double x = 1.0 + 3.0 / 0.0;\n" " double x = 1.0 + 3.0 / 0.0;\n"
" printf(\"%f\", x);\n" " printf(\"%f\", x);\n"
"}"); "}");
ASSERT_EQUALS( ASSERT_EQUALS("[test.cpp:3]: (style) Using NaN/Inf in a computation.\n",
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.st errout.str());
r());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" double x = 1.0 - 3.0 / 0.0;\n" " double x = 1.0 - 3.0 / 0.0;\n"
" printf(\"%f\", x);\n" " printf(\"%f\", x);\n"
"}"); "}");
ASSERT_EQUALS( ASSERT_EQUALS("[test.cpp:3]: (style) Using NaN/Inf in a computation.\n",
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.st errout.str());
r());
check("void f()\n" check("void f()\n"
"{\n" "{\n"
" double x = 3.0 / 0.0;\n" " double x = 3.0 / 0.0;\n"
" printf(\"%f\", x);\n" " printf(\"%f\", x);\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
skipping to change at line 2281 skipping to change at line 2280
" {\n" " {\n"
" case 2:\n" " case 2:\n"
" y++;\n" " y++;\n"
" bar();\n" " bar();\n"
" case 3:\n" " case 3:\n"
" y = 3;\n" " y = 3;\n"
" }\n" " }\n"
" bar(y);\n" " bar(y);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:10]: (warning) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errou t.str()); ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:10]: (warning) Variable 'y' is reassigned a value before the old one has been used. 'break;' missing?\n", errou t.str());
check("bool f() {\n"
" bool ret = false;\n"
" switch (switchCond) {\n"
" case 1:\n"
" ret = true;\n"
" break;\n"
" case 31:\n"
" ret = true;\n"
" break;\n"
" case 54:\n"
" ret = true;\n"
" break;\n"
" };\n"
" ret = true;\n"
" return ret;\n"
"}");
ASSERT_EQUALS("[test.cpp:5] -> [test.cpp:14]: (style) Variable 'ret' is
reassigned a value before the old one has been used.\n"
"[test.cpp:8] -> [test.cpp:14]: (style) Variable 'ret' is
reassigned a value before the old one has been used.\n"
"[test.cpp:11] -> [test.cpp:14]: (style) Variable 'ret' is
reassigned a value before the old one has been used.\n",
errout.str());
} }
void switchRedundantBitwiseOperationTest() { void switchRedundantBitwiseOperationTest() {
check("void foo(int a)\n" check("void foo(int a)\n"
"{\n" "{\n"
" int y = 1;\n" " int y = 1;\n"
" switch (a)\n" " switch (a)\n"
" {\n" " {\n"
" case 2:\n" " case 2:\n"
" y |= 3;\n" " y |= 3;\n"
skipping to change at line 2488 skipping to change at line 2508
" goto A;\n" " goto A;\n"
"}", nullptr, false, false, false); "}", nullptr, false, false, false);
ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue , goto or throw statements are unnecessary.\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue , goto or throw statements are unnecessary.\n", errout.str());
Settings settings; Settings settings;
settings.library.setnoreturn("exit", true); settings.library.setnoreturn("exit", true);
settings.library.functions["exit"].argumentChecks[1] = Library::Argument Checks(); settings.library.functions["exit"].argumentChecks[1] = Library::Argument Checks();
check("void foo() {\n" check("void foo() {\n"
" exit(0);\n" " exit(0);\n"
" break;\n" " break;\n"
"}", nullptr, false, false, false, &settings); "}", nullptr, false, false, false, false, &settings);
ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue , goto or throw statements are unnecessary.\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) Consecutive return, break, continue , goto or throw statements are unnecessary.\n", errout.str());
check("class NeonSession {\n" check("class NeonSession {\n"
" void exit();\n" " void exit();\n"
"};\n" "};\n"
"void NeonSession::exit()\n" "void NeonSession::exit()\n"
"{\n" "{\n"
" SAL_INFO(\"ucb.ucp.webdav\", \"neon commands cannot be aborte d\");\n" " SAL_INFO(\"ucb.ucp.webdav\", \"neon commands cannot be aborte d\");\n"
"}", nullptr, false, false, false, &settings); "}", nullptr, false, false, false, false, &settings);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void NeonSession::exit()\n" check("void NeonSession::exit()\n"
"{\n" "{\n"
" SAL_INFO(\"ucb.ucp.webdav\", \"neon commands cannot be aborte d\");\n" " SAL_INFO(\"ucb.ucp.webdav\", \"neon commands cannot be aborte d\");\n"
"}", nullptr, false, false, false, &settings); "}", nullptr, false, false, false, false, &settings);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void foo() { xResAccess->exit(); }", nullptr, false, false, false , &settings); check("void foo() { xResAccess->exit(); }", nullptr, false, false, false , false, &settings);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void foo(int a)\n" check("void foo(int a)\n"
"{\n" "{\n"
" switch(a) {\n" " switch(a) {\n"
" case 0:\n" " case 0:\n"
" printf(\"case 0\");\n" " printf(\"case 0\");\n"
" break;\n" " break;\n"
" break;\n" " break;\n"
" case 1:\n" " case 1:\n"
skipping to change at line 2659 skipping to change at line 2679
"}", nullptr, false, false, false); "}", nullptr, false, false, false);
ASSERT_EQUALS("[test.cpp:7]: (style) Statements following return, break, continue, goto or throw will never be executed.\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (style) Statements following return, break, continue, goto or throw will never be executed.\n", errout.str());
check("int foo() {\n" check("int foo() {\n"
" return 0;\n" " return 0;\n"
" label:\n" " label:\n"
" throw 0;\n" " throw 0;\n"
"}", nullptr, false, false, false); "}", nullptr, false, false, false);
ASSERT_EQUALS("[test.cpp:3]: (style) Label 'label' is not used.\n", erro ut.str()); ASSERT_EQUALS("[test.cpp:3]: (style) Label 'label' is not used.\n", erro ut.str());
check("void foo() {\n"
" wxCHECK2(state < 3 && state >= 0, return);\n"
" _checkboxState = state;\n"
"}");
ASSERT_EQUALS("", errout.str());
check("struct A {\n" check("struct A {\n"
" virtual void foo (P & Val) throw ();\n" " virtual void foo (P & Val) throw ();\n"
" virtual void foo1 (P & Val) throw ();\n" " virtual void foo1 (P & Val) throw ();\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("int foo() {\n" check("int foo() {\n"
" goto label;\n" " goto label;\n"
" while (true) {\n" " while (true) {\n"
" bar();\n" " bar();\n"
skipping to change at line 2755 skipping to change at line 2769
" uint64_t enter, exit;\n" " uint64_t enter, exit;\n"
" uint64_t events;\n" " uint64_t events;\n"
" per_state_info() : enter(0), exit(0), events(0) {}\n" " per_state_info() : enter(0), exit(0), events(0) {}\n"
"};", nullptr, false, false, false); "};", nullptr, false, false, false);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// #6664 // #6664
check("void foo() {\n" check("void foo() {\n"
" (beat < 100) ? (void)0 : exit(0);\n" " (beat < 100) ? (void)0 : exit(0);\n"
" bar();\n" " bar();\n"
"}", nullptr, false, false, false, &settings); "}", nullptr, false, false, false, false, &settings);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void foo() {\n" check("void foo() {\n"
" (beat < 100) ? exit(0) : (void)0;\n" " (beat < 100) ? exit(0) : (void)0;\n"
" bar();\n" " bar();\n"
"}", nullptr, false, false, false, &settings); "}", nullptr, false, false, false, false, &settings);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// #8261 // #8261
check("void foo() {\n" check("void foo() {\n"
" (beat < 100) ? (void)0 : throw(0);\n" " (beat < 100) ? (void)0 : throw(0);\n"
" bar();\n" " bar();\n"
"}", nullptr, false, false, false, &settings); "}", nullptr, false, false, false, false, &settings);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void suspiciousCase() { void suspiciousCase() {
check("void foo() {\n" check("void foo() {\n"
" switch(a) {\n" " switch(a) {\n"
" case A&&B:\n" " case A&&B:\n"
" foo();\n" " foo();\n"
" case (A||B):\n" " case (A||B):\n"
" foo();\n" " foo();\n"
skipping to change at line 3676 skipping to change at line 3690
check("int f() { return !!y; }"); // No FP check("int f() { return !!y; }"); // No FP
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// make sure there are not "same expression" fp when there are different casts // make sure there are not "same expression" fp when there are different casts
check("void f(long x) { if ((int32_t)x == (int64_t)x) {} }", check("void f(long x) { if ((int32_t)x == (int64_t)x) {} }",
nullptr, // filename nullptr, // filename
false, // experimental false, // experimental
false, // inconclusive false, // inconclusive
false, // runSimpleChecks false, // runSimpleChecks
false, // verbose
nullptr // settings nullptr // settings
); );
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// make sure there are not "same expression" fp when there are different ({}) expressions // make sure there are not "same expression" fp when there are different ({}) expressions
check("void f(long x) { if (({ 1+2; }) == ({3+4;})) {} }"); check("void f(long x) { if (({ 1+2; }) == ({3+4;})) {} }");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// #5535: Reference named like its type // #5535: Reference named like its type
check("void foo() { UMSConfig& UMSConfig = GetUMSConfiguration(); }"); check("void foo() { UMSConfig& UMSConfig = GetUMSConfiguration(); }");
skipping to change at line 3864 skipping to change at line 3879
check("class D { void strcmp(); };\n" check("class D { void strcmp(); };\n"
"void foo() {\n" "void foo() {\n"
" D d;\n" " D d;\n"
" if (d.strcmp() && d.strcmp()) {}\n" " if (d.strcmp() && d.strcmp()) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void foo() {\n" check("void foo() {\n"
" if ((mystrcmp(a, b) == 0) || (mystrcmp(a, b) == 0)) {}\n" " if ((mystrcmp(a, b) == 0) || (mystrcmp(a, b) == 0)) {}\n"
"}", "test.cpp", false, false, true, &settings); "}", "test.cpp", false, false, true, false, &settings);
ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '| |'.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '| |'.\n", errout.str());
check("void GetValue() { return rand(); }\n" check("void GetValue() { return rand(); }\n"
"void foo() {\n" "void foo() {\n"
" if ((GetValue() == 0) || (GetValue() == 0)) { dostuff(); }\n" " if ((GetValue() == 0) || (GetValue() == 0)) { dostuff(); }\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("void __attribute__((const)) GetValue() { return X; }\n" check("void __attribute__((const)) GetValue() { return X; }\n"
"void foo() {\n" "void foo() {\n"
skipping to change at line 4061 skipping to change at line 4076
" a++;\n" " a++;\n"
" }\n" " }\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("bool f(bool a, bool b) {\n" check("bool f(bool a, bool b) {\n"
" const bool c = a;\n" " const bool c = a;\n"
" return a && b && c;\n" " return a && b && c;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Same expression on both sides of '&&' because 'a' and 'c' represent the same value.\n", errout.str( )); ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Same expression on both sides of '&&' because 'a' and 'c' represent the same value.\n", errout.str( ));
// 6906
check("void f(const bool b) {\n"
" const bool b1 = !b;\n"
" if(!b && b1){}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Same expression on
both sides of '&&' because '!b' and 'b1' represent the same value.\n", errout.st
r());
// 7284
check("void f(void) {\n"
" if (a || !!a) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2]: (style) Same expression on both sides of '|
|' because 'a' and '!!a' represent the same value.\n", errout.str());
// 8205
check("void f(int x) {\n"
" int Diag = 0;\n"
" switch (x) {\n"
" case 12:\n"
" if (Diag==0) {}\n"
" break;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:5]: (style) The expression 'Dia
g == 0' is always true.\n", errout.str());
} }
void duplicateExpression8() { void duplicateExpression8() {
check("void f() {\n" check("void f() {\n"
" int a = 1;\n" " int a = 1;\n"
" int b = a;\n" " int b = a;\n"
" a = 2;\n" " a = 2;\n"
" if ( b != a){}\n" " if ( b != a){}\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
skipping to change at line 4732 skipping to change at line 4771
check("void f() {\n" check("void f() {\n"
" int activate = 0;\n" " int activate = 0;\n"
" int foo = 0;\n" " int foo = 0;\n"
" if (activate) {}\n" " if (activate) {}\n"
" else if (foo) {}\n" " else if (foo) {}\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void checkSignOfUnsignedVariable() { void checkSignOfUnsignedVariable() {
check( check("void foo() {\n"
"void foo() {\n" " for(unsigned char i = 10; i >= 0; i--) {}\n"
" for(unsigned char i = 10; i >= 0; i--)" "}");
" printf(\"%u\", i);\n" ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'i' can't be ne
"}"); gative so it is unnecessary to test it.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned variable 'i' can't be nega
tive so it is unnecessary to test it.\n", errout.str()); check("void foo(bool b) {\n"
" for(unsigned int i = 10; b || i >= 0; i--) {}\n"
check( "}");
"void foo(bool b) {\n" ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'i' can't be ne
" for(unsigned int i = 10; b || i >= 0; i--)" gative so it is unnecessary to test it.\n", errout.str());
" printf(\"%u\", i);\n"
"}"); {
ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned variable 'i' can't be nega const char code[] = "void foo(unsigned int x) {\n"
tive so it is unnecessary to test it.\n", errout.str()); " if (x < 0) {}\n"
"}";
check( check(code, nullptr, false, false, true, false);
"bool foo(unsigned int x) {\n" ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression
" if (x < 0)" 'x' is less than zero.\n", errout.str());
" return true;\n" check(code, nullptr, false, false, true, true);
" return false;\n" ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression
"}"); 'x' is less than zero.\n", errout.str());
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned variable 'x' i }
s less than zero.\n", errout.str());
check("void foo(unsigned int x) {\n"
check( " if (x < 0u) {}\n"
"bool foo(int x) {\n" "}");
" if (x < 0)" ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
" return true;\n" is less than zero.\n", errout.str());
" return false;\n"
"}"); check("void foo(int x) {\n"
ASSERT_EQUALS("", errout.str()); " if (x < 0) {}\n"
"}");
check( ASSERT_EQUALS("", errout.str());
"bool foo(unsigned int x) {\n"
" if (0 > x)" {
" return true;\n" const char code[] = "void foo(unsigned x) {\n"
" return false;\n" " int y = 0;\n"
"}"); " if (x < y) {}\n"
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned variable 'x' i "}";
s less than zero.\n", errout.str()); check(code, nullptr, false, false, true, false);
ASSERT_EQUALS("[test.cpp:3]: (style) Checking if unsigned expression
check( 'x' is less than zero.\n", errout.str());
"bool foo(int x) {\n" check(code, nullptr, false, false, true, true);
" if (0 > x)" ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) Checking if uns
" return true;\n" igned expression 'x' is less than zero.\n", errout.str());
" return false;\n" }
"}"); check("void foo(unsigned x) {\n"
ASSERT_EQUALS("", errout.str()); " int y = 0;\n"
" if (b)\n"
check( " y = 1;\n"
"bool foo(unsigned int x) {\n" " if (x < y) {}\n"
" if (x >= 0)" "}");
" return true;\n" ASSERT_EQUALS("", errout.str());
" return false;\n"
"}"); check("void foo(unsigned int x) {\n"
ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned variable 'x' can't be nega " if (0 > x) {}\n"
tive so it is unnecessary to test it.\n", errout.str()); "}");
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
check( is less than zero.\n", errout.str());
"bool foo(int x) {\n"
" if (x >= 0)" check("void foo(unsigned int x) {\n"
" return true;\n" " if (0UL > x) {}\n"
" return false;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
ASSERT_EQUALS("", errout.str()); is less than zero.\n", errout.str());
check( check("void foo(int x) {\n"
"bool foo(unsigned int x, bool y) {\n" " if (0 > x) {}\n"
" if (x < 0 && y)" "}");
" return true;\n" ASSERT_EQUALS("", errout.str());
" return false;\n"
"}"); check("void foo(unsigned int x) {\n"
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned variable 'x' i " if (x >= 0) {}\n"
s less than zero.\n", errout.str()); "}");
ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be ne
check( gative so it is unnecessary to test it.\n", errout.str());
"bool foo(int x, bool y) {\n"
" if (x < 0 && y)" check("void foo(unsigned int x, unsigned y) {\n"
" return true;\n" " if (x - y >= 0) {}\n"
" return false;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x-y' can't be
ASSERT_EQUALS("", errout.str()); negative so it is unnecessary to test it.\n", errout.str());
check( check("void foo(unsigned int x) {\n"
"bool foo(unsigned int x, bool y) {\n" " if (x >= 0ull) {}\n"
" if (0 > x && y)" "}");
" return true;\n" ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be ne
" return false;\n" gative so it is unnecessary to test it.\n", errout.str());
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned variable 'x' i check("void foo(int x) {\n"
s less than zero.\n", errout.str()); " if (x >= 0) {}\n"
"}");
check( ASSERT_EQUALS("", errout.str());
"bool foo(int x, bool y) {\n"
" if (0 > x && y)" check("void foo(unsigned int x) {\n"
" return true;\n" " if (0 <= x) {}\n"
" return false;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be ne
ASSERT_EQUALS("", errout.str()); gative so it is unnecessary to test it.\n", errout.str());
check( check("void foo(unsigned int x) {\n"
"bool foo(unsigned int x, bool y) {\n" " if (0ll <= x) {}\n"
" if (x >= 0 && y)" "}");
" return true;\n" ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be ne
" return false;\n" gative so it is unnecessary to test it.\n", errout.str());
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned variable 'x' can't be nega check("void foo(int x) {\n"
tive so it is unnecessary to test it.\n", errout.str()); " if (0 <= x) {}\n"
"}");
check( ASSERT_EQUALS("", errout.str());
"bool foo(int x, bool y) {\n"
" if (x >= 0 && y)" check("void foo(unsigned int x, bool y) {\n"
" return true;\n" " if (x < 0 && y) {}\n"
" return false;\n" "}");
"}"); ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
ASSERT_EQUALS("", errout.str()); is less than zero.\n", errout.str());
check( check("void foo(int x, bool y) {\n"
"bool foo(unsigned int x, bool y) {\n" " if (x < 0 && y) {}\n"
" if (y && x < 0)" "}");
" return true;\n" ASSERT_EQUALS("", errout.str());
" return false;\n"
"}"); check("void foo(unsigned int x, bool y) {\n"
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned variable 'x' i " if (0 > x && y) {}\n"
s less than zero.\n", errout.str()); "}");
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
check( is less than zero.\n", errout.str());
"bool foo(int x, bool y) {\n"
" if (y && x < 0)" check("void foo(int x, bool y) {\n"
" return true;\n" " if (0 > x && y) {}\n"
" return false;\n" "}");
"}"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
check("void foo(unsigned int x, bool y) {\n"
check( " if (x >= 0 && y) {}\n"
"bool foo(unsigned int x, bool y) {\n" "}");
" if (y && 0 > x)" ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be ne
" return true;\n" gative so it is unnecessary to test it.\n", errout.str());
" return false;\n"
"}"); check("void foo(int x, bool y) {\n"
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned variable 'x' i " if (x >= 0 && y) {}\n"
s less than zero.\n", errout.str()); "}");
ASSERT_EQUALS("", errout.str());
check(
"bool foo(int x, bool y) {\n" check("void foo(unsigned int x, bool y) {\n"
" if (y && 0 > x)" " if (y && x < 0) {}\n"
" return true;\n" "}");
" return false;\n" ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
"}"); is less than zero.\n", errout.str());
ASSERT_EQUALS("", errout.str());
check("void foo(int x, bool y) {\n"
check( " if (y && x < 0) {}\n"
"bool foo(unsigned int x, bool y) {\n" "}");
" if (y && x >= 0)" ASSERT_EQUALS("", errout.str());
" return true;\n"
" return false;\n" check("void foo(unsigned int x, bool y) {\n"
"}"); " if (y && 0 > x) {}\n"
ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned variable 'x' can't be nega "}");
tive so it is unnecessary to test it.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
is less than zero.\n", errout.str());
check(
"bool foo(int x, bool y) {\n" check("void foo(int x, bool y) {\n"
" if (y && x >= 0)" " if (y && 0 > x) {}\n"
" return true;\n" "}");
" return false;\n" ASSERT_EQUALS("", errout.str());
"}");
ASSERT_EQUALS("", errout.str()); check("void foo(unsigned int x, bool y) {\n"
" if (y && x >= 0) {}\n"
check( "}");
"bool foo(unsigned int x, bool y) {\n" ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be ne
" if (x < 0 || y)" gative so it is unnecessary to test it.\n", errout.str());
" return true;\n"
" return false;\n" check("void foo(int x, bool y) {\n"
"}"); " if (y && x >= 0) {}\n"
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned variable 'x' i "}");
s less than zero.\n", errout.str()); ASSERT_EQUALS("", errout.str());
check( check("void foo(unsigned int x, bool y) {\n"
"bool foo(int x, bool y) {\n" " if (x < 0 || y) {}\n"
" if (x < 0 || y)" "}");
" return true;\n" ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
" return false;\n" is less than zero.\n", errout.str());
"}");
ASSERT_EQUALS("", errout.str()); check("void foo(int x, bool y) {\n"
" if (x < 0 || y) {}\n"
check( "}");
"bool foo(unsigned int x, bool y) {\n" ASSERT_EQUALS("", errout.str());
" if (0 > x || y)"
" return true;\n" check("void foo(unsigned int x, bool y) {\n"
" return false;\n" " if (0 > x || y) {}\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned variable 'x' i ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
s less than zero.\n", errout.str()); is less than zero.\n", errout.str());
check( check("void foo(int x, bool y) {\n"
"bool foo(int x, bool y) {\n" " if (0 > x || y) {}\n"
" if (0 > x || y)" "}");
" return true;\n" ASSERT_EQUALS("", errout.str());
" return false;\n"
"}"); check("void foo(unsigned int x, bool y) {\n"
ASSERT_EQUALS("", errout.str()); " if (x >= 0 || y) {}\n"
"}");
check( ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned expression 'x' can't be ne
"bool foo(unsigned int x, bool y) {\n" gative so it is unnecessary to test it.\n", errout.str());
" if (x >= 0 || y)"
" return true;\n" check("void foo(int x, bool y) {\n"
" return false;\n" " if (x >= 0 || y) {}\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (style) Unsigned variable 'x' can't be nega
tive so it is unnecessary to test it.\n", errout.str());
check(
"bool foo(int x, bool y) {\n"
" if (x >= 0 || y)"
" return true;\n"
" return false;\n"
"}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// #3233 - FP when template is used (template parameter is numeric const ant) // #3233 - FP when template is used (template parameter is numeric const ant)
{ {
const char code[] = const char code[] = "template<int n> void foo(unsigned int x) {\n"
"template<int n> void foo(unsigned int x) {\n" " if (x <= n);\n"
" if (x <= n);\n" "}\n"
"}\n" "foo<0>();";
"foo<0>();";
check(code, nullptr, false, false); check(code, nullptr, false, false);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check(code, nullptr, false, true); check(code, nullptr, false, true);
ASSERT_EQUALS("[test.cpp:2]: (style, inconclusive) Checking if unsig ned variable 'x' is less than zero. This might be a false warning.\n", errout.st r()); ASSERT_EQUALS("", errout.str());
} }
check("template<int n> void foo(unsigned int x) {\n"
"if (x <= 0);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:2]: (style) Checking if unsigned expression 'x'
is less than zero.\n", errout.str());
// #8836
check("uint32_t value = 0xFUL;\n"
"void f() {\n"
" if (value < 0u)\n"
" {\n"
" value = 0u;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Checking if unsigned expression 'va
lue' is less than zero.\n", errout.str());
} }
void checkSignOfPointer() { void checkSignOfPointer() {
check( check("void foo(int* x) {\n"
"bool foo(int* x) {\n" " if (x >= 0) {}\n"
" if (x >= 0)" "}");
" bar();\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str());
check( {
"bool foo(int* x) {\n" const char code[] = "void foo(int* x) {\n"
" if (*x >= 0)" " int y = 0;\n"
" bar();\n" " if (x >= y) {}\n"
"}"); "}";
check(code, nullptr, false, false, true, false);
ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative s
o it is either pointless or an error to check if it is not.\n", errout.str());
check(code, nullptr, false, false, true, true);
ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) A pointer can n
ot be negative so it is either pointless or an error to check if it is not.\n",
errout.str());
}
check("void foo(int* x) {\n"
" if (*x >= 0) {}\n"
"}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check( check("void foo(int* x) {\n"
"bool foo(int* x) {\n" " if (x < 0) {}\n"
" if (x < 0)" "}");
" bar();\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str());
check( {
"bool foo(int* x) {\n" const char code[] = "void foo(int* x) {\n"
" if (*x < 0)" " unsigned y = 0u;\n"
" bar();\n" " if (x < y) {}\n"
"}"); "}";
ASSERT_EQUALS("", errout.str());
check(code, nullptr, false, false, true, false);
check( ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative s
"bool foo(int* x, int* y) {\n" o it is either pointless or an error to check if it is.\n", errout.str());
" if (x - y < 0)" check(code, nullptr, false, false, true, true);
" bar();\n" ASSERT_EQUALS("[test.cpp:2] -> [test.cpp:3]: (style) A pointer can n
"}"); ot be negative so it is either pointless or an error to check if it is.\n", erro
ASSERT_EQUALS("", errout.str()); ut.str());
}
check(
"bool foo(int* x, int* y) {\n" check("void foo(int* x) {\n"
" if (x - y <= 0)" " if (*x < 0) {}\n"
" bar();\n" "}");
"}"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
check("void foo(int* x, int* y) {\n"
check( " if (x - y < 0) {}\n"
"bool foo(int* x, int* y) {\n" "}");
" if (x - y > 0)" ASSERT_EQUALS("", errout.str());
" bar();\n"
"}"); check("void foo(int* x, int* y) {\n"
ASSERT_EQUALS("", errout.str()); " if (x - y <= 0) {}\n"
"}");
check( ASSERT_EQUALS("", errout.str());
"bool foo(int* x, int* y) {\n"
" if (x - y >= 0)" check("void foo(int* x, int* y) {\n"
" bar();\n" " if (x - y > 0) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check( check("void foo(int* x, int* y) {\n"
"bool foo(Bar* x) {\n" " if (x - y >= 0) {}\n"
" if (0 <= x)" "}");
" bar();\n" ASSERT_EQUALS("", errout.str());
"}");
check("void foo(Bar* x) {\n"
" if (0 <= x) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str());
check( check("struct S {\n"
"struct S {\n" " int* ptr;\n"
" int* ptr;\n" "};\n"
"};\n" "void foo(S* first) {\n"
"void foo(S* first) {\n" " if (first.ptr >= 0) {} \n"
" if (first.ptr >= 0) {} \n" "}");
"}");
ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str());
check( check("struct S {\n"
"struct S {\n" " int* ptr;\n"
" int* ptr;\n" "};\n"
"};\n" "void foo(S* first, S* second) {\n"
"void foo(S* first, S* second) {\n" " if((first.ptr - second.ptr) >= 0) {} \n"
" if((first.ptr - second.ptr) >= 0) {} \n" "}");
"}"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
check("struct S {\n"
check( " int* ptr;\n"
"struct S {\n" "};\n"
" int* ptr;\n" "void foo(S* first) {\n"
"};\n" " if((first.ptr) >= 0) {} \n"
"void foo(S* first) {\n" "}");
" if((first.ptr) >= 0) {} \n"
"}");
ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str()); ASSERT_EQUALS("[test.cpp:5]: (style) A pointer can not be negative so it is either pointless or an error to check if it is not.\n", errout.str());
check( check("struct S {\n"
"struct S {\n" " int* ptr;\n"
" int* ptr;\n" "};\n"
"};\n" "void foo(S* first, S* second) {\n"
"void foo(S* first, S* second) {\n" " if(0 <= first.ptr - second.ptr) {} \n"
" if(0 <= first.ptr - second.ptr) {} \n" "}");
"}"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
check("struct S {\n"
check( " int* ptr;\n"
"struct S {\n" "};\n"
" int* ptr;\n" "void foo(S* first, S* second) {\n"
"};\n" " if(0 <= (first.ptr - second.ptr)) {} \n"
"void foo(S* first, S* second) {\n" "}");
" if(0 <= (first.ptr - second.ptr)) {} \n" ASSERT_EQUALS("", errout.str());
"}");
ASSERT_EQUALS("", errout.str()); check("struct S {\n"
" int* ptr;\n"
check( "};\n"
"struct S {\n" "void foo(S* first, S* second) {\n"
" int* ptr;\n" " if(first.ptr - second.ptr < 0) {} \n"
"};\n" "}");
"void foo(S* first, S* second) {\n" ASSERT_EQUALS("", errout.str());
" if(first.ptr - second.ptr < 0) {} \n"
"}"); check("struct S {\n"
ASSERT_EQUALS("", errout.str()); " int* ptr;\n"
"};\n"
check( "void foo(S* first, S* second) {\n"
"struct S {\n" " if((first.ptr - second.ptr) < 0) {} \n"
" int* ptr;\n" "}");
"};\n" ASSERT_EQUALS("", errout.str());
"void foo(S* first, S* second) {\n"
" if((first.ptr - second.ptr) < 0) {} \n" check("struct S {\n"
"}"); " int* ptr;\n"
ASSERT_EQUALS("", errout.str()); "};\n"
"void foo(S* first, S* second) {\n"
check( " if(0 > first.ptr - second.ptr) {} \n"
"struct S {\n" "}");
" int* ptr;\n" ASSERT_EQUALS("", errout.str());
"};\n"
"void foo(S* first, S* second) {\n" check("struct S {\n"
" if(0 > first.ptr - second.ptr) {} \n" " int* ptr;\n"
"}"); "};\n"
ASSERT_EQUALS("", errout.str()); "void foo(S* first, S* second) {\n"
" if(0 > (first.ptr - second.ptr)) {} \n"
check( "}");
"struct S {\n" ASSERT_EQUALS("", errout.str());
" int* ptr;\n"
"};\n" check("void foo(int* x) {\n"
"void foo(S* first, S* second) {\n" " if (0 <= x[0]) {}\n"
" if(0 > (first.ptr - second.ptr)) {} \n" "}");
"}"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
check("void foo(Bar* x) {\n"
check( " if (0 <= x.y) {}\n"
"bool foo(int* x) {\n" "}");
" if (0 <= x[0])" ASSERT_EQUALS("", errout.str());
" bar();\n"
"}"); check("void foo(Bar* x) {\n"
ASSERT_EQUALS("", errout.str()); " if (0 <= x->y) {}\n"
"}");
check( ASSERT_EQUALS("", errout.str());
"bool foo(Bar* x) {\n"
" if (0 <= x.y)" check("void foo(Bar* x, Bar* y) {\n"
" bar();\n" " if (0 <= x->y - y->y ) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check( check("void foo(Bar* x) {\n"
"bool foo(Bar* x) {\n" " if (0 > x) {}\n"
" if (0 <= x->y)" "}");
" bar();\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
"bool foo(Bar* x, Bar* y) {\n"
" if (0 <= x->y - y->y )"
" bar();\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
"bool foo(Bar* x) {\n"
" if (0 > x)"
" bar();\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str());
check( check("void foo(int* x) {\n"
"bool foo(int* x) {\n" " if (0 > x[0]) {}\n"
" if (0 > x[0])" "}");
" bar();\n" ASSERT_EQUALS("", errout.str());
"}");
ASSERT_EQUALS("", errout.str()); check("void foo(Bar* x) {\n"
" if (0 > x.y) {}\n"
check( "}");
"bool foo(Bar* x) {\n" ASSERT_EQUALS("", errout.str());
" if (0 > x.y)"
" bar();\n" check("void foo(Bar* x) {\n"
"}"); " if (0 > x->y) {}\n"
ASSERT_EQUALS("", errout.str()); "}");
ASSERT_EQUALS("", errout.str());
check(
"bool foo(Bar* x) {\n" check("void foo() {\n"
" if (0 > x->y)" " int (*t)(void *a, void *b);\n"
" bar();\n" " if (t(a, b) < 0) {}\n"
"}"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check( check("void foo() {\n"
"void foo() {\n" " int (*t)(void *a, void *b);\n"
" int (*t)(void *a, void *b);\n" " if (0 > t(a, b)) {}\n"
" if (t(a, b) < 0)\n" "}");
" bar();\n" ASSERT_EQUALS("", errout.str());
"}");
ASSERT_EQUALS("", errout.str()); check("struct object_info { int *typep; };\n"
"void packed_object_info(struct object_info *oi) {\n"
check( " if (oi->typep < 0);\n"
"void foo() {\n" "}");
" int (*t)(void *a, void *b);\n"
" if (0 > t(a, b))\n"
" bar();\n"
"}");
ASSERT_EQUALS("", errout.str());
check(
"struct object_info { int *typep; };\n"
"void packed_object_info(struct object_info *oi) {\n"
" if (oi->typep < 0);\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str());
check( check("struct object_info { int typep[10]; };\n"
"struct object_info { int typep[10]; };\n" "void packed_object_info(struct object_info *oi) {\n"
"void packed_object_info(struct object_info *oi) {\n" " if (oi->typep < 0);\n"
" if (oi->typep < 0);\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) A pointer can not be negative so it is either pointless or an error to check if it is.\n", errout.str());
check( check("struct object_info { int *typep; };\n"
"struct object_info { int *typep; };\n" "void packed_object_info(struct object_info *oi) {\n"
"void packed_object_info(struct object_info *oi) {\n" " if (*oi->typep < 0);\n"
" if (*oi->typep < 0);\n" "}");
"}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void checkForSuspiciousSemicolon1() { void checkForSuspiciousSemicolon1() {
check( check("void foo() {\n"
"void foo() {\n" " for(int i = 0; i < 10; ++i);\n"
" for(int i = 0; i < 10; ++i);\n" "}");
"}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// Empty block // Empty block
check( check("void foo() {\n"
"void foo() {\n" " for(int i = 0; i < 10; ++i); {\n"
" for(int i = 0; i < 10; ++i); {\n" " }\n"
" }\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Suspicious use of ; at the end of 'for' statement.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Suspicious use of ; at the end of 'for' statement.\n", errout.str());
check( check("void foo() {\n"
"void foo() {\n" " while (!quit); {\n"
" while (!quit); {\n" " do_something();\n"
" do_something();\n" " }\n"
" }\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Suspicious use of ; at the end of 'while' statement.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Suspicious use of ; at the end of 'while' statement.\n", errout.str());
} }
void checkForSuspiciousSemicolon2() { void checkForSuspiciousSemicolon2() {
check( check("void foo() {\n"
"void foo() {\n" " if (i == 1); {\n"
" if (i == 1); {\n" " do_something();\n"
" do_something();\n" " }\n"
" }\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Suspicious use of ; at the end of 'if' statement.\n", errout.str()); ASSERT_EQUALS("[test.cpp:2]: (warning, inconclusive) Suspicious use of ; at the end of 'if' statement.\n", errout.str());
// Seen this in the wild // Seen this in the wild
check( check("void foo() {\n"
"void foo() {\n" " if (Match());\n"
" if (Match());\n" " do_something();\n"
" do_something();\n" "}");
"}"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
check("void foo() {\n"
check( " if (Match());\n"
"void foo() {\n" " else\n"
" if (Match());\n" " do_something();\n"
" else\n" "}");
" do_something();\n" ASSERT_EQUALS("", errout.str());
"}");
ASSERT_EQUALS("", errout.str()); check("void foo() {\n"
" if (i == 1)\n"
check( " ;\n"
"void foo() {\n" " {\n"
" if (i == 1)\n" " do_something();\n"
" ;\n" " }\n"
" {\n" "}");
" do_something();\n" ASSERT_EQUALS("", errout.str());
" }\n"
"}"); check("void foo() {\n"
ASSERT_EQUALS("", errout.str()); " if (i == 1);\n"
"\n"
check( " {\n"
"void foo() {\n" " do_something();\n"
" if (i == 1);\n" " }\n"
"\n" "}");
" {\n"
" do_something();\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void checkInvalidFree() { void checkInvalidFree() {
check( check("void foo(char *p) {\n"
"void foo(char *p) {\n" " char *a; a = malloc(1024);\n"
" char *a; a = malloc(1024);\n" " free(a + 10);\n"
" free(a + 10);\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str());
check( check("void foo(char *p) {\n"
"void foo(char *p) {\n" " char *a; a = malloc(1024);\n"
" char *a; a = malloc(1024);\n" " free(a - 10);\n"
" free(a - 10);\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str());
check( check("void foo(char *p) {\n"
"void foo(char *p) {\n" " char *a; a = malloc(1024);\n"
" char *a; a = malloc(1024);\n" " free(10 + a);\n"
" free(10 + a);\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str());
check( check("void foo(char *p) {\n"
"void foo(char *p) {\n" " char *a; a = new char[1024];\n"
" char *a; a = new char[1024];\n" " delete[] (a + 10);\n"
" delete[] (a + 10);\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str());
check( check("void foo(char *p) {\n"
"void foo(char *p) {\n" " char *a; a = new char;\n"
" char *a; a = new char;\n" " delete a + 10;\n"
" delete a + 10;\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Invalid memory address freed.\n", e rrout.str());
check( check("void foo(char *p) {\n"
"void foo(char *p) {\n" " char *a; a = new char;\n"
" char *a; a = new char;\n" " bar(a);\n"
" bar(a);\n" " delete a + 10;\n"
" delete a + 10;\n" "}");
"}"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
check("void foo(char *p) {\n"
check( " char *a; a = new char;\n"
"void foo(char *p) {\n" " char *b; b = new char;\n"
" char *a; a = new char;\n" " bar(a);\n"
" char *b; b = new char;\n" " delete a + 10;\n"
" bar(a);\n" " delete b + 10;\n"
" delete a + 10;\n" "}");
" delete b + 10;\n"
"}");
ASSERT_EQUALS("[test.cpp:6]: (error) Invalid memory address freed.\n", e rrout.str()); ASSERT_EQUALS("[test.cpp:6]: (error) Invalid memory address freed.\n", e rrout.str());
check( check("void foo(char *p) {\n"
"void foo(char *p) {\n" " char *a; a = new char;\n"
" char *a; a = new char;\n" " char *b; b = new char;\n"
" char *b; b = new char;\n" " bar(a, b);\n"
" bar(a, b);\n" " delete a + 10;\n"
" delete a + 10;\n" " delete b + 10;\n"
" delete b + 10;\n" "}");
"}"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
check("void foo(char *p) {\n"
check( " char *a; a = new char;\n"
"void foo(char *p) {\n" " bar()\n"
" char *a; a = new char;\n" " delete a + 10;\n"
" bar()\n" "}");
" delete a + 10;\n"
"}");
ASSERT_EQUALS("[test.cpp:4]: (error) Invalid memory address freed.\n", e rrout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Invalid memory address freed.\n", e rrout.str());
check( check("void foo(size_t xx) {\n"
"void foo(size_t xx) {\n" " char *ptr; ptr = malloc(42);\n"
" char *ptr; ptr = malloc(42);\n" " ptr += xx;\n"
" ptr += xx;\n" " free(ptr - xx - 1);\n"
" free(ptr - xx - 1);\n" "}");
"}");
ASSERT_EQUALS("[test.cpp:4]: (error, inconclusive) Invalid memory addres s freed.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error, inconclusive) Invalid memory addres s freed.\n", errout.str());
check( check("void foo(size_t xx) {\n"
"void foo(size_t xx) {\n" " char *ptr; ptr = malloc(42);\n"
" char *ptr; ptr = malloc(42);\n" " std::cout << ptr;\n"
" std::cout << ptr;\n" " ptr = otherPtr;\n"
" ptr = otherPtr;\n" " free(otherPtr - xx - 1);\n"
" free(otherPtr - xx - 1);\n" "}");
"}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void checkRedundantCopy() { void checkRedundantCopy() {
check("const std::string& getA(){static std::string a;return a;}\n" check("const std::string& getA(){static std::string a;return a;}\n"
"void foo() {\n" "void foo() {\n"
" const std::string a = getA();\n" " const std::string a = getA();\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Use const refer ence for 'a' to avoid unnecessary data copying.\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (performance, inconclusive) Use const refer ence for 'a' to avoid unnecessary data copying.\n", errout.str());
skipping to change at line 5959 skipping to change at line 5947
// Member variable pointers // Member variable pointers
check("void podMemPtrs() {\n" check("void podMemPtrs() {\n"
" int POD::*memptr;\n" " int POD::*memptr;\n"
" memptr = &POD::a;\n" " memptr = &POD::a;\n"
" memptr = &POD::b;\n" " memptr = &POD::b;\n"
" if (memptr)\n" " if (memptr)\n"
" memptr = 0;\n" " memptr = 0;\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Variable 'memptr' i s reassigned a value before the old one has been used.\n", errout.str()); ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Variable 'memptr' i s reassigned a value before the old one has been used.\n", errout.str());
// issue #8884 // Pointer function argument (#3857)
check("template <class F, class... Ts>\n" check("void f(float * var)\n"
"auto foo(F f, Ts... xs) {\n" "{\n"
" auto x = f(xs...);\n" " var[0] = 0.2f;\n"
" return x;\n" " var[0] = 0.2f;\n" // <-- is initialized twice
"}\n"); "}");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Variable 'var[0]' i
s reassigned a value before the old one has been used.\n", errout.str());
check("void f(float * var)\n"
"{\n"
" *var = 0.2f;\n"
" *var = 0.2f;\n" // <-- is initialized twice
"}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (style) Variable '*var' is
reassigned a value before the old one has been used.\n", errout.str());
} }
void redundantVarAssignment_struct() { void redundantVarAssignment_struct() {
check("struct foo {\n" check("struct foo {\n"
" int a,b;\n" " int a,b;\n"
"};\n" "};\n"
"\n" "\n"
"int main() {\n" "int main() {\n"
" struct foo x;\n" " struct foo x;\n"
" x.a = _mm_set1_ps(1.0);\n" " x.a = _mm_set1_ps(1.0);\n"
" x.a = _mm_set1_ps(2.0);\n" " x.a = _mm_set1_ps(2.0);\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:8]: (style) Variable 'x.a' is r eassigned a value before the old one has been used.\n", errout.str()); ASSERT_EQUALS("[test.cpp:7] -> [test.cpp:8]: (style) Variable 'x.a' is r eassigned a value before the old one has been used.\n", errout.str());
check("void f() {\n"
" struct AB ab;\n"
" ab.x = 23;\n"
" ab.y = 41;\n"
" ab.x = 1;\n"
"}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:5]: (style) Variable 'ab.x' is
reassigned a value before the old one has been used.\n", errout.str());
} }
void redundantVarAssignment_7133() { void redundantVarAssignment_7133() {
// #7133 // #7133
check("sal_Int32 impl_Export() {\n" check("sal_Int32 impl_Export() {\n"
" try {\n" " try {\n"
" try {\n" " try {\n"
" uno::Sequence< uno::Any > aArgs(2);\n" " uno::Sequence< uno::Any > aArgs(2);\n"
" beans::NamedValue aValue;\n" " beans::NamedValue aValue;\n"
" aValue.Name = \"DocumentHandler\";\n" " aValue.Name = \"DocumentHandler\";\n"
skipping to change at line 6711 skipping to change at line 6714
} }
void test_isSameExpression() { // see #5738 void test_isSameExpression() { // see #5738
check("bool isInUnoIncludeFile(StringRef name) {" check("bool isInUnoIncludeFile(StringRef name) {"
" return name.startswith(SRCDIR \"/com/\") || name.startswith(S RCDIR \"/uno/\");\n" " return name.startswith(SRCDIR \"/com/\") || name.startswith(S RCDIR \"/uno/\");\n"
"};", "test.cpp", false, false); "};", "test.cpp", false, false);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void raceAfterInterlockedDecrement() { void raceAfterInterlockedDecrement() {
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " whatever();\n"
" whatever();\n" "}\n");
"}\n"); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement("void f() {\n"
checkInterlockedDecrement( " int counter = 0;\n"
"void f() {\n" " InterlockedDecrement(&counter);\n"
" int counter = 0;\n" " if (counter)\n"
" InterlockedDecrement(&counter);\n" " return;\n"
" if (counter)\n" " destroy();\n"
" return;\n" "}\n");
" destroy();\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (!counter)\n"
" if (!counter)\n" " destroy();\n"
" destroy();\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (counter > 0)\n"
" if (counter > 0)\n" " return;\n"
" return;\n" " destroy();\n"
" destroy();\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (0 < counter)\n"
" if (0 < counter)\n" " return;\n"
" return;\n" " destroy();\n"
" destroy();\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (counter == 0)\n"
" if (counter == 0)\n" " destroy();\n"
" destroy();\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (0 == counter)\n"
" if (0 == counter)\n" " destroy();\n"
" destroy();\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (0 != counter)\n"
" if (0 != counter)\n" " return;\n"
" return;\n" " destroy()\n"
" destroy()\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (counter != 0)\n"
" if (counter != 0)\n" " return;\n"
" return;\n" " destroy()\n"
" destroy()\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (counter <= 0)\n"
" if (counter <= 0)\n" " destroy();\n"
" destroy();\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " InterlockedDecrement(&counter);\n"
" InterlockedDecrement(&counter);\n" " if (0 >= counter)\n"
" if (0 >= counter)\n" " destroy();\n"
" destroy();\n" "}\n");
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (newCount)\n" " if (newCount)\n"
" return;\n" " return;\n"
" destroy();\n" " destroy();\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (!newCount)\n" " if (!newCount)\n"
" destroy();\n" " destroy();\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (newCount > 0)\n" " if (newCount > 0)\n"
" return;\n" " return;\n"
" destroy();\n" " destroy();\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (0 < newCount)\n" " if (0 < newCount)\n"
" return;\n" " return;\n"
" destroy();\n" " destroy();\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (newCount == 0)\n" " if (newCount == 0)\n"
" destroy();\n" " destroy();\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (0 == newCount)\n" " if (0 == newCount)\n"
" destroy();\n" " destroy();\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (0 != newCount)\n" " if (0 != newCount)\n"
" return;\n" " return;\n"
" destroy()\n" " destroy()\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (newCount != 0)\n" " if (newCount != 0)\n"
" return;\n" " return;\n"
" destroy()\n" " destroy()\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (newCount <= 0)\n" " if (newCount <= 0)\n"
" destroy();\n" " destroy();\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("void f() {\n"
"void f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " int newCount = InterlockedDecrement(&coun
" int newCount = InterlockedDecrement(&counter);\n" ter);\n"
" if (0 >= newCount)\n" " if (0 >= newCount)\n"
" destroy;\n" " destroy;\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("int f() {\n"
"int f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " if (InterlockedDecrement(&counter) == 0)
" if (InterlockedDecrement(&counter) == 0) {\n" {\n"
" destroy();\n" " destroy();\n"
" return 0;\n" " return 0;\n"
" } else {\n" " } else {\n"
" return counter;\n" " return counter;\n"
" }\n" " }\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("int f() {\n"
"int f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " if (::InterlockedDecrement(&counter) == 0
" if (::InterlockedDecrement(&counter) == 0) {\n" ) {\n"
" destroy();\n" " destroy();\n"
" return 0;\n" " return 0;\n"
" } else {\n" " } else {\n"
" return counter;\n" " return counter;\n"
" }\n" " }\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("int f() {\n"
"int f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " if (InterlockedDecrement(&counter) == 0)
" if (InterlockedDecrement(&counter) == 0) {\n" {\n"
" destroy();\n" " destroy();\n"
" return 0;\n" " return 0;\n"
" }\n" " }\n"
" return counter;\n" " return counter;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("int f() {\n"
"int f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " if (::InterlockedDecrement(&counter) == 0
" if (::InterlockedDecrement(&counter) == 0) {\n" ) {\n"
" destroy();\n" " destroy();\n"
" return 0;\n" " return 0;\n"
" }\n" " }\n"
" return counter;\n" " return counter;\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("int f() {\n"
"int f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " if (InterlockedDecrement(&counter) == 0)
" if (InterlockedDecrement(&counter) == 0) {\n" {\n"
" destroy();\n" " destroy();\n"
" return 0;\n" " return 0;\n"
" } else\n" " } else\n"
" return counter;\n" " return counter;\n"
" \n" " \n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
checkInterlockedDecrement( checkInterlockedDecrement("int f() {\n"
"int f() {\n" " int counter = 0;\n"
" int counter = 0;\n" " if (::InterlockedDecrement(&counter) == 0
" if (::InterlockedDecrement(&counter) == 0) {\n" ) {\n"
" destroy();\n" " destroy();\n"
" return 0;\n" " return 0;\n"
" } else\n" " } else\n"
" return counter;\n" " return counter;\n"
" \n" " \n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str()); ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked acc ess after InterlockedDecrement(). Use InterlockedDecrement() return value instea d.\n", errout.str());
} }
void testUnusedLabel() { void testUnusedLabel() {
check("void f() {\n" check("void f() {\n"
" label:\n" " label:\n"
"}"); "}");
ASSERT_EQUALS("[test.cpp:2]: (style) Label 'label' is not used.\n", erro ut.str()); ASSERT_EQUALS("[test.cpp:2]: (style) Label 'label' is not used.\n", erro ut.str());
check("void f() {\n" check("void f() {\n"
skipping to change at line 7188 skipping to change at line 7164
" d.n = 3;\n" " d.n = 3;\n"
"\n" "\n"
" if (d.n < 0) {\n" " if (d.n < 0) {\n"
" return;\n" " return;\n"
" }\n" " }\n"
"\n" "\n"
" if (0 > d.n) {\n" " if (0 > d.n) {\n"
" return;\n" " return;\n"
" }\n" " }\n"
"}", "test.c"); "}", "test.c");
ASSERT_EQUALS("[test.c:8]: (style) Checking if unsigned variable 'd.n' i ASSERT_EQUALS("[test.c:8]: (style) Checking if unsigned expression 'd.n'
s less than zero.\n" is less than zero.\n"
"[test.c:12]: (style) Checking if unsigned variable 'd.n' "[test.c:12]: (style) Checking if unsigned expression 'd.n
is less than zero.\n", ' is less than zero.\n",
errout.str()); errout.str());
} }
void doubleMove1() { void doubleMove1() {
check("void g(A a);\n" check("void g(A a);\n"
"void f() {\n" "void f() {\n"
" A a;\n" " A a;\n"
" g(std::move(a));\n" " g(std::move(a));\n"
" g(std::move(a));\n" " g(std::move(a));\n"
"}"); "}");
skipping to change at line 7475 skipping to change at line 7451
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Function 'func2' argument order different: declaration 'a, b, c' definition 'c, b, a'\n" ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:4]: (warning) Function 'func2' argument order different: declaration 'a, b, c' definition 'c, b, a'\n"
"[test.cpp:5] -> [test.cpp:6]: (warning) Function 'func3' argument order different: declaration ', b, c' definition 'c, b, a'\n" "[test.cpp:5] -> [test.cpp:6]: (warning) Function 'func3' argument order different: declaration ', b, c' definition 'c, b, a'\n"
"[test.cpp:9] -> [test.cpp:14]: (warning) Function 'func2' argument order different: declaration 'a, b, c' definition 'c, b, a'\n" "[test.cpp:9] -> [test.cpp:14]: (warning) Function 'func2' argument order different: declaration 'a, b, c' definition 'c, b, a'\n"
"[test.cpp:10] -> [test.cpp:15]: (warning) Function 'func3 ' argument order different: declaration 'a, b, c' definition 'c, b, a'\n" "[test.cpp:10] -> [test.cpp:15]: (warning) Function 'func3 ' argument order different: declaration 'a, b, c' definition 'c, b, a'\n"
"[test.cpp:11] -> [test.cpp:16]: (warning) Function 'func4 ' argument order different: declaration ', b, c' definition 'c, b, a'\n", errout .str()); "[test.cpp:11] -> [test.cpp:16]: (warning) Function 'func4 ' argument order different: declaration ', b, c' definition 'c, b, a'\n", errout .str());
} }
// #7846 - Syntax error when using C++11 braced-initializer in default argum ent // #7846 - Syntax error when using C++11 braced-initializer in default argum ent
void cpp11FunctionArgInit() { void cpp11FunctionArgInit() {
// syntax error is not expected // syntax error is not expected
ASSERT_NO_THROW(check( ASSERT_NO_THROW(check("\n void foo(int declaration = {}) {"
"\n void foo(int declaration = {}) {" "\n for (int i = 0; i < 10; i++) {}\n"
"\n for (int i = 0; i < 10; i++) {}" "\n }"
"\n }" "\n "));
"\n "
));
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void shadowVariables() { void shadowVariables() {
check("int x;\n" check("int x;\n"
"void f() { int x; }\n"); "void f() { int x; }\n");
ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2]: (style) Local variable x sh adows outer variable\n", errout.str()); ASSERT_EQUALS("[test.cpp:1] -> [test.cpp:2]: (style) Local variable x sh adows outer variable\n", errout.str());
check("int x();\n" check("int x();\n"
"void f() { int x; }\n"); "void f() { int x; }\n");
skipping to change at line 7510 skipping to change at line 7484
" if (cond) {int x;}\n" // <- not a shadow variable " if (cond) {int x;}\n" // <- not a shadow variable
" int x;\n" " int x;\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check("int size() {\n" check("int size() {\n"
" int size;\n" // <- not a shadow variable " int size;\n" // <- not a shadow variable
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void constArgument() {
check("void g(int);\n"
"void f(int x) {\n"
" g((x & 0x01) >> 7);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Argument '(x&1)>>7' to function g i
s always 0\n", errout.str());
check("void g(int);\n"
"void f(int x) {\n"
" g((int)((x & 0x01) >> 7));\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (style) Argument '(int)((x&1)>>7)' to funct
ion g is always 0\n", errout.str());
check("void g(int);\n"
"void f(int x) {\n"
" g(0);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void g(int);\n"
"void h() { return 1; }\n"
"void f(int x) {\n"
" g(h());\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void g(int);\n"
"void f(int x) {\n"
" g(std::strlen(\"a\"));\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void g(int);\n"
"void f(int x) {\n"
" g((int)0);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void g(Foo *);\n"
"void f() {\n"
" g(reinterpret_cast<Foo*>(0));\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void g(int);\n"
"void f(int x) {\n"
" x = 0;\n"
" g(x);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void g(int);\n"
"void f() {\n"
" const int x = 0;\n"
" g(x + 1);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void g(int);\n"
"void f() {\n"
" char i = 1;\n"
" g(static_cast<int>(i));\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
}; };
REGISTER_TEST(TestOther) REGISTER_TEST(TestOther)
 End of changes. 74 change blocks. 
850 lines changed or deleted 935 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)