Skip to content

Commit 2bfef0e

Browse files
committed
introduced a cache for followAllReferences() calls
1 parent d69955c commit 2bfef0e

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
@@ -1073,7 +1073,7 @@ bool isAliasOf(const Token* tok, const Token* expr, nonneg int* indirect)
10731073
const Token* r = nullptr;
10741074
if (indirect)
10751075
*indirect = 1;
1076-
for (const ReferenceToken& ref : followAllReferences(tok)) {
1076+
for (const ReferenceToken& ref : tok->refs()) {
10771077
const bool pointer = astIsPointer(ref.token);
10781078
r = findAstNode(expr, [&](const Token* childTok) {
10791079
if (childTok->exprId() == 0)
@@ -1252,11 +1252,11 @@ static void followVariableExpressionError(const Token *tok1, const Token *tok2,
12521252
errors->push_back(std::move(item));
12531253
}
12541254

1255-
SmallVector<ReferenceToken> followAllReferences(const Token* tok,
1256-
bool temporary,
1257-
bool inconclusive,
1258-
ErrorPath errors,
1259-
int depth)
1255+
static SmallVector<ReferenceToken> followAllReferencesInternal(const Token* tok,
1256+
bool temporary = true,
1257+
bool inconclusive = true,
1258+
ErrorPath errors = ErrorPath{},
1259+
int depth = 20)
12601260
{
12611261
struct ReferenceTokenLess {
12621262
bool operator()(const ReferenceToken& x, const ReferenceToken& y) const {
@@ -1302,16 +1302,16 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13021302
return refs_result;
13031303
}
13041304
if (vartok)
1305-
return followAllReferences(vartok, temporary, inconclusive, std::move(errors), depth - 1);
1305+
return followAllReferencesInternal(vartok, temporary, inconclusive, std::move(errors), depth - 1);
13061306
}
13071307
}
13081308
} else if (Token::simpleMatch(tok, "?") && Token::simpleMatch(tok->astOperand2(), ":")) {
13091309
std::set<ReferenceToken, ReferenceTokenLess> result;
13101310
const Token* tok2 = tok->astOperand2();
13111311

1312-
auto refs = followAllReferences(tok2->astOperand1(), temporary, inconclusive, errors, depth - 1);
1312+
auto refs = followAllReferencesInternal(tok2->astOperand1(), temporary, inconclusive, errors, depth - 1);
13131313
result.insert(refs.cbegin(), refs.cend());
1314-
refs = followAllReferences(tok2->astOperand2(), temporary, inconclusive, errors, depth - 1);
1314+
refs = followAllReferencesInternal(tok2->astOperand2(), temporary, inconclusive, errors, depth - 1);
13151315
result.insert(refs.cbegin(), refs.cend());
13161316

13171317
if (!inconclusive && result.size() != 1) {
@@ -1339,7 +1339,7 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13391339
if (returnTok == tok)
13401340
continue;
13411341
for (const ReferenceToken& rt :
1342-
followAllReferences(returnTok, temporary, inconclusive, errors, depth - returns.size())) {
1342+
followAllReferencesInternal(returnTok, temporary, inconclusive, errors, depth - returns.size())) {
13431343
const Variable* argvar = rt.token->variable();
13441344
if (!argvar) {
13451345
SmallVector<ReferenceToken> refs_result;
@@ -1364,7 +1364,7 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13641364
er.emplace_back(returnTok, "Return reference.");
13651365
er.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
13661366
auto refs =
1367-
followAllReferences(argTok, temporary, inconclusive, std::move(er), depth - returns.size());
1367+
followAllReferencesInternal(argTok, temporary, inconclusive, std::move(er), depth - returns.size());
13681368
result.insert(refs.cbegin(), refs.cend());
13691369
if (!inconclusive && result.size() > 1) {
13701370
SmallVector<ReferenceToken> refs_result;
@@ -1385,11 +1385,16 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13851385
return refs_result;
13861386
}
13871387

1388+
SmallVector<ReferenceToken> followAllReferences(const Token* tok, bool temporary)
1389+
{
1390+
return followAllReferencesInternal(tok, temporary);
1391+
}
1392+
13881393
const Token* followReferences(const Token* tok, ErrorPath* errors)
13891394
{
13901395
if (!tok)
13911396
return nullptr;
1392-
auto refs = followAllReferences(tok, true, false);
1397+
auto refs = followAllReferencesInternal(tok, true, false);
13931398
if (refs.size() == 1) {
13941399
if (errors)
13951400
*errors = std::move(refs.front().errors);

lib/astutils.h

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

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

264260
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
@@ -2647,6 +2647,8 @@ Token::Impl::~Impl()
26472647
delete mOriginalName;
26482648
delete mValueType;
26492649
delete mValues;
2650+
delete mRefs;
2651+
delete mRefsTemp;
26502652

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

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_)) {}
@@ -166,6 +168,9 @@ class CPPCHECKLIB Token {
166168

167169
TokenDebug mDebug{};
168170

171+
SmallVector<ReferenceToken>* mRefs{};
172+
SmallVector<ReferenceToken>* mRefsTemp{};
173+
169174
void setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value);
170175
bool getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const;
171176

@@ -1352,6 +1357,9 @@ class CPPCHECKLIB Token {
13521357
return mImpl->mValues ? *mImpl->mValues : mEmptyValueList;
13531358
}
13541359

1360+
// provides and caches result of a followAllReferences() call
1361+
const SmallVector<ReferenceToken>& refs(bool temporary = true) const;
1362+
13551363
/**
13561364
* Sets the original name.
13571365
*/

lib/valueflow.cpp

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

32683268
for (const Token* tok2 : toks) {
3269-
for (const ReferenceToken& rt : followAllReferences(tok2, false)) {
3269+
for (const ReferenceToken& rt : tok2->refs(false)) {
32703270
ValueFlow::Value value = master;
32713271
value.tokvalue = rt.token;
32723272
value.errorPath.insert(value.errorPath.begin(), rt.errors.cbegin(), rt.errors.cend());
@@ -3978,7 +3978,7 @@ static void valueFlowForwardConst(Token* start,
39783978
} else {
39793979
[&] {
39803980
// Follow references
3981-
auto refs = followAllReferences(tok);
3981+
const auto& refs = tok->refs();
39823982
auto it = std::find_if(refs.cbegin(), refs.cend(), [&](const ReferenceToken& ref) {
39833983
return ref.token->varId() == var->declarationId();
39843984
});

lib/vf_analyzers.cpp

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

0 commit comments

Comments
 (0)