Skip to content

Commit 5276cfd

Browse files
Merge branch 'main' into chr_sibling
2 parents 6d16a57 + 91941c2 commit 5276cfd

9 files changed

Lines changed: 89 additions & 8 deletions

‎lib/checkstl.cpp‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,9 +1986,11 @@ static bool isc_strCall(const Token* tok, const Library::Container* container)
19861986

19871987
static bool isc_strConcat(const Token* tok)
19881988
{
1989-
if (!tok->isBinaryOp() || !Token::simpleMatch(tok, "+"))
1989+
if (!tok->isBinaryOp() || !Token::Match(tok, "+|+="))
19901990
return false;
19911991
for (const Token* op : { tok->astOperand1(), tok->astOperand2() }) { // NOLINT(readability-use-anyofallof)
1992+
if (tok->isAssignmentOp() && astIsLHS(op))
1993+
continue;
19921994
const Token* sibling = op->astSibling();
19931995
if (!sibling->valueType())
19941996
continue;
@@ -3338,8 +3340,8 @@ void CheckStlImpl::eraseIteratorOutOfBoundsError(const Token *ftok, const Token*
33383340
}
33393341

33403342
const Severity severity = isConditional ? Severity::warning : Severity::error;
3341-
const std::string id = isConditional ? "eraseIteratorOutOfBoundsCond" : "eraseIteratorOutOfBounds";
3342-
reportError(ftok, severity,
3343+
const char* id = isConditional ? "eraseIteratorOutOfBoundsCond" : "eraseIteratorOutOfBounds";
3344+
reportError(getErrorPath(ftok, val, msg), severity,
33433345
id,
33443346
msg, CWE628, Certainty::normal);
33453347
}

‎lib/tokenize.cpp‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3201,8 +3201,15 @@ bool Tokenizer::simplifyUsing()
32013201
continue;
32023202
}
32033203

3204-
// skip template definitions
32053204
if (Token::Match(tok1, "template < !!>")) {
3205+
Token *paramsEnd = tok1->next()->findClosingBracket();
3206+
bool shadowed = !paramsEnd;
3207+
for (const Token *param = tok1->next(); !shadowed && param != paramsEnd; param = param->next())
3208+
shadowed = param->str() == nameToken->str();
3209+
if (!shadowed) {
3210+
tok1 = paramsEnd;
3211+
continue;
3212+
}
32063213
Token *declEndToken = TemplateSimplifier::findTemplateDeclarationEnd(tok1);
32073214
if (declEndToken)
32083215
tok1 = declEndToken;
@@ -9109,7 +9116,8 @@ void Tokenizer::findGarbageCode() const
91099116
if (tok->strAt(1) == "(")
91109117
syntaxError(tok);
91119118
else if (!(tok->tokType() == Token::Type::eString && Token::simpleMatch(tok->tokAt(-1), "extern")) &&
9112-
!(tok->tokType() == Token::Type::eBoolean && cpp && Token::simpleMatch(tok->tokAt(-1), "requires")))
9119+
!(tok->tokType() == Token::Type::eBoolean && cpp && Token::simpleMatch(tok->tokAt(-1), "requires")) &&
9120+
!Token::simpleMatch(tok->linkAt(1), "} ;"))
91139121
syntaxError(tok);
91149122
}
91159123
if (Token::Match(tok, "( ) %num%|%bool%|%char%|%str%"))

