52 static const std::string
CallExpr =
"CallExpr";
53 static const std::string
CaseStmt =
"CaseStmt";
84 static const std::string
DeclStmt =
"DeclStmt";
86 static const std::string
DoStmt =
"DoStmt";
88 static const std::string
EnumDecl =
"EnumDecl";
92 static const std::string
ForStmt =
"ForStmt";
95 static const std::string
GotoStmt =
"GotoStmt";
96 static const std::string
IfStmt =
"IfStmt";
119 static std::string
unquote(
const std::string &s)
121 return (s[0] ==
'\'') ? s.substr(1, s.size() - 2) : s;
125 static std::vector<std::string>
splitString(
const std::string &line)
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);
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);
146 while (pos2 < line.size() && (line[pos2] ==
'_' || line[pos2] ==
':' || std::isalnum((
unsigned char)line[pos2])))
148 if (pos2 > pos1 && pos2 < line.size() && line[pos2] ==
'<' && std::isalpha(line[pos1])) {
150 while (++pos2 < line.size() && tlevel > 0) {
151 if (line[pos2] ==
'<')
153 else if (line[pos2] ==
'>')
156 if (tlevel == 0 && pos2 < line.size() && line[pos2] ==
' ') {
157 ret.push_back(line.substr(pos1, pos2-pos1));
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(
"::");
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) {
179 for (pos2 = pos1; pos2 < line.size(); ++pos2) {
180 if (line[pos2] ==
'<')
182 else if (line[pos2] ==
'>') {
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)
195 if (pos2 == std::string::npos) {
196 ret.push_back(line.substr(pos1));
199 ret.push_back(line.substr(pos1, pos2+1-pos1));
200 pos1 = line.find_first_not_of(
' ', pos2 + 1);
236 Decl decl(nameToken, enumerator);
237 mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
243 Decl decl(nameToken,
function);
244 mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
251 mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
256 mDeclMap.insert(std::pair<std::string, Decl>(addr, decl));
266 Decl &decl = it.second;
267 if (decl.
var == from)
281 std::vector<const Variable *> ret;
282 ret.resize(
mVarId + 1,
nullptr);
285 ret[it.second.var->declarationId()] = it.second.var;
296 return (it ==
mDeclMap.end() ?
nullptr : it->second.scope);
307 for (
Token *reftok: it->second)
334 if (!tokenList.
back()) {
338 tokenList.
setLang(Standards::Language::CPP);
350 std::ostringstream err;
351 err <<
"ClangImport: AstNodePtr::getChild(" << c <<
") out of bounds. children.size=" <<
children.size() <<
" " <<
nodeType;
370 std::string
getType(
int index = 0)
const;
392 int nameIndex = typeIndex + 1;
402 const int nameIndex = typeIndex + 1;
408 while (typeIndex >= 0 &&
mExtTokens[typeIndex][0] !=
'\'')
414 while (typeIndex > 0 && std::isalpha(
mExtTokens[typeIndex][0]))
419 const std::string &str =
mExtTokens[typeIndex - 1];
431 std::string type = getFullType(index);
432 if (type.find(
" (") != std::string::npos) {
433 const std::string::size_type pos = type.find(
" (");
437 if (type.find(
" *(") != std::string::npos) {
438 const std::string::size_type pos = type.find(
" *(") + 2;
442 if (type.find(
" &(") != std::string::npos) {
443 const std::string::size_type pos = type.find(
" &(") + 2;
453 while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] !=
'\'')
455 if (typeIndex >= mExtTokens.size())
457 std::string type = mExtTokens[typeIndex];
458 if (type.find(
"\':\'") != std::string::npos) {
460 type.erase(type.find(
"\':\'") + 1);
462 type.erase(0, type.find(
"\':\'") + 2);
469 return contains(mExtTokens,
"definition");
476 std::string templateParameters;
479 if (templateParameters.empty())
480 templateParameters =
"<";
482 templateParameters +=
",";
483 templateParameters +=
unquote(child->mExtTokens.back());
486 return templateParameters +
">";
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) {
498 children[c]->dumpAst(c,
indent + 2);
500 std::cout << std::string(
indent + 2,
' ') <<
"<<<<NULL>>>>>" << std::endl;
506 for (
const std::string &ext: mExtTokens) {
508 col = strToInt<int>(ext.substr(5, ext.find_first_of(
",>", 5) - 5));
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);
521 line = strToInt<int>(ext.substr(sep1 + 1, sep2 - sep1 - 1));
528 for (
const auto& child: children) {
530 child->setLocations(tokenList, file, line, col);
536 const Scope *scope = getNestedInScope(tokenList);
537 tokenList.
addtoken(str, mLine, mCol, mFile);
540 setValueType(tokenList.
back());
541 return tokenList.
back();
546 if (str.find(
"\':\'") != std::string::npos) {
547 return addTypeTokens(tokenList, str.substr(0, str.find(
"\':\'") + 1), scope);
554 if (str.find(
" (") != std::string::npos) {
555 if (str.find(
'<') != std::string::npos)
556 type = str.substr(1, str.find(
'<')) +
"...>";
558 type = str.substr(1,str.find(
" (")-1);
562 if (type.find(
"(*)(") != std::string::npos) {
563 type.erase(type.find(
"(*)("));
566 if (type.find(
'(') != std::string::npos)
567 type.erase(type.find(
'('));
569 std::stack<Token *> lpar;
571 Token *tok = addtoken(tokenList, s,
false);
572 if (tok->
str() ==
"(")
574 else if (tok->
str() ==
")") {
582 scope = tokenList.
back() ? tokenList.
back()->
scope() :
nullptr;
586 for (
const Token *typeToken = tokenList.
back();
Token::Match(typeToken,
"&|*|%name%"); typeToken = typeToken->previous()) {
587 if (!typeToken->isName())
591 const_cast<Token*
>(typeToken)->type(recordType);
602 std::list<const Scope *> scopes;
604 scopes.push_front(recordScope);
605 recordScope = recordScope->
nestedIn;
607 for (
const Scope *s: scopes) {
608 if (!s->className.empty()) {
609 addtoken(tokenList, s->className);
610 addtoken(tokenList,
"::");
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;
626 for (
int i = 0; i < 2; i++) {
627 const std::string &type = getType(i);
629 if (type.find(
'<') != std::string::npos)
634 decl.
setLang(tok->
isCpp() ? Standards::Language::CPP : Standards::Language::C);
635 addTypeTokens(decl, type, tok->
scope());
640 if (valueType.
type != ValueType::Type::UNKNOWN_TYPE) {
649 std::vector<AstNodePtr> children2{std::move(astNode)};
650 return createScope(tokenList, scopeType, children2, def);
657 auto *nestedIn =
const_cast<Scope *
>(getNestedInScope(tokenList));
659 symbolDatabase->
scopeList.emplace_back(
nullptr,
nullptr, nestedIn);
661 if (scopeType == Scope::ScopeType::eEnum)
663 nestedIn->nestedList.push_back(scope);
664 scope->
type = scopeType;
666 scope->
check = nestedIn->check;
668 std::map<const Variable *, const Variable *> replaceVar;
669 for (
const Token *vartok = def->
tokAt(2); vartok; vartok = vartok->
next()) {
670 if (!vartok->variable())
672 if (vartok->variable()->nameToken() == vartok) {
673 const Variable *from = vartok->variable();
674 scope->
varlist.emplace_back(*from, scope);
676 replaceVar[from] = to;
677 mData->replaceVarDecl(from, to);
679 if (replaceVar.find(vartok->variable()) != replaceVar.end())
680 const_cast<Token *
>(vartok)->
variable(replaceVar[vartok->variable()]);
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);
690 scope->
bodyStart = addtoken(tokenList,
"{");
693 if (!children2.empty()) {
695 if (astNode->nodeType ==
"VisibilityAttr")
698 if (
contains(astNode->mExtTokens,
"private"))
700 else if (
contains(astNode->mExtTokens,
"protected"))
702 else if (
contains(astNode->mExtTokens,
"public"))
706 astNode->createTokens(tokenList);
707 if (scopeType == Scope::ScopeType::eEnum)
708 astNode->addtoken(tokenList,
",");
710 astNode->addtoken(tokenList,
";");
713 scope->
bodyEnd = addtoken(tokenList,
"}");
715 mData->scopeAccessControl.erase(scope);
722 Token *array = getChild(0)->createTokens(tokenList);
723 Token *bracket1 = addtoken(tokenList,
"[");
724 Token *index = children[1]->createTokens(tokenList);
725 Token *bracket2 = addtoken(tokenList,
"]");
728 bracket1->
link(bracket2);
729 bracket2->
link(bracket1);
733 Token *tok1 = getChild(0)->createTokens(tokenList);
734 Token *binop = addtoken(tokenList,
unquote(mExtTokens.back()));
735 Token *tok2 = children[1]->createTokens(tokenList);
741 return addtoken(tokenList,
"break");
745 return addtoken(tokenList,
"\'\\0\'");
747 return addtoken(tokenList,
"\'\\r\'");
749 return addtoken(tokenList,
"\'\\n\'");
751 return addtoken(tokenList,
"\'\\t\'");
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() +
"\'");
759 return addtoken(tokenList, std::string(
"\'") +
char(c) + std::string(
"\'"));
762 return createTokensCall(tokenList);
764 Token *caseToken = addtoken(tokenList,
"case");
765 Token *exprToken = getChild(0)->createTokens(tokenList);
767 addtoken(tokenList,
":");
768 children.back()->createTokens(tokenList);
774 child->createTokens(tokenList);
779 createTokensForCXXRecord(tokenList);
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);
795 Token *lhs = getChild(0)->createTokens(tokenList);
796 Token *assign = addtoken(tokenList, getSpelling());
797 Token *rhs = children[1]->createTokens(tokenList);
804 child->createTokens(tokenList);
806 child->addtoken(tokenList,
";");
811 return children.back()->createTokens(tokenList);
813 return addtoken(tokenList,
"continue");
815 Token *par1 = addtoken(tokenList,
"(");
816 addTypeTokens(tokenList,
'\'' + getType() +
'\'');
817 Token *par2 = addtoken(tokenList,
")");
820 par1->
astOperand1(getChild(0)->createTokens(tokenList));
824 return getChild(0)->createTokens(tokenList);
826 addtoken(tokenList, mExtTokens.
back());
828 return tokenList.
back();
831 if (!children.empty())
832 return getChild(0)->createTokens(tokenList);
833 addTypeTokens(tokenList,
'\'' + getType() +
'\'');
835 Token *par1 = addtoken(tokenList,
"(");
836 Token *par2 = addtoken(tokenList,
")");
843 createTokensFunctionDecl(tokenList);
847 addtoken(tokenList,
"delete");
848 getChild(0)->createTokens(tokenList);
852 createTokensFunctionDecl(tokenList);
856 Token *forToken = addtoken(tokenList,
"for");
857 Token *par1 = addtoken(tokenList,
"(");
859 if (children[6]->nodeType ==
DeclStmt)
860 varDecl = getChild(6)->getChild(0);
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,
":");
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);
875 throw InternalError(tokenList.
back(),
"Failed to import CXXForRangeStmt. Range?");
876 Token *expr2 = range->createTokens(tokenList);
877 Token *par2 = addtoken(tokenList,
")");
887 createScope(tokenList, Scope::ScopeType::eFor, children.
back(), forToken);
891 for (
int i = 0; i+1 < mExtTokens.size(); ++i) {
892 if (mExtTokens[i] ==
"prev" && !mData->hasDecl(mExtTokens[i+1]))
895 createTokensFunctionDecl(tokenList);
899 return createTokensCall(tokenList);
901 Token *newtok = addtoken(tokenList,
"new");
903 newtok->
astOperand1(getChild(0)->createTokens(tokenList));
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);
920 return addtoken(tokenList,
"nullptr");
922 return createTokensCall(tokenList);
924 createTokensForCXXRecord(tokenList);
928 Token *cast = addtoken(tokenList, getSpelling());
929 Token *par1 = addtoken(tokenList,
"(");
930 Token *expr = getChild(0)->createTokens(tokenList);
931 Token *par2 = addtoken(tokenList,
")");
940 return getChild(0)->createTokens(tokenList);
942 return getChild(0)->createTokens(tokenList);
944 return addtoken(tokenList,
"this");
946 Token *t = addtoken(tokenList,
"throw");
947 t->
astOperand1(getChild(0)->createTokens(tokenList));
951 int addrIndex = mExtTokens.size() - 1;
952 while (addrIndex > 1 && !
startsWith(mExtTokens[addrIndex],
"0x"))
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);
961 return getChild(0)->createTokens(tokenList);
963 addtoken(tokenList,
"default");
964 addtoken(tokenList,
":");
965 children.back()->createTokens(tokenList);
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,
")");
982 Token *nameToken = addtoken(tokenList, getSpelling());
983 auto *scope =
const_cast<Scope *
>(nameToken->
scope());
985 Enumerator *e = &scope->enumeratorList.back();
987 e->
value = mData->enumValue++;
989 mData->enumDecl(mExtTokens.front(), nameToken, e);
993 int colIndex = mExtTokens.size() - 1;
994 while (colIndex > 0 && !
startsWith(mExtTokens[colIndex],
"col:") && !
startsWith(mExtTokens[colIndex],
"line:"))
999 mData->enumValue = 0;
1000 Token *enumtok = addtoken(tokenList,
"enum");
1001 const Token *nametok =
nullptr;
1003 int nameIndex = mExtTokens.size() - 1;
1004 while (nameIndex > colIndex && mExtTokens[nameIndex][0] ==
'\'')
1006 if (nameIndex > colIndex)
1007 nametok = addtoken(tokenList, mExtTokens[nameIndex]);
1008 if (mExtTokens.back()[0] ==
'\'') {
1009 addtoken(tokenList,
":");
1010 addTypeTokens(tokenList, mExtTokens.
back());
1013 Scope *enumscope = createScope(tokenList, Scope::ScopeType::eEnum, children, enumtok);
1017 const_cast<Token *
>(enumscope->
bodyEnd)->deletePrevious();
1020 mData->mSymbolDatabase->typeList.emplace_back(enumtok, enumscope, enumtok->
scope());
1021 enumscope->
definedType = &mData->mSymbolDatabase->typeList.back();
1028 return getChild(0)->createTokens(tokenList);
1030 return createTokensVarDecl(tokenList);
1032 return addtoken(tokenList, mExtTokens.
back());
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,
")");
1050 createScope(tokenList, Scope::ScopeType::eFor, children[4], forToken);
1054 createTokensFunctionDecl(tokenList);
1062 child->createTokens(tokenList);
1069 addtoken(tokenList,
"goto");
1070 addtoken(tokenList,
unquote(mExtTokens[mExtTokens.size() - 2]));
1071 addtoken(tokenList,
";");
1074 if (nodeType ==
IfStmt) {
1078 if (children.size() == 2) {
1079 cond = children[children.size() - 2];
1080 thenCode = children[children.size() - 1];
1082 cond = children[children.size() - 3];
1083 thenCode = children[children.size() - 2];
1084 elseCode = children[children.size() - 1];
1087 Token *iftok = addtoken(tokenList,
"if");
1088 Token *par1 = addtoken(tokenList,
"(");
1091 Token *par2 = addtoken(tokenList,
")");
1094 createScope(tokenList, Scope::ScopeType::eIf, std::move(thenCode), iftok);
1096 elseCode->addtoken(tokenList,
"else");
1097 createScope(tokenList, Scope::ScopeType::eElse, std::move(elseCode), tokenList.
back());
1102 Token *expr = getChild(0)->createTokens(tokenList);
1109 Token *start = addtoken(tokenList,
"{");
1110 start->
scope(scope);
1112 if (tokenList.
back()->
str() !=
"{")
1113 addtoken(tokenList,
",");
1114 child->createTokens(tokenList);
1116 Token *end = addtoken(tokenList,
"}");
1120 mData->mNotScope.insert(end);
1124 return addtoken(tokenList, mExtTokens.
back());
1126 addtoken(tokenList,
unquote(mExtTokens.back()));
1127 addtoken(tokenList,
":");
1128 for (
const auto& child: children)
1129 child->createTokens(tokenList);
1135 return getChild(0)->createTokens(tokenList);
1137 Token *s = getChild(0)->createTokens(tokenList);
1138 Token *dot = addtoken(tokenList,
".");
1139 std::string memberName = getSpelling();
1142 memberName = memberName.substr(2);
1144 memberName = memberName.substr(1);
1146 if (memberName.empty())
1147 memberName =
"<unknown>";
1148 Token *member = addtoken(tokenList, memberName);
1149 mData->ref(mExtTokens.back(), member);
1155 if (children.empty())
1157 const Token *defToken = addtoken(tokenList,
"namespace");
1158 const std::string &s = mExtTokens[mExtTokens.size() - 2];
1160 addtoken(tokenList, mExtTokens.
back()) :
nullptr;
1161 Scope *scope = createScope(tokenList, Scope::ScopeType::eNamespace, children, defToken);
1167 return addtoken(tokenList,
";");
1169 Token *par1 = addtoken(tokenList,
"(");
1170 Token *expr = getChild(0)->createTokens(tokenList);
1171 Token *par2 = addtoken(tokenList,
")");
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,
";");
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()) {
1197 Token *tok1 = addtoken(tokenList,
"return");
1198 if (!children.empty()) {
1199 getChild(0)->setValueType(tok1);
1200 tok1->
astOperand1(getChild(0)->createTokens(tokenList));
1205 return addtoken(tokenList, mExtTokens.
back());
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,
")");
1215 createScope(tokenList, Scope::ScopeType::eSwitch, children.
back(), tok1);
1219 addtoken(tokenList,
"typedef");
1220 addTypeTokens(tokenList, getType());
1221 return addtoken(tokenList, getSpelling());
1224 int index = (int)mExtTokens.size() - 1;
1225 while (index > 0 && mExtTokens[index][0] !=
'\'')
1227 Token *unop = addtoken(tokenList,
unquote(mExtTokens[index]));
1228 unop->
astOperand1(getChild(0)->createTokens(tokenList));
1232 Token *tok1 = addtoken(tokenList, getSpelling());
1233 Token *par1 = addtoken(tokenList,
"(");
1234 if (children.empty())
1235 addTypeTokens(tokenList, mExtTokens.
back());
1238 if (child && child->nodeType ==
ParenExpr)
1239 child = child->getChild(0);
1240 Token *expr = child->createTokens(tokenList);
1244 Token *par2 = addtoken(tokenList,
")");
1253 return createTokensVarDecl(tokenList);
1255 AstNodePtr cond = children[children.size() - 2];
1257 Token *whiletok = addtoken(tokenList,
"while");
1258 Token *par1 = addtoken(tokenList,
"(");
1261 Token *par2 = addtoken(tokenList,
")");
1264 createScope(tokenList, Scope::ScopeType::eWhile, std::move(body), whiletok);
1267 return addtoken(tokenList,
"?" + nodeType +
"?");
1276 Token *obj = getChild(1)->createTokens(tokenList);
1277 Token *dot = addtoken(tokenList,
".");
1278 Token *op = getChild(0)->createTokens(tokenList);
1284 f = getChild(0)->createTokens(tokenList);
1287 Token *par1 = addtoken(tokenList,
"(");
1292 Token *child =
nullptr;
1293 for (
int c = firstParam; c < args; ++c) {
1295 Token *comma = addtoken(tokenList,
",");
1298 comma->
astOperand2(children[c]->createTokens(tokenList));
1301 child = children[c]->createTokens(tokenList);
1305 Token *par2 = addtoken(tokenList,
")");
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");
1318 const Token *startToken =
nullptr;
1323 addtoken(tokenList,
"static");
1325 addtoken(tokenList,
"inline");
1326 const Token *
const before = tokenList.
back();
1327 addTypeTokens(tokenList,
'\'' + getType() +
'\'');
1328 startToken = before ? before->
next() : tokenList.
front();
1331 if (mExtTokens.size() > 4 && mExtTokens[1] ==
"parent")
1332 addFullScopeNameTokens(tokenList, mData->getScope(mExtTokens[2]));
1334 Token *nameToken = addtoken(tokenList, getSpelling() + getTemplateParameters());
1335 auto *nestedIn =
const_cast<Scope *
>(nameToken->
scope());
1338 const std::string addr = *(std::find(mExtTokens.cbegin(), mExtTokens.cend(),
"prev") + 1);
1339 mData->ref(addr, nameToken);
1343 mData->funcDecl(mExtTokens.front(), nameToken, &nestedIn->functionList.back());
1345 nestedIn->functionList.back().type = Function::Type::eConstructor;
1347 nestedIn->functionList.back().type = Function::Type::eDestructor;
1349 nestedIn->functionList.back().retDef = startToken;
1355 auto accessControl = mData->scopeAccessControl.find(tokenList.
back()->
scope());
1356 if (accessControl != mData->scopeAccessControl.end())
1357 function->
access = accessControl->second;
1360 Scope *scope =
nullptr;
1362 symbolDatabase->
scopeList.emplace_back(
nullptr,
nullptr, nestedIn);
1363 scope = &symbolDatabase->
scopeList.back();
1364 scope->
check = symbolDatabase;
1367 scope->
type = Scope::ScopeType::eFunction;
1369 nestedIn->nestedList.push_back(scope);
1370 function->hasBody(
true);
1371 function->functionScope = scope;
1374 Token *par1 = addtoken(tokenList,
"(");
1376 function->arg = par1;
1377 function->token = nameToken;
1378 if (!function->nestedIn)
1379 function->nestedIn = nestedIn;
1380 function->argDef = par1;
1382 for (
int i = 0; i < children.size(); ++i) {
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);
1395 function->argumentList.emplace_back(vartok, child->getType(),
nullptr, typeEndToken, i,
AccessControl::Argument, recordType, scope);
1397 const std::string addr = child->mExtTokens[0];
1398 mData->varDecl(addr, vartok, &function->argumentList.back());
1400 }
else if (vartok) {
1401 const std::string addr = child->mExtTokens[0];
1402 mData->ref(addr, vartok);
1405 Token *par2 = addtoken(tokenList,
")");
1409 if (function->isConst())
1410 addtoken(tokenList,
"const");
1415 Token *bodyStart = addtoken(tokenList,
"{");
1416 bodyStart->
scope(scope);
1417 children.back()->createTokens(tokenList);
1418 Token *bodyEnd = addtoken(tokenList,
"}");
1421 bodyStart->
link(bodyEnd);
1422 bodyEnd->
link(bodyStart);
1425 addtoken(tokenList,
"=");
1426 addtoken(tokenList,
"default");
1429 addtoken(tokenList,
";");
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();
1441 className = mExtTokens[mExtTokens.size() - 2];
1442 className += getTemplateParameters();
1443 addtoken(tokenList, className);
1445 bool firstBase =
true;
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()));
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;
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);
1470 mData->mSymbolDatabase->typeList.emplace_back(classToken, scope, classToken->
scope());
1471 scope->
definedType = &mData->mSymbolDatabase->typeList.back();
1474 addtoken(tokenList,
";");
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]))
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);
1491 startToken = tokenList.
front();
1492 else if (startToken->
str() !=
"static")
1493 startToken = startToken->
next();
1494 Token *vartok1 = addtoken(tokenList, name);
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,
"=");
1501 eq->
astOperand2(children.back()->createTokens(tokenList));
1504 if (mExtTokens.back() ==
"callinit") {
1505 Token *par1 = addtoken(tokenList,
"(");
1507 par1->
astOperand2(getChild(0)->createTokens(tokenList));
1508 Token *par2 = addtoken(tokenList,
")");
1513 if (mExtTokens.back() ==
"listinit") {
1514 return getChild(0)->createTokens(tokenList);
1523 for (
Token *typeToken = tok->
tokAt(2); typeToken->
str() !=
")"; typeToken = typeToken->next()) {
1524 if (typeToken->type())
1526 typeToken->type(typeToken->scope()->findType(typeToken->str()));
1551 for (
auto *tok =
const_cast<Token*
>(tokenizer.
tokens()); tok; tok = tok->
next()) {
1559 const std::string &a = arrtok->str();
1560 if (a.size() > 2 && a[0] ==
'[' && a.back() ==
']')
1561 mul *= strToInt<long long>(a.substr(1));
1567 tok->next()->addValue(v);
1578 symbolDatabase->
scopeList.emplace_back(
nullptr,
nullptr,
nullptr);
1579 symbolDatabase->scopeList.back().type = Scope::ScopeType::eGlobal;
1580 symbolDatabase->scopeList.back().check = symbolDatabase;
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)
1591 if (!tree.empty() && line.substr(pos1) ==
"-<<<NULL>>>") {
1592 const int level = (pos1 - 1) / 2;
1593 tree[level - 1]->children.push_back(
nullptr);
1596 const std::string::size_type pos2 = line.find(
' ', pos1);
1597 if (pos2 < pos1 + 4 || pos2 == std::string::npos)
1599 const std::string nodeType = line.substr(pos1+1, pos2 - pos1 - 1);
1600 const std::string ext = line.substr(pos2);
1602 if (pos1 == 1 &&
endsWith(nodeType,
"Decl")) {
1604 tree[0]->createTokens1(tokenList);
1606 tree.push_back(std::make_shared<AstNode>(nodeType, ext, &data));
1610 const int level = (pos1 - 1) / 2;
1611 if (level == 0 || level > tree.size())
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));
1619 tree[level] = std::move(newNode);
1623 tree[0]->createTokens1(tokenList);
1626 for (
const Token *tok = tokenList.
front(); tok; tok = tok->
next()) {
1628 throw InternalError(tok,
"Token::link() is not set properly");
1631 if (tokenList.
front())
1634 symbolDatabase->createSymbolDatabaseExprIds();
static const std::string BreakStmt
static const std::string CaseStmt
static const std::string StringLiteral
static const std::string CXXForRangeStmt
static const std::string CXXConstructorDecl
static const std::string DefaultStmt
static const std::string TypedefDecl
static const std::string CXXNewExpr
static const std::string MemberExpr
static const std::string CStyleCastExpr
static const std::string ImplicitCastExpr
static const std::string ReturnStmt
static const std::string CXXStdInitializerListExpr
static const std::string LinkageSpecDecl
static const std::string BinaryOperator
static const std::string IfStmt
static const std::string EnumConstantDecl
static const std::string CXXBoolLiteralExpr
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
static const std::string NullStmt
static void setTypes(TokenList &tokenList)
static const std::string EnumDecl
static const std::string CharacterLiteral
static const std::string SwitchStmt
static const std::string ContinueStmt
static const std::string AccessSpecDecl
static const std::string InitListExpr
static void setValues(const Tokenizer &tokenizer, const SymbolDatabase *symbolDatabase)
static const std::string CXXRecordDecl
static const std::string CXXNullPtrLiteralExpr
static const std::string DeclRefExpr
static const std::string FieldDecl
static const std::string DeclStmt
static std::string unquote(const std::string &s)
static const std::string CXXDestructorDecl
static const std::string ParenExpr
static const std::string CompoundStmt
static const std::string CXXOperatorCallExpr
static const std::string WhileStmt
static const std::string CXXFunctionalCastExpr
static const std::string CXXThrowExpr
static const std::string MaterializeTemporaryExpr
static const std::string UnaryExprOrTypeTraitExpr
static const std::string FunctionTemplateDecl
static const std::string ClassTemplateSpecializationDecl
static const std::string CXXDefaultArgExpr
static const std::string CXXMethodDecl
static const std::string FloatingLiteral
static const std::string ClassTemplateDecl
static const std::string CXXBindTemporaryExpr
static const std::string CXXStaticCastExpr
static const std::string ConditionalOperator
static const std::string ArraySubscriptExpr
static const std::string ForStmt
static const std::string CompoundAssignOperator
static const std::string VarDecl
static const std::string CallExpr
static const std::string CXXTemporaryObjectExpr
static const std::string CXXThisExpr
static const std::string DoStmt
static const std::string CXXDeleteExpr
static const std::string CXXMemberCallExpr
static const std::string CXXConstructExpr
static const std::string NamespaceDecl
static std::vector< std::string > splitString(const std::string &line)
static const std::string FunctionDecl
static const std::string LabelStmt
static const std::string GotoStmt
static const std::string ExprWithCleanups
static const std::string IntegerLiteral
AccessControl access
public/protected/private
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
std::list< Function > functionList
std::list< Variable > varlist
std::vector< Enumerator > enumeratorList
Function * function
function info for this function
const SymbolDatabase * check
const Token * classDef
class/struct/union/namespace token
AccessControl defaultAccess() const
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
bool isExecutable() const
This is just a container for general settings so that we don't need to pass individual values to func...
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
const Token * back() const
get last token of list
const std::string & getSourceFilePath() const
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)
const Token * front() const
get first token of list
int appendFileIfNew(std::string fileName)
append file name if seen the first time; return its index in any case
The token list that the TokenList generates is a linked-list of this class.
static bool Match(const Token *tok, const char pattern[], nonneg int varid=0)
Match given token (or list of tokens) to a pattern list.
const std::string & originalName() const
static void createMutualLinks(Token *begin, Token *end)
Links two elements against each other.
void setValueType(ValueType *vt)
const ValueType * valueType() const
const Enumerator * enumerator() const
void astOperand1(Token *tok)
void function(const Function *f)
Associate this token with given function.
const Token * tokAt(int index) const
void astOperand2(Token *tok)
void scope(const Scope *s)
Associate this token with given scope.
void link(Token *linkToToken)
Create link to given token.
const Token * linkAt(int index) const
nonneg int linenr() const
void variable(const Variable *v)
Associate this token with given variable.
static bool simpleMatch(const Token *tok, const char(&pattern)[count])
Match given token (or list of tokens) to a pattern list.
nonneg int fileIndex() const
The main purpose is to tokenize the source code.
const Settings & getSettings() const
const Token * tokens() const
void createSymbolDatabase()
TokenList list
Token list: stores all tokens.
const SymbolDatabase * getSymbolDatabase() const
Information about a class 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.
Simple container to be thrown when internal error is detected.
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)
bool startsWith(const std::string &str, const char start[], std::size_t startlen)
bool endsWith(const std::string &str, char c)
bool contains(const Range &r, const T &x)