// Return c_str void CheckAutoVariables::returncstr() { // TODO: Move this to CheckStl::string_c_str // locate function that returns a const char *.. const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list<Scope>::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction || !scope->function) continue; const Token *tok = scope->function->tokenDef; // have we reached a function that returns a const char * if (Token::simpleMatch(tok->tokAt(-3), "const char *")) { for (const Token *tok2 = scope->classStart; tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) { // return pointer to temporary.. if (returnTemporary(tok2)) { // report error.. errorReturnTempPointer(tok2); } } } } }
// Return c_str void CheckAutoVariables::returncstr() { // locate function that returns a const char *.. const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list<Scope>::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; const Token *tok = scope->classDef; // skip any qualification while (Token::Match(tok->tokAt(-2), "%type% ::")) tok = tok->tokAt(-2); // have we reached a function that returns a const char * if (Token::simpleMatch(tok->tokAt(-3), "const char *")) { // go to the '(' const Token *tok2 = scope->classDef->next(); // go to the ')' tok2 = tok2->next()->link(); unsigned int indentlevel = 0; for (; tok2; tok2 = tok2->next()) { // indentlevel.. if (tok2->str() == "{") ++indentlevel; else if (tok2->str() == "}") { if (indentlevel <= 1) break; --indentlevel; } // return.. if (Token::Match(tok2, "return %var% . c_str ( ) ;")) { // is the returned variable a local variable? const unsigned int varid = tok2->next()->varId(); const Variable *var = symbolDatabase->getVariableFromVarId(varid); if (var && var->isLocal() && !var->isStatic()) { // report error.. errorReturnAutocstr(tok2); } } // return pointer to temporary.. else if (returnTemporary(tok2)) { // report error.. errorReturnTempPointer(tok2); } } } } }
// Return c_str void CheckAutoVariables::returncstr() { // locate function that returns a const char *.. for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { // Skip executable scopes.. if (Token::Match(tok, ") const| {")) { tok = tok->next(); if (tok->str() == "const") tok = tok->next(); tok = tok->link(); continue; } // have we reached a function that returns a reference? if (Token::Match(tok, "const char * %var% (")) { // go to the '(' const Token *tok2 = tok->tokAt(4); // go to the ')' tok2 = tok2->link(); // is this a function implementation? if (Token::Match(tok2, ") const| {")) { unsigned int indentlevel = 0; std::set<unsigned int> localvar; // local variables in function while (0 != (tok2 = tok2->next())) { // indentlevel.. if (tok2->str() == "{") ++indentlevel; else if (tok2->str() == "}") { if (indentlevel <= 1) break; --indentlevel; } // declare local variable.. if (Token::Match(tok2, "[{};] %type%") && tok2->next()->str() != "return") { // goto next token.. tok2 = tok2->next(); // skip "const" if (Token::Match(tok2, "const %type%")) tok2 = tok2->next(); // skip "std::" if it is seen if (Token::simpleMatch(tok2, "std ::")) tok2 = tok2->tokAt(2); // is it a variable declaration? if (Token::Match(tok2, "%type% %var% ;")) localvar.insert(tok2->next()->varId()); } // return.. else if (Token::Match(tok2, "return %var% . c_str ( ) ;")) { // is the returned variable a local variable? if ((tok2->next()->varId() > 0) && (localvar.find(tok2->next()->varId()) != localvar.end())) { // report error.. errorReturnAutocstr(tok2); } } // return pointer to temporary.. else if (returnTemporary(tok2)) { // report error.. errorReturnTempPointer(tok2); } } } } } }