Skip to content

Commit 5f301d3

Browse files
authored
introduced a cache for followAllReferences() calls (#7192)
1 parent 5ec627f commit 5f301d3

File tree

8 files changed

+94
-70
lines changed

8 files changed

+94
-70
lines changed

Makefile

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

lib/astutils.cpp

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,10 +1069,12 @@ bool isAliasOf(const Token *tok, nonneg int varid, bool* inconclusive)
10691069

10701070
bool isAliasOf(const Token* tok, const Token* expr, nonneg int* indirect)
10711071
{
1072-
const Token* r = nullptr;
10731072
if (indirect)
10741073
*indirect = 1;
1075-
for (const ReferenceToken& ref : followAllReferences(tok)) {
1074+
if (!tok)
1075+
return false;
1076+
const Token* r = nullptr;
1077+
for (const ReferenceToken& ref : tok->refs()) {
10761078
const bool pointer = astIsPointer(ref.token);
10771079
r = findAstNode(expr, [&](const Token* childTok) {
10781080
if (childTok->exprId() == 0)
@@ -1253,11 +1255,11 @@ static void followVariableExpressionError(const Token *tok1, const Token *tok2,
12531255
errors->push_back(std::move(item));
12541256
}
12551257

1256-
SmallVector<ReferenceToken> followAllReferences(const Token* tok,
1257-
bool temporary,
1258-
bool inconclusive,
1259-
ErrorPath errors,
1260-
int depth)
1258+
static SmallVector<ReferenceToken> followAllReferencesInternal(const Token* tok,
1259+
bool temporary = true,
1260+
bool inconclusive = true,
1261+
ErrorPath errors = ErrorPath{},
1262+
int depth = 20)
12611263
{
12621264
struct ReferenceTokenLess {
12631265
bool operator()(const ReferenceToken& x, const ReferenceToken& y) const {
@@ -1303,16 +1305,16 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13031305
return refs_result;
13041306
}
13051307
if (vartok)
1306-
return followAllReferences(vartok, temporary, inconclusive, std::move(errors), depth - 1);
1308+
return followAllReferencesInternal(vartok, temporary, inconclusive, std::move(errors), depth - 1);
13071309
}
13081310
}
13091311
} else if (Token::simpleMatch(tok, "?") && Token::simpleMatch(tok->astOperand2(), ":")) {
13101312
std::set<ReferenceToken, ReferenceTokenLess> result;
13111313
const Token* tok2 = tok->astOperand2();
13121314

1313-
auto refs = followAllReferences(tok2->astOperand1(), temporary, inconclusive, errors, depth - 1);
1315+
auto refs = followAllReferencesInternal(tok2->astOperand1(), temporary, inconclusive, errors, depth - 1);
13141316
result.insert(refs.cbegin(), refs.cend());
1315-
refs = followAllReferences(tok2->astOperand2(), temporary, inconclusive, errors, depth - 1);
1317+
refs = followAllReferencesInternal(tok2->astOperand2(), temporary, inconclusive, errors, depth - 1);
13161318
result.insert(refs.cbegin(), refs.cend());
13171319

13181320
if (!inconclusive && result.size() != 1) {
@@ -1340,7 +1342,7 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13401342
if (returnTok == tok)
13411343
continue;
13421344
for (const ReferenceToken& rt :
1343-
followAllReferences(returnTok, temporary, inconclusive, errors, depth - returns.size())) {
1345+
followAllReferencesInternal(returnTok, temporary, inconclusive, errors, depth - returns.size())) {
13441346
const Variable* argvar = rt.token->variable();
13451347
if (!argvar) {
13461348
SmallVector<ReferenceToken> refs_result;
@@ -1365,7 +1367,7 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13651367
er.emplace_back(returnTok, "Return reference.");
13661368
er.emplace_back(tok->previous(), "Called function passing '" + argTok->expressionString() + "'.");
13671369
auto refs =
1368-
followAllReferences(argTok, temporary, inconclusive, std::move(er), depth - returns.size());
1370+
followAllReferencesInternal(argTok, temporary, inconclusive, std::move(er), depth - returns.size());
13691371
result.insert(refs.cbegin(), refs.cend());
13701372
if (!inconclusive && result.size() > 1) {
13711373
SmallVector<ReferenceToken> refs_result;
@@ -1386,11 +1388,16 @@ SmallVector<ReferenceToken> followAllReferences(const Token* tok,
13861388
return refs_result;
13871389
}
13881390

1391+
SmallVector<ReferenceToken> followAllReferences(const Token* tok, bool temporary)
1392+
{
1393+
return followAllReferencesInternal(tok, temporary);
1394+
}
1395+
13891396
const Token* followReferences(const Token* tok, ErrorPath* errors)
13901397
{
13911398
if (!tok)
13921399
return nullptr;
1393-
auto refs = followAllReferences(tok, true, false);
1400+
auto refs = followAllReferencesInternal(tok, true, false);
13941401
if (refs.size() == 1) {
13951402
if (errors)
13961403
*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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2738,3 +2738,16 @@ void Token::templateArgFrom(const Token* fromToken) {
27382738
mImpl->mTemplateArgLineNumber = fromToken ? fromToken->mImpl->mLineNumber : -1;
27392739
mImpl->mTemplateArgColumn = fromToken ? fromToken->mImpl->mColumn : -1;
27402740
}
2741+
2742+
const SmallVector<ReferenceToken>& Token::refs(bool temporary) const
2743+
{
2744+
if (temporary) {
2745+
if (!mImpl->mRefsTemp)
2746+
mImpl->mRefsTemp.reset(new SmallVector<ReferenceToken>(followAllReferences(this, true)));
2747+
return *mImpl->mRefsTemp;
2748+
}
2749+
2750+
if (!mImpl->mRefs)
2751+
mImpl->mRefs.reset(new SmallVector<ReferenceToken>(followAllReferences(this, false)));
2752+
return *mImpl->mRefs;
2753+
}

lib/token.h

Lines changed: 10 additions & 3 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"
@@ -54,6 +55,7 @@ class ConstTokenRange;
5455
class Token;
5556
struct TokensFrontBack;
5657
class TokenList;
58+
struct ReferenceToken;
5759

5860
struct ScopeInfo2 {
5961
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_)) {}
@@ -119,7 +121,7 @@ class CPPCHECKLIB Token {
119121
// symbol database information
120122
const Scope* mScope{};
121123
union {
122-
const Function *mFunction;
124+
const Function *mFunction{};
123125
const Variable *mVariable;
124126
const ::Type* mType;
125127
const Enumerator *mEnumerator;
@@ -167,11 +169,13 @@ class CPPCHECKLIB Token {
167169

168170
TokenDebug mDebug{};
169171

172+
std::unique_ptr<SmallVector<ReferenceToken>> mRefs;
173+
std::unique_ptr<SmallVector<ReferenceToken>> mRefsTemp;
174+
170175
void setCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint value);
171176
bool getCppcheckAttribute(CppcheckAttributesType type, MathLib::bigint &value) const;
172177

173-
Impl() : mFunction(nullptr) {}
174-
178+
Impl() = default;
175179
~Impl();
176180

177181
Impl(const Impl &) = delete;
@@ -1353,6 +1357,9 @@ class CPPCHECKLIB Token {
13531357
return mImpl->mValues ? *mImpl->mValues : mEmptyValueList;
13541358
}
13551359

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

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)