예제 #1
0
// 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);
                }
            }
        }
    }
}
예제 #2
0
void CheckAutoVariables::returnReference()
{
    if (_tokenizer->isC())
        return;

    const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();

    const std::size_t functions = symbolDatabase->functionScopes.size();
    for (std::size_t i = 0; i < functions; ++i) {
        const Scope * scope = symbolDatabase->functionScopes[i];
        if (!scope->function)
            continue;

        const Token *tok = scope->function->tokenDef;

        // have we reached a function that returns a reference?
        if (tok->previous() && tok->previous()->str() == "&") {
            for (const Token *tok2 = scope->classStart->next(); tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
                if (tok2->str() != "return")
                    continue;

                // return..
                if (Token::Match(tok2, "return %var% ;")) {
                    // is the returned variable a local variable?
                    if (isAutoVar(tok2->next())) {
                        const Variable *var1 = tok2->next()->variable();
                        // If reference variable is used, check what it references
                        if (Token::Match(var1->nameToken(), "%var% [=(]")) {
                            const Token *tok3 = var1->nameToken()->tokAt(2);
                            if (!Token::Match(tok3, "%var% [);.]"))
                                continue;

                            // Only report error if variable that is referenced is
                            // a auto variable
                            if (!isAutoVar(tok3))
                                continue;
                        }

                        // report error..
                        errorReturnReference(tok2);
                    }
                }

                // return reference to temporary..
                else if (Token::Match(tok2, "return %var% (") &&
                         Token::simpleMatch(tok2->linkAt(2), ") ;")) {
                    if (returnTemporary(tok2->next())) {
                        // report error..
                        errorReturnTempReference(tok2);
                    }
                }

                // Return reference to a literal or the result of a calculation
                else if (tok2->astOperand1() && (tok2->astOperand1()->isCalculation() || tok2->next()->isLiteral()) && astHasAutoResult(tok2->astOperand1())) {
                    errorReturnTempReference(tok2);
                }
            }
        }
    }
}
예제 #3
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);
                }
            }
        }
    }
}
예제 #4
0
void CheckAutoVariables::returnReference()
{
    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 reference?
        if (tok->previous() && tok->previous()->str() == "&") {
            for (const Token *tok2 = scope->classStart; tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
                // return..
                if (Token::Match(tok2, "return %var% ;")) {
                    // is the returned variable a local variable?
                    const unsigned int varid1 = tok2->next()->varId();
                    const Variable *var1 = symbolDatabase->getVariableFromVarId(varid1);

                    if (var1 && var1->isLocal() && !var1->isStatic()) {
                        // If reference variable is used, check what it references
                        if (Token::Match(var1->nameToken(), "%var% =")) {
                            const Token *tok3 = var1->nameToken()->tokAt(2);
                            if (!Token::Match(tok3, "%var% [;.]"))
                                continue;

                            // Only report error if variable that is referenced is
                            // a auto variable
                            const Variable *var2 = symbolDatabase->getVariableFromVarId(tok3->varId());
                            if (!var2 || !var2->isLocal() || var2->isStatic() || (var2->isPointer() && tok3->strAt(1) == "."))
                                continue;
                        }

                        // report error..
                        errorReturnReference(tok2);
                    }
                }

                // return reference to temporary..
                else if (returnTemporary(tok2)) {
                    // report error..
                    errorReturnTempReference(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);
                    }
                }
            }
        }
    }
}
예제 #6
0
// FIXME: There should be no temporary destructor in C++17.
// CHECK: void returnByValueIntoVariable()
// CHECK:          1: returnTemporary
// CHECK-NEXT:     2: [B1.1] (ImplicitCastExpr, FunctionToPointerDecay, class return_stmt_with_dtor::D (*)(void))
// CXX11-ELIDE-NEXT:     3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6], [B1.7])
// CXX11-NOELIDE-NEXT:     3: [B1.2]() (CXXRecordTypedCall, [B1.4], [B1.6])
// CXX11-NEXT:     4: [B1.3] (BindTemporary)
// CXX11-NEXT:     5: [B1.4] (ImplicitCastExpr, NoOp, const class return_stmt_with_dtor::D)
// CXX11-NEXT:     6: [B1.5]
// CXX11-NEXT:     7: [B1.6] (CXXConstructExpr, [B1.8], class return_stmt_with_dtor::D)
// CXX11-NEXT:     8: return_stmt_with_dtor::D d = returnTemporary();
// CXX11-NEXT:     9: ~return_stmt_with_dtor::D() (Temporary object destructor)
// CXX11-NEXT:    10: [B1.8].~D() (Implicit destructor)
// CXX17-NEXT:     3: [B1.2]() (CXXRecordTypedCall, [B1.5], [B1.4])
// CXX17-NEXT:     4: [B1.3] (BindTemporary)
// CXX17-NEXT:     5: return_stmt_with_dtor::D d = returnTemporary();
// CXX17-NEXT:     6: ~return_stmt_with_dtor::D() (Temporary object destructor)
// CXX17-NEXT:     7: [B1.5].~D() (Implicit destructor)
void returnByValueIntoVariable() {
  D d = returnTemporary();
}