Cppcheck
analyzer.h
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2023 Cppcheck team.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef analyzerH
20 #define analyzerH
21 
22 #include "config.h"
23 #include "mathlib.h"
24 #include <string>
25 #include <type_traits>
26 #include <vector>
27 
28 class Token;
29 template<class T>
30 class ValuePtr;
31 
32 struct Analyzer {
33  struct Action {
34 
35  Action() = default;
36  Action(const Action&) = default;
37  Action& operator=(const Action& rhs) = default;
38 
39  template<class T,
40  REQUIRES("T must be convertible to unsigned int", std::is_convertible<T, unsigned int> ),
41  REQUIRES("T must not be a bool", !std::is_same<T, bool> )>
42  // NOLINTNEXTLINE(google-explicit-constructor)
43  Action(T f) : mFlag(f) // cppcheck-suppress noExplicitConstructor
44  {}
45 
46  enum {
47  None = 0,
48  Read = (1 << 0),
49  Write = (1 << 1),
50  Invalid = (1 << 2),
51  Inconclusive = (1 << 3),
52  Match = (1 << 4),
53  Idempotent = (1 << 5),
54  Incremental = (1 << 6),
55  SymbolicMatch = (1 << 7),
56  Internal = (1 << 8),
57  };
58 
59  void set(unsigned int f, bool state = true) {
60  mFlag = state ? mFlag | f : mFlag & ~f;
61  }
62 
63  bool get(unsigned int f) const {
64  return ((mFlag & f) != 0);
65  }
66 
67  bool isRead() const {
68  return get(Read);
69  }
70 
71  bool isWrite() const {
72  return get(Write);
73  }
74 
75  bool isInvalid() const {
76  return get(Invalid);
77  }
78 
79  bool isInconclusive() const {
80  return get(Inconclusive);
81  }
82 
83  bool isNone() const {
84  return mFlag == None;
85  }
86 
87  bool isModified() const {
88  return isWrite() || isInvalid();
89  }
90 
91  bool isIdempotent() const {
92  return get(Idempotent);
93  }
94 
95  bool isIncremental() const {
96  return get(Incremental);
97  }
98 
99  bool isSymbolicMatch() const {
100  return get(SymbolicMatch);
101  }
102 
103  bool isInternal() const {
104  return get(Internal);
105  }
106 
107  bool matches() const {
108  return get(Match);
109  }
110 
112  set(a.mFlag);
113  return *this;
114  }
115 
116  friend Action operator|(Action a, Action b) {
117  a |= b;
118  return a;
119  }
120 
121  friend bool operator==(Action a, Action b) {
122  return a.mFlag == b.mFlag;
123  }
124 
125  friend bool operator!=(Action a, Action b) {
126  return a.mFlag != b.mFlag;
127  }
128 
129  private:
130  unsigned int mFlag{};
131  };
132 
134 
135  struct Result {
138  {}
141 
142  void update(Result rhs) {
143  if (terminate == Terminate::None)
144  terminate = rhs.terminate;
145  action |= rhs.action;
146  }
147  };
148 
149  enum class Direction { Forward, Reverse };
150 
151  struct Assume {
152  enum Flags {
153  None = 0,
154  Quiet = (1 << 0),
155  Absolute = (1 << 1),
156  ContainerEmpty = (1 << 2),
157  };
158  };
159 
161 
162  /// Analyze a token
163  virtual Action analyze(const Token* tok, Direction d) const = 0;
164  /// Update the state of the value
165  virtual void update(Token* tok, Action a, Direction d) = 0;
166  /// Try to evaluate the value of a token(most likely a condition)
167  virtual std::vector<MathLib::bigint> evaluate(Evaluate e, const Token* tok, const Token* ctx = nullptr) const = 0;
168  std::vector<MathLib::bigint> evaluate(const Token* tok, const Token* ctx = nullptr) const
169  {
170  return evaluate(Evaluate::Integral, tok, ctx);
171  }
172  /// Lower any values to possible
173  virtual bool lowerToPossible() = 0;
174  /// Lower any values to inconclusive
175  virtual bool lowerToInconclusive() = 0;
176  /// If the analysis is unsure whether to update a scope, this will return true if the analysis should bifurcate the scope
177  virtual bool updateScope(const Token* endBlock, bool modified) const = 0;
178  /// If the value is conditional
179  virtual bool isConditional() const = 0;
180  /// If analysis should stop on the condition
181  virtual bool stopOnCondition(const Token* condTok) const = 0;
182  /// The condition that will be assumed during analysis
183  virtual void assume(const Token* tok, bool state, unsigned int flags = 0) = 0;
184  /// Update the state of the program at the token
185  virtual void updateState(const Token* tok) = 0;
186  /// Return analyzer for expression at token
187  virtual ValuePtr<Analyzer> reanalyze(Token* tok, const std::string& msg = emptyString) const = 0;
188  virtual bool invalid() const {
189  return false;
190  }
191  virtual ~Analyzer() = default;
192  Analyzer(const Analyzer&) = default;
193 protected:
194  Analyzer() = default;
195 };
196 
197 #endif
The token list that the TokenList generates is a linked-list of this class.
Definition: token.h:150
#define REQUIRES(msg,...)
Definition: config.h:124
static const std::string emptyString
Definition: config.h:127
bool isNone() const
Definition: analyzer.h:83
friend Action operator|(Action a, Action b)
Definition: analyzer.h:116
bool isInternal() const
Definition: analyzer.h:103
bool get(unsigned int f) const
Definition: analyzer.h:63
bool matches() const
Definition: analyzer.h:107
Action(const Action &)=default
bool isInvalid() const
Definition: analyzer.h:75
bool isWrite() const
Definition: analyzer.h:71
unsigned int mFlag
Definition: analyzer.h:130
Action()=default
bool isInconclusive() const
Definition: analyzer.h:79
bool isIdempotent() const
Definition: analyzer.h:91
friend bool operator==(Action a, Action b)
Definition: analyzer.h:121
friend bool operator!=(Action a, Action b)
Definition: analyzer.h:125
bool isSymbolicMatch() const
Definition: analyzer.h:99
bool isModified() const
Definition: analyzer.h:87
Action & operator=(const Action &rhs)=default
void set(unsigned int f, bool state=true)
Definition: analyzer.h:59
bool isIncremental() const
Definition: analyzer.h:95
Action & operator|=(Action a)
Definition: analyzer.h:111
bool isRead() const
Definition: analyzer.h:67
Terminate terminate
Definition: analyzer.h:140
void update(Result rhs)
Definition: analyzer.h:142
Result(Action action=Action::None, Terminate terminate=Terminate::None)
Definition: analyzer.h:136
virtual bool isConditional() const =0
If the value is conditional.
Analyzer(const Analyzer &)=default
virtual Action analyze(const Token *tok, Direction d) const =0
Analyze a token.
Analyzer()=default
virtual void update(Token *tok, Action a, Direction d)=0
Update the state of the value.
virtual bool lowerToPossible()=0
Lower any values to possible.
virtual void updateState(const Token *tok)=0
Update the state of the program at the token.
virtual std::vector< MathLib::bigint > evaluate(Evaluate e, const Token *tok, const Token *ctx=nullptr) const =0
Try to evaluate the value of a token(most likely a condition)
virtual bool updateScope(const Token *endBlock, bool modified) const =0
If the analysis is unsure whether to update a scope, this will return true if the analysis should bif...
virtual bool stopOnCondition(const Token *condTok) const =0
If analysis should stop on the condition.
virtual ~Analyzer()=default
virtual ValuePtr< Analyzer > reanalyze(Token *tok, const std::string &msg=emptyString) const =0
Return analyzer for expression at token.
virtual bool lowerToInconclusive()=0
Lower any values to inconclusive.
virtual bool invalid() const
Definition: analyzer.h:188
virtual void assume(const Token *tok, bool state, unsigned int flags=0)=0
The condition that will be assumed during analysis.
std::vector< MathLib::bigint > evaluate(const Token *tok, const Token *ctx=nullptr) const
Definition: analyzer.h:168