Example #1
0
// 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);
                    }
                }
            }
        }
    }
}