/*
* Cppcheck - A tool for static C/C++ code analysis
* Copyright (C) 2007-2014 Daniel Marjamki and Cppcheck team.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "preprocessor.h"
#include "tokenize.h"
#include "symboldatabase.h"
#include "checkother.h"
#include "testsuite.h"
#include "testutils.h"
#include
#include
extern std::ostringstream errout;
class TestOther : public TestFixture {
public:
TestOther() : TestFixture("TestOther") {
}
private:
Settings settings_std;
void run() {
LOAD_LIB_2(settings_std.library, "std.cfg");
TEST_CASE(emptyBrackets);
TEST_CASE(zeroDiv1);
TEST_CASE(zeroDiv2);
TEST_CASE(zeroDiv3);
TEST_CASE(zeroDiv4);
TEST_CASE(zeroDiv5);
TEST_CASE(zeroDiv6);
TEST_CASE(zeroDiv7); // #4930
TEST_CASE(zeroDiv8);
TEST_CASE(zeroDivCond); // division by zero / useless condition
TEST_CASE(nanInArithmeticExpression);
TEST_CASE(invalidFunctionUsage1);
TEST_CASE(varScope1);
TEST_CASE(varScope2);
TEST_CASE(varScope3);
TEST_CASE(varScope4);
TEST_CASE(varScope5);
TEST_CASE(varScope6);
TEST_CASE(varScope7);
TEST_CASE(varScope8);
TEST_CASE(varScope9); // classes may have extra side-effects
TEST_CASE(varScope10); // Undefined macro FOR
TEST_CASE(varScope11); // #2475 - struct initialization is not inner scope
TEST_CASE(varScope12);
TEST_CASE(varScope13); // variable usage in inner loop
TEST_CASE(varScope14);
TEST_CASE(varScope15); // #4573 if-else-if
TEST_CASE(varScope16);
TEST_CASE(varScope17);
TEST_CASE(varScope18);
TEST_CASE(varScope19); // Ticket #4994
TEST_CASE(varScope20); // Ticket #5103
TEST_CASE(varScope21); // Ticket #5382
TEST_CASE(varScope22); // Ticket #5684
TEST_CASE(varScope23); // Ticket #6154
TEST_CASE(oldStylePointerCast);
TEST_CASE(invalidPointerCast);
TEST_CASE(passedByValue);
TEST_CASE(mathfunctionCall_fmod);
TEST_CASE(mathfunctionCall_sqrt);
TEST_CASE(mathfunctionCall_log);
TEST_CASE(mathfunctionCall_acos);
TEST_CASE(mathfunctionCall_asin);
TEST_CASE(mathfunctionCall_pow);
TEST_CASE(mathfunctionCall_atan2);
TEST_CASE(mathfunctionCall_precision);
TEST_CASE(switchRedundantAssignmentTest);
TEST_CASE(switchRedundantOperationTest);
TEST_CASE(switchRedundantBitwiseOperationTest);
TEST_CASE(switchFallThroughCase);
TEST_CASE(unreachableCode);
TEST_CASE(suspiciousCase);
TEST_CASE(suspiciousEqualityComparison);
TEST_CASE(selfAssignment);
TEST_CASE(trac1132);
TEST_CASE(testMisusedScopeObjectDoesNotPickFunction1);
TEST_CASE(testMisusedScopeObjectDoesNotPickFunction2);
TEST_CASE(testMisusedScopeObjectPicksClass);
TEST_CASE(testMisusedScopeObjectPicksStruct);
TEST_CASE(testMisusedScopeObjectDoesNotPickIf);
TEST_CASE(testMisusedScopeObjectDoesNotPickConstructorDeclaration);
TEST_CASE(testMisusedScopeObjectDoesNotPickFunctor);
TEST_CASE(testMisusedScopeObjectDoesNotPickLocalClassConstructors);
TEST_CASE(testMisusedScopeObjectDoesNotPickUsedObject);
TEST_CASE(testMisusedScopeObjectDoesNotPickPureC);
TEST_CASE(testMisusedScopeObjectDoesNotPickNestedClass);
TEST_CASE(testMisusedScopeObjectInConstructor);
TEST_CASE(testMisusedScopeObjectNoCodeAfter);
TEST_CASE(trac2071);
TEST_CASE(trac2084);
TEST_CASE(trac3693);
TEST_CASE(memsetZeroBytes);
TEST_CASE(memsetInvalid2ndParam);
TEST_CASE(redundantGetAndSetUserId);
TEST_CASE(clarifyCalculation);
TEST_CASE(clarifyStatement);
TEST_CASE(duplicateBranch);
TEST_CASE(duplicateBranch1); // tests extracted by http://www.viva64.com/en/b/0149/ ( Comparison between PVS-Studio and cppcheck ): Errors detected in Quake 3: Arena by PVS-Studio: Fragement 2
TEST_CASE(duplicateBranch2); // empty macro
TEST_CASE(duplicateExpression1);
TEST_CASE(duplicateExpression2); // ticket #2730
TEST_CASE(duplicateExpression3); // ticket #3317
TEST_CASE(duplicateExpression4); // ticket #3354 (++)
TEST_CASE(duplicateExpression5); // ticket #3749 (macros with same values)
TEST_CASE(duplicateExpression6); // ticket #4639
TEST_CASE(checkSignOfUnsignedVariable);
TEST_CASE(checkSignOfPointer);
TEST_CASE(checkForSuspiciousSemicolon1);
TEST_CASE(checkForSuspiciousSemicolon2);
TEST_CASE(checkDoubleFree);
TEST_CASE(checkInvalidFree);
TEST_CASE(checkRedundantCopy);
TEST_CASE(checkNegativeShift);
TEST_CASE(incompleteArrayFill);
TEST_CASE(redundantVarAssignment);
TEST_CASE(redundantMemWrite);
TEST_CASE(varFuncNullUB);
TEST_CASE(checkPipeParameterSize); // ticket #3521
TEST_CASE(checkCastIntToCharAndBack); // ticket #160
TEST_CASE(checkSleepTimeIntervall)
TEST_CASE(checkCommaSeparatedReturn);
TEST_CASE(checkComparisonFunctionIsAlwaysTrueOrFalse);
TEST_CASE(integerOverflow); // #5895
TEST_CASE(testReturnIgnoredReturnValue);
}
void check(const char code[], const char *filename = nullptr, bool experimental = false, bool inconclusive = true, bool posix = false, bool runSimpleChecks=true, Settings* settings = 0) {
// Clear the error buffer..
errout.str("");
if (!settings) {
static Settings _settings;
settings = &_settings;
}
settings->addEnabled("style");
settings->addEnabled("warning");
settings->addEnabled("portability");
settings->addEnabled("performance");
settings->inconclusive = inconclusive;
settings->experimental = experimental;
settings->standards.posix = posix;
if (posix) {
const char cfg[] = "\n"
"\n"
" 0:999999 \n"
"";
tinyxml2::XMLDocument xmldoc;
xmldoc.Parse(cfg, sizeof(cfg));
settings->library.load(xmldoc);
}
// Tokenize..
Tokenizer tokenizer(settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, filename ? filename : "test.cpp");
// Check..
CheckOther checkOther(&tokenizer, settings, this);
checkOther.runChecks(&tokenizer, settings, this);
if (runSimpleChecks) {
const std::string str1(tokenizer.tokens()->stringifyList(0,true));
tokenizer.simplifyTokenList2();
const std::string str2(tokenizer.tokens()->stringifyList(0,true));
if (str1 != str2)
warnUnsimplified(str1, str2);
checkOther.runSimplifiedChecks(&tokenizer, settings, this);
}
}
void check_preprocess_suppress(const char precode[], const char *filename = nullptr) {
// Clear the error buffer..
errout.str("");
if (filename == nullptr)
filename = "test.cpp";
Settings settings;
settings.addEnabled("warning");
settings.addEnabled("style");
settings.addEnabled("performance");
settings.experimental = true;
// Preprocess file..
SimpleSuppressor logger(settings, this);
Preprocessor preprocessor(&settings, &logger);
std::list configurations;
std::string filedata = "";
std::istringstream fin(precode);
preprocessor.preprocess(fin, filedata, configurations, filename, settings._includePaths);
const std::string code = preprocessor.getcode(filedata, "", filename);
// Tokenize..
Tokenizer tokenizer(&settings, &logger);
std::istringstream istr(code);
tokenizer.tokenize(istr, filename);
// Check..
CheckOther checkOther(&tokenizer, &settings, &logger);
checkOther.checkSwitchCaseFallThrough();
logger.reportUnmatchedSuppressions(settings.nomsg.getUnmatchedLocalSuppressions(filename, false));
}
void emptyBrackets() {
check("{\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void zeroDiv1() {
check("void foo() {\n"
" cout = 1) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x>=1' is useless or there is division by zero at line 2.\n", errout.str());
check("void f(int x) {\n"
" int y = 17 / x;\n"
" if (x == 0) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x==0' is useless or there is division by zero at line 2.\n", errout.str());
check("void f(unsigned int x) {\n"
" int y = 17 / x;\n"
" if (x != 0) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'x!=0' is useless or there is division by zero at line 2.\n", errout.str());
// function call
check("void f1(int x, int y) { c=x/y; }\n"
"void f2(unsigned int y) {\n"
" f1(123,y);\n"
" if (y>0){}\n"
"}");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:1]: (warning) Either the condition 'y>0' is useless or there is division by zero at line 1.\n", errout.str());
// avoid false positives when variable is changed after division
check("void f() {\n"
" unsigned int x = do_something();\n"
" int y = 17 / x;\n"
" x = some+calculation;\n"
" if (x != 0) {}\n"
"}");
ASSERT_EQUALS("", errout.str());
{
// function is called that might modify global variable
check("void do_something();\n"
"int x;\n"
"void f() {\n"
" int y = 17 / x;\n"
" do_something();\n"
" if (x != 0) {}\n"
"}");
ASSERT_EQUALS("", errout.str());
// function is called. but don't care, variable is local
check("void do_something();\n"
"void f() {\n"
" int x = some + calculation;\n"
" int y = 17 / x;\n"
" do_something();\n"
" if (x != 0) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:6] -> [test.cpp:4]: (warning) Either the condition 'x!=0' is useless or there is division by zero at line 4.\n", errout.str());
}
check("void do_something(int value);\n"
"void f(int x) {\n"
" int y = 17 / x;\n"
" do_something(x);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("int x;\n"
"void f() {\n"
" int y = 17 / x;\n"
" while (y || x == 0) { x--; }\n"
"}");
ASSERT_EQUALS("", errout.str());
// ticket 5033 segmentation fault (valid code) in CheckOther::checkZeroDivisionOrUselessCondition
check("void f() {\n"
"double* p1= new double[1];\n"
"double* p2= new double[1];\n"
"double* p3= new double[1];\n"
"double* pp[3] = {p1,p2,p3};\n"
"}");
ASSERT_EQUALS("", errout.str());
// #5105 - FP
check("int f(int a, int b) {\n"
" int r = a / b;\n"
" if (func(b)) {}\n"
"}");
ASSERT_EQUALS("", errout.str());
// ?:
check("int f(int d) {\n"
" int r = (a?b:c) / d;\n"
" if (d == 0) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:2]: (warning) Either the condition 'd==0' is useless or there is division by zero at line 2.\n", errout.str());
check("int f(int a) {\n"
" int r = a ? 1 / a : 0;\n"
" if (a == 0) {}\n"
"}");
ASSERT_EQUALS("", errout.str());
check("int f(int a) {\n"
" int r = (a == 0) ? 0 : 1 / a;\n"
" if (a == 0) {}\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void nanInArithmeticExpression() {
check("void f()\n"
"{\n"
" double x = 3.0 / 0.0 + 1.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());
check("void f()\n"
"{\n"
" double x = 3.0 / 0.0 - 1.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());
check("void f()\n"
"{\n"
" double x = 1.0 + 3.0 / 0.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());
check("void f()\n"
"{\n"
" double x = 1.0 - 3.0 / 0.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS(
"[test.cpp:3]: (style) Using NaN/Inf in a computation.\n", errout.str());
check("void f()\n"
"{\n"
" double x = 3.0 / 0.0\n"
" printf(\"%f\n\", x);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void invalidFunctionUsage(const char code[]) {
// Clear the error buffer..
errout.str("");
const char cfg[] = "\n"
"\n"
" \n"
" 0,2:36 \n"
"";
tinyxml2::XMLDocument xmldoc;
xmldoc.Parse(cfg, sizeof(cfg));
Settings settings;
settings.library.load(xmldoc);
// Tokenize..
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
// Check for redundant code..
CheckOther checkOther(&tokenizer, &settings, this);
checkOther.invalidFunctionUsage();
}
void invalidFunctionUsage1() {
invalidFunctionUsage("int f() { memset(a,b,sizeof(a)!=12); }");
ASSERT_EQUALS("[test.cpp:1]: (error) Invalid memset() argument nr 3. A non-boolean value is required.\n", errout.str());
invalidFunctionUsage("int f() { memset(a,b,sizeof(a)!=0); }");
TODO_ASSERT_EQUALS("error", "", errout.str());
invalidFunctionUsage("int f() { strtol(a,b,sizeof(a)!=12); }");
ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strtol() argument nr 3. The value is 0 or 1 (comparison result) but the valid values are '0,2:36'.\n", errout.str());
invalidFunctionUsage("int f() { strtol(a,b,1); }");
ASSERT_EQUALS("[test.cpp:1]: (error) Invalid strtol() argument nr 3. The value is 1 but the valid values are '0,2:36'.\n", errout.str());
invalidFunctionUsage("int f() { strtol(a,b,10); }");
ASSERT_EQUALS("", errout.str());
}
void varScope(const char code[]) {
// Clear the error buffer..
errout.str("");
Settings settings;
settings.addEnabled("style");
// Tokenize..
Tokenizer tokenizer(&settings, this);
std::istringstream istr(code);
tokenizer.tokenize(istr, "test.cpp");
// Check for redundant code..
CheckOther checkOther(&tokenizer, &settings, this);
checkOther.checkVariableScope();
}
void varScope1() {
varScope("unsigned short foo()\n"
"{\n"
" test_client CClient;\n"
" try\n"
" {\n"
" if (CClient.Open())\n"
" {\n"
" return 0;\n"
" }\n"
" }\n"
" catch (...)\n"
" {\n"
" return 2;\n"
" }\n"
"\n"
" try\n"
" {\n"
" CClient.Close();\n"
" }\n"
" catch (...)\n"
" {\n"
" return 2;\n"
" }\n"
"\n"
" return 1;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope2() {
varScope("int foo()\n"
"{\n"
" Error e;\n"
" e.SetValue(12);\n"
" throw e;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope3() {
varScope("void foo()\n"
"{\n"
" int i;\n"
" int *p = 0;\n"
" if (abc)\n"
" {\n"
" p = &i;\n"
" }\n"
" *p = 1;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope4() {
varScope("void foo()\n"
"{\n"
" int i;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope5() {
varScope("void f(int x)\n"
"{\n"
" int i = 0;\n"
" if (x) {\n"
" for ( ; i < 10; ++i) ;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) The scope of the variable 'i' can be reduced.\n", errout.str());
varScope("void f(int x) {\n"
" const unsigned char i = 0;\n"
" if (x) {\n"
" for ( ; i < 10; ++i) ;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f(int x)\n"
"{\n"
" int i = 0;\n"
" if (x) {b()}\n"
" else {\n"
" for ( ; i < 10; ++i) ;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) The scope of the variable 'i' can be reduced.\n", errout.str());
}
void varScope6() {
varScope("void f(int x)\n"
"{\n"
" int i = x;\n"
" if (a) {\n"
" x++;\n"
" }\n"
" if (b) {\n"
" c(i);\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f()\n"
"{\n"
"int foo = 0;\n"
"std::vector vec(10);\n"
"BOOST_FOREACH(int& i, vec)\n"
"{\n"
" foo += 1;\n"
" if(foo == 10)\n"
" {\n"
" return 0;\n"
" }\n"
"}\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f(int &x)\n"
"{\n"
" int n = 1;\n"
" do\n"
" {\n"
" ++n;\n"
" ++x;\n"
" } while (x);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope7() {
varScope("void f(int x)\n"
"{\n"
" int y = 0;\n"
" b(y);\n"
" if (x) {\n"
" y++;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope8() {
varScope("void test() {\n"
" float edgeResistance=1;\n"
" std::vector edges;\n"
" BOOST_FOREACH(int edge, edges) {\n"
" edgeResistance = (edge+1) / 2.0;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'edgeResistance' can be reduced.\n", errout.str());
}
void varScope9() {
// classes may have extra side effects
varScope("class fred {\n"
"public:\n"
" void x();\n"
"};\n"
"void test(int a) {\n"
" fred f;\n"
" if (a == 2) {\n"
" f.x();\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope10() {
varScope("int f()\n"
"{\n"
" int x = 0;\n"
" FOR {\n"
" foo(x++);\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope11() {
varScope("int f() {\n"
" int x = 0;\n"
" AB ab = { x, 0 };\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("int f() {\n"
" int x = 0;\n"
" if (a == 0) { ++x; }\n"
" AB ab = { x, 0 };\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("int f() {\n"
" int x = 0;\n"
" if (a == 0) { ++x; }\n"
" if (a == 1) { AB ab = { x, 0 }; }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope12() {
varScope("void f(int x) {\n"
" int i[5];\n"
" int* j = y;\n"
" if (x)\n"
" foo(i);\n"
" foo(j);\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'i' can be reduced.\n", errout.str());
varScope("void f(int x) {\n"
" int i[5];\n"
" int* j;\n"
" if (x)\n"
" j = i;\n"
" foo(j);\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f(int x) {\n"
" const bool b = true;\n"
" x++;\n"
" if (x == 5)\n"
" foo(b);\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f(int x) {\n"
" const bool b = x;\n"
" x++;\n"
" if (x == 5)\n"
" foo(b);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope13() {
// #2770
varScope("void f() {\n"
" int i = 0;\n"
" forever {\n"
" if (i++ == 42) { break; }\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope14() {
// #3941
varScope("void f() {\n"
" const int i( foo());\n"
" if(a) {\n"
" for ( ; i < 10; ++i) ;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope15() {
// #4573
varScope("void f() {\n"
" int a,b,c;\n"
" if (a);\n"
" else if(b);\n"
" else if(c);\n"
" else;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope16() {
varScope("void f() {\n"
" int a = 0;\n"
" while((++a) < 56) {\n"
" foo();\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f() {\n"
" int a = 0;\n"
" do {\n"
" foo();\n"
" } while((++a) < 56);\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f() {\n"
" int a = 0;\n"
" do {\n"
" a = 64;\n"
" foo(a);\n"
" } while((++a) < 56);\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f() {\n"
" int a = 0;\n"
" do {\n"
" a = 64;\n"
" foo(a);\n"
" } while(z());\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'a' can be reduced.\n", errout.str());
}
void varScope17() {
varScope("void f() {\n"
" int x;\n"
" if (a) {\n"
" x = stuff(x);\n"
" morestuff(x);\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
varScope("void f() {\n"
" int x;\n"
" if (a) {\n"
" x = stuff(x);\n"
" morestuff(x);\n"
" }\n"
" if (b) {}\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
}
void varScope18() {
varScope("void f() {\n"
" short x;\n"
"\n"
" switch (ab) {\n"
" case A:\n"
" break;\n"
" case B:\n"
" default:\n"
" break;\n"
" }\n"
"\n"
" if (c) {\n"
" x = foo();\n"
" do_something(x);\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
varScope("void f() {\n"
" short x;\n"
"\n"
" switch (ab) {\n"
" case A:\n"
" x = 10;\n"
" break;\n"
" case B:\n"
" default:\n"
" break;\n"
" }\n"
"\n"
" if (c) {\n"
" x = foo();\n"
" do_something(x);\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
varScope("void f() {\n"
" short x;\n"
"\n"
" switch (ab) {\n"
" case A:\n"
" if(c)\n"
" do_something(x);\n"
" break;\n"
" case B:\n"
" default:\n"
" break;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'x' can be reduced.\n", errout.str());
varScope("void f() {\n"
" short x;\n"
"\n"
" switch (ab) {\n"
" case A:\n"
" if(c)\n"
" do_something(x);\n"
" break;\n"
" case B:\n"
" default:\n"
" if(d)\n"
" do_something(x);\n"
" break;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope19() { // Ticket #4994
varScope("long f () {\n"
" return a >> extern\n"
"}\n"
"long a = 1 ;\n"
"long b = 2 ;");
ASSERT_EQUALS("", errout.str());
}
void varScope20() { // Ticket #5103 - constant variable only used in inner scope
varScope("int f(int a) {\n"
" const int x = 234;\n"
" int b = a;\n"
" if (b > 32) b = x;\n"
" return b;\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope21() { // Ticket #5382 - initializing two-dimensional array
varScope("int test() {\n"
" int test_value = 3;\n"
" int test_array[1][1] = { { test_value } };\n"
" return sizeof(test_array);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void varScope22() { // Ticket #5684 - "The scope of the variable 'p' can be reduced" - But it can not.
varScope("void foo() {\n"
" int* p( 42 );\n"
" int i = 0;\n"
" while ( i != 100 ) {\n"
" *p = i;\n"
" ++p;\n"
" ++i;\n"
" }\n"
"}");
ASSERT_EQUALS("", errout.str());
// try to avoid an obvious false negative after applying the fix for the example above:
varScope("void foo() {\n"
" int* p( 42 );\n"
" int i = 0;\n"
" int dummy = 0;\n"
" while ( i != 100 ) {\n"
" p = & dummy;\n"
" *p = i;\n"
" ++p;\n"
" ++i;\n"
" }\n"
"}");
ASSERT_EQUALS("[test.cpp:2]: (style) The scope of the variable 'p' can be reduced.\n", errout.str());
}
void varScope23() { // #6154: Don't suggest to reduce scope if inner scope is a lambda
varScope("int main() {\n"
" size_t myCounter = 0;\n"
" Test myTest([&](size_t aX){\n"
" std::cout