diff --git a/lib/astutils.cpp b/lib/astutils.cpp index fb22bb7f80c..1b3e2677411 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -101,7 +101,7 @@ const Token* findExpression(const nonneg int exprid, return nullptr; } -static void astFlattenRecursive(const Token *tok, std::vector *result, const char* op, nonneg int depth = 0) +static void astFlattenRecursive(const Token *tok, TokenVector *result, const char* op, nonneg int depth = 0) { ++depth; if (!tok || depth >= 100) @@ -114,9 +114,10 @@ static void astFlattenRecursive(const Token *tok, std::vector *re } } -std::vector astFlatten(const Token* tok, const char* op) +TokenVector astFlatten(const Token* tok, const char* op) { - std::vector result; + TokenVector result; + result.clear(); astFlattenRecursive(tok, &result, op); return result; } @@ -830,7 +831,7 @@ std::vector followAllReferences(const Token* tok, bool inconclus int n = getArgumentPos(argvar, f); if (n < 0) return {{tok, std::move(errors)}}; - std::vector args = getArguments(tok->previous()); + auto args = getArguments(tok->previous()); if (n >= args.size()) return {{tok, std::move(errors)}}; const Token* argTok = args[n]; @@ -1465,7 +1466,7 @@ bool isConstFunctionCall(const Token* ftok, const Library& library) constMember = var->isConst(); } // TODO: Only check const on lvalues - std::vector args = getArguments(ftok); + auto args = getArguments(ftok); if (memberFunction && args.empty()) return false; return constMember && std::all_of(args.begin(), args.end(), [](const Token* tok) { @@ -1747,7 +1748,7 @@ const Token * getTokenArgumentFunction(const Token * tok, int& argn) if (Token::Match(tok, "(|{")) break; } - std::vector args = getArguments(tok); + auto args = getArguments(tok); auto it = std::find(args.begin(), args.end(), argtok); if (it != args.end()) argn = std::distance(args.begin(), it); @@ -2279,13 +2280,13 @@ int numberOfArguments(const Token *start) return arguments; } -std::vector getArguments(const Token *ftok) +TokenVector getArguments(const Token *ftok) { const Token* tok = ftok; if (Token::Match(tok, "%name% (|{")) tok = ftok->next(); if (!Token::Match(tok, "(|{|[")) - return std::vector {}; + return {}; const Token *startTok = tok->astOperand2(); if (!startTok && tok->next() != tok->link()) startTok = tok->astOperand1(); @@ -2397,7 +2398,7 @@ bool isConstVarExpression(const Token *tok, const char* skipMatch) if (Token::Match(tok->previous(), "%name% (")) { if (Token::simpleMatch(tok->astOperand1(), ".") && !isConstVarExpression(tok->astOperand1(), skipMatch)) return false; - std::vector args = getArguments(tok); + auto args = getArguments(tok); return std::all_of(args.begin(), args.end(), [&](const Token* t) { return isConstVarExpression(t, skipMatch); }); @@ -2883,7 +2884,7 @@ struct FwdAnalysis::Result FwdAnalysis::checkRecursive(const Token *expr, const while (Token::simpleMatch(ftok, ",")) ftok = ftok->astParent(); if (ftok && Token::Match(ftok->previous(), "%name% (")) { - const std::vector args = getArguments(ftok); + const auto args = getArguments(ftok); int argnr = 0; while (argnr < args.size() && args[argnr] != parent) argnr++; @@ -3074,7 +3075,7 @@ bool FwdAnalysis::possiblyAliased(const Token *expr, const Token *startToken) co if (Token::Match(tok, "%name% (") && !Token::Match(tok, "if|while|for")) { // Is argument passed by reference? - const std::vector args = getArguments(tok); + const auto args = getArguments(tok); for (int argnr = 0; argnr < args.size(); ++argnr) { if (!Token::Match(args[argnr], "%name%|.|::")) continue; diff --git a/lib/astutils.h b/lib/astutils.h index e7a34aa6446..a94f02515c9 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "errortypes.h" #include "utils.h" @@ -36,6 +37,8 @@ class Settings; class Token; class Variable; +using TokenVector = boost::container::small_vector; + enum class ChildrenToVisit { none, op1, @@ -57,7 +60,7 @@ const Token* findExpression(const nonneg int exprid, const std::function& pred); const Token* findExpression(const Token* start, const nonneg int exprid); -std::vector astFlatten(const Token* tok, const char* op); +TokenVector astFlatten(const Token* tok, const char* op); bool astHasToken(const Token* root, const Token * tok); @@ -264,7 +267,7 @@ int numberOfArguments(const Token *start); /** * Get arguments (AST) */ -std::vector getArguments(const Token *ftok); +TokenVector getArguments(const Token *ftok); int getArgumentPos(const Variable* var, const Function* f); diff --git a/lib/bughuntingchecks.cpp b/lib/bughuntingchecks.cpp index cc29463e6ec..01d385f424c 100644 --- a/lib/bughuntingchecks.cpp +++ b/lib/bughuntingchecks.cpp @@ -100,7 +100,7 @@ static void bufferOverflow(const Token *tok, const ExprEngine::Value &value, Exp if (!functionCallArguments) return; - const std::vector arguments = getArguments(tok); + const auto arguments = getArguments(tok); if (functionCallArguments->argValues.size() != arguments.size()) // TODO investigate what to do return; diff --git a/lib/checkbufferoverrun.cpp b/lib/checkbufferoverrun.cpp index f4390b48104..b5b382ae21a 100644 --- a/lib/checkbufferoverrun.cpp +++ b/lib/checkbufferoverrun.cpp @@ -69,7 +69,7 @@ static const ValueFlow::Value *getBufferSizeValue(const Token *tok) return it == tokenValues.end() ? nullptr : &*it; } -static int getMinFormatStringOutputLength(const std::vector ¶meters, nonneg int formatStringArgNr) +static int getMinFormatStringOutputLength(const TokenVector ¶meters, nonneg int formatStringArgNr) { if (formatStringArgNr <= 0 || formatStringArgNr > parameters.size()) return 0; @@ -558,7 +558,7 @@ ValueFlow::Value CheckBufferOverrun::getBufferSize(const Token *bufTok) const } //--------------------------------------------------------------------------- -static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::MinSize &minsize, const std::vector &args, const MathLib::bigint bufferSize, const Settings *settings) +static bool checkBufferSize(const Token *ftok, const Library::ArgumentChecks::MinSize &minsize, const TokenVector &args, const MathLib::bigint bufferSize, const Settings *settings) { const Token * const arg = (minsize.arg > 0 && minsize.arg - 1 < args.size()) ? args[minsize.arg - 1] : nullptr; const Token * const arg2 = (minsize.arg2 > 0 && minsize.arg2 - 1 < args.size()) ? args[minsize.arg2 - 1] : nullptr; @@ -602,7 +602,7 @@ void CheckBufferOverrun::bufferOverflow() continue; if (!mSettings->library.hasminsize(tok)) continue; - const std::vector args = getArguments(tok); + const auto args = getArguments(tok); for (int argnr = 0; argnr < args.size(); ++argnr) { if (!args[argnr]->valueType() || args[argnr]->valueType()->pointer == 0) continue; @@ -720,7 +720,7 @@ void CheckBufferOverrun::stringNotZeroTerminated() for (const Token *tok = scope->bodyStart; tok && tok != scope->bodyEnd; tok = tok->next()) { if (!Token::simpleMatch(tok, "strncpy (")) continue; - const std::vector args = getArguments(tok); + const auto args = getArguments(tok); if (args.size() != 3) continue; const Token *sizeToken = args[2]; @@ -778,7 +778,7 @@ void CheckBufferOverrun::argumentSize() // If argument is '%type% a[num]' then check bounds against num const Function *callfunc = tok->function(); - const std::vector callargs = getArguments(tok); + const auto callargs = getArguments(tok); for (nonneg int paramIndex = 0; paramIndex < callargs.size() && paramIndex < callfunc->argCount(); ++paramIndex) { const Variable* const argument = callfunc->getArgumentVar(paramIndex); if (!argument || !argument->nameToken() || !argument->isArray()) diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index d4d87141ed3..a3adefd3143 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -102,7 +102,7 @@ void CheckFunctions::invalidFunctionUsage() if (!Token::Match(tok, "%name% ( !!)")) continue; const Token * const functionToken = tok; - const std::vector arguments = getArguments(tok); + const auto arguments = getArguments(tok); for (int argnr = 1; argnr <= arguments.size(); ++argnr) { const Token * const argtok = arguments[argnr-1]; @@ -465,7 +465,7 @@ void CheckFunctions::memsetZeroBytes() for (const Scope *scope : symbolDatabase->functionScopes) { for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) { if (Token::Match(tok, "memset|wmemset (") && (numberOfArguments(tok)==3)) { - const std::vector &arguments = getArguments(tok); + const auto &arguments = getArguments(tok); if (WRONG_DATA(arguments.size() != 3U, tok)) continue; const Token* lastParamTok = arguments[2]; @@ -506,7 +506,7 @@ void CheckFunctions::memsetInvalid2ndParam() if (!Token::simpleMatch(tok, "memset (")) continue; - const std::vector args = getArguments(tok); + const auto args = getArguments(tok); if (args.size() != 3) continue; diff --git a/lib/checkleakautovar.cpp b/lib/checkleakautovar.cpp index 3a59f4ae84b..1f40dc64703 100644 --- a/lib/checkleakautovar.cpp +++ b/lib/checkleakautovar.cpp @@ -480,7 +480,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken, if (tok3->str() == "(" && Token::Match(tok3->astOperand1(), "UNLIKELY|LIKELY")) { return ChildrenToVisit::op2; } else if (tok3->str() == "(" && Token::Match(tok3->previous(), "%name%")) { - const std::vector params = getArguments(tok3->previous()); + const auto params = getArguments(tok3->previous()); for (const Token *par : params) { if (!par->isComparisonOp()) continue; diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 05d4dcf2019..cd88cd7b746 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -1010,7 +1010,7 @@ void CheckMemoryLeakNoVar::checkForUnreleasedInputArgument(const Scope *scope) if (!CheckMemoryLeakInFunction::test_white_list(functionName, mSettings, mTokenizer->isCPP())) continue; - const std::vector args = getArguments(tok); + const auto args = getArguments(tok); for (const Token* arg : args) { if (arg->isOp()) continue; diff --git a/lib/checknullpointer.cpp b/lib/checknullpointer.cpp index b236bed2d67..bfba1cb95b0 100644 --- a/lib/checknullpointer.cpp +++ b/lib/checknullpointer.cpp @@ -57,7 +57,7 @@ void CheckNullPointer::parseFunctionCall(const Token &tok, std::list args = getArguments(&tok); + const auto args = getArguments(&tok); if (library || tok.function() != nullptr) { for (int argnr = 1; argnr <= args.size(); ++argnr) { @@ -368,7 +368,7 @@ void CheckNullPointer::nullConstantDereference() nullPointerError(tok); else if (Token::Match(tok->previous(), "::|. %name% (")) { - const std::vector &args = getArguments(tok); + const auto &args = getArguments(tok); for (int argnr = 0; argnr < args.size(); ++argnr) { const Token *argtok = args[argnr]; if (!argtok->hasKnownIntValue()) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index dc9e6012aa2..284c69f9e39 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -3490,7 +3490,7 @@ void CheckOther::checkOverlappingWrite() const Library::NonOverlappingData *nonOverlappingData = mSettings->library.getNonOverlappingData(tok); if (!nonOverlappingData) continue; - const std::vector args = getArguments(tok); + const auto args = getArguments(tok); if (nonOverlappingData->ptr1Arg <= 0 || nonOverlappingData->ptr1Arg > args.size()) continue; if (nonOverlappingData->ptr2Arg <= 0 || nonOverlappingData->ptr2Arg > args.size()) diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index f16dad8617e..eb8be72aa58 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -718,7 +718,7 @@ void CheckStl::mismatchingContainers() continue; const Token * const ftok = tok; - const std::vector args = getArguments(ftok); + const auto args = getArguments(ftok); if (args.size() < 2) continue; @@ -772,7 +772,7 @@ void CheckStl::mismatchingContainerIterator() if (!Token::Match(tok, "%var% . %name% ( !!)")) continue; const Token * const ftok = tok->tokAt(2); - const std::vector args = getArguments(ftok); + const auto args = getArguments(ftok); const Library::Container * c = tok->valueType()->container; Library::Container::Action action = c->getAction(tok->strAt(2)); @@ -894,7 +894,7 @@ struct InvalidContainerAnalyzer { return false; return true; }); - std::vector args = getArguments(tok); + auto args = getArguments(tok); for (Info::Reference& r : result) { r.errorPath.push_front(epi); const Variable* var = r.tok->variable(); @@ -2682,7 +2682,7 @@ void CheckStl::knownEmptyContainer() continue; knownEmptyContainerError(contTok, ""); } else { - const std::vector args = getArguments(tok); + const auto args = getArguments(tok); if (args.empty()) continue; diff --git a/lib/checkstring.cpp b/lib/checkstring.cpp index d4a0853f975..438b23ebd79 100644 --- a/lib/checkstring.cpp +++ b/lib/checkstring.cpp @@ -362,8 +362,8 @@ void CheckString::overlappingStrcmp() continue; if (!Token::Match(ne0->previous(), "strcmp|wcscmp (")) continue; - const std::vector args1 = getArguments(eq0->previous()); - const std::vector args2 = getArguments(ne0->previous()); + const auto args1 = getArguments(eq0->previous()); + const auto args2 = getArguments(ne0->previous()); if (args1.size() != 2 || args2.size() != 2) continue; if (args1[1]->isLiteral() && @@ -402,7 +402,7 @@ void CheckString::sprintfOverlappingData() if (!Token::Match(tok, "sprintf|snprintf|swprintf (")) continue; - const std::vector args = getArguments(tok); + const auto args = getArguments(tok); const int formatString = Token::simpleMatch(tok, "sprintf") ? 1 : 2; for (unsigned int argnr = formatString + 1; argnr < args.size(); ++argnr) { diff --git a/lib/ctu.cpp b/lib/ctu.cpp index 07573f4580f..8a39cadbf67 100644 --- a/lib/ctu.cpp +++ b/lib/ctu.cpp @@ -314,7 +314,7 @@ CTU::FileInfo *CTU::getFileInfo(const Tokenizer *tokenizer) continue; if (!tok->astOperand1()->function()) continue; - const std::vector args(getArguments(tok->previous())); + const auto args(getArguments(tok->previous())); for (int argnr = 0; argnr < args.size(); ++argnr) { const Token *argtok = args[argnr]; if (!argtok) diff --git a/lib/exprengine.cpp b/lib/exprengine.cpp index 2e5a95882e2..19f3344c5ae 100644 --- a/lib/exprengine.cpp +++ b/lib/exprengine.cpp @@ -2046,7 +2046,7 @@ static ExprEngine::ValuePtr executeFunctionCall(const Token *tok, Data &data) } } - const std::vector &argTokens = getArguments(tok); + const auto &argTokens = getArguments(tok); std::vector argValues; for (const Token *argtok : argTokens) { auto val = hasBody ? executeExpression1(argtok, data) : executeExpression(argtok, data); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index f3b1f7028f8..1f6dcb5cef1 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -4961,7 +4961,7 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const { const bool isCall = Token::Match(tok->next(), "(|{"); - const std::vector arguments = getArguments(tok); + const auto arguments = getArguments(tok); std::vector matches; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 86233661163..9349383eb01 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2074,7 +2074,7 @@ struct ValueFlowAnalyzer : Analyzer { result.unknown = lhs.unknown || rhs.unknown; return result; } else if (Token::Match(tok->previous(), "%name% (")) { - std::vector args = getArguments(tok->previous()); + auto args = getArguments(tok->previous()); if (Token::Match(tok->tokAt(-2), ". %name% (")) { args.push_back(tok->tokAt(-2)->astOperand1()); } @@ -2956,7 +2956,7 @@ static std::vector getLifetimeTokens(const Token* tok, int n = getArgumentPos(argvar, f); if (n < 0) return std::vector {}; - std::vector args = getArguments(tok->previous()); + auto args = getArguments(tok->previous()); // TODO: Track lifetimes of default parameters if (n >= args.size()) return std::vector {}; @@ -3358,7 +3358,7 @@ struct LifetimeStore { {} template - static void forEach(const std::vector& argtoks, + static void forEach(const TokenVector& argtoks, const std::string& message, ValueFlow::Value::LifetimeKind type, F f) { @@ -3386,7 +3386,7 @@ struct LifetimeStore { int n = getArgumentPos(var, f); if (n < 0) return LifetimeStore{}; - std::vector args = getArguments(tok); + auto args = getArguments(tok); if (n >= args.size()) { if (tokenlist->getSettings()->debugwarnings) bailout(tokenlist, @@ -3556,7 +3556,7 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog return; int returnContainer = settings->library.returnValueContainer(tok); if (returnContainer >= 0) { - std::vector args = getArguments(tok); + auto args = getArguments(tok); for (int argnr = 1; argnr <= args.size(); ++argnr) { const Library::ArgumentChecks::IteratorInfo *i = settings->library.getArgIteratorInfo(tok, argnr); if (!i) @@ -3585,7 +3585,7 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog } else if (Token::Match(tok->tokAt(-2), "%var% . push_back|push_front|insert|push|assign") && astIsContainer(tok->tokAt(-2))) { Token *vartok = tok->tokAt(-2); - std::vector args = getArguments(tok); + auto args = getArguments(tok); std::size_t n = args.size(); if (n > 1 && Token::typeStr(args[n - 2]) == Token::typeStr(args[n - 1]) && (((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) || @@ -3651,7 +3651,7 @@ static void valueFlowLifetimeConstructor(Token* tok, return; // If the type is unknown then assume it captures by value in the // constructor, but make each lifetime inconclusive - std::vector args = getArguments(tok); + auto args = getArguments(tok); LifetimeStore::forEach( args, "Passed to initializer list.", ValueFlow::Value::LifetimeKind::SubObject, [&](LifetimeStore& ls) { ls.inconclusive = true; @@ -3664,7 +3664,7 @@ static void valueFlowLifetimeConstructor(Token* tok, return; // Only support aggregate constructors for now if (scope->numConstructors == 0 && t->derivedFrom.empty() && (t->isClassType() || t->isStructType())) { - std::vector args = getArguments(tok); + auto args = getArguments(tok); auto it = scope->varlist.begin(); LifetimeStore::forEach(args, "Passed to constructor of '" + t->name() + "'.", @@ -3706,7 +3706,7 @@ static void valueFlowLifetimeConstructor(Token* tok, TokenList* tokenlist, Error if (Token::simpleMatch(parent, "{") && hasInitList(parent->astParent())) { valueFlowLifetimeConstructor(tok, Token::typeOf(parent->previous()), tokenlist, errorLogger, settings); } else if (Token::simpleMatch(tok, "{") && hasInitList(parent)) { - std::vector args = getArguments(tok); + auto args = getArguments(tok); // Assume range constructor if passed a pair of iterators if (astIsContainer(parent) && args.size() == 2 && astIsIterator(args[0]) && astIsIterator(args[1])) { LifetimeStore::forEach( @@ -3770,7 +3770,7 @@ struct Lambda { std::unordered_map> explicitCaptures; Capture implicitCapture; - std::vector getCaptures() { + TokenVector getCaptures() { return getArguments(capture); } @@ -4111,7 +4111,7 @@ static std::vector getConditions(const Token* tok, const char* op) { std::vector conds = {tok}; if (tok->str() == op) { - std::vector args = astFlatten(tok, op); + auto args = astFlatten(tok, op); std::copy_if(args.begin(), args.end(), std::back_inserter(conds), [&](const Token* tok2) { if (tok2->exprId() == 0) return false; @@ -6306,7 +6306,7 @@ static void valueFlowSubFunction(TokenList* tokenlist, SymbolDatabase* symboldat id++; std::unordered_map> argvars; // TODO: Rewrite this. It does not work well to inject 1 argument at a time. - const std::vector &callArguments = getArguments(tok); + const auto &callArguments = getArguments(tok); for (int argnr = 0U; argnr < callArguments.size(); ++argnr) { const Token *argtok = callArguments[argnr]; // Get function argument @@ -6595,7 +6595,7 @@ struct ContainerExpressionAnalyzer : ExpressionAnalyzer { } else if (Token::Match(tok, "%name% . %name% (")) { Library::Container::Action action = tok->valueType()->container->getAction(tok->strAt(2)); if (action == Library::Container::Action::PUSH || action == Library::Container::Action::POP) { - std::vector args = getArguments(tok->tokAt(3)); + auto args = getArguments(tok->tokAt(3)); if (args.size() < 2) return Action::Read | Action::Write | Action::Incremental; } @@ -6794,7 +6794,7 @@ static void valueFlowSmartPointer(TokenList *tokenlist, ErrorLogger * errorLogge } } else if (Token::Match(tok->previous(), "%name%|> (|{") && astIsSmartPointer(tok) && astIsSmartPointer(tok->astOperand1())) { - std::vector args = getArguments(tok); + auto args = getArguments(tok); if (args.empty()) continue; for (const ValueFlow::Value& v : args.front()->values()) @@ -6929,7 +6929,7 @@ static std::vector getInitListSize(const Token* tok, const Library::Container* container, bool known = true) { - std::vector args = getArguments(tok); + auto args = getArguments(tok); // Strings don't use an init list if (!args.empty() && container->stdStringLike) { if (astIsIntegral(args[0], false)) { @@ -7160,7 +7160,7 @@ static void valueFlowDynamicBufferSize(TokenList* tokenlist, SymbolDatabase* sym if (!allocFunc || allocFunc->bufferSize == Library::AllocFunc::BufferSize::none) continue; - const std::vector args = getArguments(rhs->previous()); + const auto args = getArguments(rhs->previous()); const Token * const arg1 = (args.size() >= allocFunc->bufferSizeArg1) ? args[allocFunc->bufferSizeArg1 - 1] : nullptr; const Token * const arg2 = (args.size() >= allocFunc->bufferSizeArg2) ? args[allocFunc->bufferSizeArg2 - 1] : nullptr;