Skip to content

Commit 3dd3480

Browse files
Fix #13000 FP knownConditionTrueFalse with std::string::append() (#6676)
1 parent 9c3c0ed commit 3dd3480

9 files changed

Lines changed: 39 additions & 6 deletions

File tree

cfg/cppcheck-cfg.rng

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,7 @@
709709
<value>find-const</value>
710710
<value>insert</value>
711711
<value>erase</value>
712+
<value>append</value>
712713
<value>change-content</value>
713714
<value>change-internal</value>
714715
<value>change</value>

cfg/qt.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5208,6 +5208,7 @@
52085208
<function name="reserve" action="change-internal"/>
52095209
<function name="chop" action="change"/>
52105210
<function name="remove" action="change"/>
5211+
<function name="append" action="append"/>
52115212
</size>
52125213
<access indexOperator="array-like">
52135214
<function name="at" yields="at_index"/>

cfg/std.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8913,7 +8913,7 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
89138913
<size>
89148914
<function name="push_back" action="push"/>
89158915
<function name="pop_back" action="pop"/>
8916-
<function name="append" action="push"/>
8916+
<function name="append" action="append"/>
89178917
<function name="replace" action="change"/>
89188918
<function name="reserve" action="change-internal"/>
89198919
<function name="shrink_to_fit" action="change-internal"/>

lib/astutils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2670,6 +2670,7 @@ bool isVariableChanged(const Token *tok, int indirect, const Settings &settings,
26702670
const Library::Container::Action action = c->getAction(ftok->str());
26712671
if (contains({Library::Container::Action::INSERT,
26722672
Library::Container::Action::ERASE,
2673+
Library::Container::Action::APPEND,
26732674
Library::Container::Action::CHANGE,
26742675
Library::Container::Action::CHANGE_CONTENT,
26752676
Library::Container::Action::CHANGE_INTERNAL,

lib/checkstl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ static bool containerAppendsElement(const Library::Container* container, const T
7373
if (Token::Match(parent, ". %name% (")) {
7474
const Library::Container::Action action = container->getAction(parent->strAt(1));
7575
if (contains({Library::Container::Action::INSERT,
76+
Library::Container::Action::APPEND,
7677
Library::Container::Action::CHANGE,
7778
Library::Container::Action::CHANGE_INTERNAL,
7879
Library::Container::Action::PUSH,

lib/library.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ Library::Container::Action Library::Container::actionFrom(const std::string& act
297297
return Container::Action::INSERT;
298298
if (actionName == "erase")
299299
return Container::Action::ERASE;
300+
if (actionName == "append")
301+
return Container::Action::APPEND;
300302
if (actionName == "change-content")
301303
return Container::Action::CHANGE_CONTENT;
302304
if (actionName == "change-internal")

lib/library.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ class CPPCHECKLIB Library {
193193
FIND_CONST,
194194
INSERT,
195195
ERASE,
196+
APPEND,
196197
CHANGE_CONTENT,
197198
CHANGE,
198199
CHANGE_INTERNAL,

lib/valueflow.cpp

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,6 +1044,7 @@ struct ValueFlowAnalyzer : Analyzer {
10441044
if (astIsContainer(tok) && value->isLifetimeValue() &&
10451045
contains({Library::Container::Action::PUSH,
10461046
Library::Container::Action::INSERT,
1047+
Library::Container::Action::APPEND,
10471048
Library::Container::Action::CHANGE_INTERNAL},
10481049
astContainerAction(tok)))
10491050
return read;
@@ -6492,6 +6493,8 @@ static bool isContainerSizeChangedByFunction(const Token* tok,
64926493
return (isChanged || inconclusive);
64936494
}
64946495

6496+
static MathLib::bigint valueFlowGetStrLength(const Token* tok);
6497+
64956498
struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
64966499
ContainerExpressionAnalyzer(const Token* expr, ValueFlow::Value val, const Settings& s)
64976500
: ExpressionAnalyzer(expr, std::move(val), s)
@@ -6527,9 +6530,9 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
65276530
}
65286531
} else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
65296532
const Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
6530-
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) {
6533+
if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP || action == Library::Container::Action::APPEND) { // TODO: handle more actions?
65316534
std::vector<const Token*> args = getArguments(tok->tokAt(3));
6532-
if (args.size() < 2)
6535+
if (args.size() < 2 || action == Library::Container::Action::APPEND)
65336536
return Action::Read | Action::Write | Action::Incremental;
65346537
}
65356538
}
@@ -6563,10 +6566,24 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer {
65636566
}
65646567
} else if (astIsLHS(tok) && Token::Match(tok->astParent(), ". %name% (")) {
65656568
const Library::Container::Action action = container->getAction(tok->astParent()->strAt(1));
6566-
if (action == Library::Container::Action::PUSH)
6569+
switch (action) {
6570+
case Library::Container::Action::PUSH:
65676571
n = 1;
6568-
if (action == Library::Container::Action::POP)
6572+
break;
6573+
case Library::Container::Action::POP:
65696574
n = -1;
6575+
break;
6576+
case Library::Container::Action::APPEND: {
6577+
std::vector<const Token*> args = getArguments(tok->astParent()->tokAt(2));
6578+
if (args.size() == 1) // TODO: handle overloads
6579+
n = valueFlowGetStrLength(tok->astParent()->tokAt(3));
6580+
if (n == 0) // TODO: handle known empty append
6581+
val->setPossible();
6582+
break;
6583+
}
6584+
default:
6585+
break;
6586+
}
65706587
}
65716588
if (d == Direction::Reverse)
65726589
val->intvalue -= n;
@@ -6712,6 +6729,7 @@ bool ValueFlow::isContainerSizeChanged(const Token* tok, int indirect, const Set
67126729
case Library::Container::Action::CHANGE:
67136730
case Library::Container::Action::INSERT:
67146731
case Library::Container::Action::ERASE:
6732+
case Library::Container::Action::APPEND:
67156733
return true;
67166734
case Library::Container::Action::NO_ACTION:
67176735
// Is this an unknown member function call?
@@ -7002,7 +7020,7 @@ static const Scope* getFunctionScope(const Scope* scope) {
70027020
return scope;
70037021
}
70047022

7005-
static MathLib::bigint valueFlowGetStrLength(const Token* tok)
7023+
MathLib::bigint valueFlowGetStrLength(const Token* tok)
70067024
{
70077025
if (tok->tokType() == Token::eString)
70087026
return Token::getStrLength(tok);
@@ -7175,6 +7193,7 @@ static void valueFlowContainerSize(const TokenList& tokenlist,
71757193
value.setImpossible();
71767194
valueFlowForward(tok->linkAt(2), containerTok, std::move(value), tokenlist, errorLogger, settings);
71777195
}
7196+
// TODO: handle more actions?
71787197

71797198
} else if (tok->str() == "+=" && astIsContainer(tok->astOperand1())) {
71807199
const Token* containerTok = tok->astOperand1();

test/testvalueflow.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6985,6 +6985,13 @@ class TestValueFlow : public TestFixture {
69856985
" if (c.empty()) {}\n"
69866986
"}";
69876987
ASSERT_EQUALS("", isImpossibleContainerSizeValue(tokenValues(code, "c ."), 2));
6988+
6989+
code = "void f(const std::string& a) {\n"
6990+
" std::string s;\n"
6991+
" s.append(a);\n"
6992+
" if (s.empty()) {}\n"
6993+
"}";
6994+
ASSERT_EQUALS("", isPossibleContainerSizeValue(tokenValues(code, "s . empty"), 0));
69886995
}
69896996

69906997
void valueFlowContainerElement()

0 commit comments

Comments
 (0)