parent
7368a54629
commit
5f4a900f88
|
@ -296,8 +296,14 @@ static T* nextAfterAstRightmostLeafGeneric(T* tok)
|
|||
return rightmostLeaf->next();
|
||||
}
|
||||
|
||||
const Token* nextAfterAstRightmostLeaf(const Token* tok) { return nextAfterAstRightmostLeafGeneric(tok); }
|
||||
Token* nextAfterAstRightmostLeaf(Token* tok) { return nextAfterAstRightmostLeafGeneric(tok); }
|
||||
const Token* nextAfterAstRightmostLeaf(const Token* tok)
|
||||
{
|
||||
return nextAfterAstRightmostLeafGeneric(tok);
|
||||
}
|
||||
Token* nextAfterAstRightmostLeaf(Token* tok)
|
||||
{
|
||||
return nextAfterAstRightmostLeafGeneric(tok);
|
||||
}
|
||||
|
||||
const Token* astParentSkipParens(const Token* tok)
|
||||
{
|
||||
|
@ -390,11 +396,23 @@ static T* getCondTokFromEndImpl(T* endBlock)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
Token* getCondTok(Token* tok) { return getCondTokImpl(tok); }
|
||||
const Token* getCondTok(const Token* tok) { return getCondTokImpl(tok); }
|
||||
Token* getCondTok(Token* tok)
|
||||
{
|
||||
return getCondTokImpl(tok);
|
||||
}
|
||||
const Token* getCondTok(const Token* tok)
|
||||
{
|
||||
return getCondTokImpl(tok);
|
||||
}
|
||||
|
||||
Token* getCondTokFromEnd(Token* endBlock) { return getCondTokFromEndImpl(endBlock); }
|
||||
const Token* getCondTokFromEnd(const Token* endBlock) { return getCondTokFromEndImpl(endBlock); }
|
||||
Token* getCondTokFromEnd(Token* endBlock)
|
||||
{
|
||||
return getCondTokFromEndImpl(endBlock);
|
||||
}
|
||||
const Token* getCondTokFromEnd(const Token* endBlock)
|
||||
{
|
||||
return getCondTokFromEndImpl(endBlock);
|
||||
}
|
||||
|
||||
static const Token * getVariableInitExpression(const Variable * var)
|
||||
{
|
||||
|
@ -1478,8 +1496,14 @@ T* findLambdaEndTokenGeneric(T* first)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
const Token* findLambdaEndToken(const Token* first) { return findLambdaEndTokenGeneric(first); }
|
||||
Token* findLambdaEndToken(Token* first) { return findLambdaEndTokenGeneric(first); }
|
||||
const Token* findLambdaEndToken(const Token* first)
|
||||
{
|
||||
return findLambdaEndTokenGeneric(first);
|
||||
}
|
||||
Token* findLambdaEndToken(Token* first)
|
||||
{
|
||||
return findLambdaEndTokenGeneric(first);
|
||||
}
|
||||
|
||||
bool isLikelyStream(bool cpp, const Token *stream)
|
||||
{
|
||||
|
|
|
@ -8,16 +8,18 @@ struct ForwardTraversal {
|
|||
ValuePtr<ForwardAnalyzer> analyzer;
|
||||
const Settings* settings;
|
||||
|
||||
std::pair<bool, bool> evalCond(const Token* tok)
|
||||
{
|
||||
std::pair<bool, bool> evalCond(const Token* tok) {
|
||||
std::vector<int> result = analyzer->evaluate(tok);
|
||||
bool checkThen = std::any_of(result.begin(), result.end(), [](int x) { return x; });
|
||||
bool checkElse = std::any_of(result.begin(), result.end(), [](int x) { return !x; });
|
||||
bool checkThen = std::any_of(result.begin(), result.end(), [](int x) {
|
||||
return x;
|
||||
});
|
||||
bool checkElse = std::any_of(result.begin(), result.end(), [](int x) {
|
||||
return !x;
|
||||
});
|
||||
return std::make_pair(checkThen, checkElse);
|
||||
}
|
||||
|
||||
Progress update(Token* tok)
|
||||
{
|
||||
Progress update(Token* tok) {
|
||||
ForwardAnalyzer::Action action = analyzer->analyze(tok);
|
||||
if (!action.isNone())
|
||||
analyzer->update(tok, action);
|
||||
|
@ -26,8 +28,7 @@ struct ForwardTraversal {
|
|||
return Progress::Continue;
|
||||
}
|
||||
|
||||
Progress updateTok(Token* tok, Token** out = nullptr)
|
||||
{
|
||||
Progress updateTok(Token* tok, Token** out = nullptr) {
|
||||
if (Token::Match(tok, "asm|goto|continue|setjmp|longjmp"))
|
||||
return Progress::Break;
|
||||
else if (Token::Match(tok, "return|throw") || isEscapeFunction(tok, &settings->library)) {
|
||||
|
@ -57,8 +58,7 @@ struct ForwardTraversal {
|
|||
return Progress::Continue;
|
||||
}
|
||||
|
||||
Progress updateRecursive(Token* tok)
|
||||
{
|
||||
Progress updateRecursive(Token* tok) {
|
||||
if (!tok)
|
||||
return Progress::Continue;
|
||||
if (tok->astOperand1() && updateRecursive(tok->astOperand1()) == Progress::Break)
|
||||
|
@ -71,8 +71,7 @@ struct ForwardTraversal {
|
|||
return Progress::Continue;
|
||||
}
|
||||
|
||||
Progress updateConditional(Token* tok)
|
||||
{
|
||||
Progress updateConditional(Token* tok) {
|
||||
if (Token::Match(tok, "?|&&|%oror%")) {
|
||||
Token* condTok = tok->astOperand1();
|
||||
if (updateRecursive(condTok) == Progress::Break)
|
||||
|
@ -105,8 +104,7 @@ struct ForwardTraversal {
|
|||
}
|
||||
|
||||
template <class T, class Predicate>
|
||||
T* findRange(T* start, const Token* end, Predicate pred)
|
||||
{
|
||||
T* findRange(T* start, const Token* end, Predicate pred) {
|
||||
for (T* tok = start; tok && tok != end; tok = tok->next()) {
|
||||
ForwardAnalyzer::Action action = analyzer->analyze(tok);
|
||||
if (pred(action))
|
||||
|
@ -116,13 +114,13 @@ struct ForwardTraversal {
|
|||
}
|
||||
|
||||
template <class T>
|
||||
T* findActionRange(T* start, const Token* end, ForwardAnalyzer::Action action)
|
||||
{
|
||||
return findRange(start, end, [&](ForwardAnalyzer::Action a) { return a == action; });
|
||||
T* findActionRange(T* start, const Token* end, ForwardAnalyzer::Action action) {
|
||||
return findRange(start, end, [&](ForwardAnalyzer::Action a) {
|
||||
return a == action;
|
||||
});
|
||||
}
|
||||
|
||||
ForwardAnalyzer::Action analyzeRange(const Token* start, const Token* end)
|
||||
{
|
||||
ForwardAnalyzer::Action analyzeRange(const Token* start, const Token* end) {
|
||||
ForwardAnalyzer::Action result = ForwardAnalyzer::Action::None;
|
||||
for (const Token* tok = start; tok && tok != end; tok = tok->next()) {
|
||||
ForwardAnalyzer::Action action = analyzer->analyze(tok);
|
||||
|
@ -133,18 +131,18 @@ struct ForwardTraversal {
|
|||
return result;
|
||||
}
|
||||
|
||||
void forkScope(const Token* endBlock, bool isModified = false)
|
||||
{
|
||||
void forkScope(const Token* endBlock, bool isModified = false) {
|
||||
if (analyzer->updateScope(endBlock, isModified)) {
|
||||
ForwardTraversal ft = *this;
|
||||
ft.updateRange(endBlock->link(), endBlock);
|
||||
}
|
||||
}
|
||||
|
||||
static bool hasGoto(const Token* endBlock) { return Token::findsimplematch(endBlock->link(), "goto", endBlock); }
|
||||
static bool hasGoto(const Token* endBlock) {
|
||||
return Token::findsimplematch(endBlock->link(), "goto", endBlock);
|
||||
}
|
||||
|
||||
bool isEscapeScope(const Token* endBlock, bool unknown = false)
|
||||
{
|
||||
bool isEscapeScope(const Token* endBlock, bool unknown = false) {
|
||||
const Token* ftok = nullptr;
|
||||
bool r = isReturnScope(endBlock, &settings->library, &ftok);
|
||||
if (!r && ftok)
|
||||
|
@ -159,17 +157,17 @@ struct ForwardTraversal {
|
|||
Inconclusive,
|
||||
};
|
||||
|
||||
ForwardAnalyzer::Action analyzeScope(const Token* endBlock) { return analyzeRange(endBlock->link(), endBlock); }
|
||||
ForwardAnalyzer::Action analyzeScope(const Token* endBlock) {
|
||||
return analyzeRange(endBlock->link(), endBlock);
|
||||
}
|
||||
|
||||
ForwardAnalyzer::Action checkScope(const Token* endBlock)
|
||||
{
|
||||
ForwardAnalyzer::Action checkScope(const Token* endBlock) {
|
||||
ForwardAnalyzer::Action a = analyzeScope(endBlock);
|
||||
forkScope(endBlock, a.isModified());
|
||||
return a;
|
||||
}
|
||||
|
||||
Progress updateLoop(Token* endBlock, Token* condTok)
|
||||
{
|
||||
Progress updateLoop(Token* endBlock, Token* condTok) {
|
||||
ForwardAnalyzer::Action a = analyzeScope(endBlock);
|
||||
if (a.isInconclusive()) {
|
||||
if (!analyzer->lowerToInconclusive())
|
||||
|
@ -193,8 +191,7 @@ struct ForwardTraversal {
|
|||
return Progress::Continue;
|
||||
}
|
||||
|
||||
Progress updateRange(Token* start, const Token* end)
|
||||
{
|
||||
Progress updateRange(Token* start, const Token* end) {
|
||||
for (Token* tok = start; tok && tok != end; tok = tok->next()) {
|
||||
Token* next = nullptr;
|
||||
|
||||
|
@ -348,15 +345,13 @@ struct ForwardTraversal {
|
|||
return Progress::Continue;
|
||||
}
|
||||
|
||||
static bool isUnevaluated(const Token* tok)
|
||||
{
|
||||
static bool isUnevaluated(const Token* tok) {
|
||||
if (Token::Match(tok->previous(), "sizeof|decltype ("))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static Token* assignExpr(Token* tok)
|
||||
{
|
||||
static Token* assignExpr(Token* tok) {
|
||||
while (tok->astParent() && astIsLHS(tok)) {
|
||||
if (Token::Match(tok->astParent(), "%assign%"))
|
||||
return tok->astParent();
|
||||
|
@ -365,15 +360,13 @@ struct ForwardTraversal {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static const Scope* findBreakScope(const Scope* scope)
|
||||
{
|
||||
static const Scope* findBreakScope(const Scope* scope) {
|
||||
while (scope && scope->type != Scope::eWhile && scope->type != Scope::eFor && scope->type != Scope::eSwitch)
|
||||
scope = scope->nestedIn;
|
||||
return scope;
|
||||
}
|
||||
|
||||
static Token* skipTo(Token* tok, const Token* dest, const Token* end = nullptr)
|
||||
{
|
||||
static Token* skipTo(Token* tok, const Token* dest, const Token* end = nullptr) {
|
||||
if (end && dest->index() > end->index())
|
||||
return nullptr;
|
||||
int i = dest->index() - tok->index();
|
||||
|
@ -382,8 +375,7 @@ struct ForwardTraversal {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
static bool isConditional(const Token* tok)
|
||||
{
|
||||
static bool isConditional(const Token* tok) {
|
||||
const Token* parent = tok->astParent();
|
||||
while (parent && !Token::Match(parent, "%oror%|&&|:")) {
|
||||
tok = parent;
|
||||
|
@ -393,8 +385,7 @@ struct ForwardTraversal {
|
|||
}
|
||||
|
||||
template <class T>
|
||||
static T* getInitTok(T* tok)
|
||||
{
|
||||
static T* getInitTok(T* tok) {
|
||||
if (!tok)
|
||||
return nullptr;
|
||||
if (Token::Match(tok, "%name% ("))
|
||||
|
|
|
@ -41,37 +41,55 @@ struct ForwardAnalyzer {
|
|||
Inconclusive = (1 << 3),
|
||||
};
|
||||
|
||||
void set(unsigned int f, bool state = true) { mFlag = state ? mFlag | f : mFlag & ~f; }
|
||||
void set(unsigned int f, bool state = true) {
|
||||
mFlag = state ? mFlag | f : mFlag & ~f;
|
||||
}
|
||||
|
||||
bool get(unsigned int f) const { return ((mFlag & f) != 0); }
|
||||
bool get(unsigned int f) const {
|
||||
return ((mFlag & f) != 0);
|
||||
}
|
||||
|
||||
bool isRead() const { return get(Read); }
|
||||
bool isRead() const {
|
||||
return get(Read);
|
||||
}
|
||||
|
||||
bool isWrite() const { return get(Write); }
|
||||
bool isWrite() const {
|
||||
return get(Write);
|
||||
}
|
||||
|
||||
bool isInvalid() const { return get(Invalid); }
|
||||
bool isInvalid() const {
|
||||
return get(Invalid);
|
||||
}
|
||||
|
||||
bool isInconclusive() const { return get(Inconclusive); }
|
||||
bool isInconclusive() const {
|
||||
return get(Inconclusive);
|
||||
}
|
||||
|
||||
bool isNone() const { return mFlag == None; }
|
||||
bool isNone() const {
|
||||
return mFlag == None;
|
||||
}
|
||||
|
||||
bool isModified() const { return isWrite() || isInvalid(); }
|
||||
bool isModified() const {
|
||||
return isWrite() || isInvalid();
|
||||
}
|
||||
|
||||
Action& operator|=(Action a)
|
||||
{
|
||||
Action& operator|=(Action a) {
|
||||
set(a.mFlag);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend Action operator|(Action a, Action b)
|
||||
{
|
||||
friend Action operator|(Action a, Action b) {
|
||||
a |= b;
|
||||
return a;
|
||||
}
|
||||
|
||||
friend bool operator==(Action a, Action b) { return a.mFlag == b.mFlag; }
|
||||
friend bool operator==(Action a, Action b) {
|
||||
return a.mFlag == b.mFlag;
|
||||
}
|
||||
|
||||
friend bool operator!=(Action a, Action b) { return a.mFlag != b.mFlag; }
|
||||
friend bool operator!=(Action a, Action b) {
|
||||
return a.mFlag != b.mFlag;
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned int mFlag;
|
||||
|
|
|
@ -33,7 +33,10 @@ bool ProgramMemory::getTokValue(nonneg int varid, const Token** result) const
|
|||
return found;
|
||||
}
|
||||
|
||||
void ProgramMemory::setUnknown(nonneg int varid) { values[varid].valueType = ValueFlow::Value::ValueType::UNINIT; }
|
||||
void ProgramMemory::setUnknown(nonneg int varid)
|
||||
{
|
||||
values[varid].valueType = ValueFlow::Value::ValueType::UNINIT;
|
||||
}
|
||||
|
||||
bool ProgramMemory::hasValue(nonneg int varid)
|
||||
{
|
||||
|
|
|
@ -2244,10 +2244,11 @@ struct VariableForwardAnalyzer : ForwardAnalyzer {
|
|||
|
||||
VariableForwardAnalyzer() = default;
|
||||
|
||||
bool isWritableValue() const { return value.isIntValue() || value.isFloatValue(); }
|
||||
bool isWritableValue() const {
|
||||
return value.isIntValue() || value.isFloatValue();
|
||||
}
|
||||
|
||||
virtual Action analyze(const Token* tok) const OVERRIDE
|
||||
{
|
||||
virtual Action analyze(const Token* tok) const OVERRIDE {
|
||||
bool cpp = true;
|
||||
if (tok->varId() == varid) {
|
||||
const Token* parent = tok->astParent();
|
||||
|
@ -2299,8 +2300,7 @@ struct VariableForwardAnalyzer : ForwardAnalyzer {
|
|||
}
|
||||
return Action::None;
|
||||
}
|
||||
virtual void update(Token* tok, Action a) OVERRIDE
|
||||
{
|
||||
virtual void update(Token* tok, Action a) OVERRIDE {
|
||||
if (a.isRead())
|
||||
setTokenValue(tok, value, settings);
|
||||
if (a.isInconclusive())
|
||||
|
@ -2328,8 +2328,7 @@ struct VariableForwardAnalyzer : ForwardAnalyzer {
|
|||
}
|
||||
}
|
||||
}
|
||||
virtual std::vector<int> evaluate(const Token* tok) const OVERRIDE
|
||||
{
|
||||
virtual std::vector<int> evaluate(const Token* tok) const OVERRIDE {
|
||||
if (tok->hasKnownIntValue())
|
||||
return {static_cast<int>(tok->values().front().intvalue)};
|
||||
std::vector<int> result;
|
||||
|
@ -2340,29 +2339,25 @@ struct VariableForwardAnalyzer : ForwardAnalyzer {
|
|||
result.push_back(0);
|
||||
return result;
|
||||
}
|
||||
virtual bool lowerToPossible() OVERRIDE
|
||||
{
|
||||
virtual bool lowerToPossible() OVERRIDE {
|
||||
if (value.isImpossible())
|
||||
return false;
|
||||
value.changeKnownToPossible();
|
||||
return true;
|
||||
}
|
||||
virtual bool lowerToInconclusive() OVERRIDE
|
||||
{
|
||||
virtual bool lowerToInconclusive() OVERRIDE {
|
||||
if (value.isImpossible())
|
||||
return false;
|
||||
value.setInconclusive();
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void assume(const Token*, bool) OVERRIDE
|
||||
{
|
||||
virtual void assume(const Token*, bool) OVERRIDE {
|
||||
// TODO: Use this to improve Evaluate
|
||||
value.conditional = true;
|
||||
}
|
||||
|
||||
virtual bool isConditional() const OVERRIDE
|
||||
{
|
||||
virtual bool isConditional() const OVERRIDE {
|
||||
if (value.conditional)
|
||||
return true;
|
||||
if (value.condition)
|
||||
|
@ -2370,8 +2365,7 @@ struct VariableForwardAnalyzer : ForwardAnalyzer {
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual bool updateScope(const Token* endBlock, bool) const OVERRIDE
|
||||
{
|
||||
virtual bool updateScope(const Token* endBlock, bool) const OVERRIDE {
|
||||
const Scope* scope = endBlock->scope();
|
||||
if (!scope)
|
||||
return false;
|
||||
|
|
|
@ -29,7 +29,9 @@ template <class T>
|
|||
class CPPCHECKLIB ValuePtr {
|
||||
template <class U>
|
||||
struct cloner {
|
||||
static T* apply(const T* x) { return new U(*static_cast<const U*>(x)); }
|
||||
static T* apply(const T* x) {
|
||||
return new U(*static_cast<const U*>(x));
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -44,39 +46,48 @@ class CPPCHECKLIB ValuePtr {
|
|||
ValuePtr(const U& value) : mPtr(cloner<U>::apply(&value)), mClone(&cloner<U>::apply)
|
||||
{}
|
||||
|
||||
ValuePtr(const ValuePtr& rhs) : mPtr(nullptr), mClone(rhs.mClone)
|
||||
{
|
||||
ValuePtr(const ValuePtr& rhs) : mPtr(nullptr), mClone(rhs.mClone) {
|
||||
if (rhs) {
|
||||
mPtr.reset(mClone(rhs.get()));
|
||||
}
|
||||
}
|
||||
ValuePtr(ValuePtr&& rhs) : mPtr(std::move(rhs.mPtr)), mClone(std::move(rhs.mClone)) {}
|
||||
|
||||
pointer release() { return mPtr.release(); }
|
||||
pointer release() {
|
||||
return mPtr.release();
|
||||
}
|
||||
|
||||
T* get() NOEXCEPT { return mPtr.get(); }
|
||||
const T* get() const NOEXCEPT { return mPtr.get(); }
|
||||
const T* get() const NOEXCEPT {
|
||||
return mPtr.get();
|
||||
}
|
||||
|
||||
T& operator*() { return *get(); }
|
||||
const T& operator*() const { return *get(); }
|
||||
T& operator*() {
|
||||
return *get();
|
||||
}
|
||||
const T& operator*() const {
|
||||
return *get();
|
||||
}
|
||||
|
||||
T* operator->() NOEXCEPT { return get(); }
|
||||
const T* operator->() const NOEXCEPT { return get(); }
|
||||
const T* operator->() const NOEXCEPT {
|
||||
return get();
|
||||
}
|
||||
|
||||
void swap(ValuePtr& rhs)
|
||||
{
|
||||
void swap(ValuePtr& rhs) {
|
||||
using std::swap;
|
||||
swap(mPtr, rhs.mPtr);
|
||||
swap(mClone, rhs.mClone);
|
||||
}
|
||||
|
||||
ValuePtr<T>& operator=(ValuePtr rhs)
|
||||
{
|
||||
ValuePtr<T>& operator=(ValuePtr rhs) {
|
||||
swap(rhs);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() const NOEXCEPT { return !!mPtr; }
|
||||
operator bool() const NOEXCEPT {
|
||||
return !!mPtr;
|
||||
}
|
||||
~ValuePtr() {}
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue