--------------------------------------------------------------------------- Creating instance of classes which are destroyed immediately ---------------------------------------------------------------------------
| 2542 | // Creating instance of classes which are destroyed immediately |
| 2543 | //--------------------------------------------------------------------------- |
| 2544 | void CheckOtherImpl::checkMisusedScopedObject() |
| 2545 | { |
| 2546 | // Skip this check for .c files |
| 2547 | if (mTokenizer->isC()) |
| 2548 | return; |
| 2549 | |
| 2550 | if (!mSettings.severity.isEnabled(Severity::style) && !mSettings.isPremiumEnabled("unusedScopedObject")) |
| 2551 | return; |
| 2552 | |
| 2553 | logChecker("CheckOther::checkMisusedScopedObject"); // style,c++ |
| 2554 | |
| 2555 | auto getConstructorTok = [](const Token* tok, std::string& typeStr) -> const Token* { |
| 2556 | if (!Token::Match(tok, "[;{}] %name%") || tok->next()->isKeyword()) |
| 2557 | return nullptr; |
| 2558 | tok = tok->next(); |
| 2559 | typeStr.clear(); |
| 2560 | while (Token::Match(tok, "%name% ::")) { |
| 2561 | typeStr += tok->str(); |
| 2562 | typeStr += "::"; |
| 2563 | tok = tok->tokAt(2); |
| 2564 | } |
| 2565 | typeStr += tok->str(); |
| 2566 | const Token* endTok = tok; |
| 2567 | if (Token::Match(endTok, "%name% <")) |
| 2568 | endTok = endTok->linkAt(1); |
| 2569 | if (Token::Match(endTok, "%name%|> (|{") && Token::Match(endTok->linkAt(1), ")|} ;") && |
| 2570 | !Token::simpleMatch(endTok->next()->astParent(), ";")) { // for loop condition |
| 2571 | return tok; |
| 2572 | } |
| 2573 | return nullptr; |
| 2574 | }; |
| 2575 | |
| 2576 | auto isLibraryConstructor = [&](const Token* tok, const std::string& typeStr) -> bool { |
| 2577 | const Library::TypeCheck typeCheck = mSettings.library.getTypeCheck("unusedvar", typeStr); |
| 2578 | if (typeCheck == Library::TypeCheck::check || typeCheck == Library::TypeCheck::checkFiniteLifetime) |
| 2579 | return true; |
| 2580 | return mSettings.library.detectContainerOrIterator(tok); |
| 2581 | }; |
| 2582 | |
| 2583 | const SymbolDatabase* const symbolDatabase = mTokenizer->getSymbolDatabase(); |
| 2584 | std::string typeStr; |
| 2585 | for (const Scope * scope : symbolDatabase->functionScopes) { |
| 2586 | for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { |
| 2587 | const Token* ctorTok = getConstructorTok(tok, typeStr); |
| 2588 | if (ctorTok && (((ctorTok->type() || ctorTok->isStandardType() || (ctorTok->function() && ctorTok->function()->isConstructor())) // TODO: The rhs of || should be removed; It is a workaround for a symboldatabase bug |
| 2589 | && (!ctorTok->function() || ctorTok->function()->isConstructor()) // // is not a function on this scope or is function in this scope and it's a ctor |
| 2590 | && ctorTok->str() != "void") || isLibraryConstructor(tok->next(), typeStr))) { |
| 2591 | const Token* parTok = ctorTok->next(); |
| 2592 | if (Token::simpleMatch(parTok, "<") && parTok->link()) |
| 2593 | parTok = parTok->link()->next(); |
| 2594 | if (const Token* arg = parTok->astOperand2()) { |
| 2595 | if (!isConstStatement(arg, mSettings.library, false)) |
| 2596 | continue; |
| 2597 | if (parTok->str() == "(") { |
| 2598 | if (arg->varId() && !(arg->variable() && arg->variable()->nameToken() != arg)) |
| 2599 | continue; |
| 2600 | const Token* rml = nextAfterAstRightmostLeaf(arg); |
| 2601 | if (rml && rml->previous() && rml->previous()->varId()) |
no test coverage detected