Cppcheck
clangimport.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 #include "clangimport.h"
20 
21 #include "errortypes.h"
22 #include "mathlib.h"
23 #include "settings.h"
24 #include "standards.h"
25 #include "symboldatabase.h"
26 #include "token.h"
27 #include "tokenize.h"
28 #include "tokenlist.h"
29 #include "utils.h"
30 #include "vfvalue.h"
31 
32 #include <algorithm>
33 #include <cctype>
34 #include <cstring>
35 #include <iostream>
36 #include <iterator>
37 #include <list>
38 #include <map>
39 #include <memory>
40 #include <set>
41 #include <sstream>
42 #include <stack>
43 #include <string>
44 #include <utility>
45 #include <vector>
46 #include <numeric>
47 
48 static const std::string AccessSpecDecl = "AccessSpecDecl";
49 static const std::string ArraySubscriptExpr = "ArraySubscriptExpr";
50 static const std::string BinaryOperator = "BinaryOperator";
51 static const std::string BreakStmt = "BreakStmt";
52 static const std::string CallExpr = "CallExpr";
53 static const std::string CaseStmt = "CaseStmt";
54 static const std::string CharacterLiteral = "CharacterLiteral";
55 static const std::string ClassTemplateDecl = "ClassTemplateDecl";
56 static const std::string ClassTemplateSpecializationDecl = "ClassTemplateSpecializationDecl";
57 static const std::string ConditionalOperator = "ConditionalOperator";
58 static const std::string ConstantExpr = "ConstantExpr";
59 static const std::string CompoundAssignOperator = "CompoundAssignOperator";
60 static const std::string CompoundStmt = "CompoundStmt";
61 static const std::string ContinueStmt = "ContinueStmt";
62 static const std::string CStyleCastExpr = "CStyleCastExpr";
63 static const std::string CXXBindTemporaryExpr = "CXXBindTemporaryExpr";
64 static const std::string CXXBoolLiteralExpr = "CXXBoolLiteralExpr";
65 static const std::string CXXConstructorDecl = "CXXConstructorDecl";
66 static const std::string CXXConstructExpr = "CXXConstructExpr";
67 static const std::string CXXDefaultArgExpr = "CXXDefaultArgExpr";
68 static const std::string CXXDeleteExpr = "CXXDeleteExpr";
69 static const std::string CXXDestructorDecl = "CXXDestructorDecl";
70 static const std::string CXXForRangeStmt = "CXXForRangeStmt";
71 static const std::string CXXFunctionalCastExpr = "CXXFunctionalCastExpr";
72 static const std::string CXXMemberCallExpr = "CXXMemberCallExpr";
73 static const std::string CXXMethodDecl = "CXXMethodDecl";
74 static const std::string CXXNewExpr = "CXXNewExpr";
75 static const std::string CXXNullPtrLiteralExpr = "CXXNullPtrLiteralExpr";
76 static const std::string CXXOperatorCallExpr = "CXXOperatorCallExpr";
77 static const std::string CXXRecordDecl = "CXXRecordDecl";
78 static const std::string CXXStaticCastExpr = "CXXStaticCastExpr";
79 static const std::string CXXStdInitializerListExpr = "CXXStdInitializerListExpr";
80 static const std::string CXXTemporaryObjectExpr = "CXXTemporaryObjectExpr";
81 static const std::string CXXThisExpr = "CXXThisExpr";
82 static const std::string CXXThrowExpr = "CXXThrowExpr";
83 static const std::string DeclRefExpr = "DeclRefExpr";
84 static const std::string DeclStmt = "DeclStmt";
85 static const std::string DefaultStmt = "DefaultStmt";
86 static const std::string DoStmt = "DoStmt";
87 static const std::string EnumConstantDecl = "EnumConstantDecl";
88 static const std::string EnumDecl = "EnumDecl";
89 static const std::string ExprWithCleanups = "ExprWithCleanups";
90 static const std::string FieldDecl = "FieldDecl";
91 static const std::string FloatingLiteral = "FloatingLiteral";
92 static const std::string ForStmt = "ForStmt";
93 static const std::string FunctionDecl = "FunctionDecl";
94 static const std::string FunctionTemplateDecl = "FunctionTemplateDecl";
95 static const std::string GotoStmt = "GotoStmt";
96 static const std::string IfStmt = "IfStmt";
97 static const std::string ImplicitCastExpr = "ImplicitCastExpr";
98 static const std::string InitListExpr = "InitListExpr";
99 static const std::string IntegerLiteral = "IntegerLiteral";
100 static const std::string LabelStmt = "LabelStmt";
101 static const std::string LinkageSpecDecl = "LinkageSpecDecl";
102 static const std::string MaterializeTemporaryExpr = "MaterializeTemporaryExpr";
103 static const std::string MemberExpr = "MemberExpr";
104 static const std::string NamespaceDecl = "NamespaceDecl";
105 static const std::string NullStmt = "NullStmt";
106 static const std::string ParenExpr = "ParenExpr";
107 static const std::string ParmVarDecl = "ParmVarDecl";
108 static const std::string RecordDecl = "RecordDecl";
109 static const std::string ReturnStmt = "ReturnStmt";
110 static const std::string StringLiteral = "StringLiteral";
111 static const std::string SwitchStmt = "SwitchStmt";
112 static const std::string TemplateArgument = "TemplateArgument";
113 static const std::string TypedefDecl = "TypedefDecl";
114 static const std::string UnaryOperator = "UnaryOperator";
115 static const std::string UnaryExprOrTypeTraitExpr = "UnaryExprOrTypeTraitExpr";
116 static const std::string VarDecl = "VarDecl";
117 static const std::string WhileStmt = "WhileStmt";
118 
119 static std::string unquote(const std::string &s)
120 {
121  return (s[0] == '\'') ? s.substr(1, s.size() - 2) : s;
122 }
123 
124 
125 static std::vector<std::string> splitString(const std::string &line)
126 {
127  std::vector<std::string> ret;
128  std::string::size_type pos1 = line.find_first_not_of(' ');
129  while (pos1 < line.size()) {
130  std::string::size_type pos2;
131  if (std::strchr("*()", line[pos1])) {
132  ret.push_back(line.substr(pos1,1));
133  pos1 = line.find_first_not_of(' ', pos1 + 1);
134  continue;
135  }
136  if (line[pos1] == '<')
137  pos2 = line.find('>', pos1);
138  else if (line[pos1] == '\"')
139  pos2 = line.find('\"', pos1+1);
140  else if (line[pos1] == '\'') {
141  pos2 = line.find('\'', pos1+1);
142  if (pos2 < (int)line.size() - 3 && line.compare(pos2, 3, "\':\'", 0, 3) == 0)
143  pos2 = line.find('\'', pos2 + 3);
144  } else {
145  pos2 = pos1;
146  while (pos2 < line.size() && (line[pos2] == '_' || line[pos2] == ':' || std::isalnum((unsigned char)line[pos2])))
147  ++pos2;
148  if (pos2 > pos1 && pos2 < line.size() && line[pos2] == '<' && std::isalpha(line[pos1])) {
149  int tlevel = 1;
150  while (++pos2 < line.size() && tlevel > 0) {
151  if (line[pos2] == '<')
152  ++tlevel;
153  else if (line[pos2] == '>')
154  --tlevel;
155  }
156  if (tlevel == 0 && pos2 < line.size() && line[pos2] == ' ') {
157  ret.push_back(line.substr(pos1, pos2-pos1));
158  pos1 = pos2 + 1;
159  continue;
160  }
161  }
162 
163  pos2 = line.find(' ', pos1) - 1;
164  if ((std::isalpha(line[pos1]) || line[pos1] == '_') &&
165  line.find("::", pos1) < pos2 &&
166  line.find("::", pos1) < line.find('<', pos1)) {
167  pos2 = line.find("::", pos1);
168  ret.push_back(line.substr(pos1, pos2-pos1));
169  ret.emplace_back("::");
170  pos1 = pos2 + 2;
171  continue;
172  }
173  if ((std::isalpha(line[pos1]) || line[pos1] == '_') &&
174  line.find('<', pos1) < pos2 &&
175  line.find("<<",pos1) != line.find('<',pos1) &&
176  line.find('>', pos1) != std::string::npos &&
177  line.find('>', pos1) > pos2) {
178  int level = 0;
179  for (pos2 = pos1; pos2 < line.size(); ++pos2) {
180  if (line[pos2] == '<')
181  ++level;
182  else if (line[pos2] == '>') {
183  if (level <= 1)
184  break;
185  --level;
186  }
187  }
188  if (level > 1 && pos2 + 1 >= line.size())
189  return std::vector<std::string> {};
190  pos2 = line.find(' ', pos2);
191  if (pos2 != std::string::npos)
192  --pos2;
193  }
194  }
195  if (pos2 == std::string::npos) {
196  ret.push_back(line.substr(pos1));
197  break;
198  }
199  ret.push_back(line.substr(pos1, pos2+1-pos1));
200  pos1 = line.find_first_not_of(' ', pos2 + 1);
201  }
202  return ret;
203 }
204 
205 
206 namespace clangimport {
207  struct Data {
208  struct Decl {
209  explicit Decl(Scope *scope) : scope(scope) {}
211  Decl(Token *def, Function *function) : def(def), function(function) {}
213  void ref(Token *tok) const {
214  if (enumerator)
215  tok->enumerator(enumerator);
216  if (function)
217  tok->function(function);
218  if (var) {
219  tok->variable(var);
220  tok->varId(var->declarationId());
221  }
222  }
223  Token* def{};
225  Function* function{};
228  };
229 
230  const Settings *mSettings = nullptr;
232 
233  int enumValue = 0;
234 
235  void enumDecl(const std::string &addr, Token *nameToken, Enumerator *enumerator) {
236  Decl decl(nameToken, enumerator);
237  mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
238  nameToken->enumerator(enumerator);
239  notFound(addr);
240  }
241 
242  void funcDecl(const std::string &addr, Token *nameToken, Function *function) {
243  Decl decl(nameToken, function);
244  mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
245  nameToken->function(function);
246  notFound(addr);
247  }
248 
249  void scopeDecl(const std::string &addr, Scope *scope) {
250  Decl decl(scope);
251  mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
252  }
253 
254  void varDecl(const std::string &addr, Token *def, Variable *var) {
255  Decl decl(def, var);
256  mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
257  def->varId(++mVarId);
258  def->variable(var);
259  if (def->valueType())
260  var->setValueType(*def->valueType());
261  notFound(addr);
262  }
263 
264  void replaceVarDecl(const Variable *from, Variable *to) {
265  for (auto &it: mDeclMap) {
266  Decl &decl = it.second;
267  if (decl.var == from)
268  decl.var = to;
269  }
270  }
271 
272  void ref(const std::string &addr, Token *tok) {
273  auto it = mDeclMap.find(addr);
274  if (it != mDeclMap.end())
275  it->second.ref(tok);
276  else
277  mNotFound[addr].push_back(tok);
278  }
279 
280  std::vector<const Variable *> getVariableList() const {
281  std::vector<const Variable *> ret;
282  ret.resize(mVarId + 1, nullptr);
283  for (const auto& it: mDeclMap) {
284  if (it.second.var)
285  ret[it.second.var->declarationId()] = it.second.var;
286  }
287  return ret;
288  }
289 
290  bool hasDecl(const std::string &addr) const {
291  return mDeclMap.find(addr) != mDeclMap.end();
292  }
293 
294  const Scope *getScope(const std::string &addr) {
295  auto it = mDeclMap.find(addr);
296  return (it == mDeclMap.end() ? nullptr : it->second.scope);
297  }
298 
299  // "}" tokens that are not end-of-scope
300  std::set<Token *> mNotScope;
301 
302  std::map<const Scope *, AccessControl> scopeAccessControl;
303  private:
304  void notFound(const std::string &addr) {
305  auto it = mNotFound.find(addr);
306  if (it != mNotFound.end()) {
307  for (Token *reftok: it->second)
308  ref(addr, reftok);
309  mNotFound.erase(it);
310  }
311  }
312 
313  std::map<std::string, Decl> mDeclMap;
314  std::map<std::string, std::vector<Token *>> mNotFound;
315  int mVarId = 0;
316  };
317 
318  class AstNode;
319  using AstNodePtr = std::shared_ptr<AstNode>;
320 
321  class AstNode {
322  public:
323  AstNode(std::string nodeType, const std::string &ext, Data *data)
324  : nodeType(std::move(nodeType)), mExtTokens(splitString(ext)), mData(data)
325  {}
326  std::string nodeType;
327  std::vector<AstNodePtr> children;
328 
329  void setLocations(TokenList &tokenList, int file, int line, int col);
330 
331  void dumpAst(int num = 0, int indent = 0) const;
332  void createTokens1(TokenList &tokenList) {
333  //dumpAst();
334  if (!tokenList.back()) {
335  setLocations(tokenList, 0, 1, 1);
336  // FIXME: treat as C++ if no filename (i.e. no lang) is specified for now
337  if (tokenList.getSourceFilePath().empty())
338  tokenList.setLang(Standards::Language::CPP);
339  }
340  else
341  setLocations(tokenList, tokenList.back()->fileIndex(), tokenList.back()->linenr(), 1);
342  createTokens(tokenList);
344  addtoken(tokenList, ";");
345  mData->mNotScope.clear();
346  }
347 
349  if (c >= children.size()) {
350  std::ostringstream err;
351  err << "ClangImport: AstNodePtr::getChild(" << c << ") out of bounds. children.size=" << children.size() << " " << nodeType;
352  for (const std::string &s: mExtTokens)
353  err << " " << s;
354  throw InternalError(nullptr, err.str());
355  }
356  return children[c];
357  }
358  private:
359  Token *createTokens(TokenList &tokenList);
360  Token *addtoken(TokenList &tokenList, const std::string &str, bool valueType=true);
361  const ::Type *addTypeTokens(TokenList &tokenList, const std::string &str, const Scope *scope = nullptr);
362  void addFullScopeNameTokens(TokenList &tokenList, const Scope *recordScope);
363  Scope *createScope(TokenList &tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def);
364  Scope *createScope(TokenList &tokenList, Scope::ScopeType scopeType, const std::vector<AstNodePtr> &children2, const Token *def);
365  Token *createTokensCall(TokenList &tokenList);
366  void createTokensFunctionDecl(TokenList &tokenList);
367  void createTokensForCXXRecord(TokenList &tokenList);
368  Token *createTokensVarDecl(TokenList &tokenList);
369  std::string getSpelling() const;
370  std::string getType(int index = 0) const;
371  std::string getFullType(int index = 0) const;
372  bool isDefinition() const;
373  std::string getTemplateParameters() const;
374  const Scope *getNestedInScope(TokenList &tokenList);
375  void setValueType(Token *tok);
376 
377  int mFile = 0;
378  int mLine = 1;
379  int mCol = 1;
380  std::vector<std::string> mExtTokens;
382  };
383 }
384 
386 {
388  int typeIndex = 1;
389  while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'')
390  typeIndex++;
391  // name is next quoted token
392  int nameIndex = typeIndex + 1;
393  while (nameIndex < mExtTokens.size() && mExtTokens[nameIndex][0] != '\'')
394  nameIndex++;
395  return (nameIndex < mExtTokens.size()) ? unquote(mExtTokens[nameIndex]) : "";
396  }
397 
399  int typeIndex = 1;
400  while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'')
401  typeIndex++;
402  const int nameIndex = typeIndex + 1;
403  return (nameIndex < mExtTokens.size()) ? unquote(mExtTokens[nameIndex]) : "";
404  }
405 
406  int typeIndex = mExtTokens.size() - 1;
408  while (typeIndex >= 0 && mExtTokens[typeIndex][0] != '\'')
409  typeIndex--;
410  if (typeIndex <= 0)
411  return "";
412  }
413  if (nodeType == DeclRefExpr) {
414  while (typeIndex > 0 && std::isalpha(mExtTokens[typeIndex][0]))
415  typeIndex--;
416  if (typeIndex <= 0)
417  return "";
418  }
419  const std::string &str = mExtTokens[typeIndex - 1];
420  if (startsWith(str,"col:"))
421  return "";
422  if (startsWith(str,"<invalid"))
423  return "";
424  if (nodeType == RecordDecl && str == "struct")
425  return "";
426  return str;
427 }
428 
429 std::string clangimport::AstNode::getType(int index) const
430 {
431  std::string type = getFullType(index);
432  if (type.find(" (") != std::string::npos) {
433  const std::string::size_type pos = type.find(" (");
434  type[pos] = '\'';
435  type.erase(pos+1);
436  }
437  if (type.find(" *(") != std::string::npos) {
438  const std::string::size_type pos = type.find(" *(") + 2;
439  type[pos] = '\'';
440  type.erase(pos+1);
441  }
442  if (type.find(" &(") != std::string::npos) {
443  const std::string::size_type pos = type.find(" &(") + 2;
444  type[pos] = '\'';
445  type.erase(pos+1);
446  }
447  return unquote(type);
448 }
449 
450 std::string clangimport::AstNode::getFullType(int index) const
451 {
452  int typeIndex = 1;
453  while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'')
454  typeIndex++;
455  if (typeIndex >= mExtTokens.size())
456  return "";
457  std::string type = mExtTokens[typeIndex];
458  if (type.find("\':\'") != std::string::npos) {
459  if (index == 0)
460  type.erase(type.find("\':\'") + 1);
461  else
462  type.erase(0, type.find("\':\'") + 2);
463  }
464  return type;
465 }
466 
468 {
469  return contains(mExtTokens, "definition");
470 }
471 
473 {
474  if (children.empty() || children[0]->nodeType != TemplateArgument)
475  return "";
476  std::string templateParameters;
477  for (const AstNodePtr& child: children) {
478  if (child->nodeType == TemplateArgument) {
479  if (templateParameters.empty())
480  templateParameters = "<";
481  else
482  templateParameters += ",";
483  templateParameters += unquote(child->mExtTokens.back());
484  }
485  }
486  return templateParameters + ">";
487 }
488 
489 void clangimport::AstNode::dumpAst(int num, int indent) const
490 {
491  (void)num;
492  std::cout << std::string(indent, ' ') << nodeType;
493  for (const auto& tok: mExtTokens)
494  std::cout << " " << tok;
495  std::cout << std::endl;
496  for (int c = 0; c < children.size(); ++c) {
497  if (children[c])
498  children[c]->dumpAst(c, indent + 2);
499  else
500  std::cout << std::string(indent + 2, ' ') << "<<<<NULL>>>>>" << std::endl;
501  }
502 }
503 
504 void clangimport::AstNode::setLocations(TokenList &tokenList, int file, int line, int col)
505 {
506  for (const std::string &ext: mExtTokens) {
507  if (startsWith(ext, "<col:"))
508  col = strToInt<int>(ext.substr(5, ext.find_first_of(",>", 5) - 5));
509  else if (startsWith(ext, "<line:")) {
510  line = strToInt<int>(ext.substr(6, ext.find_first_of(":,>", 6) - 6));
511  const auto pos = ext.find(", col:");
512  if (pos != std::string::npos)
513  col = strToInt<int>(ext.substr(pos+6, ext.find_first_of(":,>", pos+6) - (pos+6)));
514  } else if (ext[0] == '<') {
515  const std::string::size_type colon = ext.find(':');
516  if (colon != std::string::npos) {
517  const bool windowsPath = colon == 2 && ext.size() > 3 && ext[2] == ':';
518  const std::string::size_type sep1 = windowsPath ? ext.find(':', 4) : colon;
519  const std::string::size_type sep2 = ext.find(':', sep1 + 1);
520  file = tokenList.appendFileIfNew(ext.substr(1, sep1 - 1));
521  line = strToInt<int>(ext.substr(sep1 + 1, sep2 - sep1 - 1));
522  }
523  }
524  }
525  mFile = file;
526  mLine = line;
527  mCol = col;
528  for (const auto& child: children) {
529  if (child)
530  child->setLocations(tokenList, file, line, col);
531  }
532 }
533 
534 Token *clangimport::AstNode::addtoken(TokenList &tokenList, const std::string &str, bool valueType)
535 {
536  const Scope *scope = getNestedInScope(tokenList);
537  tokenList.addtoken(str, mLine, mCol, mFile);
538  tokenList.back()->scope(scope);
539  if (valueType)
540  setValueType(tokenList.back());
541  return tokenList.back();
542 }
543 
544 const ::Type * clangimport::AstNode::addTypeTokens(TokenList &tokenList, const std::string &str, const Scope *scope)
545 {
546  if (str.find("\':\'") != std::string::npos) {
547  return addTypeTokens(tokenList, str.substr(0, str.find("\':\'") + 1), scope);
548  }
549 
550  if (startsWith(str, "'enum (anonymous"))
551  return nullptr;
552 
553  std::string type;
554  if (str.find(" (") != std::string::npos) {
555  if (str.find('<') != std::string::npos)
556  type = str.substr(1, str.find('<')) + "...>";
557  else
558  type = str.substr(1,str.find(" (")-1);
559  } else
560  type = unquote(str);
561 
562  if (type.find("(*)(") != std::string::npos) {
563  type.erase(type.find("(*)("));
564  type += "*";
565  }
566  if (type.find('(') != std::string::npos)
567  type.erase(type.find('('));
568 
569  std::stack<Token *> lpar;
570  for (const std::string &s: splitString(type)) {
571  Token *tok = addtoken(tokenList, s, false);
572  if (tok->str() == "(")
573  lpar.push(tok);
574  else if (tok->str() == ")") {
575  Token::createMutualLinks(tok, lpar.top());
576  lpar.pop();
577  }
578  }
579 
580  // Set Type
581  if (!scope) {
582  scope = tokenList.back() ? tokenList.back()->scope() : nullptr;
583  if (!scope)
584  return nullptr;
585  }
586  for (const Token *typeToken = tokenList.back(); Token::Match(typeToken, "&|*|%name%"); typeToken = typeToken->previous()) {
587  if (!typeToken->isName())
588  continue;
589  const ::Type *recordType = scope->check->findVariableType(scope, typeToken);
590  if (recordType) {
591  const_cast<Token*>(typeToken)->type(recordType);
592  return recordType;
593  }
594  }
595  return nullptr;
596 }
597 
599 {
600  if (!recordScope)
601  return;
602  std::list<const Scope *> scopes;
603  while (recordScope && recordScope != tokenList.back()->scope() && !recordScope->isExecutable()) {
604  scopes.push_front(recordScope);
605  recordScope = recordScope->nestedIn;
606  }
607  for (const Scope *s: scopes) {
608  if (!s->className.empty()) {
609  addtoken(tokenList, s->className);
610  addtoken(tokenList, "::");
611  }
612  }
613 }
614 
616 {
617  if (!tokenList.back())
618  return &mData->mSymbolDatabase->scopeList.front();
619  if (tokenList.back()->str() == "}" && mData->mNotScope.find(tokenList.back()) == mData->mNotScope.end())
620  return tokenList.back()->scope()->nestedIn;
621  return tokenList.back()->scope();
622 }
623 
625 {
626  for (int i = 0; i < 2; i++) {
627  const std::string &type = getType(i);
628 
629  if (type.find('<') != std::string::npos)
630  // TODO
631  continue;
632 
633  TokenList decl(nullptr);
634  decl.setLang(tok->isCpp() ? Standards::Language::CPP : Standards::Language::C);
635  addTypeTokens(decl, type, tok->scope());
636  if (!decl.front())
637  break;
638 
639  const ValueType valueType = ValueType::parseDecl(decl.front(), *mData->mSettings);
640  if (valueType.type != ValueType::Type::UNKNOWN_TYPE) {
641  tok->setValueType(new ValueType(valueType));
642  break;
643  }
644  }
645 }
646 
648 {
649  std::vector<AstNodePtr> children2{std::move(astNode)};
650  return createScope(tokenList, scopeType, children2, def);
651 }
652 
653 Scope *clangimport::AstNode::createScope(TokenList &tokenList, Scope::ScopeType scopeType, const std::vector<AstNodePtr> & children2, const Token *def)
654 {
655  SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
656 
657  auto *nestedIn = const_cast<Scope *>(getNestedInScope(tokenList));
658 
659  symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nestedIn);
660  Scope *scope = &symbolDatabase->scopeList.back();
661  if (scopeType == Scope::ScopeType::eEnum)
662  scope->enumeratorList.reserve(children2.size());
663  nestedIn->nestedList.push_back(scope);
664  scope->type = scopeType;
665  scope->classDef = def;
666  scope->check = nestedIn->check;
667  if (Token::Match(def, "if|for|while (")) {
668  std::map<const Variable *, const Variable *> replaceVar;
669  for (const Token *vartok = def->tokAt(2); vartok; vartok = vartok->next()) {
670  if (!vartok->variable())
671  continue;
672  if (vartok->variable()->nameToken() == vartok) {
673  const Variable *from = vartok->variable();
674  scope->varlist.emplace_back(*from, scope);
675  Variable *to = &scope->varlist.back();
676  replaceVar[from] = to;
677  mData->replaceVarDecl(from, to);
678  }
679  if (replaceVar.find(vartok->variable()) != replaceVar.end())
680  const_cast<Token *>(vartok)->variable(replaceVar[vartok->variable()]);
681  }
682  std::list<Variable> &varlist = const_cast<Scope *>(def->scope())->varlist;
683  for (std::list<Variable>::iterator var = varlist.begin(); var != varlist.end();) {
684  if (replaceVar.find(&(*var)) != replaceVar.end())
685  var = varlist.erase(var);
686  else
687  ++var;
688  }
689  }
690  scope->bodyStart = addtoken(tokenList, "{");
691  tokenList.back()->scope(scope);
692  mData->scopeAccessControl[scope] = scope->defaultAccess();
693  if (!children2.empty()) {
694  for (const AstNodePtr &astNode: children2) {
695  if (astNode->nodeType == "VisibilityAttr")
696  continue;
697  if (astNode->nodeType == AccessSpecDecl) {
698  if (contains(astNode->mExtTokens, "private"))
699  mData->scopeAccessControl[scope] = AccessControl::Private;
700  else if (contains(astNode->mExtTokens, "protected"))
701  mData->scopeAccessControl[scope] = AccessControl::Protected;
702  else if (contains(astNode->mExtTokens, "public"))
703  mData->scopeAccessControl[scope] = AccessControl::Public;
704  continue;
705  }
706  astNode->createTokens(tokenList);
707  if (scopeType == Scope::ScopeType::eEnum)
708  astNode->addtoken(tokenList, ",");
709  else if (!Token::Match(tokenList.back(), "[;{}]"))
710  astNode->addtoken(tokenList, ";");
711  }
712  }
713  scope->bodyEnd = addtoken(tokenList, "}");
714  Token::createMutualLinks(const_cast<Token*>(scope->bodyStart), const_cast<Token*>(scope->bodyEnd));
715  mData->scopeAccessControl.erase(scope);
716  return scope;
717 }
718 
720 {
721  if (nodeType == ArraySubscriptExpr) {
722  Token *array = getChild(0)->createTokens(tokenList);
723  Token *bracket1 = addtoken(tokenList, "[");
724  Token *index = children[1]->createTokens(tokenList);
725  Token *bracket2 = addtoken(tokenList, "]");
726  bracket1->astOperand1(array);
727  bracket1->astOperand2(index);
728  bracket1->link(bracket2);
729  bracket2->link(bracket1);
730  return bracket1;
731  }
732  if (nodeType == BinaryOperator) {
733  Token *tok1 = getChild(0)->createTokens(tokenList);
734  Token *binop = addtoken(tokenList, unquote(mExtTokens.back()));
735  Token *tok2 = children[1]->createTokens(tokenList);
736  binop->astOperand1(tok1);
737  binop->astOperand2(tok2);
738  return binop;
739  }
740  if (nodeType == BreakStmt)
741  return addtoken(tokenList, "break");
742  if (nodeType == CharacterLiteral) {
743  const int c = MathLib::toBigNumber(mExtTokens.back());
744  if (c == 0)
745  return addtoken(tokenList, "\'\\0\'");
746  if (c == '\r')
747  return addtoken(tokenList, "\'\\r\'");
748  if (c == '\n')
749  return addtoken(tokenList, "\'\\n\'");
750  if (c == '\t')
751  return addtoken(tokenList, "\'\\t\'");
752  if (c == '\\')
753  return addtoken(tokenList, "\'\\\\\'");
754  if (c < ' ' || c >= 0x80) {
755  std::ostringstream hex;
756  hex << std::hex << ((c>>4) & 0xf) << (c&0xf);
757  return addtoken(tokenList, "\'\\x" + hex.str() + "\'");
758  }
759  return addtoken(tokenList, std::string("\'") + char(c) + std::string("\'"));
760  }
761  if (nodeType == CallExpr)
762  return createTokensCall(tokenList);
763  if (nodeType == CaseStmt) {
764  Token *caseToken = addtoken(tokenList, "case");
765  Token *exprToken = getChild(0)->createTokens(tokenList);
766  caseToken->astOperand1(exprToken);
767  addtoken(tokenList, ":");
768  children.back()->createTokens(tokenList);
769  return nullptr;
770  }
771  if (nodeType == ClassTemplateDecl) {
772  for (const AstNodePtr& child: children) {
773  if (child->nodeType == ClassTemplateSpecializationDecl)
774  child->createTokens(tokenList);
775  }
776  return nullptr;
777  }
778  if (nodeType == ClassTemplateSpecializationDecl) {
779  createTokensForCXXRecord(tokenList);
780  return nullptr;
781  }
782  if (nodeType == ConditionalOperator) {
783  Token *expr1 = getChild(0)->createTokens(tokenList);
784  Token *tok1 = addtoken(tokenList, "?");
785  Token *expr2 = children[1]->createTokens(tokenList);
786  Token *tok2 = addtoken(tokenList, ":");
787  Token *expr3 = children[2]->createTokens(tokenList);
788  tok2->astOperand1(expr2);
789  tok2->astOperand2(expr3);
790  tok1->astOperand1(expr1);
791  tok1->astOperand2(tok2);
792  return tok1;
793  }
794  if (nodeType == CompoundAssignOperator) {
795  Token *lhs = getChild(0)->createTokens(tokenList);
796  Token *assign = addtoken(tokenList, getSpelling());
797  Token *rhs = children[1]->createTokens(tokenList);
798  assign->astOperand1(lhs);
799  assign->astOperand2(rhs);
800  return assign;
801  }
802  if (nodeType == CompoundStmt) {
803  for (const AstNodePtr& child: children) {
804  child->createTokens(tokenList);
805  if (!Token::Match(tokenList.back(), "[;{}]"))
806  child->addtoken(tokenList, ";");
807  }
808  return nullptr;
809  }
810  if (nodeType == ConstantExpr)
811  return children.back()->createTokens(tokenList);
812  if (nodeType == ContinueStmt)
813  return addtoken(tokenList, "continue");
814  if (nodeType == CStyleCastExpr) {
815  Token *par1 = addtoken(tokenList, "(");
816  addTypeTokens(tokenList, '\'' + getType() + '\'');
817  Token *par2 = addtoken(tokenList, ")");
818  par1->link(par2);
819  par2->link(par1);
820  par1->astOperand1(getChild(0)->createTokens(tokenList));
821  return par1;
822  }
823  if (nodeType == CXXBindTemporaryExpr)
824  return getChild(0)->createTokens(tokenList);
825  if (nodeType == CXXBoolLiteralExpr) {
826  addtoken(tokenList, mExtTokens.back());
827  tokenList.back()->setValueType(new ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0));
828  return tokenList.back();
829  }
830  if (nodeType == CXXConstructExpr) {
831  if (!children.empty())
832  return getChild(0)->createTokens(tokenList);
833  addTypeTokens(tokenList, '\'' + getType() + '\'');
834  Token *type = tokenList.back();
835  Token *par1 = addtoken(tokenList, "(");
836  Token *par2 = addtoken(tokenList, ")");
837  par1->link(par2);
838  par2->link(par1);
839  par1->astOperand1(type);
840  return par1;
841  }
842  if (nodeType == CXXConstructorDecl) {
843  createTokensFunctionDecl(tokenList);
844  return nullptr;
845  }
846  if (nodeType == CXXDeleteExpr) {
847  addtoken(tokenList, "delete");
848  getChild(0)->createTokens(tokenList);
849  return nullptr;
850  }
851  if (nodeType == CXXDestructorDecl) {
852  createTokensFunctionDecl(tokenList);
853  return nullptr;
854  }
855  if (nodeType == CXXForRangeStmt) {
856  Token *forToken = addtoken(tokenList, "for");
857  Token *par1 = addtoken(tokenList, "(");
858  AstNodePtr varDecl;
859  if (children[6]->nodeType == DeclStmt)
860  varDecl = getChild(6)->getChild(0);
861  else
862  varDecl = getChild(5)->getChild(0);
863  varDecl->mExtTokens.pop_back();
864  varDecl->children.clear();
865  Token *expr1 = varDecl->createTokens(tokenList);
866  Token *colon = addtoken(tokenList, ":");
867  AstNodePtr range;
868  for (int i = 0; i < 2; i++) {
869  if (children[i] && children[i]->nodeType == DeclStmt && children[i]->getChild(0)->nodeType == VarDecl) {
870  range = children[i]->getChild(0)->getChild(0);
871  break;
872  }
873  }
874  if (!range)
875  throw InternalError(tokenList.back(), "Failed to import CXXForRangeStmt. Range?");
876  Token *expr2 = range->createTokens(tokenList);
877  Token *par2 = addtoken(tokenList, ")");
878 
879  par1->link(par2);
880  par2->link(par1);
881 
882  colon->astOperand1(expr1);
883  colon->astOperand2(expr2);
884  par1->astOperand1(forToken);
885  par1->astOperand2(colon);
886 
887  createScope(tokenList, Scope::ScopeType::eFor, children.back(), forToken);
888  return nullptr;
889  }
890  if (nodeType == CXXMethodDecl) {
891  for (int i = 0; i+1 < mExtTokens.size(); ++i) {
892  if (mExtTokens[i] == "prev" && !mData->hasDecl(mExtTokens[i+1]))
893  return nullptr;
894  }
895  createTokensFunctionDecl(tokenList);
896  return nullptr;
897  }
898  if (nodeType == CXXMemberCallExpr)
899  return createTokensCall(tokenList);
900  if (nodeType == CXXNewExpr) {
901  Token *newtok = addtoken(tokenList, "new");
902  if (children.size() == 1 && getChild(0)->nodeType == CXXConstructExpr) {
903  newtok->astOperand1(getChild(0)->createTokens(tokenList));
904  return newtok;
905  }
906  std::string type = getType();
907  if (type.find('*') != std::string::npos)
908  type = type.erase(type.rfind('*'));
909  addTypeTokens(tokenList, type);
910  if (!children.empty()) {
911  Token *bracket1 = addtoken(tokenList, "[");
912  getChild(0)->createTokens(tokenList);
913  Token *bracket2 = addtoken(tokenList, "]");
914  bracket1->link(bracket2);
915  bracket2->link(bracket1);
916  }
917  return newtok;
918  }
919  if (nodeType == CXXNullPtrLiteralExpr)
920  return addtoken(tokenList, "nullptr");
921  if (nodeType == CXXOperatorCallExpr)
922  return createTokensCall(tokenList);
923  if (nodeType == CXXRecordDecl) {
924  createTokensForCXXRecord(tokenList);
925  return nullptr;
926  }
927  if (nodeType == CXXStaticCastExpr || nodeType == CXXFunctionalCastExpr) {
928  Token *cast = addtoken(tokenList, getSpelling());
929  Token *par1 = addtoken(tokenList, "(");
930  Token *expr = getChild(0)->createTokens(tokenList);
931  Token *par2 = addtoken(tokenList, ")");
932  par1->link(par2);
933  par2->link(par1);
934  par1->astOperand1(cast);
935  par1->astOperand2(expr);
936  setValueType(par1);
937  return par1;
938  }
939  if (nodeType == CXXStdInitializerListExpr)
940  return getChild(0)->createTokens(tokenList);
941  if (nodeType == CXXTemporaryObjectExpr && !children.empty())
942  return getChild(0)->createTokens(tokenList);
943  if (nodeType == CXXThisExpr)
944  return addtoken(tokenList, "this");
945  if (nodeType == CXXThrowExpr) {
946  Token *t = addtoken(tokenList, "throw");
947  t->astOperand1(getChild(0)->createTokens(tokenList));
948  return t;
949  }
950  if (nodeType == DeclRefExpr) {
951  int addrIndex = mExtTokens.size() - 1;
952  while (addrIndex > 1 && !startsWith(mExtTokens[addrIndex],"0x"))
953  --addrIndex;
954  const std::string addr = mExtTokens[addrIndex];
955  std::string name = unquote(getSpelling());
956  Token *reftok = addtoken(tokenList, name.empty() ? "<NoName>" : std::move(name));
957  mData->ref(addr, reftok);
958  return reftok;
959  }
960  if (nodeType == DeclStmt)
961  return getChild(0)->createTokens(tokenList);
962  if (nodeType == DefaultStmt) {
963  addtoken(tokenList, "default");
964  addtoken(tokenList, ":");
965  children.back()->createTokens(tokenList);
966  return nullptr;
967  }
968  if (nodeType == DoStmt) {
969  addtoken(tokenList, "do");
970  createScope(tokenList, Scope::ScopeType::eDo, getChild(0), tokenList.back());
971  Token *tok1 = addtoken(tokenList, "while");
972  Token *par1 = addtoken(tokenList, "(");
973  Token *expr = children[1]->createTokens(tokenList);
974  Token *par2 = addtoken(tokenList, ")");
975  par1->link(par2);
976  par2->link(par1);
977  par1->astOperand1(tok1);
978  par1->astOperand2(expr);
979  return nullptr;
980  }
981  if (nodeType == EnumConstantDecl) {
982  Token *nameToken = addtoken(tokenList, getSpelling());
983  auto *scope = const_cast<Scope *>(nameToken->scope());
984  scope->enumeratorList.emplace_back(nameToken->scope());
985  Enumerator *e = &scope->enumeratorList.back();
986  e->name = nameToken;
987  e->value = mData->enumValue++;
988  e->value_known = true;
989  mData->enumDecl(mExtTokens.front(), nameToken, e);
990  return nameToken;
991  }
992  if (nodeType == EnumDecl) {
993  int colIndex = mExtTokens.size() - 1;
994  while (colIndex > 0 && !startsWith(mExtTokens[colIndex],"col:") && !startsWith(mExtTokens[colIndex],"line:"))
995  --colIndex;
996  if (colIndex == 0)
997  return nullptr;
998 
999  mData->enumValue = 0;
1000  Token *enumtok = addtoken(tokenList, "enum");
1001  const Token *nametok = nullptr;
1002  {
1003  int nameIndex = mExtTokens.size() - 1;
1004  while (nameIndex > colIndex && mExtTokens[nameIndex][0] == '\'')
1005  --nameIndex;
1006  if (nameIndex > colIndex)
1007  nametok = addtoken(tokenList, mExtTokens[nameIndex]);
1008  if (mExtTokens.back()[0] == '\'') {
1009  addtoken(tokenList, ":");
1010  addTypeTokens(tokenList, mExtTokens.back());
1011  }
1012  }
1013  Scope *enumscope = createScope(tokenList, Scope::ScopeType::eEnum, children, enumtok);
1014  if (nametok)
1015  enumscope->className = nametok->str();
1016  if (enumscope->bodyEnd && Token::simpleMatch(enumscope->bodyEnd->previous(), ", }"))
1017  const_cast<Token *>(enumscope->bodyEnd)->deletePrevious();
1018 
1019  // Create enum type
1020  mData->mSymbolDatabase->typeList.emplace_back(enumtok, enumscope, enumtok->scope());
1021  enumscope->definedType = &mData->mSymbolDatabase->typeList.back();
1022  if (nametok)
1023  const_cast<Scope *>(enumtok->scope())->definedTypesMap[nametok->str()] = enumscope->definedType;
1024 
1025  return nullptr;
1026  }
1027  if (nodeType == ExprWithCleanups)
1028  return getChild(0)->createTokens(tokenList);
1029  if (nodeType == FieldDecl)
1030  return createTokensVarDecl(tokenList);
1031  if (nodeType == FloatingLiteral)
1032  return addtoken(tokenList, mExtTokens.back());
1033  if (nodeType == ForStmt) {
1034  Token *forToken = addtoken(tokenList, "for");
1035  Token *par1 = addtoken(tokenList, "(");
1036  Token *expr1 = getChild(0) ? children[0]->createTokens(tokenList) : nullptr;
1037  Token *sep1 = addtoken(tokenList, ";");
1038  Token *expr2 = children[2] ? children[2]->createTokens(tokenList) : nullptr;
1039  Token *sep2 = addtoken(tokenList, ";");
1040  Token *expr3 = children[3] ? children[3]->createTokens(tokenList) : nullptr;
1041  Token *par2 = addtoken(tokenList, ")");
1042  par1->link(par2);
1043  par2->link(par1);
1044  par1->astOperand1(forToken);
1045  par1->astOperand2(sep1);
1046  sep1->astOperand1(expr1);
1047  sep1->astOperand2(sep2);
1048  sep2->astOperand1(expr2);
1049  sep2->astOperand2(expr3);
1050  createScope(tokenList, Scope::ScopeType::eFor, children[4], forToken);
1051  return nullptr;
1052  }
1053  if (nodeType == FunctionDecl) {
1054  createTokensFunctionDecl(tokenList);
1055  return nullptr;
1056  }
1057  if (nodeType == FunctionTemplateDecl) {
1058  bool first = true;
1059  for (const AstNodePtr& child: children) {
1060  if (child->nodeType == FunctionDecl) {
1061  if (!first)
1062  child->createTokens(tokenList);
1063  first = false;
1064  }
1065  }
1066  return nullptr;
1067  }
1068  if (nodeType == GotoStmt) {
1069  addtoken(tokenList, "goto");
1070  addtoken(tokenList, unquote(mExtTokens[mExtTokens.size() - 2]));
1071  addtoken(tokenList, ";");
1072  return nullptr;
1073  }
1074  if (nodeType == IfStmt) {
1075  AstNodePtr cond;
1076  AstNodePtr thenCode;
1077  AstNodePtr elseCode;
1078  if (children.size() == 2) {
1079  cond = children[children.size() - 2];
1080  thenCode = children[children.size() - 1];
1081  } else {
1082  cond = children[children.size() - 3];
1083  thenCode = children[children.size() - 2];
1084  elseCode = children[children.size() - 1];
1085  }
1086 
1087  Token *iftok = addtoken(tokenList, "if");
1088  Token *par1 = addtoken(tokenList, "(");
1089  par1->astOperand1(iftok);
1090  par1->astOperand2(cond->createTokens(tokenList));
1091  Token *par2 = addtoken(tokenList, ")");
1092  par1->link(par2);
1093  par2->link(par1);
1094  createScope(tokenList, Scope::ScopeType::eIf, std::move(thenCode), iftok);
1095  if (elseCode) {
1096  elseCode->addtoken(tokenList, "else");
1097  createScope(tokenList, Scope::ScopeType::eElse, std::move(elseCode), tokenList.back());
1098  }
1099  return nullptr;
1100  }
1101  if (nodeType == ImplicitCastExpr) {
1102  Token *expr = getChild(0)->createTokens(tokenList);
1103  if (!expr->valueType() || contains(mExtTokens, "<ArrayToPointerDecay>"))
1104  setValueType(expr);
1105  return expr;
1106  }
1107  if (nodeType == InitListExpr) {
1108  const Scope *scope = tokenList.back()->scope();
1109  Token *start = addtoken(tokenList, "{");
1110  start->scope(scope);
1111  for (const AstNodePtr& child: children) {
1112  if (tokenList.back()->str() != "{")
1113  addtoken(tokenList, ",");
1114  child->createTokens(tokenList);
1115  }
1116  Token *end = addtoken(tokenList, "}");
1117  end->scope(scope);
1118  start->link(end);
1119  end->link(start);
1120  mData->mNotScope.insert(end);
1121  return start;
1122  }
1123  if (nodeType == IntegerLiteral)
1124  return addtoken(tokenList, mExtTokens.back());
1125  if (nodeType == LabelStmt) {
1126  addtoken(tokenList, unquote(mExtTokens.back()));
1127  addtoken(tokenList, ":");
1128  for (const auto& child: children)
1129  child->createTokens(tokenList);
1130  return nullptr;
1131  }
1132  if (nodeType == LinkageSpecDecl)
1133  return nullptr;
1134  if (nodeType == MaterializeTemporaryExpr)
1135  return getChild(0)->createTokens(tokenList);
1136  if (nodeType == MemberExpr) {
1137  Token *s = getChild(0)->createTokens(tokenList);
1138  Token *dot = addtoken(tokenList, ".");
1139  std::string memberName = getSpelling();
1140  if (startsWith(memberName, "->")) {
1141  dot->originalName("->");
1142  memberName = memberName.substr(2);
1143  } else if (startsWith(memberName, ".")) {
1144  memberName = memberName.substr(1);
1145  }
1146  if (memberName.empty())
1147  memberName = "<unknown>";
1148  Token *member = addtoken(tokenList, memberName);
1149  mData->ref(mExtTokens.back(), member);
1150  dot->astOperand1(s);
1151  dot->astOperand2(member);
1152  return dot;
1153  }
1154  if (nodeType == NamespaceDecl) {
1155  if (children.empty())
1156  return nullptr;
1157  const Token *defToken = addtoken(tokenList, "namespace");
1158  const std::string &s = mExtTokens[mExtTokens.size() - 2];
1159  const Token* nameToken = (startsWith(s, "col:") || startsWith(s, "line:")) ?
1160  addtoken(tokenList, mExtTokens.back()) : nullptr;
1161  Scope *scope = createScope(tokenList, Scope::ScopeType::eNamespace, children, defToken);
1162  if (nameToken)
1163  scope->className = nameToken->str();
1164  return nullptr;
1165  }
1166  if (nodeType == NullStmt)
1167  return addtoken(tokenList, ";");
1168  if (nodeType == ParenExpr) {
1169  Token *par1 = addtoken(tokenList, "(");
1170  Token *expr = getChild(0)->createTokens(tokenList);
1171  Token *par2 = addtoken(tokenList, ")");
1172  par1->link(par2);
1173  par2->link(par1);
1174  return expr;
1175  }
1176  if (nodeType == RecordDecl) {
1177  const Token *classDef = addtoken(tokenList, "struct");
1178  const std::string &recordName = getSpelling();
1179  if (!recordName.empty())
1180  addtoken(tokenList, getSpelling());
1181  if (!isDefinition()) {
1182  addtoken(tokenList, ";");
1183  return nullptr;
1184  }
1185 
1186  Scope *recordScope = createScope(tokenList, Scope::ScopeType::eStruct, children, classDef);
1187  mData->mSymbolDatabase->typeList.emplace_back(classDef, recordScope, classDef->scope());
1188  recordScope->definedType = &mData->mSymbolDatabase->typeList.back();
1189  if (!recordName.empty()) {
1190  recordScope->className = recordName;
1191  const_cast<Scope *>(classDef->scope())->definedTypesMap[recordName] = recordScope->definedType;
1192  }
1193 
1194  return nullptr;
1195  }
1196  if (nodeType == ReturnStmt) {
1197  Token *tok1 = addtoken(tokenList, "return");
1198  if (!children.empty()) {
1199  getChild(0)->setValueType(tok1);
1200  tok1->astOperand1(getChild(0)->createTokens(tokenList));
1201  }
1202  return tok1;
1203  }
1204  if (nodeType == StringLiteral)
1205  return addtoken(tokenList, mExtTokens.back());
1206  if (nodeType == SwitchStmt) {
1207  Token *tok1 = addtoken(tokenList, "switch");
1208  Token *par1 = addtoken(tokenList, "(");
1209  Token *expr = children[children.size() - 2]->createTokens(tokenList);
1210  Token *par2 = addtoken(tokenList, ")");
1211  par1->link(par2);
1212  par2->link(par1);
1213  par1->astOperand1(tok1);
1214  par1->astOperand2(expr);
1215  createScope(tokenList, Scope::ScopeType::eSwitch, children.back(), tok1);
1216  return nullptr;
1217  }
1218  if (nodeType == TypedefDecl) {
1219  addtoken(tokenList, "typedef");
1220  addTypeTokens(tokenList, getType());
1221  return addtoken(tokenList, getSpelling());
1222  }
1223  if (nodeType == UnaryOperator) {
1224  int index = (int)mExtTokens.size() - 1;
1225  while (index > 0 && mExtTokens[index][0] != '\'')
1226  --index;
1227  Token *unop = addtoken(tokenList, unquote(mExtTokens[index]));
1228  unop->astOperand1(getChild(0)->createTokens(tokenList));
1229  return unop;
1230  }
1231  if (nodeType == UnaryExprOrTypeTraitExpr) {
1232  Token *tok1 = addtoken(tokenList, getSpelling());
1233  Token *par1 = addtoken(tokenList, "(");
1234  if (children.empty())
1235  addTypeTokens(tokenList, mExtTokens.back());
1236  else {
1237  AstNodePtr child = getChild(0);
1238  if (child && child->nodeType == ParenExpr)
1239  child = child->getChild(0);
1240  Token *expr = child->createTokens(tokenList);
1241  child->setValueType(expr);
1242  par1->astOperand2(expr);
1243  }
1244  Token *par2 = addtoken(tokenList, ")");
1245  par1->link(par2);
1246  par2->link(par1);
1247  par1->astOperand1(tok1);
1248  par1->astOperand2(par1->next());
1249  setValueType(par1);
1250  return par1;
1251  }
1252  if (nodeType == VarDecl)
1253  return createTokensVarDecl(tokenList);
1254  if (nodeType == WhileStmt) {
1255  AstNodePtr cond = children[children.size() - 2];
1256  AstNodePtr body = children.back();
1257  Token *whiletok = addtoken(tokenList, "while");
1258  Token *par1 = addtoken(tokenList, "(");
1259  par1->astOperand1(whiletok);
1260  par1->astOperand2(cond->createTokens(tokenList));
1261  Token *par2 = addtoken(tokenList, ")");
1262  par1->link(par2);
1263  par2->link(par1);
1264  createScope(tokenList, Scope::ScopeType::eWhile, std::move(body), whiletok);
1265  return nullptr;
1266  }
1267  return addtoken(tokenList, "?" + nodeType + "?");
1268 }
1269 
1271 {
1272  int firstParam;
1273  Token *f;
1274  if (nodeType == CXXOperatorCallExpr) {
1275  firstParam = 2;
1276  Token *obj = getChild(1)->createTokens(tokenList);
1277  Token *dot = addtoken(tokenList, ".");
1278  Token *op = getChild(0)->createTokens(tokenList);
1279  dot->astOperand1(obj);
1280  dot->astOperand2(op);
1281  f = dot;
1282  } else {
1283  firstParam = 1;
1284  f = getChild(0)->createTokens(tokenList);
1285  }
1286  f->setValueType(nullptr);
1287  Token *par1 = addtoken(tokenList, "(");
1288  par1->astOperand1(f);
1289  int args = 0;
1290  while (args < children.size() && children[args]->nodeType != CXXDefaultArgExpr)
1291  args++;
1292  Token *child = nullptr;
1293  for (int c = firstParam; c < args; ++c) {
1294  if (child) {
1295  Token *comma = addtoken(tokenList, ",");
1296  comma->setValueType(nullptr);
1297  comma->astOperand1(child);
1298  comma->astOperand2(children[c]->createTokens(tokenList));
1299  child = comma;
1300  } else {
1301  child = children[c]->createTokens(tokenList);
1302  }
1303  }
1304  par1->astOperand2(child);
1305  Token *par2 = addtoken(tokenList, ")");
1306  par1->link(par2);
1307  par2->link(par1);
1308  return par1;
1309 }
1310 
1312 {
1313  const bool prev = contains(mExtTokens, "prev");
1314  const bool hasBody = !children.empty() && children.back()->nodeType == CompoundStmt;
1315  const bool isStatic = contains(mExtTokens, "static");
1316  const bool isInline = contains(mExtTokens, "inline");
1317 
1318  const Token *startToken = nullptr;
1319 
1320  SymbolDatabase *symbolDatabase = mData->mSymbolDatabase;
1321  if (nodeType != CXXConstructorDecl && nodeType != CXXDestructorDecl) {
1322  if (isStatic)
1323  addtoken(tokenList, "static");
1324  if (isInline)
1325  addtoken(tokenList, "inline");
1326  const Token * const before = tokenList.back();
1327  addTypeTokens(tokenList, '\'' + getType() + '\'');
1328  startToken = before ? before->next() : tokenList.front();
1329  }
1330 
1331  if (mExtTokens.size() > 4 && mExtTokens[1] == "parent")
1332  addFullScopeNameTokens(tokenList, mData->getScope(mExtTokens[2]));
1333 
1334  Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters());
1335  auto *nestedIn = const_cast<Scope *>(nameToken->scope());
1336 
1337  if (prev) {
1338  const std::string addr = *(std::find(mExtTokens.cbegin(), mExtTokens.cend(), "prev") + 1);
1339  mData->ref(addr, nameToken);
1340  }
1341  if (!nameToken->function()) {
1342  nestedIn->functionList.emplace_back(nameToken, unquote(getFullType()));
1343  mData->funcDecl(mExtTokens.front(), nameToken, &nestedIn->functionList.back());
1344  if (nodeType == CXXConstructorDecl)
1345  nestedIn->functionList.back().type = Function::Type::eConstructor;
1346  else if (nodeType == CXXDestructorDecl)
1347  nestedIn->functionList.back().type = Function::Type::eDestructor;
1348  else
1349  nestedIn->functionList.back().retDef = startToken;
1350  }
1351 
1352  auto * const function = const_cast<Function*>(nameToken->function());
1353 
1354  if (!prev) {
1355  auto accessControl = mData->scopeAccessControl.find(tokenList.back()->scope());
1356  if (accessControl != mData->scopeAccessControl.end())
1357  function->access = accessControl->second;
1358  }
1359 
1360  Scope *scope = nullptr;
1361  if (hasBody) {
1362  symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nestedIn);
1363  scope = &symbolDatabase->scopeList.back();
1364  scope->check = symbolDatabase;
1365  scope->function = function;
1366  scope->classDef = nameToken;
1367  scope->type = Scope::ScopeType::eFunction;
1368  scope->className = nameToken->str();
1369  nestedIn->nestedList.push_back(scope);
1370  function->hasBody(true);
1371  function->functionScope = scope;
1372  }
1373 
1374  Token *par1 = addtoken(tokenList, "(");
1375  if (!function->arg)
1376  function->arg = par1;
1377  function->token = nameToken;
1378  if (!function->nestedIn)
1379  function->nestedIn = nestedIn;
1380  function->argDef = par1;
1381  // Function arguments
1382  for (int i = 0; i < children.size(); ++i) {
1383  AstNodePtr child = children[i];
1384  if (child->nodeType != ParmVarDecl)
1385  continue;
1386  if (tokenList.back() != par1)
1387  addtoken(tokenList, ",");
1388  const Type *recordType = addTypeTokens(tokenList, child->mExtTokens.back(), nestedIn);
1389  const Token *typeEndToken = tokenList.back();
1390  const std::string spelling = child->getSpelling();
1391  Token *vartok = nullptr;
1392  if (!spelling.empty())
1393  vartok = child->addtoken(tokenList, spelling);
1394  if (!prev) {
1395  function->argumentList.emplace_back(vartok, child->getType(), nullptr, typeEndToken, i, AccessControl::Argument, recordType, scope);
1396  if (vartok) {
1397  const std::string addr = child->mExtTokens[0];
1398  mData->varDecl(addr, vartok, &function->argumentList.back());
1399  }
1400  } else if (vartok) {
1401  const std::string addr = child->mExtTokens[0];
1402  mData->ref(addr, vartok);
1403  }
1404  }
1405  Token *par2 = addtoken(tokenList, ")");
1406  par1->link(par2);
1407  par2->link(par1);
1408 
1409  if (function->isConst())
1410  addtoken(tokenList, "const");
1411 
1412  // Function body
1413  if (hasBody) {
1414  symbolDatabase->functionScopes.push_back(scope);
1415  Token *bodyStart = addtoken(tokenList, "{");
1416  bodyStart->scope(scope);
1417  children.back()->createTokens(tokenList);
1418  Token *bodyEnd = addtoken(tokenList, "}");
1419  scope->bodyStart = bodyStart;
1420  scope->bodyEnd = bodyEnd;
1421  bodyStart->link(bodyEnd);
1422  bodyEnd->link(bodyStart);
1423  } else {
1424  if (nodeType == CXXConstructorDecl && contains(mExtTokens, "default")) {
1425  addtoken(tokenList, "=");
1426  addtoken(tokenList, "default");
1427  }
1428 
1429  addtoken(tokenList, ";");
1430  }
1431 }
1432 
1434 {
1435  const bool isStruct = contains(mExtTokens, "struct");
1436  Token * const classToken = addtoken(tokenList, isStruct ? "struct" : "class");
1437  std::string className;
1438  if (mExtTokens[mExtTokens.size() - 2] == (isStruct?"struct":"class"))
1439  className = mExtTokens.back();
1440  else
1441  className = mExtTokens[mExtTokens.size() - 2];
1442  className += getTemplateParameters();
1443  /*Token *nameToken =*/ addtoken(tokenList, className);
1444  // base classes
1445  bool firstBase = true;
1446  for (const AstNodePtr &child: children) {
1447  if (child->nodeType == "public" || child->nodeType == "protected" || child->nodeType == "private") {
1448  addtoken(tokenList, firstBase ? ":" : ",");
1449  addtoken(tokenList, child->nodeType);
1450  addtoken(tokenList, unquote(child->mExtTokens.back()));
1451  firstBase = false;
1452  }
1453  }
1454  // definition
1455  if (isDefinition()) {
1456  std::vector<AstNodePtr> children2;
1457  std::copy_if(children.cbegin(), children.cend(), std::back_inserter(children2), [](const AstNodePtr& child) {
1458  return child->nodeType == CXXConstructorDecl ||
1459  child->nodeType == CXXDestructorDecl ||
1460  child->nodeType == CXXMethodDecl ||
1461  child->nodeType == FieldDecl ||
1462  child->nodeType == VarDecl ||
1463  child->nodeType == AccessSpecDecl ||
1464  child->nodeType == TypedefDecl;
1465  });
1466  Scope *scope = createScope(tokenList, isStruct ? Scope::ScopeType::eStruct : Scope::ScopeType::eClass, children2, classToken);
1467  const std::string addr = mExtTokens[0];
1468  mData->scopeDecl(addr, scope);
1469  scope->className = className;
1470  mData->mSymbolDatabase->typeList.emplace_back(classToken, scope, classToken->scope());
1471  scope->definedType = &mData->mSymbolDatabase->typeList.back();
1472  const_cast<Scope *>(classToken->scope())->definedTypesMap[className] = scope->definedType;
1473  }
1474  addtoken(tokenList, ";");
1475  tokenList.back()->scope(classToken->scope());
1476 }
1477 
1479 {
1480  const std::string addr = mExtTokens.front();
1481  if (contains(mExtTokens, "static"))
1482  addtoken(tokenList, "static");
1483  int typeIndex = mExtTokens.size() - 1;
1484  while (typeIndex > 1 && std::isalpha(mExtTokens[typeIndex][0]))
1485  typeIndex--;
1486  const std::string type = mExtTokens[typeIndex];
1487  const std::string name = mExtTokens[typeIndex - 1];
1488  const Token *startToken = tokenList.back();
1489  const ::Type *recordType = addTypeTokens(tokenList, type);
1490  if (!startToken)
1491  startToken = tokenList.front();
1492  else if (startToken->str() != "static")
1493  startToken = startToken->next();
1494  Token *vartok1 = addtoken(tokenList, name);
1495  auto *scope = const_cast<Scope *>(tokenList.back()->scope());
1496  scope->varlist.emplace_back(vartok1, unquote(type), startToken, vartok1->previous(), 0, scope->defaultAccess(), recordType, scope);
1497  mData->varDecl(addr, vartok1, &scope->varlist.back());
1498  if (mExtTokens.back() == "cinit" && !children.empty()) {
1499  Token *eq = addtoken(tokenList, "=");
1500  eq->astOperand1(vartok1);
1501  eq->astOperand2(children.back()->createTokens(tokenList));
1502  return eq;
1503  }
1504  if (mExtTokens.back() == "callinit") {
1505  Token *par1 = addtoken(tokenList, "(");
1506  par1->astOperand1(vartok1);
1507  par1->astOperand2(getChild(0)->createTokens(tokenList));
1508  Token *par2 = addtoken(tokenList, ")");
1509  par1->link(par2);
1510  par2->link(par1);
1511  return par1;
1512  }
1513  if (mExtTokens.back() == "listinit") {
1514  return getChild(0)->createTokens(tokenList);
1515  }
1516  return vartok1;
1517 }
1518 
1519 static void setTypes(TokenList &tokenList)
1520 {
1521  for (Token *tok = tokenList.front(); tok; tok = tok->next()) {
1522  if (Token::simpleMatch(tok, "sizeof (")) {
1523  for (Token *typeToken = tok->tokAt(2); typeToken->str() != ")"; typeToken = typeToken->next()) {
1524  if (typeToken->type())
1525  continue;
1526  typeToken->type(typeToken->scope()->findType(typeToken->str()));
1527  }
1528  }
1529  }
1530 }
1531 
1532 static void setValues(const Tokenizer &tokenizer, const SymbolDatabase *symbolDatabase)
1533 {
1534  const Settings & settings = tokenizer.getSettings();
1535 
1536  for (const Scope& scope : symbolDatabase->scopeList) {
1537  if (!scope.definedType)
1538  continue;
1539 
1540  int typeSize = 0;
1541  for (const Variable &var: scope.varlist) {
1542  const int mul = std::accumulate(var.dimensions().cbegin(), var.dimensions().cend(), 1, [](int v, const Dimension& dim) {
1543  return v * dim.num;
1544  });
1545  if (var.valueType())
1546  typeSize += mul * var.valueType()->typeSize(settings.platform, true);
1547  }
1548  scope.definedType->sizeOf = typeSize;
1549  }
1550 
1551  for (auto *tok = const_cast<Token*>(tokenizer.tokens()); tok; tok = tok->next()) {
1552  if (Token::simpleMatch(tok, "sizeof (")) {
1553  ValueType vt = ValueType::parseDecl(tok->tokAt(2), settings);
1554  const int sz = vt.typeSize(settings.platform, true);
1555  if (sz <= 0)
1556  continue;
1557  long long mul = 1;
1558  for (const Token *arrtok = tok->linkAt(1)->previous(); arrtok; arrtok = arrtok->previous()) {
1559  const std::string &a = arrtok->str();
1560  if (a.size() > 2 && a[0] == '[' && a.back() == ']')
1561  mul *= strToInt<long long>(a.substr(1));
1562  else
1563  break;
1564  }
1565  ValueFlow::Value v(mul * sz);
1566  v.setKnown();
1567  tok->next()->addValue(v);
1568  }
1569  }
1570 }
1571 
1572 void clangimport::parseClangAstDump(Tokenizer &tokenizer, std::istream &f)
1573 {
1574  TokenList &tokenList = tokenizer.list;
1575 
1576  tokenizer.createSymbolDatabase();
1577  auto *symbolDatabase = const_cast<SymbolDatabase *>(tokenizer.getSymbolDatabase());
1578  symbolDatabase->scopeList.emplace_back(nullptr, nullptr, nullptr);
1579  symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
1580  symbolDatabase->scopeList.back().check = symbolDatabase;
1581 
1582  clangimport::Data data;
1583  data.mSettings = &tokenizer.getSettings();
1584  data.mSymbolDatabase = symbolDatabase;
1585  std::string line;
1586  std::vector<AstNodePtr> tree;
1587  while (std::getline(f,line)) {
1588  const std::string::size_type pos1 = line.find('-');
1589  if (pos1 == std::string::npos)
1590  continue;
1591  if (!tree.empty() && line.substr(pos1) == "-<<<NULL>>>") {
1592  const int level = (pos1 - 1) / 2;
1593  tree[level - 1]->children.push_back(nullptr);
1594  continue;
1595  }
1596  const std::string::size_type pos2 = line.find(' ', pos1);
1597  if (pos2 < pos1 + 4 || pos2 == std::string::npos)
1598  continue;
1599  const std::string nodeType = line.substr(pos1+1, pos2 - pos1 - 1);
1600  const std::string ext = line.substr(pos2);
1601 
1602  if (pos1 == 1 && endsWith(nodeType, "Decl")) {
1603  if (!tree.empty())
1604  tree[0]->createTokens1(tokenList);
1605  tree.clear();
1606  tree.push_back(std::make_shared<AstNode>(nodeType, ext, &data));
1607  continue;
1608  }
1609 
1610  const int level = (pos1 - 1) / 2;
1611  if (level == 0 || level > tree.size())
1612  continue;
1613 
1614  AstNodePtr newNode = std::make_shared<AstNode>(nodeType, ext, &data);
1615  tree[level - 1]->children.push_back(newNode);
1616  if (level >= tree.size())
1617  tree.push_back(std::move(newNode));
1618  else
1619  tree[level] = std::move(newNode);
1620  }
1621 
1622  if (!tree.empty())
1623  tree[0]->createTokens1(tokenList);
1624 
1625  // Validation
1626  for (const Token *tok = tokenList.front(); tok; tok = tok->next()) {
1627  if (Token::Match(tok, "(|)|[|]|{|}") && !tok->link())
1628  throw InternalError(tok, "Token::link() is not set properly");
1629  }
1630 
1631  if (tokenList.front())
1632  tokenList.front()->assignIndexes();
1633  symbolDatabase->clangSetVariables(data.getVariableList());
1634  symbolDatabase->createSymbolDatabaseExprIds();
1635  tokenList.clangSetOrigFiles();
1636  setTypes(tokenList);
1637  setValues(tokenizer, symbolDatabase);
1638 }
1639 
static const std::string BreakStmt
Definition: clangimport.cpp:51
static const std::string CaseStmt
Definition: clangimport.cpp:53
static const std::string StringLiteral
static const std::string CXXForRangeStmt
Definition: clangimport.cpp:70
static const std::string CXXConstructorDecl
Definition: clangimport.cpp:65
static const std::string DefaultStmt
Definition: clangimport.cpp:85
static const std::string TypedefDecl
static const std::string CXXNewExpr
Definition: clangimport.cpp:74
static const std::string MemberExpr
static const std::string CStyleCastExpr
Definition: clangimport.cpp:62
static const std::string ImplicitCastExpr
Definition: clangimport.cpp:97
static const std::string ReturnStmt
static const std::string CXXStdInitializerListExpr
Definition: clangimport.cpp:79
static const std::string LinkageSpecDecl
static const std::string BinaryOperator
Definition: clangimport.cpp:50
static const std::string IfStmt
Definition: clangimport.cpp:96
static const std::string EnumConstantDecl
Definition: clangimport.cpp:87
static const std::string CXXBoolLiteralExpr
Definition: clangimport.cpp:64
static const std::string TemplateArgument
static const std::string UnaryOperator
static const std::string RecordDecl
static const std::string ParmVarDecl
static const std::string ConstantExpr
Definition: clangimport.cpp:58
static const std::string NullStmt
static void setTypes(TokenList &tokenList)
static const std::string EnumDecl
Definition: clangimport.cpp:88
static const std::string CharacterLiteral
Definition: clangimport.cpp:54
static const std::string SwitchStmt
static const std::string ContinueStmt
Definition: clangimport.cpp:61
static const std::string AccessSpecDecl
Definition: clangimport.cpp:48
static const std::string InitListExpr
Definition: clangimport.cpp:98
static void setValues(const Tokenizer &tokenizer, const SymbolDatabase *symbolDatabase)
static const std::string CXXRecordDecl
Definition: clangimport.cpp:77
static const std::string CXXNullPtrLiteralExpr
Definition: clangimport.cpp:75
static const std::string DeclRefExpr
Definition: clangimport.cpp:83
static const std::string FieldDecl
Definition: clangimport.cpp:90
static const std::string DeclStmt
Definition: clangimport.cpp:84
static std::string unquote(const std::string &s)
static const std::string CXXDestructorDecl
Definition: clangimport.cpp:69
static const std::string ParenExpr
static const std::string CompoundStmt
Definition: clangimport.cpp:60
static const std::string CXXOperatorCallExpr
Definition: clangimport.cpp:76
static const std::string WhileStmt
static const std::string CXXFunctionalCastExpr
Definition: clangimport.cpp:71
static const std::string CXXThrowExpr
Definition: clangimport.cpp:82
static const std::string MaterializeTemporaryExpr
static const std::string UnaryExprOrTypeTraitExpr
static const std::string FunctionTemplateDecl
Definition: clangimport.cpp:94
static const std::string ClassTemplateSpecializationDecl
Definition: clangimport.cpp:56
static const std::string CXXDefaultArgExpr
Definition: clangimport.cpp:67
static const std::string CXXMethodDecl
Definition: clangimport.cpp:73
static const std::string FloatingLiteral
Definition: clangimport.cpp:91
static const std::string ClassTemplateDecl
Definition: clangimport.cpp:55
static const std::string CXXBindTemporaryExpr
Definition: clangimport.cpp:63
static const std::string CXXStaticCastExpr
Definition: clangimport.cpp:78
static const std::string ConditionalOperator
Definition: clangimport.cpp:57
static const std::string ArraySubscriptExpr
Definition: clangimport.cpp:49
static const std::string ForStmt
Definition: clangimport.cpp:92
static const std::string CompoundAssignOperator
Definition: clangimport.cpp:59
static const std::string VarDecl
static const std::string CallExpr
Definition: clangimport.cpp:52
static const std::string CXXTemporaryObjectExpr
Definition: clangimport.cpp:80
static const std::string CXXThisExpr
Definition: clangimport.cpp:81
static const std::string DoStmt
Definition: clangimport.cpp:86
static const std::string CXXDeleteExpr
Definition: clangimport.cpp:68
static const std::string CXXMemberCallExpr
Definition: clangimport.cpp:72
static const std::string CXXConstructExpr
Definition: clangimport.cpp:66
static const std::string NamespaceDecl
static std::vector< std::string > splitString(const std::string &line)
static const std::string FunctionDecl
Definition: clangimport.cpp:93
static const std::string LabelStmt
static const std::string GotoStmt
Definition: clangimport.cpp:95
static const std::string ExprWithCleanups
Definition: clangimport.cpp:89
static const std::string IntegerLiteral
Definition: clangimport.cpp:99
AccessControl access
public/protected/private
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
Definition: mathlib.cpp:368
std::list< Function > functionList
std::list< Variable > varlist
ScopeType type
std::vector< Enumerator > enumeratorList
Type * definedType
Function * function
function info for this function
const SymbolDatabase * check
const Scope * nestedIn
const Token * classDef
class/struct/union/namespace token
AccessControl defaultAccess() const
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
std::string className
bool isExecutable() const
This is just a container for general settings so that we don't need to pass individual values to func...
Definition: settings.h:95
Platform platform
Definition: settings.h:255
std::vector< const Scope * > functionScopes
Fast access to function scopes.
std::list< Scope > scopeList
Information about all namespaces/classes/structures.
const Type * findVariableType(const Scope *start, const Token *typeTok) const
find a variable type if it's a user defined type
void clangSetOrigFiles()
Definition: tokenlist.cpp:127
const Token * back() const
get last token of list
Definition: tokenlist.h:128
const std::string & getSourceFilePath() const
Definition: tokenlist.cpp:75
void setLang(Standards::Language lang)
void addtoken(const std::string &str, const nonneg int lineno, const nonneg int column, const nonneg int fileno, bool split=false)
Definition: tokenlist.cpp:145
const Token * front() const
get first token of list
Definition: tokenlist.h:119
int appendFileIfNew(std::string fileName)
append file name if seen the first time; return its index in any case
Definition: tokenlist.cpp:110
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
const std::string & originalName() const
Definition: token.h:1193
static void createMutualLinks(Token *begin, Token *end)
Links two elements against each other.
Definition: token.cpp:1282
bool isCpp() const
Definition: token.cpp:2752
void setValueType(ValueType *vt)
Definition: token.cpp:2359
const ValueType * valueType() const
Definition: token.h:331
const Enumerator * enumerator() const
Definition: token.h:1111
void astOperand1(Token *tok)
Definition: token.cpp:1490
void function(const Function *f)
Associate this token with given function.
Definition: token.cpp:1127
nonneg int varId() const
Definition: token.h:870
void assignIndexes()
Definition: token.cpp:2351
const Token * tokAt(int index) const
Definition: token.cpp:427
void astOperand2(Token *tok)
Definition: token.cpp:1502
void scope(const Scope *s)
Associate this token with given scope.
Definition: token.h:1042
void link(Token *linkToToken)
Create link to given token.
Definition: token.h:1015
const Token * linkAt(int index) const
Definition: token.cpp:447
Token * previous()
Definition: token.h:862
nonneg int linenr() const
Definition: token.h:816
void variable(const Variable *v)
Associate this token with given variable.
Definition: token.h:1070
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
nonneg int fileIndex() const
Definition: token.h:809
The main purpose is to tokenize the source code.
Definition: tokenize.h:46
const Settings & getSettings() const
Definition: tokenize.h:615
const Token * tokens() const
Definition: tokenize.h:592
void createSymbolDatabase()
TokenList list
Token list: stores all tokens.
Definition: tokenize.h:590
const SymbolDatabase * getSymbolDatabase() const
Definition: tokenize.h:563
Information about a class type.
MathLib::bigint sizeOf
void setKnown()
Definition: vfvalue.h:349
Value type.
enum ValueType::Type type
MathLib::bigint typeSize(const Platform &platform, bool p=false) const
static ValueType parseDecl(const Token *type, const Settings &settings)
Information about a member variable.
nonneg int declarationId() const
Get declaration ID (varId used for variable in its declaration).
const std::vector< Dimension > & dimensions() const
Get array dimensions.
void setValueType(const ValueType &valueType)
const ValueType * valueType() const
Token * createTokens(TokenList &tokenList)
const ::Type * addTypeTokens(TokenList &tokenList, const std::string &str, const Scope *scope=nullptr)
AstNode(std::string nodeType, const std::string &ext, Data *data)
void createTokensFunctionDecl(TokenList &tokenList)
Token * addtoken(TokenList &tokenList, const std::string &str, bool valueType=true)
void createTokens1(TokenList &tokenList)
std::vector< std::string > mExtTokens
Token * createTokensVarDecl(TokenList &tokenList)
const Scope * getNestedInScope(TokenList &tokenList)
void createTokensForCXXRecord(TokenList &tokenList)
std::string getTemplateParameters() const
std::vector< AstNodePtr > children
void setLocations(TokenList &tokenList, int file, int line, int col)
Token * createTokensCall(TokenList &tokenList)
Scope * createScope(TokenList &tokenList, Scope::ScopeType scopeType, AstNodePtr astNode, const Token *def)
std::string getType(int index=0) const
std::string getSpelling() const
void dumpAst(int num=0, int indent=0) const
AstNodePtr getChild(int c)
bool isDefinition() const
void setValueType(Token *tok)
void addFullScopeNameTokens(TokenList &tokenList, const Scope *recordScope)
std::string getFullType(int index=0) const
void CPPCHECKLIB parseClangAstDump(Tokenizer &tokenizer, std::istream &f)
std::shared_ptr< AstNode > AstNodePtr
Array dimension information.
const Token * name
MathLib::bigint value
Simple container to be thrown when internal error is detected.
Definition: errortypes.h:36
Decl(Token *def, Function *function)
void ref(Token *tok) const
Decl(Token *def, Variable *var)
Decl(Token *def, Enumerator *enumerator)
void enumDecl(const std::string &addr, Token *nameToken, Enumerator *enumerator)
void scopeDecl(const std::string &addr, Scope *scope)
void replaceVarDecl(const Variable *from, Variable *to)
std::map< const Scope *, AccessControl > scopeAccessControl
std::map< std::string, std::vector< Token * > > mNotFound
std::vector< const Variable * > getVariableList() const
std::set< Token * > mNotScope
void funcDecl(const std::string &addr, Token *nameToken, Function *function)
bool hasDecl(const std::string &addr) const
void varDecl(const std::string &addr, Token *def, Variable *var)
void ref(const std::string &addr, Token *tok)
const Settings * mSettings
SymbolDatabase * mSymbolDatabase
const Scope * getScope(const std::string &addr)
void notFound(const std::string &addr)
std::map< std::string, Decl > mDeclMap
static void indent(std::string &str, const nonneg int indent1, const nonneg int indent2)
Definition: token.cpp:1742
bool startsWith(const std::string &str, const char start[], std::size_t startlen)
Definition: utils.h:94
bool endsWith(const std::string &str, char c)
Definition: utils.h:110
bool contains(const Range &r, const T &x)
Definition: utils.h:62