Skip to content

Commit e38dfa5

Browse files
committed
Merge branch 'main' into complete-copyable-types
2 parents 598158d + cb9f2a2 commit e38dfa5

13 files changed

Lines changed: 156 additions & 21 deletions

lib/checkcondition.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,10 +1575,19 @@ void CheckConditionImpl::alwaysTrueFalse()
15751575
continue;
15761576
if (Token::simpleMatch(tok->astParent(), "return") && Token::Match(tok, ".|%var%"))
15771577
continue;
1578-
if (Token::Match(tok, "%num%|%bool%|%char%"))
1579-
continue;
1580-
if (Token::Match(tok, "! %num%|%bool%|%char%"))
1581-
continue;
1578+
bool warnForNumber = false;
1579+
if (Token::Match(tok, "%num%|%bool%|%char%")) {
1580+
const bool isZeroOrOne = (tok->getKnownIntValue() >> 1) == 0;
1581+
warnForNumber = !isZeroOrOne && tok->tokType() == Token::eNumber && tok->astParent() == condition->astParent();
1582+
if (!warnForNumber)
1583+
continue;
1584+
}
1585+
if (Token::Match(tok, "! %num%|%bool%|%char%")) {
1586+
const bool isZeroOrOne = tok->next()->hasKnownIntValue() && (tok->next()->getKnownIntValue() >> 1) == 0;
1587+
warnForNumber = !isZeroOrOne && tok->next()->tokType() == Token::eNumber && tok->astParent() == condition->astParent();
1588+
if (!warnForNumber)
1589+
continue;
1590+
}
15821591
if (Token::Match(tok, "%oror%|&&")) {
15831592
bool bail = false;
15841593
for (const Token* op : { tok->astOperand1(), tok->astOperand2() }) {
@@ -1603,7 +1612,7 @@ void CheckConditionImpl::alwaysTrueFalse()
16031612
true))
16041613
continue;
16051614

