Cppcheck
checkstring.cpp
Go to the documentation of this file.
1 /*
2  * Cppcheck - A tool for static C/C++ code analysis
3  * Copyright (C) 2007-2024 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 //---------------------------------------------------------------------------
21 #include "checkstring.h"
22 
23 #include "astutils.h"
24 #include "errortypes.h"
25 #include "mathlib.h"
26 #include "settings.h"
27 #include "symboldatabase.h"
28 #include "token.h"
29 #include "tokenize.h"
30 #include "utils.h"
31 
32 #include <cstddef>
33 #include <list>
34 #include <vector>
35 #include <utility>
36 
37 //---------------------------------------------------------------------------
38 
39 // Register this check class (by creating a static instance of it)
40 namespace {
41  CheckString instance;
42 }
43 
44 // CWE ids used:
45 static const CWE CWE570(570U); // Expression is Always False
46 static const CWE CWE571(571U); // Expression is Always True
47 static const CWE CWE595(595U); // Comparison of Object References Instead of Object Contents
48 static const CWE CWE628(628U); // Function Call with Incorrectly Specified Arguments
49 static const CWE CWE665(665U); // Improper Initialization
50 static const CWE CWE758(758U); // Reliance on Undefined, Unspecified, or Implementation-Defined Behavior
51 
52 //---------------------------------------------------------------------------
53 // Writing string literal is UB
54 //---------------------------------------------------------------------------
56 {
57  logChecker("CheckString::stringLiteralWrite");
58  const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
59  for (const Scope * scope : symbolDatabase->functionScopes) {
60  for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
61  if (!tok->variable() || !tok->variable()->isPointer())
62  continue;
63  const Token *str = tok->getValueTokenMinStrSize(*mSettings);
64  if (!str)
65  continue;
66  if (Token::Match(tok, "%var% [") && Token::simpleMatch(tok->linkAt(1), "] ="))
67  stringLiteralWriteError(tok, str);
68  else if (Token::Match(tok->previous(), "* %var% ="))
69  stringLiteralWriteError(tok, str);
70  }
71  }
72 }
73 
74 void CheckString::stringLiteralWriteError(const Token *tok, const Token *strValue)
75 {
76  std::list<const Token*> callstack{ tok };
77  if (strValue)
78  callstack.push_back(strValue);
79 
80  std::string errmsg("Modifying string literal");
81  if (strValue) {
82  std::string s = strValue->str();
83  // 20 is an arbitrary value, the max string length shown in a warning message
84  if (s.size() > 20U)
85  s.replace(17, std::string::npos, "..\"");
86  errmsg += " " + s;
87  }
88  errmsg += " directly or indirectly is undefined behaviour.";
89 
90  reportError(callstack, Severity::error, "stringLiteralWrite", errmsg, CWE758, Certainty::normal);
91 }
92 
93 //---------------------------------------------------------------------------
94 // Check for string comparison involving two static strings.
95 // if(strcmp("00FF00","00FF00")==0) // <- statement is always true
96 //---------------------------------------------------------------------------
98 {
100  return;
101 
102  logChecker("CheckString::checkAlwaysTrueOrFalseStringCompare"); // warning
103 
104  for (const Token* tok = mTokenizer->tokens(); tok; tok = tok->next()) {
105  if (tok->isName() && tok->strAt(1) == "(" && Token::Match(tok, "memcmp|strncmp|strcmp|stricmp|strverscmp|bcmp|strcmpi|strcasecmp|strncasecmp|strncasecmp_l|strcasecmp_l|wcsncasecmp|wcscasecmp|wmemcmp|wcscmp|wcscasecmp_l|wcsncasecmp_l|wcsncmp|_mbscmp|_mbscmp_l|_memicmp|_memicmp_l|_stricmp|_wcsicmp|_mbsicmp|_stricmp_l|_wcsicmp_l|_mbsicmp_l")) {
106  if (Token::Match(tok->tokAt(2), "%str% , %str% ,|)")) {
107  const std::string &str1 = tok->strAt(2);
108  const std::string &str2 = tok->strAt(4);
109  if (!tok->isExpandedMacro() && !tok->tokAt(2)->isExpandedMacro() && !tok->tokAt(4)->isExpandedMacro())
110  alwaysTrueFalseStringCompareError(tok, str1, str2);
111  tok = tok->tokAt(5);
112  } else if (Token::Match(tok->tokAt(2), "%name% , %name% ,|)")) {
113  const std::string &str1 = tok->strAt(2);
114  const std::string &str2 = tok->strAt(4);
115  if (str1 == str2)
116  alwaysTrueStringVariableCompareError(tok, str1, str2);
117  tok = tok->tokAt(5);
118  } else if (Token::Match(tok->tokAt(2), "%name% . c_str ( ) , %name% . c_str ( ) ,|)")) {
119  const std::string &str1 = tok->strAt(2);
120  const std::string &str2 = tok->strAt(8);
121  if (str1 == str2)
122  alwaysTrueStringVariableCompareError(tok, str1, str2);
123  tok = tok->tokAt(13);
124  }
125  } else if (tok->isName() && Token::Match(tok, "QString :: compare ( %str% , %str% )")) {
126  const std::string &str1 = tok->strAt(4);
127  const std::string &str2 = tok->strAt(6);
128  alwaysTrueFalseStringCompareError(tok, str1, str2);
129  tok = tok->tokAt(7);
130  } else if (Token::Match(tok, "!!+ %str% ==|!= %str% !!+")) {
131  const std::string &str1 = tok->strAt(1);
132  const std::string &str2 = tok->strAt(3);
133  alwaysTrueFalseStringCompareError(tok, str1, str2);
134  tok = tok->tokAt(5);
135  }
136  if (!tok)
137  break;
138  }
139 }
140 
141 void CheckString::alwaysTrueFalseStringCompareError(const Token *tok, const std::string& str1, const std::string& str2)
142 {
143  constexpr std::size_t stringLen = 10;
144  const std::string string1 = (str1.size() < stringLen) ? str1 : (str1.substr(0, stringLen-2) + "..");
145  const std::string string2 = (str2.size() < stringLen) ? str2 : (str2.substr(0, stringLen-2) + "..");
146 
147  reportError(tok, Severity::warning, "staticStringCompare",
148  "Unnecessary comparison of static strings.\n"
149  "The compared strings, '" + string1 + "' and '" + string2 + "', are always " + (str1==str2?"identical":"unequal") + ". "
150  "Therefore the comparison is unnecessary and looks suspicious.", (str1==str2)?CWE571:CWE570, Certainty::normal);
151 }
152 
153 void CheckString::alwaysTrueStringVariableCompareError(const Token *tok, const std::string& str1, const std::string& str2)
154 {
155  reportError(tok, Severity::warning, "stringCompare",
156  "Comparison of identical string variables.\n"
157  "The compared strings, '" + str1 + "' and '" + str2 + "', are identical. "
158  "This could be a logic bug.", CWE571, Certainty::normal);
159 }
160 
161 
162 //-----------------------------------------------------------------------------
163 // Detect "str == '\0'" where "*str == '\0'" is correct.
164 // Comparing char* with each other instead of using strcmp()
165 //-----------------------------------------------------------------------------
167 {
169  return;
170 
171  logChecker("CheckString::checkSuspiciousStringCompare"); // warning
172 
173  const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase();
174  for (const Scope * scope : symbolDatabase->functionScopes) {
175  for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
176  if (!tok->isComparisonOp())
177  continue;
178 
179  const Token* varTok = tok->astOperand1();
180  const Token* litTok = tok->astOperand2();
181  if (!varTok || !litTok) // <- failed to create AST for comparison
182  continue;
183  if (Token::Match(varTok, "%char%|%num%|%str%"))
184  std::swap(varTok, litTok);
185  else if (!Token::Match(litTok, "%char%|%num%|%str%"))
186  continue;
187 
188  if (varTok->isLiteral())
189  continue;
190 
191  const ValueType* varType = varTok->valueType();
192  if (varTok->isCpp() && (!varType || !varType->isIntegral()))
193  continue;
194 
195  if (litTok->tokType() == Token::eString) {
196  if (varTok->isC() || (varType && varType->pointer))
197  suspiciousStringCompareError(tok, varTok->expressionString(), litTok->isLong());
198  } else if (litTok->tokType() == Token::eChar && varType && varType->pointer) {
200  }
201  }
202  }
203 }
204 
205 void CheckString::suspiciousStringCompareError(const Token* tok, const std::string& var, bool isLong)
206 {
207  const std::string cmpFunc = isLong ? "wcscmp" : "strcmp";
208  reportError(tok, Severity::warning, "literalWithCharPtrCompare",
209  "$symbol:" + var + "\nString literal compared with variable '$symbol'. Did you intend to use " + cmpFunc + "() instead?", CWE595, Certainty::normal);
210 }
211 
212 void CheckString::suspiciousStringCompareError_char(const Token* tok, const std::string& var)
213 {
214  reportError(tok, Severity::warning, "charLiteralWithCharPtrCompare",
215  "$symbol:" + var + "\nChar literal compared with pointer '$symbol'. Did you intend to dereference it?", CWE595, Certainty::normal);
216 }
217 
218 
219 //---------------------------------------------------------------------------
220 // Adding C-string and char with operator+
221 //---------------------------------------------------------------------------
222 
223 static bool isChar(const Variable* var)
224 {
225  return (var && !var->isPointer() && !var->isArray() && (var->typeStartToken()->str() == "char" || var->typeStartToken()->str() == "wchar_t"));
226 }
227 
229 {
230  logChecker("CheckString::strPlusChar");
231  const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase();
232  for (const Scope * scope : symbolDatabase->functionScopes) {
233  for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
234  if (tok->str() == "+") {
235  if (tok->astOperand1() && (tok->astOperand1()->tokType() == Token::eString)) { // string literal...
236  if (tok->astOperand2() && (tok->astOperand2()->tokType() == Token::eChar || isChar(tok->astOperand2()->variable()))) // added to char variable or char constant
237  strPlusCharError(tok);
238  }
239  }
240  }
241  }
242 }
243 
245 {
246  std::string charType = "char";
247  if (tok && tok->astOperand2() && tok->astOperand2()->variable())
248  charType = tok->astOperand2()->variable()->typeStartToken()->str();
249  else if (tok && tok->astOperand2() && tok->astOperand2()->tokType() == Token::eChar && tok->astOperand2()->isLong())
250  charType = "wchar_t";
251  reportError(tok, Severity::error, "strPlusChar", "Unusual pointer arithmetic. A value of type '" + charType +"' is added to a string literal.", CWE665, Certainty::normal);
252 }
253 
254 static bool isMacroUsage(const Token* tok)
255 {
256  if (const Token* parent = tok->astParent()) {
257  while (parent && parent->isCast())
258  parent = parent->astParent();
259  if (!parent)
260  return false;
261  if (parent->isExpandedMacro())
262  return true;
263  if (parent->isUnaryOp("!") || parent->isComparisonOp()) {
264  int argn{};
265  const Token* ftok = getTokenArgumentFunction(parent, argn);
266  if (ftok && !ftok->function())
267  return true;
268  }
269  }
270  return false;
271 }
272 
273 //---------------------------------------------------------------------------
274 // Implicit casts of string literals to bool
275 // Comparing string literal with strlen() with wrong length
276 //---------------------------------------------------------------------------
278 {
280  return;
281 
282  logChecker("CheckString::checkIncorrectStringCompare"); // warning
283 
284  const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
285  for (const Scope * scope : symbolDatabase->functionScopes) {
286  for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
287  // skip "assert(str && ..)" and "assert(.. && str)"
288  if ((endsWith(tok->str(), "assert") || endsWith(tok->str(), "ASSERT")) &&
289  Token::Match(tok, "%name% (") &&
290  (Token::Match(tok->tokAt(2), "%str% &&") || Token::Match(tok->next()->link()->tokAt(-2), "&& %str% )")))
291  tok = tok->next()->link();
292 
293  if (Token::simpleMatch(tok, ". substr (") && Token::Match(tok->tokAt(3)->nextArgument(), "%num% )")) {
294  const MathLib::biguint clen = MathLib::toBigUNumber(tok->linkAt(2)->strAt(-1));
295  const Token* begin = tok->previous();
296  for (;;) { // Find start of statement
297  while (begin->link() && Token::Match(begin, "]|)|>"))
298  begin = begin->link()->previous();
299  if (Token::Match(begin->previous(), ".|::"))
300  begin = begin->tokAt(-2);
301  else
302  break;
303  }
304  begin = begin->previous();
305  const Token* end = tok->linkAt(2)->next();
306  if (Token::Match(begin->previous(), "%str% ==|!=") && begin->strAt(-2) != "+") {
307  const std::size_t slen = Token::getStrLength(begin->previous());
308  if (clen != slen) {
309  incorrectStringCompareError(tok->next(), "substr", begin->strAt(-1));
310  }
311  } else if (Token::Match(end, "==|!= %str% !!+")) {
312  const std::size_t slen = Token::getStrLength(end->next());
313  if (clen != slen) {
314  incorrectStringCompareError(tok->next(), "substr", end->strAt(1));
315  }
316  }
317  } else if (Token::Match(tok, "%str%|%char%") &&
318  isUsedAsBool(tok, *mSettings) &&
319  !isMacroUsage(tok))
320  incorrectStringBooleanError(tok, tok->str());
321  }
322  }
323 }
324 
325 void CheckString::incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string)
326 {
327  reportError(tok, Severity::warning, "incorrectStringCompare", "$symbol:" + func + "\nString literal " + string + " doesn't match length argument for $symbol().", CWE570, Certainty::normal);
328 }
329 
330 void CheckString::incorrectStringBooleanError(const Token *tok, const std::string& string)
331 {
332  const bool charLiteral = isCharLiteral(string);
333  const std::string literalType = charLiteral ? "char" : "string";
334  const std::string result = bool_to_string(getCharLiteral(string) != "\\0");
335  reportError(tok,
337  charLiteral ? "incorrectCharBooleanError" : "incorrectStringBooleanError",
338  "Conversion of " + literalType + " literal " + string + " to bool always evaluates to " + result + '.', CWE571, Certainty::normal);
339 }
340 
341 //---------------------------------------------------------------------------
342 // always true: strcmp(str,"a")==0 || strcmp(str,"b")
343 // TODO: Library configuration for string comparison functions
344 //---------------------------------------------------------------------------
346 {
348  return;
349 
350  logChecker("CheckString::overlappingStrcmp"); // warning
351 
352  const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase();
353  for (const Scope * scope : symbolDatabase->functionScopes) {
354  for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
355  if (tok->str() != "||")
356  continue;
357  std::list<const Token *> equals0;
358  std::list<const Token *> notEquals0;
359  visitAstNodes(tok, [&](const Token * t) {
360  if (!t)
361  return ChildrenToVisit::none;
362  if (t->str() == "||") {
363  return ChildrenToVisit::op1_and_op2;
364  }
365  if (t->str() == "==") {
366  if (Token::simpleMatch(t->astOperand1(), "(") && Token::simpleMatch(t->astOperand2(), "0"))
367  equals0.push_back(t->astOperand1());
368  else if (Token::simpleMatch(t->astOperand2(), "(") && Token::simpleMatch(t->astOperand1(), "0"))
369  equals0.push_back(t->astOperand2());
370  return ChildrenToVisit::none;
371  }
372  if (t->str() == "!=") {
373  if (Token::simpleMatch(t->astOperand1(), "(") && Token::simpleMatch(t->astOperand2(), "0"))
374  notEquals0.push_back(t->astOperand1());
375  else if (Token::simpleMatch(t->astOperand2(), "(") && Token::simpleMatch(t->astOperand1(), "0"))
376  notEquals0.push_back(t->astOperand2());
377  return ChildrenToVisit::none;
378  }
379  if (t->str() == "!" && Token::simpleMatch(t->astOperand1(), "("))
380  equals0.push_back(t->astOperand1());
381  else if (t->str() == "(")
382  notEquals0.push_back(t);
383  return ChildrenToVisit::none;
384  });
385 
386  for (const Token *eq0 : equals0) {
387  for (const Token * ne0 : notEquals0) {
388  if (!Token::Match(eq0->previous(), "strcmp|wcscmp ("))
389  continue;
390  if (!Token::Match(ne0->previous(), "strcmp|wcscmp ("))
391  continue;
392  const std::vector<const Token *> args1 = getArguments(eq0->previous());
393  const std::vector<const Token *> args2 = getArguments(ne0->previous());
394  if (args1.size() != 2 || args2.size() != 2)
395  continue;
396  if (args1[1]->isLiteral() &&
397  args2[1]->isLiteral() &&
398  args1[1]->str() != args2[1]->str() &&
399  isSameExpression(true, args1[0], args2[0], *mSettings, true, false))
400  overlappingStrcmpError(eq0, ne0);
401  }
402  }
403  }
404  }
405 }
406 
407 void CheckString::overlappingStrcmpError(const Token *eq0, const Token *ne0)
408 {
409  std::string eq0Expr(eq0 ? eq0->expressionString() : std::string("strcmp(x,\"abc\")"));
410  if (eq0 && eq0->astParent()->str() == "!")
411  eq0Expr = "!" + eq0Expr;
412  else
413  eq0Expr += " == 0";
414 
415  const std::string ne0Expr = (ne0 ? ne0->expressionString() : std::string("strcmp(x,\"def\")")) + " != 0";
416 
417  reportError(ne0, Severity::warning, "overlappingStrcmp", "The expression '" + ne0Expr + "' is suspicious. It overlaps '" + eq0Expr + "'.");
418 }
419 
420 //---------------------------------------------------------------------------
421 // Overlapping source and destination passed to sprintf().
422 // TODO: Library configuration for overlapping arguments
423 //---------------------------------------------------------------------------
425 {
426  logChecker("CheckString::sprintfOverlappingData");
427 
428  const SymbolDatabase* symbolDatabase = mTokenizer->getSymbolDatabase();
429  for (const Scope * scope : symbolDatabase->functionScopes) {
430  for (const Token* tok = scope->bodyStart->next(); tok != scope->bodyEnd; tok = tok->next()) {
431  if (!Token::Match(tok, "sprintf|snprintf|swprintf ("))
432  continue;
433 
434  const std::vector<const Token *> args = getArguments(tok);
435 
436  const int formatString = Token::simpleMatch(tok, "sprintf") ? 1 : 2;
437  for (unsigned int argnr = formatString + 1; argnr < args.size(); ++argnr) {
438  const Token *dest = args[0];
439  while (dest->isCast())
440  dest = dest->astOperand2() ? dest->astOperand2() : dest->astOperand1();
441  const Token *arg = args[argnr];
442  if (!arg->valueType() || arg->valueType()->pointer != 1)
443  continue;
444  while (arg->isCast())
445  arg = arg->astOperand2() ? arg->astOperand2() : arg->astOperand1();
446 
447  const bool same = isSameExpression(false,
448  dest,
449  arg,
450  *mSettings,
451  true,
452  false);
453  if (same) {
454  sprintfOverlappingDataError(tok, args[argnr], arg->expressionString());
455  }
456  }
457  }
458  }
459 }
460 
461 void CheckString::sprintfOverlappingDataError(const Token *funcTok, const Token *tok, const std::string &varname)
462 {
463  const std::string func = funcTok ? funcTok->str() : "s[n]printf";
464 
465  reportError(tok, Severity::error, "sprintfOverlappingData",
466  "$symbol:" + varname + "\n"
467  "Undefined behavior: Variable '$symbol' is used as parameter and destination in " + func + "().\n" +
468  "The variable '$symbol' is used both as a parameter and as destination in " +
469  func + "(). The origin and destination buffers overlap. Quote from glibc (C-library) "
470  "documentation (http://www.gnu.org/software/libc/manual/html_mono/libc.html#Formatted-Output-Functions): "
471  "\"If copying takes place between objects that overlap as a result of a call "
472  "to sprintf() or snprintf(), the results are undefined.\"", CWE628, Certainty::normal);
473 }
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
Definition: astutils.cpp:3078
bool isSameExpression(bool macro, const Token *tok1, const Token *tok2, const Settings &settings, bool pure, bool followVar, ErrorPath *errors)
Definition: astutils.cpp:1549
const Token * getTokenArgumentFunction(const Token *tok, int &argn)
Return the token to the function and the argument number.
Definition: astutils.cpp:2355
bool isUsedAsBool(const Token *const tok, const Settings &settings)
Is token used as boolean, that is to say cast to a bool, or used as a condition in a if/while/for.
Definition: astutils.cpp:1482
void visitAstNodes(T *ast, const TFunc &visitor)
Visit AST nodes recursively.
Definition: astutils.h:54
static const CWE CWE571(571U)
static bool isMacroUsage(const Token *tok)
static const CWE CWE595(595U)
static const CWE CWE758(758U)
static const CWE CWE570(570U)
static const CWE CWE665(665U)
static bool isChar(const Variable *var)
static const CWE CWE628(628U)
Detect misusage of C-style strings and related standard functions.
Definition: checkstring.h:41
void checkSuspiciousStringCompare()
Check for comparison of a string literal with a char* variable
void checkIncorrectStringCompare()
Check for using bad usage of strncmp and substr
void suspiciousStringCompareError(const Token *tok, const std::string &var, bool isLong)
void incorrectStringBooleanError(const Token *tok, const std::string &string)
void overlappingStrcmp()
Check for overlapping strcmp()
void incorrectStringCompareError(const Token *tok, const std::string &func, const std::string &string)
void strPlusCharError(const Token *tok)
void suspiciousStringCompareError_char(const Token *tok, const std::string &var)
void sprintfOverlappingData()
Check for overlapping source and destination passed to sprintf()
void stringLiteralWriteError(const Token *tok, const Token *strValue)
Definition: checkstring.cpp:74
void alwaysTrueStringVariableCompareError(const Token *tok, const std::string &str1, const std::string &str2)
void overlappingStrcmpError(const Token *eq0, const Token *ne0)
void stringLiteralWrite()
undefined behaviour, writing string literal
Definition: checkstring.cpp:55
void strPlusChar()
str plus char (unusual pointer arithmetic)
void alwaysTrueFalseStringCompareError(const Token *tok, const std::string &str1, const std::string &str2)
void sprintfOverlappingDataError(const Token *funcTok, const Token *tok, const std::string &varname)
void checkAlwaysTrueOrFalseStringCompare()
Check for suspicious code that compares string literals for equality
Definition: checkstring.cpp:97
void reportError(const Token *tok, const Severity severity, const std::string &id, const std::string &msg)
report an error
Definition: check.h:138
const Settings *const mSettings
Definition: check.h:134
const Tokenizer *const mTokenizer
Definition: check.h:133
void logChecker(const char id[])
log checker
Definition: check.cpp:129
static biguint toBigUNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
Definition: mathlib.cpp:289
unsigned long long biguint
Definition: mathlib.h:69
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
SimpleEnableGroup< Severity > severity
Definition: settings.h:358
bool isEnabled(T flag) const
Definition: settings.h:66
std::vector< const Scope * > functionScopes
Fast access to function scopes.
The token list that the TokenList generates is a linked-list of this class.
Definition: token.h:150
void str(T &&s)
Definition: token.h:179
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
Definition: token.cpp:722
bool isC() const
Definition: token.cpp:2757
const Token * getValueTokenMinStrSize(const Settings &settings, MathLib::bigint *path=nullptr) const
Definition: token.cpp:2022
bool isCpp() const
Definition: token.cpp:2752
static nonneg int getStrLength(const Token *tok)
Definition: token.cpp:811
const ValueType * valueType() const
Definition: token.h:331
const std::string & strAt(int index) const
Definition: token.cpp:457
void astOperand1(Token *tok)
Definition: token.cpp:1490
void function(const Function *f)
Associate this token with given function.
Definition: token.cpp:1127
std::string expressionString() const
Definition: token.cpp:1681
bool isCast() const
Definition: token.h:458
bool isLiteral() const
Definition: token.h:368
const Token * tokAt(int index) const
Definition: token.cpp:427
Token::Type tokType() const
Definition: token.h:343
void astOperand2(Token *tok)
Definition: token.cpp:1502
bool isLong() const
Definition: token.h:443
void link(Token *linkToToken)
Create link to given token.
Definition: token.h:1015
const Token * linkAt(int index) const
Definition: token.cpp:447
@ eString
Definition: token.h:162
@ eChar
Definition: token.h:162
Token * previous()
Definition: token.h:862
Token * next()
Definition: token.h:830
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
Definition: token.h:252
void astParent(Token *tok)
Definition: token.cpp:1471
const Token * tokens() const
Definition: tokenize.h:592
const SymbolDatabase * getSymbolDatabase() const
Definition: tokenize.h:563
Value type.
bool isIntegral() const
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
Information about a member variable.
bool isArray() const
Is variable an array.
const Token * typeStartToken() const
Get type start token.
bool isPointer() const
Is pointer variable.
@ warning
Warning.
@ error
Programming error.
bool endsWith(const std::string &str, char c)
Definition: utils.h:110
static bool isCharLiteral(const std::string &str)
Definition: utils.h:164
static const char * bool_to_string(bool b)
Definition: utils.h:345
static std::string getCharLiteral(const std::string &str)
Definition: utils.h:182