‎lib/valueflow.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,7 @@ static void valueFlowImpossibleValues(TokenList& tokenList, const Settings& sett
11181118
value.setImpossible();
11191119
setTokenValue(tok, std::move(value), settings);
11201120
} else if (tok->variable() && tok->variable()->isArray() && !tok->variable()->isArgument() &&
1121-
!tok->variable()->isStlType()) {
1121+
tok->variable()->getTypeName() != "std::array") {
11221122
ValueFlow::Value value{0};
11231123
value.setImpossible();
11241124
setTokenValue(tok, std::move(value), settings);

‎lib/vf_settokenvalue.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ namespace ValueFlow
617617
// ~
618618
else if (parent->str() == "~") {
619619
for (const Value &val : tok->values()) {
620-
if (!val.isIntValue())
620+
if (!val.isIntValue() || (val.isImpossible() && val.intvalue < 0))
621621
continue;
622622
Value v(val);
623623
v.intvalue = ~v.intvalue;

‎test/testcondition.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3449,6 +3449,12 @@ class TestCondition : public TestFixture {
34493449
"}\n");
34503450
ASSERT_EQUALS("", errout_str());
34513451

3452+
check("std::string a[3];\n" // #15065
3453+
"void f() {\n"
3454+
" if (a) {}\n"
3455+
"}\n");
3456+
ASSERT_EQUALS("[test.cpp:3:8]: (style) Condition 'a' is always true [knownConditionTrueFalse]\n", errout_str());
3457+
34523458
// Avoid FP when condition comes from macro
34533459
check("#define NOT !\n"
34543460
"void f() {\n"

‎test/testsimplifyusing.cpp‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class TestSimplifyUsing : public TestFixture {
7979
TEST_CASE(simplifyUsing39);
8080
TEST_CASE(simplifyUsing40);
8181
TEST_CASE(simplifyUsing41);
82+
TEST_CASE(simplifyUsing42);
8283

8384
TEST_CASE(simplifyUsing8970);
8485
TEST_CASE(simplifyUsing8971);
@@ -956,6 +957,40 @@ class TestSimplifyUsing : public TestFixture {
956957
ASSERT_EQUALS(expected, tok(code));
957958
}
958959

960+
void simplifyUsing42() {
961+
{
962+
const char code[] = "using A = bool;\n"
963+
"template<typename T> A func() {}\n";
964+
const char expected[] = "template < typename T > bool func ( ) { }";
965+
ASSERT_EQUALS(expected, tok(code));
966+
}
967+
{
968+
const char code[] = "using A = bool;\n"
969+
"template<typename A> A func() {}\n";
970+
const char expected[] = "template < typename A > A func ( ) { }";
971+
ASSERT_EQUALS(expected, tok(code));
972+
}
973+
{
974+
const char code[] = "using A = bool;\n"
975+
"template<typename T> class C { A x; }\n";
976+
const char expected[] = "template < typename T > class C { bool x ; }";
977+
ASSERT_EQUALS(expected, tok(code));
978+
}
979+
{
980+
const char code[] = "using A = bool;\n"
981+
"template<typename A> class C { A x; }\n";
982+
const char expected[] = "template < typename A > class C { A x ; }";
983+
ASSERT_EQUALS(expected, tok(code));
984+
}
985+
{
986+
const char code[] = "using A = bool;\n"
987+
"template<typename T> class C { using A = T; A x; }\n"
988+
"C<int> c;\n";
989+
const char expected[] = "class C<int> ; C<int> c ; class C<int> { int x ; }";
990+
ASSERT_EQUALS(expected, tok(code));
991+
}
992+
}
993+
959994
void simplifyUsing8970() {
960995
const char code[] = "using V = std::vector<int>;\n"
961996
"struct A {\n"

‎test/teststl.cpp‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1140,6 +1140,20 @@ class TestStl : public TestFixture {
11401140
"[test.cpp:3:11]: note: Assuming that condition 'i>5' is not redundant\n"
11411141
"[test.cpp:5:13]: note: Access out of bounds\n",
11421142
errout_str());
1143+
1144+
check("void f(std::vector<int>& v) {\n"
1145+
" std::vector<int>::iterator it;\n"
1146+
" for (it = v.begin(); it != v.end(); ++it) {\n"
1147+
" if (*it == 0)\n"
1148+
" break;\n"
1149+
" }\n"
1150+
" v.erase(it);\n"
1151+
"}\n", s);
1152+
ASSERT_EQUALS("[test.cpp:4:13]: style: Consider using std::find_if algorithm instead of a raw loop. [useStlAlgorithm]\n"
1153+
"[test.cpp:7:7]: warning: Either the condition is redundant or function 'erase()' is called on the iterator 'it' which is out of bounds. [eraseIteratorOutOfBoundsCond]\n"
1154+
"[test.cpp:3:29]: note: Assuming that condition 'it!=v.end()' is not redundant\n"
1155+
"[test.cpp:7:7]: note: Either the condition is redundant or function 'erase()' is called on the iterator 'it' which is out of bounds.\n",
1156+
errout_str());
11431157
}
11441158

11451159
void iterator1() {
@@ -2441,7 +2455,7 @@ class TestStl : public TestFixture {
24412455
" if (it == v.end()) {}\n"
24422456
" v.erase(it);\n"
24432457
"}\n");
2444-
ASSERT_EQUALS("[test.cpp:3:7]: (warning) Either the condition 'it==v.end()' is redundant or function 'erase()' is called on the iterator 'it' which is out of bounds. [eraseIteratorOutOfBoundsCond]\n",
2458+
ASSERT_EQUALS("[test.cpp:2:12] -> [test.cpp:3:7]: (warning) Either the condition 'it==v.end()' is redundant or function 'erase()' is called on the iterator 'it' which is out of bounds. [eraseIteratorOutOfBoundsCond]\n",
24452459
errout_str());
24462460

24472461
check("void f() {\n"
@@ -5161,6 +5175,12 @@ class TestStl : public TestFixture {
51615175
"}\n");
51625176
ASSERT_EQUALS("[test.cpp:2:17]: (performance) Constructing a std::string from the result of c_str() is slow and redundant. [stlcstrConstructor]\n",
51635177
errout_str());
5178+
5179+
check("void f(std::string& a, const std::string& b) {\n"
5180+
" a += b.c_str();\n"
5181+
"}\n");
5182+
ASSERT_EQUALS("[test.cpp:2:7]: (performance) Concatenating the result of c_str() and a std::string is slow and redundant. [stlcstrConcat]\n",
5183+
errout_str());
51645184
}
51655185

51665186
void uselessCalls() {

‎test/testtokenize.cpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8138,6 +8138,7 @@ class TestTokenizer : public TestFixture {
81388138
ignore_errout();
81398139

81408140
ASSERT_EQUALS(";", tokenizeAndStringify("typedef std::size_t size_t;\n")); // #14809
8141+
ASSERT_EQUALS("struct S { int i { 0 } ; } ;", tokenizeAndStringify("struct S { int i : 1{0}; };\n")); // #15070
81418142
}
81428143

81438144

‎test/testvalueflow.cpp‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,6 +1263,15 @@ class TestValueFlow : public TestFixture {
12631263
ASSERT_EQUALS(1U, values.size());
12641264
ASSERT_EQUALS(~0U, values.back().intvalue);
12651265

1266+
// #15015
1267+
code = "void f(unsigned u) {\n"
1268+
" if (~u) {}\n"
1269+
"}";
1270+
values = tokenValues(code, "~");
1271+
ASSERT_EQUALS(1U, values.size());
1272+
ASSERT_EQUALS(-1, values.back().intvalue);
1273+
ASSERT(values.back().isImpossible());
1274+
12661275
// !
12671276
code = "void f(int x) {\n"
12681277
" a = !x;\n"

0 commit comments

Comments
 (0)