Skip to content

Commit fdd2939

Browse files
committed
introduced a cache for followAllReferences() calls with default parameters [skip ci]
1 parent 1c02772 commit fdd2939

File tree

8 files changed

+90
-66
lines changed

8 files changed

+90
-66
lines changed

Makefile

Lines changed: 32 additions & 32 deletions
Large diffs are not rendered by default.

lib/astutils.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,7 +1066,7 @@ bool isAliasOf(const Token* tok, const Token* expr, int* indirect)
10661066
const Token* r = nullptr;
10671067
if (indirect)
10681068
*indirect = 1;
1069-
for (const ReferenceToken& ref : followAllReferences(tok)) {
1069+
for (const ReferenceToken& ref : tok->refs()) {
10701070
const bool pointer = astIsPointer(ref.token);
10711071
r = findAstNode(expr, [&](const Token* childTok) {
10721072
if (childTok->exprId() == 0)
@@ -1244,11 +1244,11 @@ static void followVariableExpressionError(const Token *tok1, const Token *tok2,
12441244
errors->push_back(std::move(item));
12451245
}
12461246

1247-
SmallVector<ReferenceToken> followAllReferences(const Token* tok,
1248-
bool temporary,
1249-
bool inconclusive,
1250-
ErrorPath errors,
1251-
int depth)
1247+
static SmallVector<ReferenceToken> followAllReferencesInternal(const Token* tok,
1248+
bool temporary = true,
1249+
bool inconclusive = true,
1250+
ErrorPath errors = ErrorPath{},
1251+
int depth = 20)
12521252
{
12531253
struct ReferenceTokenLess {
12541254
bool operator()(const ReferenceToken& x, const ReferenceToken& y) const {
@@ -1294,16 +1294,16 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
12941294
return refs_result;
12951295
}
12961296
if (vartok)
1297-
return followAllReferences(vartok, temporary, inconclusive, std::move(errors), depth - 1);
1297+
return followAllReferencesInternal(vartok, temporary, inconclusive, std::move(errors), depth - 1);
12981298
}
12991299
}
13001300
} else if (Token::simpleMatch(tok, "?") && Token::simpleMatch(tok->astOperand2(), ":")) {
13011301
std::set<ReferenceToken, ReferenceTokenLess> result;
13021302
const Token* tok2 = tok->astOperand2();
13031303

1304-
auto refs = followAllReferences(tok2->astOperand1(), temporary, inconclusive, errors, depth - 1);
1304+
auto refs = followAllReferencesInternal(tok2->astOperand1(), temporary, inconclusive, errors, depth - 1);
13051305
result.insert(refs.cbegin(), refs.cend());
1306-
refs = followAllReferences(tok2->astOperand2(), temporary, inconclusive, errors, depth - 1);
1306+
refs = followAllReferencesInternal(tok2->astOperand2(), temporary, inconclusive, errors, depth - 1);
13071307
result.insert(refs.cbegin(), refs.cend());
13081308

13091309
if (!inconclusive && result.size() != 1) {
@@ -1331,7 +1331,7 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13311331
if (returnTok == tok)
13321332
continue;
13331333
for (const ReferenceToken& rt :
1334-
followAllReferences(returnTok, temporary, inconclusive, errors, depth - returns.size())) {
1334+
followAllReferencesInternal(returnTok, temporary, inconclusive, errors, depth - returns.size())) {
13351335
const Variable* argvar = rt.token->variable();
13361336
if (!argvar) {
13371337
SmallVector<ReferenceToken> refs_result;
@@ -1356,7 +1356,7 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13561356
er.emplace_back(returnTok, "Return reference.");
13571357
er.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
13581358
auto refs =
1359-
followAllReferences(argTok, temporary, inconclusive, std::move(er), depth - returns.size());
1359+
followAllReferencesInternal(argTok, temporary, inconclusive, std::move(er), depth - returns.size());
13601360
result.insert(refs.cbegin(), refs.cend());
13611361
if (!inconclusive && result.size() > 1) {
13621362
SmallVector<ReferenceToken> refs_result;
@@ -1377,11 +1377,16 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13771377
return refs_result;
13781378
}
13791379

1380+
SmallVector<ReferenceToken> followAllReferences(const Token* tok, bool temporary)
1381+
{
1382+
return followAllReferencesInternal(tok, temporary);
1383+
}
1384+
13801385
const Token* followReferences(const Token* tok, ErrorPath* errors)
13811386
{
13821387
if (!tok)
13831388
return nullptr;
1384-
auto refs = followAllReferences(tok, true, false);
1389+
auto refs = followAllReferencesInternal(tok, true, false);
13851390
if (refs.size() == 1) {
13861391
if (errors)
13871392
*errors = std::move(refs.front().errors);

lib/astutils.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,11 +253,7 @@ struct ReferenceToken {
253253
ErrorPath errors;
254254
};
255255

256-
SmallVector<ReferenceToken> followAllReferences(const Token* tok,
257-
bool temporary = true,
258-
bool inconclusive = true,
259-
ErrorPath errors = ErrorPath{},
260-
int depth = 20);
256+
SmallVector<ReferenceToken> followAllReferences(const Token* tok, bool temporary = true);
261257
const Token* followReferences(const Token* tok, ErrorPath* errors = nullptr);
262258

263259
CPPCHECKLIB bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Settings& settings, bool pure, bool followVar, ErrorPath* errors=nullptr);

lib/token.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,6 +2637,7 @@ TokenImpl::~TokenImpl()
26372637
delete mOriginalName;
26382638
delete mValueType;
26392639
delete mValues;
2640+
delete mRefs;
26402641

26412642
if (mTemplateSimplifierPointers) {
26422643
for (auto *templateSimplifierPointer : *mTemplateSimplifierPointers) {
@@ -2721,3 +2722,16 @@ Token* findLambdaEndScope(Token* tok)
27212722
const Token* findLambdaEndScope(const Token* tok) {
27222723
return findLambdaEndScope(const_cast<Token*>(tok));
27232724
}
2725+
2726+
const SmallVector<ReferenceToken>& Token::refs(bool temporary) const
2727+
{
2728+
if (temporary) {
2729+
if (!mImpl->mRefsTemp)
2730+
mImpl->mRefsTemp = new SmallVector<ReferenceToken>(followAllReferences(this, true));
2731+
return *mImpl->mRefsTemp;
2732+
}
2733+
2734+
if (!mImpl->mRefs)
2735+
mImpl->mRefs = new SmallVector<ReferenceToken>(followAllReferences(this, false));
2736+
return *mImpl->mRefs;
2737+
}

lib/token.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "config.h"
2525
#include "errortypes.h"
2626
#include "mathlib.h"
27+
#include "smallvector.h"
2728
#include "templatesimplifier.h"
2829
#include "utils.h"
2930
#include "vfvalue.h"
@@ -53,6 +54,7 @@ class ConstTokenRange;
5354
class Token;
5455
struct TokensFrontBack;
5556
class TokenList;
57+
struct ReferenceToken;
5658

5759
struct ScopeInfo2 {
5860
ScopeInfo2(std::string name_, const Token *bodyEnd_, std::set<std::string> usingNamespaces_ = std::set<std::string>()) : name(std::move(name_)), bodyEnd(bodyEnd_), usingNamespaces(std::move(usingNamespaces_)) {}
@@ -144,6 +146,9 @@ struct TokenImpl {
144146
void setCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint value);
145147
bool getCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint &value) const;
146148

149+
SmallVector<ReferenceToken>* mRefs{};
150+
SmallVector<ReferenceToken>* mRefsTemp{};
151+
147152
TokenImpl() : mFunction(nullptr) {}
148153

149154
~TokenImpl();
@@ -1292,6 +1297,9 @@ class CPPCHECKLIB Token {
12921297
return mImpl->mValues ? *mImpl->mValues : TokenImpl::mEmptyValueList;
12931298
}
12941299

1300+
// provides and caches result of a followAllReferences() call
1301+
const SmallVector<ReferenceToken>& refs(bool temporary = true) const;
1302+
12951303
/**
12961304
* Sets the original name.
12971305
*/

lib/valueflow.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,7 +3202,7 @@ static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger &errorLogger, co
32023202
}
32033203

32043204
for (const Token* tok2 : toks) {
3205-
for (const ReferenceToken& rt : followAllReferences(tok2, false)) {
3205+
for (const ReferenceToken& rt : tok2->refs(false)) {
32063206
ValueFlow::Value value = master;
32073207
value.tokvalue = rt.token;
32083208
value.errorPath.insert(value.errorPath.begin(), rt.errors.cbegin(), rt.errors.cend());
@@ -3914,7 +3914,7 @@ static void valueFlowForwardConst(Token* start,
39143914
} else {
39153915
[&] {
39163916
// Follow references
3917-
auto refs = followAllReferences(tok);
3917+
const auto& refs = tok->refs();
39183918
auto it = std::find_if(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
39193919
return ref.token->varId() == var->declarationId();
39203920
});

lib/vf_analyzers.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,8 @@ struct ValueFlowAnalyzer : Analyzer {
645645
if (invalid())
646646
return Action::Invalid;
647647
// Follow references
648-
auto refs = followAllReferences(tok);
648+
// TODO: avoid copy
649+
auto refs = tok->refs();
649650
const bool inconclusiveRefs = refs.size() != 1;
650651
if (std::none_of(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
651652
return tok == ref.token;

0 commit comments

Comments
 (0)