1606-
if (!pedantic && isConstVarExpression(tok, [](const Token* tok) {
1615+
if (!pedantic && !warnForNumber && isConstVarExpression(tok, [](const Token* tok) {
16071616
return Token::Match(tok, "[|(|&|+|-|*|/|%|^|>>|<<") && !Token::simpleMatch(tok, "( )");
16081617
}))
16091618
continue;

lib/checkleakautovar.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,8 @@ bool CheckLeakAutoVarImpl::checkScope(const Token * const startToken,
342342
}
343343
}
344344

345+
if (tok == tok->scope()->bodyEnd && tok->scope()->type == ScopeType::eUnconditional)
346+
ret(tok, varInfo, /*isEndOfScope*/ true);
345347

346348
// look for end of statement
347349
const bool isInit = Token::Match(tok->tokAt(-1), "%var% {|(") && tok->tokAt(-1)->variable() && tok->tokAt(-1) == tok->tokAt(-1)->variable()->nameToken();

lib/symboldatabase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5086,7 +5086,7 @@ void Scope::getVariableList()
50865086
void Scope::getVariableList(const Token* start, const Token* end)
50875087
{
50885088
// Variable declared in condition: if (auto x = bar())
5089-
if (Token::Match(classDef, "if|while ( %type%") && Token::simpleMatch(classDef->next()->astOperand2(), "=")) {
5089+
if (Token::Match(classDef, "if|while|switch ( %type%") && Token::simpleMatch(classDef->next()->astOperand2(), "=")) {
50905090
checkVariable(classDef->tokAt(2), defaultAccess());
50915091
}
50925092

lib/tokenize.cpp

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,20 @@ namespace {
563563
if (Token::simpleMatch(start, "typename"))
564564
start = start->next();
565565

566+
const auto checkForRecursion = [this]() {
567+
if (Token::Match(mTypedefToken, "typedef %name% %name% ;"))
568+
return;
569+
for (const Token *tok = mTypedefToken; tok != mEndToken; tok = tok->next()) {
570+
if (tok == mNameToken)
571+
continue;
572+
if (tok->str() != mNameToken->str())
573+
continue;
574+
if (Token::Match(tok->previous(), "struct|class|enum|union"))
575+
continue;
576+
throw InternalError(tok, "recursive typedef encountered");
577+
}
578+
};
579+
566580
// TODO handle unnamed structs etc
567581
if (Token::Match(start, "const| enum|struct|union|class %name%| {")) {
568582
const std::pair<const Token*, Token*> rangeBefore(start, Token::findsimplematch(start, "{"));
@@ -585,24 +599,11 @@ namespace {
585599
}
586600
mNameToken = nameTok;
587601
mEndToken = nameTok->next();
602+
checkForRecursion();
588603
return;
589604
}
590605
}
591606

592-
const auto checkForRecursion = [this]() {
593-
if (Token::Match(mTypedefToken, "typedef %name% %name% ;"))
594-
return;
595-
for (const Token *tok = mTypedefToken; tok != mEndToken; tok = tok->next()) {
596-
if (tok == mNameToken)
597-
continue;
598-
if (tok->str() != mNameToken->str())
599-
continue;
600-
if (Token::Match(tok->previous(), "struct|class|enum|union"))
601-
continue;
602-
throw InternalError(tok, "recursive typedef encountered");
603-
}
604-
};
605-
606607
for (Token* type = start; Token::Match(type, "%name%|*|&|&&"); type = type->next()) {
607608
if (type != start && Token::Match(type, "%name% ;") && !type->isStandardType()) {
608609
mRangeType.first = start;
@@ -4548,7 +4549,7 @@ static void setVarIdStructMembers(Token *&tok1,
45484549
return;
45494550
}
45504551

4551-
while (Token::Match(tok->next(), ")| . %name% !!(")) {
4552+
while (Token::Match(tok->next(), ")| . %name%")) {
45524553
// Don't set varid for trailing return type
45534554
if (tok->strAt(1) == ")" && Token::Match(tok->linkAt(1)->tokAt(-1), "%name%|]") && !tok->linkAt(1)->tokAt(-1)->isKeyword() &&
45544555
TokenList::isFunctionHead(tok->linkAt(1), "{;")) {
@@ -4570,6 +4571,8 @@ static void setVarIdStructMembers(Token *&tok1,
45704571
std::map<std::string, nonneg int>& members = structMembers[struct_varid];
45714572
const auto it = utils::as_const(members).find(tok->str());
45724573
if (it == members.cend()) {
4574+
if (Token::Match(tok, "%name% ("))
4575+
break;
45734576
members[tok->str()] = ++varId;
45744577
tok->varId(varId);
45754578
} else {

lib/valueflow.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2543,6 +2543,8 @@ static void valueFlowLifetimeFunction(Token *tok, const TokenList &tokenlist, Er
25432543
for (const Token* returnTok : returns) {
25442544
if (returnTok == tok)
25452545
continue;
2546+
if (!ValueFlow::isLifetimeBorrowed(returnTok, settings))
2547+
return;
25462548
const Variable *returnVar = ValueFlow::getLifetimeVariable(returnTok, settings);
25472549
if (returnVar && returnVar->isArgument() && (returnVar->isConst() || !isVariableChanged(returnVar, settings))) {
25482550
LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, returnVar, tokenlist, settings, errorLogger);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
typedef struct D{itoftor;}tor tor;

test/testautovariables.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,6 +2962,15 @@ class TestAutoVariables : public TestFixture {
29622962
" int m;\n"
29632963
"}\n");
29642964
ASSERT_EQUALS("", errout_str());
2965+
2966+
check("std::string to_string(const char* p) {\n" // #14818
2967+
" return p;\n"
2968+
"}\n"
2969+
"std::string get() {\n"
2970+
" std::string s;\n"
2971+
" return to_string(s.c_str());\n"
2972+
"}\n");
2973+
ASSERT_EQUALS("", errout_str());
29652974
}
29662975

29672976
void danglingLifetimeContainerView()

test/testcondition.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4949,6 +4949,28 @@ class TestCondition : public TestFixture {
49494949
" return x ? false : true;\n"
49504950
"}\n");
49514951
ASSERT_EQUALS("", errout_str());
4952+
4953+
check("void f() {\n"
4954+
" if (42) {}\n"
4955+
" if (42U) {}\n"
4956+
" if (42L) {}\n"
4957+
" if (42UL) {}\n"
4958+
" if (42LL) {}\n"
4959+
" if (042) {}\n"
4960+
" if (0x42) {}\n"
4961+
" if (0b101010) {}\n"
4962+
" if (!42) {}\n"
4963+
"}\n");
4964+
ASSERT_EQUALS("[test.cpp:2:9]: (style) Condition '42' is always true [knownConditionTrueFalse]\n"
4965+
"[test.cpp:3:9]: (style) Condition '42U' is always true [knownConditionTrueFalse]\n"
4966+
"[test.cpp:4:9]: (style) Condition '42L' is always true [knownConditionTrueFalse]\n"
4967+
"[test.cpp:5:9]: (style) Condition '42UL' is always true [knownConditionTrueFalse]\n"
4968+
"[test.cpp:6:9]: (style) Condition '42LL' is always true [knownConditionTrueFalse]\n"
4969+
"[test.cpp:7:9]: (style) Condition '042' is always true [knownConditionTrueFalse]\n"
4970+
"[test.cpp:8:9]: (style) Condition '0x42' is always true [knownConditionTrueFalse]\n"
4971+
"[test.cpp:9:9]: (style) Condition '0b101010' is always true [knownConditionTrueFalse]\n"
4972+
"[test.cpp:10:9]: (style) Condition '!42' is always false [knownConditionTrueFalse]\n",
4973+
errout_str());
49524974
}
49534975

49544976
void alwaysTrueSymbolic()

test/testleakautovar.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ class TestLeakAutoVar : public TestFixture {
211211
TEST_CASE(inlineFunction); // #3989
212212

213213
TEST_CASE(smartPtrInContainer); // #8262
214+
TEST_CASE(unconditionalScope);
214215

215216
TEST_CASE(functionCallCastConfig); // #9652
216217
TEST_CASE(functionCallLeakIgnoreConfig); // #7923
@@ -3178,6 +3179,34 @@ class TestLeakAutoVar : public TestFixture {
31783179
ASSERT_EQUALS("", errout_str());
31793180
}
31803181

3182+
void unconditionalScope() {
3183+
check("void f() {\n" // #14945
3184+
" {\n"
3185+
" int* p = new int;\n"
3186+
" *p = 1;\n"
3187+
" }\n"
3188+
" {\n"
3189+
" int* q = new int;\n"
3190+
" *q = 2;\n"
3191+
" delete q;\n"
3192+
" }\n"
3193+
" int* r = new int;\n"
3194+
" *r = 3;\n"
3195+
" delete r;\n"
3196+
"}\n", dinit(CheckOptions, $.cpp = true));
3197+
ASSERT_EQUALS("[test.cpp:5:5]: (error) Memory leak: p [memleak]\n", errout_str());
3198+
3199+
check("void f() {\n"
3200+
" int* p = new int;\n"
3201+
" {\n"
3202+
" (void)p;\n"
3203+
" }\n"
3204+
" *p = 1;\n"
3205+
" delete p;\n"
3206+
"}\n", dinit(CheckOptions, $.cpp = true));
3207+
ASSERT_EQUALS("", errout_str());
3208+
}
3209+
31813210
void functionCallCastConfig() { // #9652
31823211
constexpr char xmldata[] = "<?xml version=\"1.0\"?>\n"
31833212
"<def format=\"2\">\n"

test/testother.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4155,6 +4155,17 @@ class TestOther : public TestFixture {
41554155
" return r;\n"
41564156
"}\n");
41574157
ASSERT_EQUALS("", errout_str());
4158+
4159+
check("struct Item { int state; };\n"
4160+
"void foo(std::vector<Item> &items) {\n"
4161+
" for (auto &item : items) {\n"
4162+
" switch (auto &s = item.state) {\n"
4163+
" case 0: s = 1; break;\n"
4164+
" default: break;\n"
4165+
" }\n"
4166+
" }\n"
4167+
"}\n");
4168+
ASSERT_EQUALS("", errout_str());
41584169
}
41594170

41604171
void constParameterCallback() {

0 commit comments

Comments
 (0)