1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2021 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 //---------------------------------------------------------------------------
20 #ifndef tokenH
21 #define tokenH
22 //---------------------------------------------------------------------------
23 
24 #include "config.h"
25 #include "mathlib.h"
26 #include "valueflow.h"
27 #include "templatesimplifier.h"
28 #include "utils.h"
29 
30 #include <cstddef>
31 #include <functional>
32 #include <list>
33 #include <memory>
34 #include <ostream>
35 #include <string>
36 #include <vector>
37 
38 class Enumerator;
39 class Function;
40 class Scope;
41 class Settings;
42 class Type;
43 class ValueType;
44 class Variable;
45 class TokenList;
46 
47 class ConstTokenRange;
48 
49 /**
50  * @brief This struct stores pointers to the front and back tokens of the list this token is in.
51  */
52 struct TokensFrontBack {
53     Token *front;
54     Token *back;
55     const TokenList* list;
56 };
57 
58 struct ScopeInfo2 {
nameScopeInfo259     ScopeInfo2(const std::string &name_, const Token *bodyEnd_, const std::set<std::string> &usingNamespaces_ = std::set<std::string>()) : name(name_), bodyEnd(bodyEnd_), usingNamespaces(usingNamespaces_) {}
60     std::string name;
61     const Token * const bodyEnd;
62     std::set<std::string> usingNamespaces;
63 };
64 
65 struct TokenImpl {
66     nonneg int mVarId;
67     nonneg int mFileIndex;
68     nonneg int mLineNumber;
69     nonneg int mColumn;
70     nonneg int mExprId;
71 
72     // AST..
73     Token *mAstOperand1;
74     Token *mAstOperand2;
75     Token *mAstParent;
76 
77     // symbol database information
78     const Scope *mScope;
79     union {
80         const Function *mFunction;
81         const Variable *mVariable;
82         const ::Type* mType;
83         const Enumerator *mEnumerator;
84     };
85 
86     /**
87      * A value from 0-100 that provides a rough idea about where in the token
88      * list this token is located.
89      */
90     nonneg int mProgressValue;
91 
92     /**
93      * Token index. Position in token list
94      */
95     nonneg int mIndex;
96 
97     // original name like size_t
98     std::string* mOriginalName;
99 
100     // ValueType
101     ValueType *mValueType;
102 
103     // ValueFlow
104     std::list<ValueFlow::Value>* mValues;
105     static const std::list<ValueFlow::Value> mEmptyValueList;
106 
107     // Pointer to a template in the template simplifier
108     std::set<TemplateSimplifier::TokenAndName*>* mTemplateSimplifierPointers;
109 
110     // Pointer to the object representing this token's scope
111     std::shared_ptr<ScopeInfo2> mScopeInfo;
112 
113     // __cppcheck_in_range__
114     struct CppcheckAttributes {
115         enum Type {LOW,HIGH} type;
116         MathLib::bigint value;
117         struct CppcheckAttributes *next;
118     };
119     struct CppcheckAttributes *mCppcheckAttributes;
120 
121     // For memoization, to speed up parsing of huge arrays #8897
122     enum class Cpp11init {UNKNOWN, CPP11INIT, NOINIT} mCpp11init;
123 
124     /** Bitfield bit count. */
125     unsigned char mBits;
126 
127     void setCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint value);
128     bool getCppcheckAttribute(CppcheckAttributes::Type type, MathLib::bigint *value) const;
129 
TokenImplTokenImpl130     TokenImpl()
131         : mVarId(0)
132         , mFileIndex(0)
133         , mLineNumber(0)
134         , mColumn(0)
135         , mExprId(0)
136         , mAstOperand1(nullptr)
137         , mAstOperand2(nullptr)
138         , mAstParent(nullptr)
139         , mScope(nullptr)
140         , mFunction(nullptr) // Initialize whole union
141         , mProgressValue(0)
142         , mIndex(0)
143         , mOriginalName(nullptr)
144         , mValueType(nullptr)
145         , mValues(nullptr)
146         , mTemplateSimplifierPointers(nullptr)
147         , mScopeInfo(nullptr)
148         , mCppcheckAttributes(nullptr)
149         , mCpp11init(Cpp11init::UNKNOWN)
150         , mBits(0)
151     {}
152 
153     ~TokenImpl();
154 };
155 
156 /// @addtogroup Core
157 /// @{
158 
159 /**
160  * @brief The token list that the TokenList generates is a linked-list of this class.
161  *
162  * Tokens are stored as strings. The "if", "while", etc are stored in plain text.
163  * The reason the Token class is needed (instead of using the string class) is that some extra functionality is also needed for tokens:
164  *  - location of the token is stored (fileIndex, linenr, column)
165  *  - functions for classifying the token (isName, isNumber, isBoolean, isStandardType)
166  *
167  * The Token class also has other functions for management of token list, matching tokens, etc.
168  */
169 class CPPCHECKLIB Token {
170 private:
171     TokensFrontBack* mTokensFrontBack;
172 
173     // Not implemented..
174     Token(const Token &);
175     Token operator=(const Token &);
176 
177 public:
178     enum Type {
179         eVariable, eType, eFunction, eKeyword, eName, // Names: Variable (varId), Type (typeId, later), Function (FuncId, later), Language keyword, Name (unknown identifier)
180         eNumber, eString, eChar, eBoolean, eLiteral, eEnumerator, // Literals: Number, String, Character, Boolean, User defined literal (C++11), Enumerator
181         eArithmeticalOp, eComparisonOp, eAssignmentOp, eLogicalOp, eBitOp, eIncDecOp, eExtendedOp, // Operators: Arithmetical, Comparison, Assignment, Logical, Bitwise, ++/--, Extended
182         eBracket, // {, }, <, >: < and > only if link() is set. Otherwise they are comparison operators.
183         eLambda, // A function without a name
184         eEllipsis, // "..."
185         eOther,
186         eNone
187     };
188 
189     explicit Token(TokensFrontBack *tokensFrontBack = nullptr);
190     ~Token();
191 
192     ConstTokenRange until(const Token * t) const;
193 
194     template<typename T>
str(T && s)195     void str(T&& s) {
196         mStr = s;
197         mImpl->mVarId = 0;
198 
199         update_property_info();
200     }
201 
202     /**
203      * Concatenate two (quoted) strings. Automatically cuts of the last/first character.
204      * Example: "hello ""world" -> "hello world". Used by the token simplifier.
205      */
206     void concatStr(std::string const& b);
207 
str()208     const std::string &str() const {
209         return mStr;
210     }
211 
212     /**
213      * Unlink and delete the next 'count' tokens.
214      */
215     void deleteNext(nonneg int count = 1);
216 
217     /**
218      * Unlink and delete the previous 'count' tokens.
219      */
220     void deletePrevious(nonneg int count = 1);
221 
222     /**
223      * Swap the contents of this token with the next token.
224      */
225     void swapWithNext();
226 
227     /**
228      * @return token in given index, related to this token.
229      * For example index 1 would return next token, and 2
230      * would return next from that one.
231      */
232     const Token *tokAt(int index) const;
tokAt(int index)233     Token *tokAt(int index) {
234         return const_cast<Token *>(const_cast<const Token *>(this)->tokAt(index));
235     }
236 
237     /**
238      * @return the link to the token in given index, related to this token.
239      * For example index 1 would return the link to next token.
240      */
241     const Token *linkAt(int index) const;
linkAt(int index)242     Token *linkAt(int index) {
243         return const_cast<Token *>(const_cast<const Token *>(this)->linkAt(index));
244     }
245 
246     /**
247      * @return String of the token in given index, related to this token.
248      * If that token does not exist, an empty string is being returned.
249      */
250     const std::string &strAt(int index) const;
251 
252     /**
253      * Match given token (or list of tokens) to a pattern list.
254      *
255      * Possible patterns
256      * "someRandomText" If token contains "someRandomText".
257      * @note Use Match() if you want to use flags in patterns
258      *
259      * The patterns can be also combined to compare to multiple tokens at once
260      * by separating tokens with a space, e.g.
261      * ") void {" will return true if first token is ')' next token
262      * is "void" and token after that is '{'. If even one of the tokens does
263      * not match its pattern, false is returned.
264      *
265      * @param tok List of tokens to be compared to the pattern
266      * @param pattern The pattern against which the tokens are compared,
267      * e.g. "const" or ") void {".
268      * @return true if given token matches with given pattern
269      *         false if given token does not match with given pattern
270      */
271     template<size_t count>
simpleMatch(const Token * tok,const char (& pattern)[count])272     static bool simpleMatch(const Token *tok, const char (&pattern)[count]) {
273         return simpleMatch(tok, pattern, count-1);
274     }
275 
276     static bool simpleMatch(const Token *tok, const char pattern[], size_t pattern_len);
277 
278     /**
279      * Match given token (or list of tokens) to a pattern list.
280      *
281      * Possible patterns
282      * - "%any%" any token
283      * - "%assign%" a assignment operand
284      * - "%bool%" true or false
285      * - "%char%" Any token enclosed in &apos;-character.
286      * - "%comp%" Any token such that isComparisonOp() returns true.
287      * - "%cop%" Any token such that isConstOp() returns true.
288      * - "%name%" any token which is a name, variable or type e.g. "hello" or "int"
289      * - "%num%" Any numeric token, e.g. "23"
290      * - "%op%" Any token such that isOp() returns true.
291      * - "%or%" A bitwise-or operator '|'
292      * - "%oror%" A logical-or operator '||'
293      * - "%type%" Anything that can be a variable type, e.g. "int", but not "delete".
294      * - "%str%" Any token starting with &quot;-character (C-string).
295      * - "%var%" Match with token with varId > 0
296      * - "%varid%" Match with parameter varid
297      * - "[abc]" Any of the characters 'a' or 'b' or 'c'
298      * - "int|void|char" Any of the strings, int, void or char
299      * - "int|void|char|" Any of the strings, int, void or char or empty string
300      * - "!!else" No tokens or any token that is not "else".
301      * - "someRandomText" If token contains "someRandomText".
302      *
303      * multi-compare patterns such as "int|void|char" can contain %%or%, %%oror% and %%op%
304      * it is recommended to put such an %%cmd% as the first pattern.
305      * For example: "%var%|%num%|)" means yes to a variable, a number or ')'.
306      *
307      * The patterns can be also combined to compare to multiple tokens at once
308      * by separating tokens with a space, e.g.
309      * ") const|void {" will return true if first token is ')' next token is either
310      * "const" or "void" and token after that is '{'. If even one of the tokens does not
311      * match its pattern, false is returned.
312      *
313      * @param tok List of tokens to be compared to the pattern
314      * @param pattern The pattern against which the tokens are compared,
315      * e.g. "const" or ") const|volatile| {".
316      * @param varid if %%varid% is given in the pattern the Token::varId
317      * will be matched against this argument
318      * @return true if given token matches with given pattern
319      *         false if given token does not match with given pattern
320      */
321     static bool Match(const Token *tok, const char pattern[], nonneg int varid = 0);
322 
323     /**
324      * @return length of C-string.
325      *
326      * Should be called for %%str%% tokens only.
327      *
328      * @param tok token with C-string
329      **/
330     static nonneg int getStrLength(const Token *tok);
331 
332     /**
333      * @return array length of C-string.
334      *
335      * Should be called for %%str%% tokens only.
336      *
337      * @param tok token with C-string
338      **/
339     static nonneg int getStrArraySize(const Token *tok);
340 
341     /**
342      * @return sizeof of C-string.
343      *
344      * Should be called for %%str%% tokens only.
345      *
346      * @param tok token with C-string
347      * @param settings Settings
348      **/
349     static nonneg int getStrSize(const Token *tok, const Settings *const settings);
350 
351     /**
352      * @return char of C-string at index (possible escaped "\\n")
353      *
354      * Should be called for %%str%% tokens only.
355      *
356      * @param tok token with C-string
357      * @param index position of character
358      **/
359     static std::string getCharAt(const Token *tok, MathLib::bigint index);
360 
valueType()361     const ValueType *valueType() const {
362         return mImpl->mValueType;
363     }
364     void setValueType(ValueType *vt);
365 
argumentType()366     const ValueType *argumentType() const {
367         const Token *top = this;
368         while (top && !Token::Match(top->astParent(), ",|("))
369             top = top->astParent();
370         return top ? top->mImpl->mValueType : nullptr;
371     }
372 
tokType()373     Token::Type tokType() const {
374         return mTokType;
375     }
tokType(Token::Type t)376     void tokType(Token::Type t) {
377         mTokType = t;
378 
379         const bool memoizedIsName = (mTokType == eName || mTokType == eType || mTokType == eVariable ||
380                                      mTokType == eFunction || mTokType == eKeyword || mTokType == eBoolean ||
381                                      mTokType == eEnumerator); // TODO: "true"/"false" aren't really a name...
382         setFlag(fIsName, memoizedIsName);
383 
384         const bool memoizedIsLiteral = (mTokType == eNumber || mTokType == eString || mTokType == eChar ||
385                                         mTokType == eBoolean || mTokType == eLiteral || mTokType == eEnumerator);
386         setFlag(fIsLiteral, memoizedIsLiteral);
387     }
isKeyword()388     bool isKeyword() const {
389         return mTokType == eKeyword;
390     }
isName()391     bool isName() const {
392         return getFlag(fIsName);
393     }
isNameOnly()394     bool isNameOnly() const {
395         return mFlags == fIsName && mTokType == eName;
396     }
397     bool isUpperCaseName() const;
isLiteral()398     bool isLiteral() const {
399         return getFlag(fIsLiteral);
400     }
isNumber()401     bool isNumber() const {
402         return mTokType == eNumber;
403     }
isEnumerator()404     bool isEnumerator() const {
405         return mTokType == eEnumerator;
406     }
isOp()407     bool isOp() const {
408         return (isConstOp() ||
409                 isAssignmentOp() ||
410                 mTokType == eIncDecOp);
411     }
isConstOp()412     bool isConstOp() const {
413         return (isArithmeticalOp() ||
414                 mTokType == eLogicalOp ||
415                 mTokType == eComparisonOp ||
416                 mTokType == eBitOp);
417     }
isExtendedOp()418     bool isExtendedOp() const {
419         return isConstOp() ||
420                mTokType == eExtendedOp;
421     }
isArithmeticalOp()422     bool isArithmeticalOp() const {
423         return mTokType == eArithmeticalOp;
424     }
isComparisonOp()425     bool isComparisonOp() const {
426         return mTokType == eComparisonOp;
427     }
isAssignmentOp()428     bool isAssignmentOp() const {
429         return mTokType == eAssignmentOp;
430     }
isBoolean()431     bool isBoolean() const {
432         return mTokType == eBoolean;
433     }
isIncDecOp()434     bool isIncDecOp() const {
435         return mTokType == eIncDecOp;
436     }
isBinaryOp()437     bool isBinaryOp() const {
438         return astOperand1() != nullptr && astOperand2() != nullptr;
439     }
isUnaryOp(const std::string & s)440     bool isUnaryOp(const std::string &s) const {
441         return s == mStr && astOperand1() != nullptr && astOperand2() == nullptr;
442     }
443     bool isUnaryPreOp() const;
444 
flags()445     unsigned int flags() const {
446         return mFlags;
447     }
flags(const unsigned int flags_)448     void flags(const unsigned int flags_) {
449         mFlags = flags_;
450     }
isUnsigned()451     bool isUnsigned() const {
452         return getFlag(fIsUnsigned);
453     }
isUnsigned(const bool sign)454     void isUnsigned(const bool sign) {
455         setFlag(fIsUnsigned, sign);
456     }
isSigned()457     bool isSigned() const {
458         return getFlag(fIsSigned);
459     }
isSigned(const bool sign)460     void isSigned(const bool sign) {
461         setFlag(fIsSigned, sign);
462     }
isPointerCompare()463     bool isPointerCompare() const {
464         return getFlag(fIsPointerCompare);
465     }
isPointerCompare(const bool b)466     void isPointerCompare(const bool b) {
467         setFlag(fIsPointerCompare, b);
468     }
isLong()469     bool isLong() const {
470         return getFlag(fIsLong);
471     }
isLong(bool size)472     void isLong(bool size) {
473         setFlag(fIsLong, size);
474     }
isStandardType()475     bool isStandardType() const {
476         return getFlag(fIsStandardType);
477     }
isStandardType(const bool b)478     void isStandardType(const bool b) {
479         setFlag(fIsStandardType, b);
480     }
isExpandedMacro()481     bool isExpandedMacro() const {
482         return getFlag(fIsExpandedMacro);
483     }
isExpandedMacro(const bool m)484     void isExpandedMacro(const bool m) {
485         setFlag(fIsExpandedMacro, m);
486     }
isCast()487     bool isCast() const {
488         return getFlag(fIsCast);
489     }
isCast(bool c)490     void isCast(bool c) {
491         setFlag(fIsCast, c);
492     }
isAttributeConstructor()493     bool isAttributeConstructor() const {
494         return getFlag(fIsAttributeConstructor);
495     }
isAttributeConstructor(const bool ac)496     void isAttributeConstructor(const bool ac) {
497         setFlag(fIsAttributeConstructor, ac);
498     }
isAttributeDestructor()499     bool isAttributeDestructor() const {
500         return getFlag(fIsAttributeDestructor);
501     }
isAttributeDestructor(const bool value)502     void isAttributeDestructor(const bool value) {
503         setFlag(fIsAttributeDestructor, value);
504     }
isAttributeUnused()505     bool isAttributeUnused() const {
506         return getFlag(fIsAttributeUnused);
507     }
isAttributeUnused(bool unused)508     void isAttributeUnused(bool unused) {
509         setFlag(fIsAttributeUnused, unused);
510     }
isAttributeUsed()511     bool isAttributeUsed() const {
512         return getFlag(fIsAttributeUsed);
513     }
isAttributeUsed(const bool unused)514     void isAttributeUsed(const bool unused) {
515         setFlag(fIsAttributeUsed, unused);
516     }
isAttributePure()517     bool isAttributePure() const {
518         return getFlag(fIsAttributePure);
519     }
isAttributePure(const bool value)520     void isAttributePure(const bool value) {
521         setFlag(fIsAttributePure, value);
522     }
isAttributeConst()523     bool isAttributeConst() const {
524         return getFlag(fIsAttributeConst);
525     }
isAttributeConst(bool value)526     void isAttributeConst(bool value) {
527         setFlag(fIsAttributeConst, value);
528     }
isAttributeNoreturn()529     bool isAttributeNoreturn() const {
530         return getFlag(fIsAttributeNoreturn);
531     }
isAttributeNoreturn(const bool value)532     void isAttributeNoreturn(const bool value) {
533         setFlag(fIsAttributeNoreturn, value);
534     }
isAttributeNothrow()535     bool isAttributeNothrow() const {
536         return getFlag(fIsAttributeNothrow);
537     }
isAttributeNothrow(const bool value)538     void isAttributeNothrow(const bool value) {
539         setFlag(fIsAttributeNothrow, value);
540     }
isAttributePacked()541     bool isAttributePacked() const {
542         return getFlag(fIsAttributePacked);
543     }
isAttributePacked(const bool value)544     void isAttributePacked(const bool value) {
545         setFlag(fIsAttributePacked, value);
546     }
isAttributeNodiscard()547     bool isAttributeNodiscard() const {
548         return getFlag(fIsAttributeNodiscard);
549     }
isAttributeNodiscard(const bool value)550     void isAttributeNodiscard(const bool value) {
551         setFlag(fIsAttributeNodiscard, value);
552     }
isAttributeMaybeUnused()553     bool isAttributeMaybeUnused() const {
554         return getFlag(fIsAttributeMaybeUnused);
555     }
isAttributeMaybeUnused(const bool value)556     void isAttributeMaybeUnused(const bool value) {
557         setFlag(fIsAttributeMaybeUnused, value);
558     }
setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type,MathLib::bigint value)559     void setCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint value) {
560         mImpl->setCppcheckAttribute(type, value);
561     }
getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type,MathLib::bigint * value)562     bool getCppcheckAttribute(TokenImpl::CppcheckAttributes::Type type, MathLib::bigint *value) const {
563         return mImpl->getCppcheckAttribute(type, value);
564     }
hasCppcheckAttributes()565     bool hasCppcheckAttributes() const {
566         return nullptr != mImpl->mCppcheckAttributes;
567     }
isControlFlowKeyword()568     bool isControlFlowKeyword() const {
569         return getFlag(fIsControlFlowKeyword);
570     }
isOperatorKeyword()571     bool isOperatorKeyword() const {
572         return getFlag(fIsOperatorKeyword);
573     }
isOperatorKeyword(const bool value)574     void isOperatorKeyword(const bool value) {
575         setFlag(fIsOperatorKeyword, value);
576     }
isComplex()577     bool isComplex() const {
578         return getFlag(fIsComplex);
579     }
isComplex(const bool value)580     void isComplex(const bool value) {
581         setFlag(fIsComplex, value);
582     }
isEnumType()583     bool isEnumType() const {
584         return getFlag(fIsEnumType);
585     }
isEnumType(const bool value)586     void isEnumType(const bool value) {
587         setFlag(fIsEnumType, value);
588     }
isAtAddress()589     bool isAtAddress() const {
590         return getFlag(fAtAddress);
591     }
isAtAddress(bool b)592     void isAtAddress(bool b) {
593         setFlag(fAtAddress, b);
594     }
isIncompleteVar()595     bool isIncompleteVar() const {
596         return getFlag(fIncompleteVar);
597     }
isIncompleteVar(bool b)598     void isIncompleteVar(bool b) {
599         setFlag(fIncompleteVar, b);
600     }
601 
isConstexpr()602     bool isConstexpr() const {
603         return getFlag(fConstexpr);
604     }
isConstexpr(bool b)605     void isConstexpr(bool b) {
606         setFlag(fConstexpr, b);
607     }
608 
isExternC()609     bool isExternC() const {
610         return getFlag(fExternC);
611     }
isExternC(bool b)612     void isExternC(bool b) {
613         setFlag(fExternC, b);
614     }
615 
isSplittedVarDeclComma()616     bool isSplittedVarDeclComma() const {
617         return getFlag(fIsSplitVarDeclComma);
618     }
isSplittedVarDeclComma(bool b)619     void isSplittedVarDeclComma(bool b) {
620         setFlag(fIsSplitVarDeclComma, b);
621     }
622 
isSplittedVarDeclEq()623     bool isSplittedVarDeclEq() const {
624         return getFlag(fIsSplitVarDeclEq);
625     }
isSplittedVarDeclEq(bool b)626     void isSplittedVarDeclEq(bool b) {
627         setFlag(fIsSplitVarDeclEq, b);
628     }
629 
isImplicitInt()630     bool isImplicitInt() const {
631         return getFlag(fIsImplicitInt);
632     }
isImplicitInt(bool b)633     void isImplicitInt(bool b) {
634         setFlag(fIsImplicitInt, b);
635     }
636 
isInline()637     bool isInline() const {
638         return getFlag(fIsInline);
639     }
isInline(bool b)640     void isInline(bool b) {
641         setFlag(fIsInline, b);
642     }
643 
isTemplate()644     bool isTemplate() const {
645         return getFlag(fIsTemplate);
646     }
isTemplate(bool b)647     void isTemplate(bool b) {
648         setFlag(fIsTemplate, b);
649     }
650 
isBitfield()651     bool isBitfield() const {
652         return mImpl->mBits > 0;
653     }
bits()654     unsigned char bits() const {
655         return mImpl->mBits;
656     }
templateSimplifierPointers()657     std::set<TemplateSimplifier::TokenAndName*>* templateSimplifierPointers() const {
658         return mImpl->mTemplateSimplifierPointers;
659     }
templateSimplifierPointer(TemplateSimplifier::TokenAndName * tokenAndName)660     void templateSimplifierPointer(TemplateSimplifier::TokenAndName* tokenAndName) {
661         if (!mImpl->mTemplateSimplifierPointers)
662             mImpl->mTemplateSimplifierPointers = new std::set<TemplateSimplifier::TokenAndName*>;
663         mImpl->mTemplateSimplifierPointers->insert(tokenAndName);
664     }
setBits(const unsigned char b)665     void setBits(const unsigned char b) {
666         mImpl->mBits = b;
667     }
668 
isUtf8()669     bool isUtf8() const {
670         return (((mTokType == eString) && isPrefixStringCharLiteral(mStr, '"', "u8")) ||
671                 ((mTokType == eChar) && isPrefixStringCharLiteral(mStr, '\'', "u8")));
672     }
673 
isUtf16()674     bool isUtf16() const {
675         return (((mTokType == eString) && isPrefixStringCharLiteral(mStr, '"', "u")) ||
676                 ((mTokType == eChar) && isPrefixStringCharLiteral(mStr, '\'', "u")));
677     }
678 
isUtf32()679     bool isUtf32() const {
680         return (((mTokType == eString) && isPrefixStringCharLiteral(mStr, '"', "U")) ||
681                 ((mTokType == eChar) && isPrefixStringCharLiteral(mStr, '\'', "U")));
682     }
683 
isCChar()684     bool isCChar() const {
685         return (((mTokType == eString) && isPrefixStringCharLiteral(mStr, '"', "")) ||
686                 ((mTokType ==  eChar) && isPrefixStringCharLiteral(mStr, '\'', "") && mStr.length() == 3));
687     }
688 
isCMultiChar()689     bool isCMultiChar() const {
690         return (((mTokType ==  eChar) && isPrefixStringCharLiteral(mStr, '\'', "")) &&
691                 (mStr.length() > 3));
692     }
693     /**
694      * @brief Is current token a template argument?
695      *
696      * Original code:
697      *
698      *     template<class C> struct S {
699      *         C x;
700      *     };
701      *     S<int> s;
702      *
703      * Resulting code:
704      *
705      *     struct S<int> {
706      *         int x ;  // <- "int" is a template argument
707      *     }
708      *     S<int> s;
709      */
isTemplateArg()710     bool isTemplateArg() const {
711         return getFlag(fIsTemplateArg);
712     }
isTemplateArg(const bool value)713     void isTemplateArg(const bool value) {
714         setFlag(fIsTemplateArg, value);
715     }
716 
717     template<size_t count>
findsimplematch(const Token * const startTok,const char (& pattern)[count])718     static const Token *findsimplematch(const Token * const startTok, const char (&pattern)[count]) {
719         return findsimplematch(startTok, pattern, count-1);
720     }
721     static const Token *findsimplematch(const Token * const startTok, const char pattern[], size_t pattern_len);
722 
723     template<size_t count>
findsimplematch(const Token * const startTok,const char (& pattern)[count],const Token * const end)724     static const Token *findsimplematch(const Token * const startTok, const char (&pattern)[count], const Token * const end) {
725         return findsimplematch(startTok, pattern, count-1, end);
726     }
727     static const Token *findsimplematch(const Token * const startTok, const char pattern[], size_t pattern_len, const Token * const end);
728 
729     static const Token *findmatch(const Token * const startTok, const char pattern[], const nonneg int varId = 0);
730     static const Token *findmatch(const Token * const startTok, const char pattern[], const Token * const end, const nonneg int varId = 0);
731 
732     template<size_t count>
findsimplematch(Token * const startTok,const char (& pattern)[count])733     static Token *findsimplematch(Token * const startTok, const char (&pattern)[count]) {
734         return findsimplematch(startTok, pattern, count-1);
735     }
findsimplematch(Token * const startTok,const char pattern[],size_t pattern_len)736     static Token *findsimplematch(Token * const startTok, const char pattern[], size_t pattern_len) {
737         return const_cast<Token *>(findsimplematch(const_cast<const Token *>(startTok), pattern, pattern_len));
738     }
739     template<size_t count>
findsimplematch(Token * const startTok,const char (& pattern)[count],const Token * const end)740     static Token *findsimplematch(Token * const startTok, const char (&pattern)[count], const Token * const end) {
741         return findsimplematch(startTok, pattern, count-1, end);
742     }
findsimplematch(Token * const startTok,const char pattern[],size_t pattern_len,const Token * const end)743     static Token *findsimplematch(Token * const startTok, const char pattern[], size_t pattern_len, const Token * const end) {
744         return const_cast<Token *>(findsimplematch(const_cast<const Token *>(startTok), pattern, pattern_len, end));
745     }
746 
747     static Token *findmatch(Token * const startTok, const char pattern[], const nonneg int varId = 0) {
748         return const_cast<Token *>(findmatch(const_cast<const Token *>(startTok), pattern, varId));
749     }
750     static Token *findmatch(Token * const startTok, const char pattern[], const Token * const end, const nonneg int varId = 0) {
751         return const_cast<Token *>(findmatch(const_cast<const Token *>(startTok), pattern, end, varId));
752     }
753 
754     /**
755      * Needle is build from multiple alternatives. If one of
756      * them is equal to haystack, return value is 1. If there
757      * are no matches, but one alternative to needle is empty
758      * string, return value is 0. If needle was not found, return
759      * value is -1.
760      *
761      * @param tok Current token (needle)
762      * @param haystack e.g. "one|two" or "|one|two"
763      * @param varid optional varid of token
764      * @return 1 if needle is found from the haystack
765      *         0 if needle was empty string
766      *        -1 if needle was not found
767      */
768     static int multiCompare(const Token *tok, const char *haystack, nonneg int varid);
769 
fileIndex()770     nonneg int fileIndex() const {
771         return mImpl->mFileIndex;
772     }
fileIndex(nonneg int indexOfFile)773     void fileIndex(nonneg int indexOfFile) {
774         mImpl->mFileIndex = indexOfFile;
775     }
776 
linenr()777     nonneg int linenr() const {
778         return mImpl->mLineNumber;
779     }
linenr(nonneg int lineNumber)780     void linenr(nonneg int lineNumber) {
781         mImpl->mLineNumber = lineNumber;
782     }
783 
column()784     nonneg int column() const {
785         return mImpl->mColumn;
786     }
column(nonneg int c)787     void column(nonneg int c) {
788         mImpl->mColumn = c;
789     }
790 
next()791     Token *next() const {
792         return mNext;
793     }
794 
795 
796     /**
797      * Delete tokens between begin and end. E.g. if begin = 1
798      * and end = 5, tokens 2,3 and 4 would be erased.
799      *
800      * @param begin Tokens after this will be erased.
801      * @param end Tokens before this will be erased.
802      */
803     static void eraseTokens(Token *begin, const Token *end);
804 
805     /**
806      * Insert new token after this token. This function will handle
807      * relations between next and previous token also.
808      * @param tokenStr String for the new token.
809      * @param originalNameStr String used for Token::originalName().
810      * @param prepend Insert the new token before this token when it's not
811      * the first one on the tokens list.
812      */
813     void insertToken(const std::string &tokenStr, const std::string &originalNameStr=emptyString, bool prepend=false);
814 
previous()815     Token *previous() const {
816         return mPrevious;
817     }
818 
819 
varId()820     nonneg int varId() const {
821         return mImpl->mVarId;
822     }
varId(nonneg int id)823     void varId(nonneg int id) {
824         mImpl->mVarId = id;
825         if (id != 0) {
826             tokType(eVariable);
827             isStandardType(false);
828         } else {
829             update_property_info();
830         }
831     }
832 
exprId()833     nonneg int exprId() const {
834         if (mImpl->mExprId)
835             return mImpl->mExprId;
836         return mImpl->mVarId;
837     }
exprId(nonneg int id)838     void exprId(nonneg int id) {
839         mImpl->mExprId = id;
840     }
841 
842     /**
843      * For debugging purposes, prints token and all tokens
844      * followed by it.
845      * @param title Title for the printout or use default parameter or 0
846      * for no title.
847      */
848     void printOut(const char *title = nullptr) const;
849 
850     /**
851      * For debugging purposes, prints token and all tokens
852      * followed by it.
853      * @param title Title for the printout or use default parameter or 0
854      * for no title.
855      * @param fileNames Prints out file name instead of file index.
856      * File index should match the index of the string in this vector.
857      */
858     void printOut(const char *title, const std::vector<std::string> &fileNames) const;
859 
860     /**
861      * print out tokens
862      */
863     void printLines(int lines=5) const;
864 
865     /**
866      * Replace token replaceThis with tokens between start and end,
867      * including start and end. The replaceThis token is deleted.
868      * @param replaceThis This token will be deleted.
869      * @param start This will be in the place of replaceThis
870      * @param end This is also in the place of replaceThis
871      */
872     static void replace(Token *replaceThis, Token *start, Token *end);
873 
874     struct stringifyOptions {
875         bool varid = false;
876         bool exprid = false;
877         bool idtype = false; // distinguish varid / exprid
878         bool attributes = false;
879         bool macro = false;
880         bool linenumbers = false;
881         bool linebreaks = false;
882         bool files = false;
forDebugstringifyOptions883         static stringifyOptions forDebug() {
884             stringifyOptions options;
885             options.attributes = true;
886             options.macro = true;
887             options.linenumbers = true;
888             options.linebreaks = true;
889             options.files = true;
890             return options;
891         }
forDebugVarIdstringifyOptions892         static stringifyOptions forDebugVarId() {
893             stringifyOptions options = forDebug();
894             options.varid = true;
895             return options;
896         }
forDebugExprIdstringifyOptions897         static stringifyOptions forDebugExprId() {
898             stringifyOptions options = forDebug();
899             options.exprid = true;
900             return options;
901         }
forPrintOutstringifyOptions902         static stringifyOptions forPrintOut() {
903             stringifyOptions options = forDebug();
904             options.exprid = true;
905             options.varid = true;
906             options.idtype = true;
907             return options;
908         }
909     };
910 
911     std::string stringify(const stringifyOptions& options) const;
912 
913     /**
914      * Stringify a token
915      * @param varid Print varids. (Style: "varname\@id")
916      * @param attributes Print attributes of tokens like "unsigned" in front of it.
917      * @param macro Prints $ in front of the token if it was expanded from a macro.
918      */
919     std::string stringify(bool varid, bool attributes, bool macro) const;
920 
921     std::string stringifyList(const stringifyOptions& options, const std::vector<std::string>* fileNames = nullptr, const Token* end = nullptr) const;
922     std::string stringifyList(const Token* end, bool attributes = true) const;
923     std::string stringifyList(bool varid = false) const;
924 
925     /**
926      * Stringify a list of token, from current instance on.
927      * @param varid Print varids. (Style: "varname\@id")
928      * @param attributes Print attributes of tokens like "unsigned" in front of it.
929      * @param linenumbers Print line number in front of each line
930      * @param linebreaks Insert "\\n" into string when line number changes
931      * @param files print Files as numbers or as names (if fileNames is given)
932      * @param fileNames Vector of filenames. Used (if given) to print filenames as strings instead of numbers.
933      * @param end Stringification ends before this token is reached. 0 to stringify until end of list.
934      * @return Stringified token list as a string
935      */
936     std::string stringifyList(bool varid, bool attributes, bool linenumbers, bool linebreaks, bool files, const std::vector<std::string>* fileNames = nullptr, const Token* end = nullptr) const;
937 
938     /**
939      * Remove the contents for this token from the token list.
940      *
941      * The contents are replaced with the contents of the next token and
942      * the next token is unlinked and deleted from the token list.
943      *
944      * So this token will still be valid after the 'deleteThis()'.
945      */
946     void deleteThis();
947 
948     /**
949      * Create link to given token
950      * @param linkToToken The token where this token should link
951      * to.
952      */
link(Token * linkToToken)953     void link(Token *linkToToken) {
954         mLink = linkToToken;
955         if (mStr == "<" || mStr == ">")
956             update_property_info();
957     }
958 
959     /**
960      * Return token where this token links to.
961      * Supported links are:
962      * "{" <-> "}"
963      * "(" <-> ")"
964      * "[" <-> "]"
965      *
966      * @return The token where this token links to.
967      */
link()968     Token *link() const {
969         return mLink;
970     }
971 
972     /**
973      * Associate this token with given scope
974      * @param s Scope to be associated
975      */
scope(const Scope * s)976     void scope(const Scope *s) {
977         mImpl->mScope = s;
978     }
979 
980     /**
981      * @return a pointer to the scope containing this token.
982      */
scope()983     const Scope *scope() const {
984         return mImpl->mScope;
985     }
986 
987     /**
988      * Associate this token with given function
989      * @param f Function to be associated
990      */
991     void function(const Function *f);
992 
993     /**
994      * @return a pointer to the Function associated with this token.
995      */
function()996     const Function *function() const {
997         return mTokType == eFunction || mTokType == eLambda ? mImpl->mFunction : nullptr;
998     }
999 
1000     /**
1001      * Associate this token with given variable
1002      * @param v Variable to be associated
1003      */
variable(const Variable * v)1004     void variable(const Variable *v) {
1005         mImpl->mVariable = v;
1006         if (v || mImpl->mVarId)
1007             tokType(eVariable);
1008         else if (mTokType == eVariable)
1009             tokType(eName);
1010     }
1011 
1012     /**
1013      * @return a pointer to the variable associated with this token.
1014      */
variable()1015     const Variable *variable() const {
1016         return mTokType == eVariable ? mImpl->mVariable : nullptr;
1017     }
1018 
1019     /**
1020      * Associate this token with given type
1021      * @param t Type to be associated
1022      */
1023     void type(const ::Type *t);
1024 
1025     /**
1026      * @return a pointer to the type associated with this token.
1027      */
type()1028     const ::Type *type() const {
1029         return mTokType == eType ? mImpl->mType : nullptr;
1030     }
1031 
1032     static const ::Type* typeOf(const Token* tok, const Token** typeTok = nullptr);
1033 
1034     static std::pair<const Token*, const Token*> typeDecl(const Token * tok);
1035 
1036     static std::string typeStr(const Token* tok);
1037 
1038     /**
1039      * @return a pointer to the Enumerator associated with this token.
1040      */
enumerator()1041     const Enumerator *enumerator() const {
1042         return mTokType == eEnumerator ? mImpl->mEnumerator : nullptr;
1043     }
1044 
1045     /**
1046      * Associate this token with given enumerator
1047      * @param e Enumerator to be associated
1048      */
enumerator(const Enumerator * e)1049     void enumerator(const Enumerator *e) {
1050         mImpl->mEnumerator = e;
1051         if (e)
1052             tokType(eEnumerator);
1053         else if (mTokType == eEnumerator)
1054             tokType(eName);
1055     }
1056 
1057     /**
1058      * Links two elements against each other.
1059      **/
1060     static void createMutualLinks(Token *begin, Token *end);
1061 
1062     /**
1063      * This can be called only for tokens that are strings, else
1064      * the assert() is called. If Token is e.g. '"hello"', this will return
1065      * 'hello' (removing the double quotes).
1066      * @return String value
1067      */
1068     std::string strValue() const;
1069 
1070     /**
1071      * Move srcStart and srcEnd tokens and all tokens between them
1072      * into new a location. Only links between tokens are changed.
1073      * @param srcStart This is the first token to be moved
1074      * @param srcEnd The last token to be moved
1075      * @param newLocation srcStart will be placed after this token.
1076      */
1077     static void move(Token *srcStart, Token *srcEnd, Token *newLocation);
1078 
1079     /** Get progressValue (0 - 100) */
progressValue()1080     nonneg int progressValue() const {
1081         return mImpl->mProgressValue;
1082     }
1083 
1084     /** Calculate progress values for all tokens */
1085     static void assignProgressValues(Token *tok);
1086 
1087     /**
1088      * @return the first token of the next argument. Does only work on argument
1089      * lists. Requires that Tokenizer::createLinks2() has been called before.
1090      * Returns 0, if there is no next argument.
1091      */
1092     Token* nextArgument() const;
1093 
1094     /**
1095      * @return the first token of the next argument. Does only work on argument
1096      * lists. Should be used only before Tokenizer::createLinks2() was called.
1097      * Returns 0, if there is no next argument.
1098      */
1099     Token* nextArgumentBeforeCreateLinks2() const;
1100 
1101     /**
1102      * @return the first token of the next template argument. Does only work on template argument
1103      * lists. Requires that Tokenizer::createLinks2() has been called before.
1104      * Returns 0, if there is no next argument.
1105      */
1106     Token* nextTemplateArgument() const;
1107 
1108     /**
1109      * Returns the closing bracket of opening '<'. Should only be used if link()
1110      * is unavailable.
1111      * @return closing '>', ')', ']' or '}'. if no closing bracket is found, NULL is returned
1112      */
1113     const Token* findClosingBracket() const;
1114     Token* findClosingBracket();
1115 
1116     const Token* findOpeningBracket() const;
1117     Token* findOpeningBracket();
1118 
1119     /**
1120      * @return the original name.
1121      */
originalName()1122     const std::string & originalName() const {
1123         return mImpl->mOriginalName ? *mImpl->mOriginalName : emptyString;
1124     }
1125 
values()1126     const std::list<ValueFlow::Value>& values() const {
1127         return mImpl->mValues ? *mImpl->mValues : TokenImpl::mEmptyValueList;
1128     }
1129 
1130     /**
1131      * Sets the original name.
1132      */
1133     template<typename T>
originalName(T && name)1134     void originalName(T&& name) {
1135         if (!mImpl->mOriginalName)
1136             mImpl->mOriginalName = new std::string(name);
1137         else
1138             *mImpl->mOriginalName = name;
1139     }
1140 
1141     bool hasKnownIntValue() const;
1142     bool hasKnownValue() const;
1143     bool hasKnownValue(ValueFlow::Value::ValueType t) const;
1144     bool hasKnownSymbolicValue(const Token* tok) const;
1145 
1146     const ValueFlow::Value* getKnownValue(ValueFlow::Value::ValueType t) const;
getKnownIntValue()1147     MathLib::bigint getKnownIntValue() const {
1148         return mImpl->mValues->front().intvalue;
1149     }
1150 
1151     bool isImpossibleIntValue(const MathLib::bigint val) const;
1152 
1153     const ValueFlow::Value* getValue(const MathLib::bigint val) const;
1154 
1155     const ValueFlow::Value* getMaxValue(bool condition, MathLib::bigint path = 0) const;
1156 
1157     const ValueFlow::Value* getMovedValue() const;
1158 
1159     const ValueFlow::Value * getValueLE(const MathLib::bigint val, const Settings *settings) const;
1160     const ValueFlow::Value * getValueGE(const MathLib::bigint val, const Settings *settings) const;
1161 
1162     const ValueFlow::Value * getInvalidValue(const Token *ftok, nonneg int argnr, const Settings *settings) const;
1163 
1164     const ValueFlow::Value* getContainerSizeValue(const MathLib::bigint val) const;
1165 
1166     const Token *getValueTokenMaxStrLength() const;
1167     const Token *getValueTokenMinStrSize(const Settings *settings) const;
1168 
1169     const Token *getValueTokenDeadPointer() const;
1170 
1171     /** Add token value. Return true if value is added. */
1172     bool addValue(const ValueFlow::Value &value);
1173 
removeValues(std::function<bool (const ValueFlow::Value &)> pred)1174     void removeValues(std::function<bool(const ValueFlow::Value &)> pred) {
1175         if (mImpl->mValues)
1176             mImpl->mValues->remove_if(pred);
1177     }
1178 
index()1179     nonneg int index() const {
1180         return mImpl->mIndex;
1181     }
1182 
1183     void assignIndexes();
1184 
1185 private:
1186 
next(Token * nextToken)1187     void next(Token *nextToken) {
1188         mNext = nextToken;
1189     }
previous(Token * previousToken)1190     void previous(Token *previousToken) {
1191         mPrevious = previousToken;
1192     }
1193 
1194     /** used by deleteThis() to take data from token to delete */
1195     void takeData(Token *fromToken);
1196 
1197     /**
1198      * Works almost like strcmp() except returns only true or false and
1199      * if str has empty space &apos; &apos; character, that character is handled
1200      * as if it were &apos;\\0&apos;
1201      */
1202     static bool firstWordEquals(const char *str, const char *word);
1203 
1204     /**
1205      * Works almost like strchr() except
1206      * if str has empty space &apos; &apos; character, that character is handled
1207      * as if it were &apos;\\0&apos;
1208      */
1209     static const char *chrInFirstWord(const char *str, char c);
1210 
1211     std::string mStr;
1212 
1213     Token *mNext;
1214     Token *mPrevious;
1215     Token *mLink;
1216 
1217     enum : uint64_t {
1218         fIsUnsigned             = (1 << 0),
1219         fIsSigned               = (1 << 1),
1220         fIsPointerCompare       = (1 << 2),
1221         fIsLong                 = (1 << 3),
1222         fIsStandardType         = (1 << 4),
1223         fIsExpandedMacro        = (1 << 5),
1224         fIsCast                 = (1 << 6),
1225         fIsAttributeConstructor = (1 << 7),  // __attribute__((constructor)) __attribute__((constructor(priority)))
1226         fIsAttributeDestructor  = (1 << 8),  // __attribute__((destructor))  __attribute__((destructor(priority)))
1227         fIsAttributeUnused      = (1 << 9),  // __attribute__((unused))
1228         fIsAttributePure        = (1 << 10), // __attribute__((pure))
1229         fIsAttributeConst       = (1 << 11), // __attribute__((const))
1230         fIsAttributeNoreturn    = (1 << 12), // __attribute__((noreturn)), __declspec(noreturn)
1231         fIsAttributeNothrow     = (1 << 13), // __attribute__((nothrow)), __declspec(nothrow)
1232         fIsAttributeUsed        = (1 << 14), // __attribute__((used))
1233         fIsAttributePacked      = (1 << 15), // __attribute__((packed))
1234         fIsAttributeMaybeUnused = (1 << 16), // [[maybe_unsed]]
1235         fIsControlFlowKeyword   = (1 << 17), // if/switch/while/...
1236         fIsOperatorKeyword      = (1 << 18), // operator=, etc
1237         fIsComplex              = (1 << 19), // complex/_Complex type
1238         fIsEnumType             = (1 << 20), // enumeration type
1239         fIsName                 = (1 << 21),
1240         fIsLiteral              = (1 << 22),
1241         fIsTemplateArg          = (1 << 23),
1242         fIsAttributeNodiscard   = (1 << 24), // __attribute__ ((warn_unused_result)), [[nodiscard]]
1243         fAtAddress              = (1 << 25), // @ 0x4000
1244         fIncompleteVar          = (1 << 26),
1245         fConstexpr              = (1 << 27),
1246         fExternC                = (1 << 28),
1247         fIsSplitVarDeclComma    = (1 << 29), // set to true when variable declarations are split up ('int a,b;' => 'int a; int b;')
1248         fIsSplitVarDeclEq       = (1 << 30), // set to true when variable declaration with initialization is split up ('int a=5;' => 'int a; a=5;')
1249         fIsImplicitInt          = (1U << 31),   // Is "int" token implicitly added?
1250         fIsInline               = (1ULL << 32), // Is this a inline type
1251         fIsTemplate             = (1ULL << 33)
1252     };
1253 
1254     Token::Type mTokType;
1255 
1256     uint64_t mFlags;
1257 
1258     TokenImpl *mImpl;
1259 
1260     /**
1261      * Get specified flag state.
1262      * @param flag_ flag to get state of
1263      * @return true if flag set or false in flag not set
1264      */
getFlag(uint64_t flag_)1265     bool getFlag(uint64_t flag_) const {
1266         return ((mFlags & flag_) != 0);
1267     }
1268 
1269     /**
1270      * Set specified flag state.
1271      * @param flag_ flag to set state
1272      * @param state_ new state of flag
1273      */
setFlag(uint64_t flag_,bool state_)1274     void setFlag(uint64_t flag_, bool state_) {
1275         mFlags = state_ ? mFlags | flag_ : mFlags & ~flag_;
1276     }
1277 
1278     /** Updates internal property cache like _isName or _isBoolean.
1279         Called after any mStr() modification. */
1280     void update_property_info();
1281 
1282     /** Update internal property cache about isStandardType() */
1283     void update_property_isStandardType();
1284 
1285     /** Update internal property cache about string and char literals */
1286     void update_property_char_string_literal();
1287 
1288     /** Internal helper function to avoid excessive string allocations */
1289     void astStringVerboseRecursive(std::string& ret, const nonneg int indent1 = 0, const nonneg int indent2 = 0) const;
1290 
1291 public:
1292     void astOperand1(Token *tok);
1293     void astOperand2(Token *tok);
1294     void astParent(Token* tok);
1295 
astOperand1()1296     Token * astOperand1() {
1297         return mImpl->mAstOperand1;
1298     }
astOperand1()1299     const Token * astOperand1() const {
1300         return mImpl->mAstOperand1;
1301     }
astOperand2()1302     Token * astOperand2() {
1303         return mImpl->mAstOperand2;
1304     }
astOperand2()1305     const Token * astOperand2() const {
1306         return mImpl->mAstOperand2;
1307     }
astParent()1308     Token * astParent() {
1309         return mImpl->mAstParent;
1310     }
astParent()1311     const Token * astParent() const {
1312         return mImpl->mAstParent;
1313     }
astSibling()1314     Token * astSibling() {
1315         if (!astParent())
1316             return nullptr;
1317         if (this == astParent()->astOperand1())
1318             return astParent()->astOperand2();
1319         else if (this == astParent()->astOperand2())
1320             return astParent()->astOperand1();
1321         return nullptr;
1322 
1323     }
astSibling()1324     const Token * astSibling() const {
1325         if (!astParent())
1326             return nullptr;
1327         if (this == astParent()->astOperand1())
1328             return astParent()->astOperand2();
1329         else if (this == astParent()->astOperand2())
1330             return astParent()->astOperand1();
1331         return nullptr;
1332 
1333     }
astTop()1334     Token *astTop() {
1335         Token *ret = this;
1336         while (ret->mImpl->mAstParent)
1337             ret = ret->mImpl->mAstParent;
1338         return ret;
1339     }
1340 
astTop()1341     const Token *astTop() const {
1342         const Token *ret = this;
1343         while (ret->mImpl->mAstParent)
1344             ret = ret->mImpl->mAstParent;
1345         return ret;
1346     }
1347 
1348     std::pair<const Token *, const Token *> findExpressionStartEndTokens() const;
1349 
1350     /**
1351      * Is current token a calculation? Only true for operands.
1352      * For '*' and '&' tokens it is looked up if this is a
1353      * dereference or address-of. A dereference or address-of is not
1354      * counted as a calculation.
1355      * @return returns true if current token is a calculation
1356      */
1357     bool isCalculation() const;
1358 
clearAst()1359     void clearAst() {
1360         mImpl->mAstOperand1 = mImpl->mAstOperand2 = mImpl->mAstParent = nullptr;
1361     }
1362 
clearValueFlow()1363     void clearValueFlow() {
1364         delete mImpl->mValues;
1365         mImpl->mValues = nullptr;
1366     }
1367 
1368     std::string astString(const char *sep = "") const {
1369         std::string ret;
1370         if (mImpl->mAstOperand1)
1371             ret = mImpl->mAstOperand1->astString(sep);
1372         if (mImpl->mAstOperand2)
1373             ret += mImpl->mAstOperand2->astString(sep);
1374         return ret + sep + mStr;
1375     }
1376 
1377     std::string astStringVerbose() const;
1378 
1379     std::string astStringZ3() const;
1380 
1381     std::string expressionString() const;
1382 
1383     void printAst(bool verbose, bool xml, const std::vector<std::string> &fileNames, std::ostream &out) const;
1384 
1385     void printValueFlow(bool xml, std::ostream &out) const;
1386 
1387     void scopeInfo(std::shared_ptr<ScopeInfo2> newScopeInfo);
1388     std::shared_ptr<ScopeInfo2> scopeInfo() const;
1389 
setCpp11init(bool cpp11init)1390     void setCpp11init(bool cpp11init) const {
1391         mImpl->mCpp11init=cpp11init ? TokenImpl::Cpp11init::CPP11INIT : TokenImpl::Cpp11init::NOINIT;
1392     }
isCpp11init()1393     TokenImpl::Cpp11init isCpp11init() const {
1394         return mImpl->mCpp11init;
1395     }
1396 };
1397 
1398 Token* findTypeEnd(Token* tok);
1399 const Token* findTypeEnd(const Token* tok);
1400 Token* findLambdaEndScope(Token* tok);
1401 const Token* findLambdaEndScope(const Token* tok);
1402 
1403 /// @}
1404 //---------------------------------------------------------------------------
1405 #endif // tokenH
1406