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