@@ -1959,29 +1959,53 @@ static bool isLocal(const Token *tok)
19591959 return var && !var->isStatic () && var->isLocal ();
19601960}
19611961
1962+ static bool isc_strCall (const Token* tok)
1963+ {
1964+ if (!Token::simpleMatch (tok, " (" ))
1965+ return false ;
1966+ const Token* dot = tok->astOperand1 ();
1967+ if (!Token::simpleMatch (dot, " ." ))
1968+ return false ;
1969+ const Token* obj = dot->astOperand1 ();
1970+ if (!obj || !obj->valueType () || !obj->valueType ()->container || !obj->valueType ()->container ->stdStringLike )
1971+ return false ;
1972+ return Token::Match (dot->astOperand2 (), " c_str|data ( )" );
1973+ }
1974+
19621975static bool isc_strConcat (const Token* tok)
19631976{
19641977 if (!Token::simpleMatch (tok, " +" ))
19651978 return false ;
19661979 const Token* cstr = nullptr ;
19671980 for (const Token* op : { tok->astOperand1 (), tok->astOperand2 () }) {
1968- if (!Token::simpleMatch (op, " (" ))
1969- continue ;
1970- const Token* dot = op->astOperand1 ();
1971- if (!Token::simpleMatch (dot, " ." ) || !dot->astOperand1 ())
1972- continue ;
1973- const ValueType* vtObject = dot->astOperand1 ()->valueType ();
1974- if (!vtObject || !vtObject->container || !vtObject->container ->stdStringLike )
1975- continue ;
1976- if (!Token::Match (dot->astOperand2 (), " c_str|data ( )" ))
1977- continue ;
1978- cstr = op;
1979- break ;
1981+ if (isc_strCall (op)) {
1982+ cstr = op;
1983+ break ;
1984+ }
19801985 }
19811986 if (!cstr)
19821987 return false ;
1983- const ValueType* vtStr = (cstr == tok->astOperand1 () ? tok->astOperand2 () : tok->astOperand1 ())->valueType ();
1984- return vtStr && vtStr->container && vtStr->container ->stdStringLike ;
1988+ const Token* strTok = (cstr == tok->astOperand1 ()) ? tok->astOperand2 () : tok->astOperand1 ();
1989+ return strTok->valueType () && strTok->valueType ()->container && strTok->valueType ()->container ->stdStringLike ;
1990+ }
1991+
1992+ static bool isc_strAssignment (const Token* tok)
1993+ {
1994+ if (!Token::simpleMatch (tok, " =" ))
1995+ return false ;
1996+ if (!isc_strCall (tok->astOperand2 ()))
1997+ return false ;
1998+ const Token* strTok = tok->astOperand1 ();
1999+ return strTok && strTok->valueType () && strTok->valueType ()->container && strTok->valueType ()->container ->stdStringLike ;
2000+ }
2001+
2002+ static bool isc_strConstructor (const Token* tok)
2003+ {
2004+ if (!Token::Match (tok, " %var% (|{" ))
2005+ return false ;
2006+ if (!isc_strCall (tok->tokAt (1 )->astOperand2 ()))
2007+ return false ;
2008+ return tok->valueType () && tok->valueType ()->container && tok->valueType ()->container ->stdStringLike ;
19852009}
19862010
19872011namespace {
@@ -2052,16 +2076,14 @@ void CheckStl::string_c_str()
20522076 const Variable* var2 = tok->tokAt (2 )->variable ();
20532077 if (var->isPointer () && var2 && var2->isStlType (stl_string_stream))
20542078 string_c_strError (tok);
2079+ } else if (printPerformance && isc_strAssignment (tok->tokAt (1 ))) {
2080+ string_c_strAssignment (tok, tok->variable ()->getTypeName ());
20552081 } else if (Token::Match (tok->tokAt (2 ), " %name% (" ) &&
20562082 Token::Match (tok->linkAt (3 ), " ) . c_str|data ( ) ;" ) &&
20572083 tok->tokAt (2 )->function () && Token::Match (tok->tokAt (2 )->function ()->retDef , " std :: string|wstring %name%" )) {
20582084 const Variable* var = tok->variable ();
20592085 if (var->isPointer ())
20602086 string_c_strError (tok);
2061- } else if (printPerformance && tok->tokAt (1 )->astOperand2 () && Token::Match (tok->tokAt (1 )->astOperand2 ()->tokAt (-3 ), " %var% . c_str|data ( ) ;" )) {
2062- const Token* vartok = tok->tokAt (1 )->astOperand2 ()->tokAt (-3 );
2063- if ((tok->variable ()->isStlStringType () || tok->variable ()->isStlStringViewType ()) && vartok->variable () && vartok->variable ()->isStlStringType ())
2064- string_c_strAssignment (tok, tok->variable ()->getTypeName ());
20652087 }
20662088 } else if (printPerformance && tok->function () && Token::Match (tok, " %name% ( !!)" ) && tok->str () != scope.className ) {
20672089 const auto range = c_strFuncParam.equal_range (tok->function ());
@@ -2093,9 +2115,7 @@ void CheckStl::string_c_str()
20932115 }
20942116 }
20952117 }
2096- } else if (printPerformance && Token::Match (tok, " %var% (|{ %var% . c_str|data ( ) !!," ) &&
2097- tok->variable () && (tok->variable ()->isStlStringType () || tok->variable ()->isStlStringViewType ()) &&
2098- tok->tokAt (2 )->variable () && tok->tokAt (2 )->variable ()->isStlStringType ()) {
2118+ } else if (printPerformance && isc_strConstructor (tok)) {
20992119 string_c_strConstructor (tok, tok->variable ()->getTypeName ());
21002120 } else if (printPerformance && isc_strConcat (tok)) {
21012121 string_c_strConcat (tok);
0 commit comments