@@ -2009,6 +2009,18 @@ void CheckStl::string_c_str()
20092009 ((Token::Match (tok->previous (), " %var% + %var% . c_str|data ( )" ) && tok->previous ()->variable () && tok->previous ()->variable ()->isStlStringType ()) ||
20102010 (Token::Match (tok->tokAt (-5 ), " %var% . c_str|data ( ) + %var%" ) && tok->tokAt (-5 )->variable () && tok->tokAt (-5 )->variable ()->isStlStringType ()))) {
20112011 string_c_strConcat (tok);
2012+ } else if (printPerformance && Token::simpleMatch (tok, " <<" ) && tok->astOperand2 () && Token::simpleMatch (tok->astOperand2 ()->astOperand1 (), " . c_str ( )" )) {
2013+ const Token* str = tok->astOperand2 ()->astOperand1 ()->astOperand1 ();
2014+ if (Token::Match (str, " (|[" ))
2015+ str = str->previous ();
2016+ if (str && ((str->variable () && str->variable ()->isStlStringType ()) ||
2017+ (str->function () && isStlStringType (str->function ()->retDef )))) {
2018+ const Token* strm = tok;
2019+ while (Token::simpleMatch (strm, " <<" ))
2020+ strm = strm->astOperand1 ();
2021+ if (strm && strm->variable () && strm->variable ()->isStlType ())
2022+ string_c_strStream (tok);
2023+ }
20122024 }
20132025
20142026 // Using c_str() to get the return value is only dangerous if the function returns a char*
@@ -2118,22 +2130,32 @@ void CheckStl::string_c_strParam(const Token* tok, nonneg int number)
21182130
21192131void CheckStl::string_c_strConstructor (const Token* tok)
21202132{
2121- std::string msg = " Constructing a std::string from the result of c_str() is slow and redundant.\n Solve that by directly passing the string." ;
2133+ std::string msg = " Constructing a std::string from the result of c_str() is slow and redundant.\n "
2134+ " Constructing a std::string from const char* requires a call to strlen(). Solve that by directly passing the string." ;
21222135 reportError (tok, Severity::performance, " stlcstrConstructor" , msg, CWE704 , Certainty::normal);
21232136}
21242137
21252138void CheckStl::string_c_strAssignment (const Token* tok)
21262139{
2127- std::string msg = " Assigning the result of c_str() to a std::string is slow and redundant.\n Solve that by directly assigning the string." ;
2140+ std::string msg = " Assigning the result of c_str() to a std::string is slow and redundant.\n "
2141+ " Assigning a const char* to a std::string requires a call to strlen(). Solve that by directly assigning the string." ;
21282142 reportError (tok, Severity::performance, " stlcstrAssignment" , msg, CWE704 , Certainty::normal);
21292143}
21302144
21312145void CheckStl::string_c_strConcat (const Token* tok)
21322146{
2133- std::string msg = " Concatenating the result of c_str() and a std::string is slow and redundant.\n Solve that by directly concatenating the strings." ;
2147+ std::string msg = " Concatenating the result of c_str() and a std::string is slow and redundant.\n "
2148+ " Concatenating a const char* with a std::string requires a call to strlen(). Solve that by directly concatenating the strings." ;
21342149 reportError (tok, Severity::performance, " stlcstrConcat" , msg, CWE704 , Certainty::normal);
21352150}
21362151
2152+ void CheckStl::string_c_strStream (const Token* tok)
2153+ {
2154+ std::string msg = " Passing the result of c_str() to a stream is slow and redundant.\n "
2155+ " Passing a const char* to a stream requires a call to strlen(). Solve that by directly passing the string." ;
2156+ reportError (tok, Severity::performance, " stlcstrStream" , msg, CWE704 , Certainty::normal);
2157+ }
2158+
21372159// ---------------------------------------------------------------------------
21382160//
21392161// ---------------------------------------------------------------------------
0 commit comments