-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added (optional) lazy execution of ValueFlow #4521
base: main
Are you sure you want to change the base?
Conversation
2b93752
to
07ba92f
Compare
|
||
std::function<void()> mValuesFunc; | ||
mutable bool mValuesSet; | ||
mutable bool mInSetValues; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These two variables can be moved into the mValuesFunc
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could do something similar to what we do for memoize
:
template<class F>
static std::function<void()> once(F f)
{
bool ran = false;
return [=]() mutable {
if (ran)
return;
ran = true;
f();
};
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was very hacky. I just tried to get rid what I wanted it to do.
These two variables can be moved into the
mValuesFunc
.
Good point.
We could do something similar to what we do for [
memoize
]
Will take a look. I know there are patterns for this but I rarely use them so I keep forgetting them.
} | ||
|
||
// cppcheck-suppress unusedFunction | ||
const ValueFlow::Value* Token::getContainerSizeValue(const MathLib::bigint val) const | ||
{ | ||
if (!mImpl->mValues) | ||
if (values().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kept it to avoid the function calls (which obviously won't do much) since some of these might be called loooooots of times. I haven't profiled any of this yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would not call it "redundant" but "unnecessary". Still needs to be profiled.
@@ -2388,24 +2385,24 @@ const ValueFlow::Value* Token::getMaxValue(bool condition, MathLib::bigint path) | |||
|
|||
const ValueFlow::Value* Token::getMovedValue() const | |||
{ | |||
if (!mImpl->mValues) | |||
if (values().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
} | ||
|
||
const ValueFlow::Value* Token::getMaxValue(bool condition, MathLib::bigint path) const | ||
{ | ||
if (!mImpl->mValues) | ||
if (values().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
} | ||
|
||
const ValueFlow::Value* Token::getValue(const MathLib::bigint val) const | ||
{ | ||
if (!mImpl->mValues) | ||
if (values().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
@@ -2340,39 +2337,39 @@ bool Token::hasKnownSymbolicValue(const Token* tok) const | |||
{ | |||
if (tok->exprId() == 0) | |||
return false; | |||
return mImpl->mValues && | |||
std::any_of(mImpl->mValues->begin(), mImpl->mValues->end(), [&](const ValueFlow::Value& value) { | |||
return !values().empty() && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
return value.isKnown() && value.isIntValue(); | ||
}); | ||
} | ||
|
||
bool Token::hasKnownValue() const | ||
{ | ||
return mImpl->mValues && std::any_of(mImpl->mValues->begin(), mImpl->mValues->end(), std::mem_fn(&ValueFlow::Value::isKnown)); | ||
return !values().empty() && std::any_of(values().begin(), values().end(), std::mem_fn(&ValueFlow::Value::isKnown)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
@@ -2316,22 +2314,21 @@ std::shared_ptr<ScopeInfo2> Token::scopeInfo() const | |||
|
|||
bool Token::hasKnownIntValue() const | |||
{ | |||
if (!mImpl->mValues) | |||
if (values().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
@@ -1868,12 +1866,12 @@ const Token *Token::getValueTokenMinStrSize(const Settings *settings, MathLib::b | |||
|
|||
const Token *Token::getValueTokenMaxStrLength() const | |||
{ | |||
if (!mImpl->mValues) | |||
if (values().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
@@ -1847,12 +1845,12 @@ const ValueFlow::Value * Token::getInvalidValue(const Token *ftok, nonneg int ar | |||
|
|||
const Token *Token::getValueTokenMinStrSize(const Settings *settings, MathLib::bigint* path) const | |||
{ | |||
if (!mImpl->mValues) | |||
if (values().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
return !v.isImpossible() && v.isIntValue() && v.intvalue >= val; | ||
}); | ||
} | ||
|
||
const ValueFlow::Value * Token::getInvalidValue(const Token *ftok, nonneg int argnr, const Settings *settings) const | ||
{ | ||
if (!mImpl->mValues || !settings) | ||
if (values().empty() || !settings) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
return !v.isImpossible() && v.isIntValue() && v.intvalue <= val; | ||
}); | ||
} | ||
|
||
const ValueFlow::Value * Token::getValueGE(const MathLib::bigint val, const Settings *settings) const | ||
{ | ||
if (!mImpl->mValues) | ||
if (values().empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values().empty()
is redundant here.
I think its a lot cleaner to use |
That was my takeaway as well after I "cracked" this and saw only one method needs to access the raw pointers - which is quite nice. I will extract the encapsulation and cleanup parts of this into a separate PR but it still needs some work (see below).
I am aware of that. I already fixed up a few mistakes I made in earlier revisions. But it is still very much WIP... I still have to profile this with valueflow enabled and disabled. Also the lazy execution doesn't save anything at all. There's also some tests failing with the lazy execution. But I guess they just lack the lazy execution hook. Still it is interesting and maybe we should make valueflow more explicit in tests so we know what depends on it. It might also help with determining how to increase the test coverage. But I haven't looked into this at all. |
This should "help" (as in executing less code) with tests which use the |
I will try to pull out the wrapper function for values so this can finally progress. |
No description provided.