-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Fix #14533, #14536 FN stlcstrConcat, stlcstrAssignment, stlcstrConstructor #8261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
5f7d92b
0ec9223
d4269dd
4614417
a8bdf5f
6559527
1eafc89
82b2a0f
f6b00d6
c359ded
ed47749
a271422
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1959,6 +1959,59 @@ static bool isLocal(const Token *tok) | |
| return var && !var->isStatic() && var->isLocal(); | ||
| } | ||
|
|
||
| static bool isc_strCall(const Token* tok) | ||
| { | ||
| if (!Token::simpleMatch(tok, "(")) | ||
| return false; | ||
| const Token* dot = tok->astOperand1(); | ||
| if (!Token::simpleMatch(dot, ".")) | ||
| return false; | ||
| const Token* obj = dot->astOperand1(); | ||
| if (!obj || !obj->valueType() || !obj->valueType()->container || | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I assume that now we will not warn for: my suggestion is that we warn when the same container is used. s1 and s2 have the same container pointer. Does that sound good?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No, we won't warn, although that is a fixable issue.
We can do that, so we will also warn for
|
||
| !obj->valueType()->container->stdStringLike || !obj->valueType()->container->startPatternHasStd) | ||
| return false; | ||
| return Token::Match(dot->astOperand2(), "c_str|data ( )"); | ||
| } | ||
|
|
||
| static bool isc_strConcat(const Token* tok) | ||
| { | ||
| if (!Token::simpleMatch(tok, "+") || !tok->isBinaryOp()) | ||
| return false; | ||
| const Token* cstr = nullptr; | ||
| for (const Token* op : { tok->astOperand1(), tok->astOperand2() }) { | ||
| if (isc_strCall(op)) { | ||
| cstr = op; | ||
| break; | ||
| } | ||
| } | ||
| if (!cstr) | ||
| return false; | ||
| const Token* strTok = (cstr == tok->astOperand1()) ? tok->astOperand2() : tok->astOperand1(); | ||
| return strTok->valueType() && strTok->valueType()->container && | ||
| strTok->valueType()->container->stdStringLike && strTok->valueType()->container->startPatternHasStd; | ||
| } | ||
|
|
||
| static bool isc_strAssignment(const Token* tok) | ||
| { | ||
| if (!Token::simpleMatch(tok, "=")) | ||
| return false; | ||
| if (!isc_strCall(tok->astOperand2())) | ||
| return false; | ||
| const Token* strTok = tok->astOperand1(); | ||
| return strTok && strTok->valueType() && strTok->valueType()->container && | ||
| strTok->valueType()->container->stdStringLike && strTok->valueType()->container->startPatternHasStd; | ||
| } | ||
|
|
||
| static bool isc_strConstructor(const Token* tok) | ||
| { | ||
| if (!Token::Match(tok, "%var% (|{")) | ||
| return false; | ||
| if (!isc_strCall(tok->tokAt(1)->astOperand2())) | ||
| return false; | ||
| return tok->valueType() && tok->valueType()->container && | ||
| tok->valueType()->container->stdStringLike && tok->valueType()->container->startPatternHasStd; | ||
| } | ||
|
|
||
| namespace { | ||
| const std::set<std::string> stl_string_stream = { | ||
| "istringstream", "ostringstream", "stringstream", "wstringstream" | ||
|
|
@@ -2027,16 +2080,14 @@ void CheckStl::string_c_str() | |
| const Variable* var2 = tok->tokAt(2)->variable(); | ||
| if (var->isPointer() && var2 && var2->isStlType(stl_string_stream)) | ||
| string_c_strError(tok); | ||
| } else if (printPerformance && isc_strAssignment(tok->tokAt(1))) { | ||
| string_c_strAssignment(tok, tok->variable()->getTypeName()); | ||
| } else if (Token::Match(tok->tokAt(2), "%name% (") && | ||
| Token::Match(tok->linkAt(3), ") . c_str|data ( ) ;") && | ||
| tok->tokAt(2)->function() && Token::Match(tok->tokAt(2)->function()->retDef, "std :: string|wstring %name%")) { | ||
| const Variable* var = tok->variable(); | ||
| if (var->isPointer()) | ||
| string_c_strError(tok); | ||
| } else if (printPerformance && tok->tokAt(1)->astOperand2() && Token::Match(tok->tokAt(1)->astOperand2()->tokAt(-3), "%var% . c_str|data ( ) ;")) { | ||
| const Token* vartok = tok->tokAt(1)->astOperand2()->tokAt(-3); | ||
| if ((tok->variable()->isStlStringType() || tok->variable()->isStlStringViewType()) && vartok->variable() && vartok->variable()->isStlStringType()) | ||
| string_c_strAssignment(tok, tok->variable()->getTypeName()); | ||
| } | ||
| } else if (printPerformance && tok->function() && Token::Match(tok, "%name% ( !!)") && tok->str() != scope.className) { | ||
| const auto range = c_strFuncParam.equal_range(tok->function()); | ||
|
|
@@ -2068,13 +2119,9 @@ void CheckStl::string_c_str() | |
| } | ||
| } | ||
| } | ||
| } else if (printPerformance && Token::Match(tok, "%var% (|{ %var% . c_str|data ( ) !!,") && | ||
| tok->variable() && (tok->variable()->isStlStringType() || tok->variable()->isStlStringViewType()) && | ||
| tok->tokAt(2)->variable() && tok->tokAt(2)->variable()->isStlStringType()) { | ||
| } else if (printPerformance && isc_strConstructor(tok)) { | ||
| string_c_strConstructor(tok, tok->variable()->getTypeName()); | ||
| } else if (printPerformance && tok->next() && tok->next()->variable() && tok->next()->variable()->isStlStringType() && tok->valueType() && tok->valueType()->type == ValueType::CONTAINER && | ||
| ((Token::Match(tok->previous(), "%var% + %var% . c_str|data ( )") && tok->previous()->variable() && tok->previous()->variable()->isStlStringType()) || | ||
| (Token::Match(tok->tokAt(-5), "%var% . c_str|data ( ) + %var%") && tok->tokAt(-5)->variable() && tok->tokAt(-5)->variable()->isStlStringType()))) { | ||
| } else if (printPerformance && isc_strConcat(tok)) { | ||
| string_c_strConcat(tok); | ||
| } else if (printPerformance && Token::simpleMatch(tok, "<<") && tok->astOperand2() && Token::Match(tok->astOperand2()->astOperand1(), ". c_str|data ( )")) { | ||
| const Token* str = tok->astOperand2()->astOperand1()->astOperand1(); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.