Skip to content

Commit 92ad6f3

Browse files
committed
introduced a cache for followAllReferences() calls [skip ci]
1 parent 3e169d6 commit 92ad6f3

File tree

8 files changed

+91
-66
lines changed

8 files changed

+91
-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
@@ -1067,7 +1067,7 @@ bool isAliasOf(const Token* tok, const Token* expr, int* indirect)
10671067
const Token* r = nullptr;
10681068
if (indirect)
10691069
*indirect = 1;
1070-
for (const ReferenceToken& ref : followAllReferences(tok)) {
1070+
for (const ReferenceToken& ref : tok->refs()) {
10711071
const bool pointer = astIsPointer(ref.token);
10721072
r = findAstNode(expr, [&](const Token* childTok) {
10731073
if (childTok->exprId() == 0)
@@ -1246,11 +1246,11 @@ static void followVariableExpressionError(const Token *tok1, const Token *tok2,
12461246
errors->push_back(std::move(item));
12471247
}
12481248

1249-
SmallVector<ReferenceToken> followAllReferences(const Token* tok,
1250-
bool temporary,
1251-
bool inconclusive,
1252-
ErrorPath errors,
1253-
int depth)
1249+
static SmallVector<ReferenceToken> followAllReferencesInternal(const Token* tok,
1250+
bool temporary = true,
1251+
bool inconclusive = true,
1252+
ErrorPath errors = ErrorPath{},
1253+
int depth = 20)
12541254
{
12551255
struct ReferenceTokenLess {
12561256
bool operator()(const ReferenceToken& x, const ReferenceToken& y) const {
@@ -1296,16 +1296,16 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
12961296
return refs_result;
12971297
}
12981298
if (vartok)
1299-
return followAllReferences(vartok, temporary, inconclusive, std::move(errors), depth - 1);
1299+
return followAllReferencesInternal(vartok, temporary, inconclusive, std::move(errors), depth - 1);
13001300
}
13011301
}
13021302
} else if (Token::simpleMatch(tok, "?") && Token::simpleMatch(tok->astOperand2(), ":")) {
13031303
std::set<ReferenceToken, ReferenceTokenLess> result;
13041304
const Token* tok2 = tok->astOperand2();
13051305

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

13111311
if (!inconclusive && result.size() != 1) {
@@ -1333,7 +1333,7 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13331333
if (returnTok == tok)
13341334
continue;
13351335
for (const ReferenceToken& rt :
1336-
followAllReferences(returnTok, temporary, inconclusive, errors, depth - returns.size())) {
1336+
followAllReferencesInternal(returnTok, temporary, inconclusive, errors, depth - returns.size())) {
13371337
const Variable* argvar = rt.token->variable();
13381338
if (!argvar) {
13391339
SmallVector<ReferenceToken> refs_result;
@@ -1358,7 +1358,7 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13581358
er.emplace_back(returnTok, "Return reference.");
13591359
er.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
13601360
auto refs =
1361-
followAllReferences(argTok, temporary, inconclusive, std::move(er), depth - returns.size());
1361+
followAllReferencesInternal(argTok, temporary, inconclusive, std::move(er), depth - returns.size());
13621362
result.insert(refs.cbegin(), refs.cend());
13631363
if (!inconclusive && result.size() > 1) {
13641364
SmallVector<ReferenceToken> refs_result;
@@ -1379,11 +1379,16 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13791379
return refs_result;
13801380
}
13811381

1382+
SmallVector<ReferenceToken> followAllReferences(const Token* tok, bool temporary)
1383+
{
1384+
return followAllReferencesInternal(tok, temporary);
1385+
}
1386+
13821387
const Token* followReferences(const Token* tok, ErrorPath* errors)
13831388
{
13841389
if (!tok)
13851390
return nullptr;
1386-
auto refs = followAllReferences(tok, true, false);
1391+
auto refs = followAllReferencesInternal(tok, true, false);
13871392
if (refs.size() == 1) {
13881393
if (errors)
13891394
*errors = std::move(refs.front().errors);

lib/astutils.h

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

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

262258
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: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,6 +2648,8 @@ TokenImpl::~TokenImpl()
26482648
delete mOriginalName;
26492649
delete mValueType;
26502650
delete mValues;
2651+
delete mRefs;
2652+
delete mRefsTemp;
26512653

26522654
if (mTemplateSimplifierPointers) {
26532655
for (auto *templateSimplifierPointer : *mTemplateSimplifierPointers) {
@@ -2739,3 +2741,16 @@ void Token::templateArgFrom(const Token* fromToken) {
27392741
mImpl->mTemplateArgLineNumber = fromToken ? fromToken->mImpl->mLineNumber : -1;
27402742
mImpl->mTemplateArgColumn = fromToken ? fromToken->mImpl->mColumn : -1;
27412743
}
2744+
2745+
const SmallVector<ReferenceToken>& Token::refs(bool temporary) const
2746+
{
2747+
if (temporary) {
2748+
if (!mImpl->mRefsTemp)
2749+
mImpl->mRefsTemp = new SmallVector<ReferenceToken>(followAllReferences(this, true));
2750+
return *mImpl->mRefsTemp;
2751+
}
2752+
2753+
if (!mImpl->mRefs)
2754+
mImpl->mRefs = new SmallVector<ReferenceToken>(followAllReferences(this, false));
2755+
return *mImpl->mRefs;
2756+
}

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_)) {}
@@ -149,6 +151,9 @@ struct TokenImpl {
149151
void setCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint value);
150152
bool getCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint &value) const;
151153

154+
SmallVector<ReferenceToken>* mRefs{};
155+
SmallVector<ReferenceToken>* mRefsTemp{};
156+
152157
TokenImpl() : mFunction(nullptr) {}
153158

154159
~TokenImpl();
@@ -1349,6 +1354,9 @@ class CPPCHECKLIB Token {
13491354
return mImpl->mValues ? *mImpl->mValues : TokenImpl::mEmptyValueList;
13501355
}
13511356

1357+
// provides and caches result of a followAllReferences() call
1358+
const SmallVector<ReferenceToken>& refs(bool temporary = true) const;
1359+
13521360
/**
13531361
* Sets the original name.
13541362
*/

lib/valueflow.cpp

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

32703270
for (const Token* tok2 : toks) {
3271-
for (const ReferenceToken& rt : followAllReferences(tok2, false)) {
3271+
for (const ReferenceToken& rt : tok2->refs(false)) {
32723272
ValueFlow::Value value = master;
32733273
value.tokvalue = rt.token;
32743274
value.errorPath.insert(value.errorPath.begin(), rt.errors.cbegin(), rt.errors.cend());
@@ -3980,7 +3980,7 @@ static void valueFlowForwardConst(Token* start,
39803980
} else {
39813981
[&] {
39823982
// Follow references
3983-
auto refs = followAllReferences(tok);
3983+
const auto& refs = tok->refs();
39843984
auto it = std::find_if(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
39853985
return ref.token->varId() == var->declarationId();
39863986
});

lib/vf_analyzers.cpp

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

0 commit comments

Comments
 (0)