42 #include <initializer_list>
50 #include <type_traits>
51 #include <unordered_map>
52 #include <unordered_set>
56 : mTokenizer(tokenizer), mSettings(settings), mErrorLogger(errorLogger)
97 if (tok->
strAt(1) ==
"::")
110 const Token * tok2 = tok->
link()->previous();
132 if (tok->
str() ==
"{")
143 scopeList.emplace_back(
this,
nullptr,
nullptr);
149 std::stack<std::pair<const Token*, const Scope*>> endInitList;
150 auto inInitList = [&] {
151 if (endInitList.empty())
153 return endInitList.top().second == scope;
156 auto addLambda = [
this, &scope](
const Token* tok,
const Token* lambdaEndToken) ->
const Token* {
157 const Token* lambdaStartToken = lambdaEndToken->
link();
163 return lambdaStartToken;
167 std::map<const Scope*, AccessControl> access;
177 ((
Token::Match(tok,
"class|struct|union|namespace ::| %name% final| {|:|::|<") &&
178 !
Token::Match(tok->
previous(),
"new|friend|const|enum|typedef|mutable|volatile|using|)|(|<")) ||
183 if (tok->
strAt(1) ==
"::")
185 else if (tok->
isCpp() && tok->
strAt(1) ==
"class")
189 tok2 = tok2->
tokAt(2);
191 tok2 = tok2->
tokAt(2);
194 while (tok2 && tok2->
str() ==
"<" && tok2->
link()) {
195 tok2 = tok2->
link()->next();
197 tok2 = tok2->
tokAt(2);
207 if (tok2 && tok2->
next()) {
208 if (tok2->
next()->
str() ==
";")
214 tok2->
next()->
link()->strAt(1) ==
";")
239 tok = tok2->
link()->next();
250 if (name->
str() ==
"class" && name->
strAt(-1) ==
"enum")
269 if (tok->
isCpp() && tok->
str() ==
"class") {
272 }
else if (tok->
str() ==
"struct") {
286 scopeList.emplace_back(
this, tok, scope);
289 if (tok->
str() ==
"class")
291 else if (tok->
str() ==
"struct" || tok->
str() ==
"union")
316 if (tok2->
str() ==
":") {
317 tok2 = tok2->
tokAt(2);
331 tok2 = new_scope->
addEnum(tok);
351 scopeList.emplace_back(
this, tok, scope);
375 tok->
strAt(-1) !=
"friend") {
378 typeList.emplace_back(tok,
nullptr, scope);
389 using_info.
start = tok;
395 if (tok->
strAt(2) ==
"::")
409 typeList.emplace_back(tok,
nullptr, scope);
416 while (tok && tok->
str() !=
";") {
427 scopeList.emplace_back(
this, tok, scope);
433 if (varNameTok->
str() ==
"*") {
434 varNameTok = varNameTok->
next();
435 }
else if (varNameTok->
str() ==
"&") {
436 varNameTok = varNameTok->
next();
439 typeList.emplace_back(tok, new_scope, scope);
459 scope->nestedList.push_back(new_scope);
469 scopeList.emplace_back(
this, tok, scope);
478 typeList.emplace_back(tok, new_scope, scope);
500 typeList.emplace_back(tok,
nullptr, scope);
507 else if (tok == scope->
bodyEnd) {
515 else if (inInitList() && tok == endInitList.top().first) {
522 const Token *funcStart =
nullptr;
523 const Token *argStart =
nullptr;
524 const Token *declEnd =
nullptr;
527 if (tok->
str() ==
"private:")
529 else if (tok->
str() ==
"protected:")
531 else if (tok->
str() ==
"public:" || tok->
str() ==
"__published:")
533 else if (
Token::Match(tok,
"public|protected|private %name% :")) {
534 if (tok->
str() ==
"private")
536 else if (tok->
str() ==
"protected")
545 else if (
isFunction(tok, scope, funcStart, argStart, declEnd)) {
547 Function function(tok, scope, funcStart, argStart);
550 function.
access = access[scope];
552 const Token *end =
function.argDef->
link();
555 if (
function.isConstructor())
556 scope->numConstructors++;
559 function.
token =
function.tokenDef;
560 function.arg =
function.argDef;
565 scope->addFunction(std::move(
function));
571 bool foundInitList =
false;
572 while (end && end->
str() !=
"{" && end->
str() !=
";") {
575 }
else if (foundInitList &&
580 if (end->
str() ==
":")
581 foundInitList =
true;
586 if (!end || end->
str() ==
";")
589 scope->addFunction(
function);
591 Function* funcptr = &scope->functionList.back();
592 const Token *tok2 = funcStart;
596 scope->functionOf =
function.
nestedIn;
597 scope->function = funcptr;
635 friendInfo.
type =
nullptr;
643 const Token *funcStart =
nullptr;
644 const Token *argStart =
nullptr;
645 const Token *declEnd =
nullptr;
648 if (
isFunction(tok, scope, funcStart, argStart, declEnd)) {
650 if (declEnd && declEnd->
str() ==
"{") {
660 tok->
strAt(-2) ==
"::")
676 else if (declEnd && declEnd->
str() ==
";") {
685 for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
686 if (it->second->argsMatch(scope, it->second->argDef, argStart,
emptyString, 0)) {
701 tok = addLambda(tok, lambdaEndToken);
706 if (tok->
str() ==
"else")
708 else if (tok->
str() ==
"do")
718 if (tok->
str() ==
"if")
720 else if (tok->
str() ==
"for") {
722 }
else if (tok->
str() ==
"while")
724 else if (tok->
str() ==
"catch") {
737 endInitList.emplace(tok->
next()->
link(), scope);
740 tok = addLambda(tok, lambdaEndToken);
741 }
else if (tok->
str() ==
"{") {
743 endInitList.emplace(tok->
link(), scope);
749 endInitList.emplace(tok->
link(), scope);
757 if (!ftok || ftok->
str() !=
"(")
761 const Token *funcStart =
nullptr;
762 const Token *argStart =
nullptr;
763 const Token *declEnd =
nullptr;
764 if (
isFunction(ftok, scope, funcStart, argStart, declEnd)) {
765 if (declEnd && declEnd->
str() ==
";") {
768 for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
769 if (it->second->argsMatch(scope, it->second->argDef, argStart,
emptyString, 0)) {
776 Function function(ftok, scope, funcStart, argStart);
777 if (
function.isExtern()) {
778 scope->addFunction(std::move(
function));
790 if (tok->
str() ==
"}")
805 if (usingInfo.
scope ==
nullptr) {
810 usingInfo.
scope = found;
850 std::list<Function>::iterator func;
852 for (func = scope.functionList.begin(); func != scope.functionList.end(); ++func) {
854 func->addArguments(
this, &scope);
863 if (!scope.isClassOrStruct())
866 std::list<Function>::iterator func;
867 for (func = scope.functionList.begin(); func != scope.functionList.end(); ++func) {
868 if (!func->isConstructor() || func->minArgCount() != 1)
871 const Variable* firstArg = func->getArgumentVar(0);
872 if (firstArg->
type() == scope.definedType) {
881 scope.numCopyOrMoveConstructors++;
899 if (scope.isClassOrStruct())
908 std::list<Function>::iterator func;
910 for (func = scope.functionList.begin(); func != scope.functionList.end(); ++func) {
913 const Token *type = func->retDef;
914 while (
Token::Match(type,
"static|const|struct|union|enum"))
931 if (scope.definedType)
936 unsigned int unknowns = 0;
937 unsigned int retry = 0;
943 if (!scope.isClassOrStructOrUnion())
948 if (!scope.definedType) {
955 bool hasDefaultConstructor =
false;
957 for (
const Function& func : scope.functionList) {
961 hasDefaultConstructor =
true;
967 hasDefaultConstructor =
true;
976 if (hasDefaultConstructor)
981 bool needInitialization =
false;
982 bool unknown =
false;
984 for (
const Variable& var: scope.varlist) {
991 needInitialization =
true;
998 needInitialization =
true;
1003 if (needInitialization)
1017 }
while (unknowns && retry < 100);
1023 debugMessage(scope.classDef,
"debug",
"SymbolDatabase couldn't resolve all user defined types.");
1038 for (
Variable& var: scope.varlist) {
1051 for (
Function& func : scope.functionList) {
1070 for (
const Token *tok = func->bodyStart->
next(); tok && tok != func->bodyEnd; tok = tok->
next()) {
1076 tokDot = tokDot->
link()->next();
1096 auto setScopePointers = [](
const Scope &scope,
const Token *bodyStart,
const Token *bodyEnd) {
1100 const_cast<Token *
>(bodyEnd)->scope(&scope);
1102 for (
auto* tok =
const_cast<Token *
>(bodyStart); tok != bodyEnd; tok = tok->
next()) {
1103 if (bodyStart != bodyEnd && tok->str() ==
"{") {
1104 bool isEndOfScope =
false;
1107 if (std::find(list.cbegin(), list.cend(), tok) != list.cend()) {
1109 if (tok->next() == bodyEnd || !tok->next()) {
1110 isEndOfScope =
true;
1130 setScopePointers(scope, bodyStart, bodyStart->
link());
1140 for (
const Function& func: scope.functionList) {
1145 const_cast<Token *
>(func.
token)->
function(&func);
1151 const Token* inTemplateArg =
nullptr;
1153 if (inTemplateArg ==
nullptr && tok->
link() && tok->str() ==
"<")
1154 inTemplateArg = tok->
link();
1155 if (inTemplateArg == tok)
1156 inTemplateArg =
nullptr;
1157 if (tok->isName() && !tok->function() && tok->varId() == 0 && ((tok->astParent() && tok->astParent()->isComparisonOp()) ||
Token::Match(tok,
"%name% [{(,)>;]")) && !
isReservedName(tok)) {
1158 if (tok->next()->str() ==
">" && !tok->next()->link())
1162 if (!
function || (inTemplateArg && function->isConstructor()))
1165 tok->function(
function);
1167 if (tok->next()->str() !=
"(")
1168 const_cast<Function *
>(
function)->functionPointerUsage = tok;
1174 for (
const Function& func: scope.functionList) {
1178 if (tok->
str() ==
"noexcept") {
1180 if (!closingParenTok || !closingParenTok->
next()) {
1183 tok = closingParenTok->
next();
1185 if (tok->
str() !=
":") {
1194 const_cast<Token *
>(tok)->
function(
function);
1208 std::unordered_set<std::string> typenames;
1210 typenames.insert(t.name());
1215 if (!tok->isName() || tok->varId() || tok->function() || tok->type() || tok->enumerator())
1218 if (typenames.find(tok->str()) == typenames.end())
1230 for (
Variable &var: scope.varlist) {
1242 VarIdMap::iterator varId = varIds.find(vartok->
varId());
1243 if (varId == varIds.end()) {
1245 if (membertok->
varId() == 0) {
1250 varIds.insert(std::make_pair(vartok->
varId(), memberId));
1251 varId = varIds.find(vartok->
varId());
1253 MemberIdMap::iterator memberId = varId->second.find(membervar->
nameToken()->
varId());
1254 if (memberId == varId->second.end()) {
1255 if (membertok->
varId() == 0) {
1262 if (membertok->
varId() == 0)
1263 membertok->
varId(memberId->second);
1272 auto setMemberVar = [&](
const Variable* membervar,
Token* membertok,
const Token* vartok) ->
void {
1274 membertok->variable(membervar);
1275 if (vartok && (membertok->varId() == 0 ||
mVariableList[membertok->varId()] ==
nullptr))
1276 fixVarId(varIds, vartok, membertok, membervar);
1282 if (!tok->isName() || tok->isKeyword() || tok->isStandardType())
1289 const bool isVar = tok->variable() && (tok->variable()->typeScope() || tok->variable()->isSmartPointer() ||
1292 const bool isDirectAccess = isVar && !isArrayAccess &&
Token::simpleMatch(tok->astParent(),
".");
1294 if (isVar && (isArrayAccess || isDirectAccess || isDerefAccess)) {
1296 if (isArrayAccess) {
1299 membertok = membertok->astParent();
1301 membertok = membertok->astOperand2();
1303 else if (isDirectAccess) {
1304 membertok = tok->astParent()->astOperand2();
1305 if (membertok == tok) {
1310 membertok = gptok->
astParent()->astOperand2();
1314 membertok = tok->astParent();
1316 membertok = membertok->astParent();
1318 membertok = membertok->astOperand2();
1321 if (membertok && membertok != tok) {
1322 const Variable *var = tok->variable();
1325 setMemberVar(membervar, membertok, tok);
1327 const Scope *classScope = type->classScope;
1328 const Variable *membervar = classScope ? classScope->
getVariable(membertok->str()) :
nullptr;
1329 setMemberVar(membervar, membertok, tok);
1332 while (ctt && ctt->isKeyword())
1337 setMemberVar(membervar, membertok, tok);
1341 if (iterType->classScope && iterType->classScope->definedType) {
1342 const Variable *membervar = iterType->classScope->getVariable(membertok->str());
1343 setMemberVar(membervar, membertok, tok);
1352 else if (tok->function() && tok->next()->str() ==
"(" &&
1353 (
Token::Match(tok->next()->link(),
") . %name% !!(") ||
1354 (
Token::Match(tok->next()->link(),
") [") &&
Token::Match(tok->next()->link()->next()->link(),
"] . %name% !!(")))) {
1355 const Type *type = tok->function()->retType;
1357 if (tok->next()->link()->next()->str() ==
".")
1358 membertok = tok->
next()->
link()->next()->next();
1360 membertok = tok->
next()->
link()->next()->link()->next()->next();
1366 setMemberVar(membervar, membertok, tok->
function()->retDef);
1372 if (spType->classScope) {
1373 const Variable* membervar = spType->classScope->getVariable(membertok->
str());
1374 setMemberVar(membervar, membertok, tok->
function()->retDef);
1382 const ValueType* vt = tok->astParent()->astOperand1()->valueType();
1384 auto it = cont->
functions.find(tok->str());
1388 const Type* contType{};
1390 while (scope && !contType) {
1391 contType = scope->
findType(typeStr);
1394 if (contType && contType->classScope) {
1395 const Variable* membervar = contType->classScope->getVariable(memberTok->
str());
1411 for (
const Enumerator & i : scope.enumeratorList)
1412 const_cast<Token *
>(i.
name)->enumerator(&i);
1415 std::set<std::string> tokensThatAreNotEnumeratorValues;
1421 for (
const Enumerator & enumerator : scope.enumeratorList) {
1423 if (enumerator.
start) {
1424 if (!enumerator.
end)
1426 for (
const Token * tok3 = enumerator.
start; tok3 && tok3 != enumerator.
end->
next(); tok3 = tok3->
next()) {
1430 const_cast<Token *
>(tok3)->enumerator(e);
1439 const bool isVariable = (tok->tokType() ==
Token::eVariable && !tok->variable());
1446 tok->enumerator(enumerator);
1454 const Scope * scope = tok->scope();
1459 if (tok->varId() != 0)
1461 if (tok->isCast() && !
isCPPCast(tok) && tok->link() && tok->str() ==
"(") {
1465 if (tok->isCpp() && (
Token::Match(tok,
"catch|typeid (") ||
1466 Token::Match(tok,
"static_cast|dynamic_cast|const_cast|reinterpret_cast"))) {
1467 tok = tok->linkAt(1);
1470 if (tok->str() ==
"NULL")
1472 if (tok->isKeyword() || !tok->isNameOnly())
1478 if (
Token::Match(tok->next(),
"&|&&|* *| *| )|,|%var%|const"))
1485 tok = tok->linkAt(1);
1491 std::string fstr = tok->str();
1497 ftok = ftok->
tokAt(-2);
1511 tok->isIncompleteVar(
true);
1520 Function *
function = scope.function;
1536 if (!
Token::Match(tok,
"(|.|[|::|?|:|++|--|%cop%|%assign%"))
1553 std::string result = tok->
str() +
"@";
1561 std::string parentOp;
1564 bool operator<(
const ExprIdKey& k)
const {
1565 return std::tie(parentOp, operand1, operand2) < std::tie(k.parentOp, k.operand1, k.operand2);
1568 using ExprIdMap = std::map<ExprIdKey, nonneg int>;
1569 void setParentExprId(
Token* tok, ExprIdMap& exprIdMap,
nonneg int &
id) {
1576 if (op2 &&
op2->exprId() == 0 &&
1586 setParentExprId(tok->
astParent(), exprIdMap,
id);
1592 key.operand1 =
op1 ?
op1->exprId() : 0;
1593 key.operand2 =
op2 ?
op2->exprId() : 0;
1596 const Token* typeStartToken;
1597 const Token* typeEndToken;
1599 typeStartToken = tok->
astParent()->astOperand1();
1602 typeStartToken = tok->
astParent()->next();
1603 typeEndToken = tok->
astParent()->link();
1606 for (
const Token* t = typeStartToken; t != typeEndToken; t = t->
next()) {
1607 type +=
" " + t->str();
1609 key.parentOp += type;
1613 if (ref.token->exprId() != 0) {
1614 key.operand1 = ref.token->exprId();
1619 if (ref.token->exprId() != 0) {
1620 key.operand2 = ref.token->exprId();
1625 if (key.operand1 > key.operand2 && key.operand2 &&
1628 if (!tok->
isCpp() ||
1629 key.parentOp !=
"+" ||
1631 tok->
astParent()->valueType()->isIntegral() ||
1632 tok->
astParent()->valueType()->isFloat() ||
1633 tok->
astParent()->valueType()->pointer > 0)
1634 std::swap(key.operand1, key.operand2);
1637 const auto it = exprIdMap.find(key);
1638 if (it == exprIdMap.end()) {
1639 exprIdMap[key] = id;
1645 setParentExprId(tok->
astParent(), exprIdMap,
id);
1652 nonneg int maximumVarId = 0;
1654 if (tok->
varId() > maximumVarId)
1655 maximumVarId = tok->
varId();
1657 nonneg int id = maximumVarId + 1;
1659 std::unordered_map<std::string, nonneg int> unknownConstantIds;
1660 const Token* inConstExpr =
nullptr;
1663 tok = tok->
next()->
link()->previous();
1664 }
else if (tok == inConstExpr) {
1665 inConstExpr =
nullptr;
1666 }
else if (inConstExpr) {
1672 if (unknownConstantIds.count(name) > 0)
1674 unknownConstantIds[name] =
id++;
1675 }
else if (tok->
link() && tok->
str() ==
"<") {
1676 inConstExpr = tok->
link();
1683 std::copy_if(
scopeList.front().nestedList.begin(),
scopeList.front().nestedList.end(), std::back_inserter(exprScopes), [](
const Scope* scope) {
1684 return scope && scope->type == Scope::eLambda;
1687 for (
const Scope * scope : exprScopes) {
1688 std::unordered_map<std::string, std::vector<Token*>> exprs;
1690 std::unordered_map<std::string, nonneg int> unknownIds;
1700 if (unknownConstantIds.count(name) > 0) {
1701 sid = unknownConstantIds.at(name);
1703 }
else if (unknownIds.count(name) == 0) {
1705 unknownIds[name] = sid;
1707 sid = unknownIds.at(name);
1714 ExprIdMap exprIdMap;
1715 std::map<std::string, std::pair<nonneg int, const Token*>> baseIds;
1717 if (tok->
varId() > 0) {
1720 setParentExprId(tok, exprIdMap,
id);
1722 if (tok->
tokType() == Token::Type::eBracket)
1733 const auto it = baseIds.find(tok->
str());
1735 tok->
exprId(it->second.first);
1737 baseIds[tok->
str()] = { id, tok };
1743 setParentExprId(tok, exprIdMap,
id);
1756 std::vector<std::pair<Token*, int>> uniqueExprId(
id);
1758 const auto id2 = tok->
exprId();
1759 if (id2 == 0 || id2 <= maximumVarId)
1761 uniqueExprId[id2].first = tok;
1762 uniqueExprId[id2].second++;
1764 for (
const auto& p : uniqueExprId) {
1765 if (!p.first || p.second != 1)
1767 if (p.first->variable()) {
1768 const Variable* var = p.first->variable();
1772 p.first->setUniqueExprId();
1781 if (!var || !var->isArray())
1784 for (
const Dimension &const_dimension : var->dimensions()) {
1785 auto &dimension =
const_cast<Dimension &
>(const_dimension);
1786 if (dimension.num != 0 || !dimension.tok)
1790 if (dimension.known)
1798 tokenList.
addtoken(
";", 0, 0, 0,
false);
1816 tokenList.
addtoken(
";", 0, 0, 0,
false);
1820 tok = tokenList.
front();
1826 dimension.known =
true;
1834 dimension.known =
false;
1837 if (dimension.tok->hasKnownIntValue()) {
1838 dimension.known =
true;
1839 dimension.num = dimension.tok->getKnownIntValue();
1843 if (dimension.tok->valueType() && dimension.tok->valueType()->pointer == 0) {
1845 switch (dimension.tok->valueType()->type) {
1846 case ValueType::Type::CHAR:
1849 case ValueType::Type::SHORT:
1852 case ValueType::Type::INT:
1855 case ValueType::Type::LONG:
1858 case ValueType::Type::LONGLONG:
1865 if (bits > 0 && bits <= 62) {
1866 if (dimension.tok->valueType()->sign == ValueType::Sign::UNSIGNED)
1867 dimension.num = 1LL << bits;
1869 dimension.num = 1LL << (bits - 1);
1880 tok->
scope(
nullptr);
1897 if ((
false) && tok->
str() ==
"(" && tok->
strAt(1) !=
"*" &&
1899 const Token* tok2 = tok->
link()->next();
1901 const Token* argStartTok;
1902 if (tok->
link()->previous()->str() ==
"const")
1903 argStartTok = tok->
link()->linkAt(-2);
1905 argStartTok = tok->
link()->linkAt(-1);
1906 funcStart = argStartTok->
previous();
1907 argStart = argStartTok;
1911 if (tok2 && tok2->
str() ==
"[") {
1912 while (tok2 && tok2->
str() ==
"[")
1913 tok2 = tok2->
link()->next();
1915 const Token* argStartTok;
1916 if (tok->
link()->previous()->str() ==
"const")
1917 argStartTok = tok->
link()->linkAt(-2);
1919 argStartTok = tok->
link()->linkAt(-1);
1920 funcStart = argStartTok->
previous();
1921 argStart = argStartTok;
1942 if (tok1->
str() ==
"~")
1948 if (tok1 && tok1->
isName())
1951 tok1 = tok1->
link()->tokAt(-2);
1955 while (
Token::Match(tok2,
"const|noexcept|throw|override|final|volatile|&|&&")) {
1956 tok2 = tok2->
next();
1957 if (tok2 && tok2->
str() ==
"(")
1958 tok2 = tok2->
link()->next();
1962 bool hasTrailingRet =
false;
1963 if (tok2 && tok2->
str() ==
".") {
1964 hasTrailingRet =
true;
1965 for (tok2 = tok2->
next(); tok2; tok2 = tok2->
next()) {
1969 tok2 = tok2->
link();
1974 if (!
Token::Match(tok1,
"{|}|;|public:|protected:|private:") && tok1) {
1982 tok1 = tok1->
link()->tokAt(-2);
1985 if (tok1 && tok1->
str() ==
">") {
1987 tok1 = tok1->
link()->previous();
1997 if (tok1 && tok1->
isName()) {
1998 if (tok1->
str() ==
"return")
2000 if (tok1->
str() !=
"friend")
2007 if (tok1 && tok1->
isName())
2010 tok1 = tok1->
link()->tokAt(-2);
2013 tok1 = tok1->
link()->tokAt(-2);
2017 while (
Token::Match(tok1,
"const|static|extern|template|virtual|struct|class|enum|%name%")) {
2019 if (tok1->
isCpp() && tok1->
str() ==
"friend" && tok2->
str() ==
";")
2025 if (!
Token::Match(tok1,
">|{|}|;|public:|protected:|private:") && tok1)
2036 (hasTrailingRet &&
Token::Match(tok2,
"final|override")))) {
2038 argStart = tok->
next();
2051 argStart = tok->
next();
2065 argStart = tok2->
link();
2078 argStart = tok->
next();
2091 for (std::size_t i = 0; i < functions; ++i) {
2095 const std::list<const Token*> callstack(1, scope->
classDef);
2096 const std::string msg = std::string(
"Executable scope '") + scope->
classDef->
str() +
"' with unknown function.";
2098 "symbolDatabaseWarning",
2110 auto it = std::find_if(scope->functionList.begin(), scope->functionList.end(), [&](
const Function&
function) {
2111 for (std::size_t arg = 0; arg < function.argCount(); ++arg) {
2112 if (var == function.getArgumentVar(arg))
2117 if (it != scope->functionList.end())
2127 const Variable *
const var = *iter;
2129 if (!var->
scope()) {
2130 const Function*
function = getFunctionForArgumentvariable(var);
2131 if (!var->
isArgument() || (!
function || function->hasBody())) {
2161 std::string msg =
"Value type is ";
2170 errorPath.emplace_back(tok,
"");
2180 : mNameToken(name_),
2181 mTypeStartToken(typeStart),
2182 mTypeEndToken(typeEnd),
2208 std::string::size_type pos = clangType.find(
'[');
2209 if (pos != std::string::npos) {
2212 const std::string::size_type pos1 = pos+1;
2213 pos = clangType.find(
']', pos1);
2216 dim.
known = pos > pos1;
2223 }
while (pos < clangType.size() && clangType[pos] ==
'[');
2228 while (initTok && initTok->
str() ==
"[")
2229 initTok = initTok->
link()->next();
2293 declEnd = declEnd->
link();
2294 declEnd = declEnd->
next();
2304 initTok = initTok->
link()->next();
2306 initTok = initTok->
next();
2314 bool isContainer =
false;
2327 while (tok != end) {
2328 if (tok->
str() ==
"static")
2330 else if (tok->
str() ==
"extern")
2334 else if (tok->
str() ==
"mutable")
2336 else if (tok->
str() ==
"const")
2338 else if (tok->
str() ==
"constexpr") {
2341 }
else if (tok->
str() ==
"*") {
2344 }
else if (tok->
str() ==
"&") {
2348 }
else if (tok->
str() ==
"&&") {
2357 if (tok->
str() ==
"<" && tok->
link())
2371 strtype +=
"::" + typeToken->strAt(2);
2383 while (tok && tok->
str() ==
"]")
2384 tok = tok->
link()->previous();
2386 if (tok && tok->
next()->
str() ==
"[")
2392 while (tok->
str() ==
"[")
2442 typeTok = typeTok->
next();
2446 const Type* ptrType{};
2447 while (
scope && !ptrType) {
2477 ret += typeTok->str();
2479 typeTok = typeTok->next()->link();
2490 const std::string &name = tokenDef->
str();
2491 return name.size() > 8 &&
startsWith(name,
"operator") && std::strchr(
"+-*/%&|~^<>!=[(", name[8]);
2496 const Token *tokDef,
2497 const Token *tokArgDef)
2546 if (tok1->
str() ==
">")
2547 tok1 = tok1->
next();
2548 while (
Token::Match(tok1,
"extern|virtual|static|friend|struct|union|enum"))
2549 tok1 = tok1->
next();
2559 if (tok->
str() ==
"const")
2561 else if (tok->
str() ==
"&")
2563 else if (tok->
str() ==
"&&")
2565 else if (tok->
str() ==
"override")
2567 else if (tok->
str() ==
"final")
2569 else if (tok->
str() ==
"volatile")
2571 else if (tok->
str() ==
"noexcept") {
2573 if (tok->
next()->
str() ==
"(")
2577 if (tok->
strAt(2) !=
")")
2580 }
else if (
Token::Match(tok,
"= 0|default|delete ;")) {
2581 const std::string& modifier = tok->
strAt(1);
2585 }
else if (tok->
str() ==
".") {
2605 : tokenDef(tokenDef)
2640 else if (tok1->
str() ==
"virtual") {
2645 else if (tok1->
str() ==
"static") {
2652 else if (tok1->
str() ==
"friend") {
2657 else if (tok1->
str() ==
"constexpr") {
2663 tok1 = tok1->
link()->previous();
2666 else if (tok1->
link() && tok1->
str() ==
">") {
2672 tok1 = tok1->
link();
2680 std::string ret =
name();
2682 if (!s->className.empty())
2683 ret = s->className +
"::" + ret;
2687 ret += (a.index() == 0 ?
"" :
",") + a.name();
2705 const Token *tok1 = first;
2706 const Token *tok2 = second;
2709 if (tok1->
str() == tok2->
str()) {
2710 tok1 = tok1->
tokAt(2);
2711 tok2 = tok2->
tokAt(2);
2723 std::string name = first->
str();
2727 name += (
" :: " + first->
str());
2729 first = first->
tokAt(2);
2730 if (first->
str() == second->
str()) {
2737 for (
const auto & info : scope->
usingList) {
2746 while (start && start->
str() !=
";") {
2747 if (!nsName.empty())
2749 nsName += start->
str();
2750 start = start->
next();
2764 const Scope *first_scope,
2765 const Token *first_token,
2766 const Scope *second_scope,
2767 const Token *second_token,
2768 const Token *&new_first,
2769 const Token *&new_second)
2772 const Type* first_type = first_scope->
check->
findType(first_token, first_scope,
true);
2775 const Type* second_type = second_scope->
check->
findType(second_token, second_scope,
true);
2777 if (first_type == second_type) {
2778 const Token* tok1 = first_token;
2779 while (tok1 && tok1->
str() != first_type->
name())
2780 tok1 = tok1->
next();
2781 const Token *tok2 = second_token;
2782 while (tok2 && tok2->
str() != second_type->
name())
2783 tok2 = tok2->
next();
2797 if (!first->
isCpp())
2800 int arg_path_length = path_length;
2809 auto skipTopLevelConst = [](
const Token* start) ->
const Token* {
2816 return start->
next();
2821 while (first->
str() == second->
str() &&
2824 if (first->
str() ==
"(")
2828 else if (first->
str() ==
")") {
2836 first = first->
next();
2838 second = second->
next();
2841 const Token*
const oldSecond = second;
2842 first = skipTopLevelConst(first);
2843 second = skipTopLevelConst(second);
2846 if (oldSecond == second && first->
next()->
str() ==
"=") {
2849 first = first->
tokAt(-2);
2850 if (second->
next()->
str() ==
"=") {
2853 second = second->
tokAt(-2);
2854 if (!first || !second) {
2855 return !first && !second;
2857 }
else if (!first) {
2860 }
else if (oldSecond == second && second->
next()->
str() ==
"=") {
2863 second = second->
tokAt(-2);
2870 else if ((first->
next()->
str() ==
"," && second->
next()->
str() !=
",") ||
2872 second = second->
next();
2874 if (second->
next()->
str() ==
"=") {
2876 second = second->
next();
2879 }
else if (first->
next()->
str() ==
"[" && second->
next()->
str() !=
"[")
2880 second = second->
next();
2883 else if ((second->
next()->
str() ==
"," && first->
next()->
str() !=
",") ||
2885 first = first->
next();
2887 if (first->
next()->
str() ==
"=") {
2889 first = first->
next();
2892 }
else if (second->
next()->
str() ==
"[" && first->
next()->
str() !=
"[")
2893 first = first->
next();
2899 first = first->
next();
2900 second = second->
next();
2905 else if (openParen == 1 && second->
str() ==
")" && first->
str() !=
")")
2912 first = first->
next();
2915 second = second->
next();
2920 else if (first->
next()->
str() ==
"*" && second->
next()->
str() ==
"*" &&
2921 ((first->
strAt(2) !=
"const" && second->
strAt(2) ==
"const") ||
2922 (first->
strAt(2) ==
"const" && second->
strAt(2) !=
"const"))) {
2923 if (first->
strAt(2) !=
"const") {
2928 first = first->
next();
2929 second = second->
tokAt(2);
2936 first = first->
tokAt(2);
2937 second = second->
next();
2947 first = first->
next();
2948 second = second->
next();
2951 if (first->
next()->
str() ==
"=") {
2953 first = first->
next();
2960 first = first->
tokAt(offset);
2968 std::string param = path;
2973 second = second->
tokAt(arg_path_length);
2974 arg_path_length = 0;
2990 second = second->
tokAt(2);
2994 else if (arg_path_length > 2 && first->
strAt(1) != second->
strAt(1)) {
2995 std::string short_path = path;
2996 unsigned int short_path_length = arg_path_length;
2999 short_path.resize(short_path.size() - 4);
3000 short_path_length--;
3003 std::string::size_type lastSpace = short_path.find_last_of(
' ');
3004 if (lastSpace != std::string::npos) {
3005 short_path.resize(lastSpace+1);
3006 short_path_length--;
3007 if (short_path[short_path.size() - 1] ==
'>') {
3008 short_path.resize(short_path.size() - 3);
3009 while (short_path[short_path.size() - 1] ==
'<') {
3010 lastSpace = short_path.find_last_of(
' ');
3011 short_path.resize(lastSpace+1);
3012 short_path_length--;
3017 param = std::move(short_path);
3019 second = second->
tokAt(
int(short_path_length));
3020 arg_path_length = 0;
3025 first = first->
next();
3026 second = second->
next();
3029 if (first->
str() ==
"," || second->
str() ==
",")
3030 arg_path_length = path_length;
3039 start = start->
next();
3064 template<
class Predicate>
3071 const Token* defStart =
function->retDef;
3074 const Token* defEnd =
function->returnDefEnd();
3077 if (defEnd == defStart)
3079 if (pred(defStart, defEnd))
3088 const Token* enableIfEnd =
nullptr;
3092 enableIfEnd = defEnd->
tokAt(-3);
3093 if (enableIfEnd && enableIfEnd->
link() &&
3094 Token::Match(enableIfEnd->
link()->previous(),
"enable_if|enable_if_t|EnableIf")) {
3097 defEnd = enableIfEnd;
3099 return emptyEnableIf;
3102 assert(defEnd != defStart);
3103 if (pred(defStart, defEnd))
3147 std::vector<const Token*> result;
3156 if (tok->
str() ==
"{" && tok->
scope() &&
3162 result.push_back(tok);
3166 if (lambdaEndToken) {
3167 tok = lambdaEndToken;
3180 return arg->
link()->linkAt(2)->next();
3210 if (tok->
str() !=
"[") {
3212 for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
3217 function =
const_cast<Function *
>(it->second);
3226 function->arg = argStart;
3227 function->token = funcStart;
3228 function->hasBody(
true);
3242 Function function(tok, scope, funcStart, argStart);
3249 const bool destructor(tok->
previous()->
str() ==
"~");
3250 const bool has_const(argStart->
link()->strAt(1) ==
"const");
3251 const bool lval(argStart->
link()->strAt(has_const ? 2 : 1) ==
"&");
3252 const bool rval(argStart->
link()->strAt(has_const ? 2 : 1) ==
"&&");
3255 unsigned int path_length = 0;
3256 const Token *tok1 = tok;
3267 if (tok2->
str() ==
">")
3268 tok2 = tok2->
link()->previous();
3275 }
while (tok1 != tok2);
3285 if (tok1->
strAt(-1) ==
"::") {
3287 path.insert(0,
":: ");
3291 for (std::list<Scope>::iterator it1 =
scopeList.begin(); it1 !=
scopeList.end(); ++it1) {
3292 Scope *scope1 = &(*it1);
3297 if (scope == scope1 && !scope1->
usingList.empty()) {
3298 std::vector<Scope::UsingInfo>::const_iterator it2;
3314 func->
arg = argStart;
3331 if ((scope == scope1->
nestedIn) || (scope &&
3338 const Scope *s1 = scope;
3351 Scope *scope2 = scope1;
3353 while (scope2 && count > 1) {
3355 if (tok1->
strAt(1) ==
"<")
3358 tok1 = tok1->
tokAt(2);
3361 if (scope2 && isAnonymousNamespace)
3364 if (count == 1 && scope2) {
3373 for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
3374 auto * func =
const_cast<Function *
>(it->second);
3375 if (!func->hasBody()) {
3376 if (func->argsMatch(scope1, func->argDef, tok->
next(), path, path_length)) {
3381 func->isDefault(
true);
3385 func->hasBody(
true);
3388 const bool hasConstKeyword = closeParen->
next()->
str() ==
"const";
3389 if ((func->isConst() == hasConstKeyword) &&
3390 (func->hasLvalRefQualifier() == lval) &&
3391 (func->hasRvalRefQualifier() == rval)) {
3392 func->hasBody(
true);
3397 if (func->hasBody()) {
3399 func->arg = argStart;
3420 const Token *tok1 = tok;
3421 scopeList.emplace_back(
this, tok1, scope);
3425 bool foundInitList =
false;
3426 while (tok1 && tok1->
str() !=
"{" && tok1->
str() !=
";") {
3428 tok1 = tok1->
link();
3432 if (tok1->
str() ==
":")
3433 foundInitList =
true;
3434 tok1 = tok1->
next();
3438 if (tok1 && tok1->
str() ==
"{") {
3451 throw InternalError(tok,
"Analysis failed (function not recognized). If the code is valid then please report this failure.");
3481 const Token *tok2 = tok1;
3482 while (tok2 && tok2->
str() !=
"{") {
3484 if (tok2->
str() ==
"<")
3485 tok2 = tok2->
link();
3489 tok2 = tok2->
next();
3492 if (!tok2 || !tok2->
next())
3497 if (tok2->
str() ==
"virtual") {
3499 tok2 = tok2->
next();
3502 if (tok2->
str() ==
"public") {
3504 tok2 = tok2->
next();
3505 }
else if (tok2->
str() ==
"protected") {
3507 tok2 = tok2->
next();
3508 }
else if (tok2->
str() ==
"private") {
3510 tok2 = tok2->
next();
3512 if (tok->
str() ==
"class")
3514 else if (tok->
str() ==
"struct")
3519 if (tok2->
str() ==
"virtual") {
3521 tok2 = tok2->
next();
3528 if (tok2->
str() ==
"::") {
3529 tok2 = tok2->
next();
3534 tok2 = tok2->
tokAt(2);
3541 tok2 = tok2->
next();
3543 if (tok2 && tok2->
link() && tok2->
str() ==
"<") {
3544 for (
const Token*
const end = tok2->
link()->next(); tok2 != end; tok2 = tok2->
next()) {
3551 base.
type = baseType;
3556 tok2 = tok2->
next();
3566 start = start->
tokAt(1);
3567 else if (start->
str() ==
"class")
3568 start = start->
tokAt(1);
3569 else if (!start->
isName())
3571 const Token* next = start;
3572 while (
Token::Match(next,
"::|<|>|(|)|[|]|*|&|&&|%name%")) {
3574 next = next->
link();
3575 next = next->
next();
3578 for (
const Token* tok = start; tok != next; tok = tok->
next()) {
3579 if (!result.empty())
3581 result += tok->
str();
3589 const std::list<const Token*> locationList(1, tok);
3602 const std::list<const Token*> locationList(1, tok);
3605 "returnImplicitInt",
3606 "Omitted return type of function '" + tok->
str() +
"' defaults to int, this is not supported by ISO C99 and later standards.",
3615 const std::multimap<std::string, const Function *>::const_iterator it =
classScope->
functionMap.find(funcName);
3633 std::set<BaseInfo> knownAncestors;
3635 ancestors=&knownAncestors;
3637 for (std::vector<BaseInfo>::const_iterator parent=
derivedFrom.cbegin(); parent!=
derivedFrom.cend(); ++parent) {
3640 if (
this==parent->type)
3642 if (ancestors->find(*parent)!=ancestors->end())
3645 ancestors->insert(*parent);
3646 if (parent->type->hasCircularDependencies(ancestors))
3655 return d.type && (d.type == this || d.type->findDependency(ancestor));
3661 for (std::vector<BaseInfo>::const_iterator parent=
derivedFrom.cbegin(); parent!=
derivedFrom.cend(); ++parent) {
3662 if (parent->name == ancestor)
3664 if (parent->type && parent->type->isDerivedFrom(ancestor))
3672 isContainer =
false;
3684 dimension_.
tok = tok;
3685 dimension_.
known =
true;
3688 dimension_.
tok = tok;
3689 dimension_.
known =
false;
3701 while (dim && dim->
str() ==
"]")
3702 dim = dim->
link()->previous();
3706 if (dim && dim->
str() ==
")")
3710 while (dim && dim->
next() && dim->
str() ==
"[") {
3712 dimension_.
known =
false;
3714 if (dim->
next()->
str() !=
"]") {
3719 dimension_.
known =
true;
3723 dim = dim->
link()->next();
3732 case Scope::ScopeType::eGlobal:
3734 case Scope::ScopeType::eClass:
3736 case Scope::ScopeType::eStruct:
3738 case Scope::ScopeType::eUnion:
3740 case Scope::ScopeType::eNamespace:
3742 case Scope::ScopeType::eFunction:
3744 case Scope::ScopeType::eIf:
3746 case Scope::ScopeType::eElse:
3748 case Scope::ScopeType::eFor:
3750 case Scope::ScopeType::eWhile:
3752 case Scope::ScopeType::eDo:
3754 case Scope::ScopeType::eSwitch:
3756 case Scope::ScopeType::eTry:
3758 case Scope::ScopeType::eCatch:
3760 case Scope::ScopeType::eUnconditional:
3761 return "Unconditional";
3762 case Scope::ScopeType::eLambda:
3764 case Scope::ScopeType::eEnum:
3803 return "Constructor";
3805 return "CopyConstructor";
3807 return "MoveConstructor";
3809 return "OperatorEqual";
3811 return "Destructor";
3823 std::ostringstream oss;
3825 oss << tok->
str() <<
" ";
3834 std::ostringstream oss;
3836 oss << scope->
type <<
" ";
3848 std::ostringstream oss;
3873 const Token * autoTok =
nullptr;
3874 std::cout <<
indent <<
" ";
3877 if (tok->
str() ==
"auto")
3880 std::cout << std::endl;
3883 std::cout <<
indent <<
" auto valueType: " << valueType << std::endl;
3885 std::cout <<
indent <<
" " << valueType->
str() << std::endl;
3891 std::cout <<
indent <<
"mIndex: " << var->
index() << std::endl;
3893 std::cout <<
indent <<
"mFlags: " << std::endl;
3894 std::cout <<
indent <<
" isMutable: " << var->
isMutable() << std::endl;
3895 std::cout <<
indent <<
" isStatic: " << var->
isStatic() << std::endl;
3896 std::cout <<
indent <<
" isExtern: " << var->
isExtern() << std::endl;
3897 std::cout <<
indent <<
" isLocal: " << var->
isLocal() << std::endl;
3898 std::cout <<
indent <<
" isConst: " << var->
isConst() << std::endl;
3899 std::cout <<
indent <<
" isClass: " << var->
isClass() << std::endl;
3900 std::cout <<
indent <<
" isArray: " << var->
isArray() << std::endl;
3901 std::cout <<
indent <<
" isPointer: " << var->
isPointer() << std::endl;
3905 std::cout <<
indent <<
" isStlType: " << var->
isStlType() << std::endl;
3906 std::cout <<
indent <<
"mType: ";
3910 std::cout <<
" " << var->
type() << std::endl;
3912 std::cout <<
"none" << std::endl;
3916 std::cout <<
indent <<
"valueType: " << valueType << std::endl;
3918 std::cout <<
indent <<
" " << valueType->
str() << std::endl;
3924 std::cout <<
indent <<
"mDimensions:";
3925 for (std::size_t i = 0; i < var->
dimensions().size(); i++) {
3930 std::cout << std::endl;
3935 std::cout << std::setiosflags(std::ios::boolalpha);
3937 std::cout <<
"\n### " << title <<
" ###\n";
3939 for (std::list<Scope>::const_iterator scope =
scopeList.cbegin(); scope !=
scopeList.cend(); ++scope) {
3940 std::cout <<
"Scope: " << &*scope <<
" " << scope->type << std::endl;
3941 std::cout <<
" className: " << scope->className << std::endl;
3947 for (
auto func = scope->functionList.cbegin(); func != scope->functionList.cend(); ++func) {
3948 std::cout <<
" Function: " << &*func << std::endl;
3952 std::cout <<
" hasBody: " << func->hasBody() << std::endl;
3953 std::cout <<
" isInline: " << func->isInline() << std::endl;
3954 std::cout <<
" isConst: " << func->isConst() << std::endl;
3955 std::cout <<
" hasVirtualSpecifier: " << func->hasVirtualSpecifier() << std::endl;
3956 std::cout <<
" isPure: " << func->isPure() << std::endl;
3957 std::cout <<
" isStatic: " << func->isStatic() << std::endl;
3958 std::cout <<
" isStaticLocal: " << func->isStaticLocal() << std::endl;
3959 std::cout <<
" isExtern: " << func->isExtern() << std::endl;
3960 std::cout <<
" isFriend: " << func->isFriend() << std::endl;
3961 std::cout <<
" isExplicit: " << func->isExplicit() << std::endl;
3962 std::cout <<
" isDefault: " << func->isDefault() << std::endl;
3963 std::cout <<
" isDelete: " << func->isDelete() << std::endl;
3964 std::cout <<
" hasOverrideSpecifier: " << func->hasOverrideSpecifier() << std::endl;
3965 std::cout <<
" hasFinalSpecifier: " << func->hasFinalSpecifier() << std::endl;
3966 std::cout <<
" isNoExcept: " << func->isNoExcept() << std::endl;
3967 std::cout <<
" isThrow: " << func->isThrow() << std::endl;
3968 std::cout <<
" isOperator: " << func->isOperator() << std::endl;
3969 std::cout <<
" hasLvalRefQual: " << func->hasLvalRefQualifier() << std::endl;
3970 std::cout <<
" hasRvalRefQual: " << func->hasRvalRefQualifier() << std::endl;
3971 std::cout <<
" isVariadic: " << func->isVariadic() << std::endl;
3972 std::cout <<
" isVolatile: " << func->isVolatile() << std::endl;
3973 std::cout <<
" hasTrailingReturnType: " << func->hasTrailingReturnType() << std::endl;
3974 std::cout <<
" attributes:";
3975 if (func->isAttributeConst())
3976 std::cout <<
" const ";
3977 if (func->isAttributePure())
3978 std::cout <<
" pure ";
3979 if (func->isAttributeNoreturn())
3980 std::cout <<
" noreturn ";
3981 if (func->isAttributeNothrow())
3982 std::cout <<
" nothrow ";
3983 if (func->isAttributeConstructor())
3984 std::cout <<
" constructor ";
3985 if (func->isAttributeDestructor())
3986 std::cout <<
" destructor ";
3987 if (func->isAttributeNodiscard())
3988 std::cout <<
" nodiscard ";
3989 std::cout << std::endl;
3990 std::cout <<
" noexceptArg: " << (func->noexceptArg ? func->noexceptArg->str() :
"none") << std::endl;
3991 std::cout <<
" throwArg: " << (func->throwArg ? func->throwArg->str() :
"none") << std::endl;
3994 if (!func->isConstructor() && !func->isDestructor())
3998 for (
const Token * tok = func->retDef; tok && tok != func->tokenDef && !
Token::Match(tok,
"{|;|override|final"); tok = tok->
next())
4000 std::cout << std::endl;
4002 std::cout <<
" retType: " << func->retType << std::endl;
4004 if (
const ValueType* valueType = func->tokenDef->next()->valueType()) {
4005 std::cout <<
" valueType: " << valueType << std::endl;
4006 std::cout <<
" " << valueType->str() << std::endl;
4009 if (func->hasBody()) {
4016 for (
auto var = func->argumentList.cbegin(); var != func->argumentList.cend(); ++var) {
4017 std::cout <<
" Variable: " << &*var << std::endl;
4022 for (
auto var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) {
4023 std::cout <<
" Variable: " << &*var << std::endl;
4028 std::cout <<
" enumType: ";
4029 if (scope->enumType) {
4030 std::cout << scope->enumType->stringify(
false,
true,
false);
4033 std::cout << std::endl;
4034 std::cout <<
" enumClass: " << scope->enumClass << std::endl;
4035 for (
const Enumerator &enumerator : scope->enumeratorList) {
4036 std::cout <<
" Enumerator: " << enumerator.
name->
str() <<
" = ";
4038 std::cout << enumerator.
value;
4040 if (enumerator.
start) {
4042 std::cout << (enumerator.
value_known ?
" " :
"") <<
"[" << tok->
str();
4043 while (tok && tok != enumerator.
end) {
4045 std::cout <<
" " << tok->
next()->
str();
4052 std::cout << std::endl;
4056 std::cout <<
" nestedIn: " << scope->nestedIn;
4057 if (scope->nestedIn) {
4058 std::cout <<
" " << scope->nestedIn->
type <<
" "
4059 << scope->nestedIn->className;
4061 std::cout << std::endl;
4063 std::cout <<
" definedType: " << scope->definedType << std::endl;
4065 std::cout <<
" nestedList[" << scope->nestedList.size() <<
"] = (";
4067 std::size_t count = scope->nestedList.size();
4068 for (std::vector<Scope*>::const_iterator nsi = scope->nestedList.cbegin(); nsi != scope->nestedList.cend(); ++nsi) {
4069 std::cout <<
" " << (*nsi) <<
" " << (*nsi)->type <<
" " << (*nsi)->className;
4074 std::cout <<
" )" << std::endl;
4076 for (
auto use = scope->usingList.cbegin(); use != scope->usingList.cend(); ++use) {
4077 std::cout <<
" using: " << use->scope <<
" " << use->start->strAt(2);
4079 while (tok1 && tok1->
str() ==
"::") {
4080 std::cout <<
"::" << tok1->
strAt(1);
4081 tok1 = tok1->
tokAt(2);
4088 std::cout <<
" function: " << scope->function;
4089 if (scope->function)
4090 std::cout <<
" " << scope->function->name();
4091 std::cout << std::endl;
4094 for (std::list<Type>::const_iterator type =
typeList.cbegin(); type !=
typeList.cend(); ++type) {
4095 std::cout <<
"Type: " << &(*type) << std::endl;
4096 std::cout <<
" name: " << type->name() << std::endl;
4098 std::cout <<
" classScope: " << type->classScope << std::endl;
4099 std::cout <<
" enclosingScope: " << type->enclosingScope;
4100 if (type->enclosingScope) {
4101 std::cout <<
" " << type->enclosingScope->type <<
" "
4102 << type->enclosingScope->className;
4104 std::cout << std::endl;
4108 "Invalid") << std::endl;
4110 std::cout <<
" derivedFrom[" << type->derivedFrom.size() <<
"] = (";
4111 std::size_t count = type->derivedFrom.size();
4114 std::cout <<
"Virtual ";
4122 std::cout <<
" " << i.
type;
4124 std::cout <<
" Unknown";
4126 std::cout <<
" " << i.
name;
4131 std::cout <<
" )" << std::endl;
4133 std::cout <<
" friendList[" << type->friendList.size() <<
"] = (";
4134 for (
size_t i = 0; i < type->friendList.size(); i++) {
4135 if (type->friendList[i].type)
4136 std::cout << type->friendList[i].type;
4138 std::cout <<
" Unknown";
4141 if (type->friendList[i].nameEnd)
4142 std::cout << type->friendList[i].nameEnd->str();
4143 if (i+1 < type->friendList.size())
4147 std::cout <<
" )" << std::endl;
4151 std::cout <<
"mVariableList[" << i <<
"]: " <<
mVariableList[i];
4156 std::cout << std::endl;
4158 std::cout << std::resetiosflags(std::ios::boolalpha);
4165 std::set<const Variable *> variables;
4168 outs +=
" <scopes>\n";
4169 for (std::list<Scope>::const_iterator scope =
scopeList.cbegin(); scope !=
scopeList.cend(); ++scope) {
4177 if (!scope->className.empty()) {
4178 outs +=
" className=\"";
4182 if (scope->bodyStart) {
4183 outs +=
" bodyStart=\"";
4187 if (scope->bodyEnd) {
4188 outs +=
" bodyEnd=\"";
4192 if (scope->nestedIn) {
4193 outs +=
" nestedIn=\"";
4197 if (scope->function) {
4198 outs +=
" function=\"";
4202 if (scope->definedType) {
4203 outs +=
" definedType=\"";
4207 if (scope->functionList.empty() && scope->varlist.empty())
4211 if (!scope->functionList.empty()) {
4212 outs +=
" <functionList>\n";
4213 for (std::list<Function>::const_iterator
function = scope->functionList.cbegin();
function != scope->functionList.cend(); ++
function) {
4214 outs +=
" <function id=\"";
4216 outs +=
"\" token=\"";
4218 outs +=
"\" tokenDef=\"";
4220 outs +=
"\" name=\"";
4226 if (function->nestedIn->definedType) {
4227 if (function->hasVirtualSpecifier())
4228 outs +=
" hasVirtualSpecifier=\"true\"";
4229 else if (function->isImplicitlyVirtual())
4230 outs +=
" isImplicitlyVirtual=\"true\"";
4233 outs +=
" access=\"";
4237 if (function->isOperator())
4238 outs +=
" isOperator=\"true\"";
4239 if (function->isExplicit())
4240 outs +=
" isExplicit=\"true\"";
4241 if (function->hasOverrideSpecifier())
4242 outs +=
" hasOverrideSpecifier=\"true\"";
4243 if (function->hasFinalSpecifier())
4244 outs +=
" hasFinalSpecifier=\"true\"";
4245 if (function->isInlineKeyword())
4246 outs +=
" isInlineKeyword=\"true\"";
4247 if (function->isStatic())
4248 outs +=
" isStatic=\"true\"";
4249 if (function->isAttributeNoreturn())
4250 outs +=
" isAttributeNoreturn=\"true\"";
4252 outs +=
" overriddenFunction=\"";
4256 if (function->argCount() == 0U)
4260 for (
unsigned int argnr = 0; argnr <
function->argCount(); ++argnr) {
4261 const Variable *arg =
function->getArgumentVar(argnr);
4262 outs +=
" <arg nr=\"";
4263 outs += std::to_string(argnr+1);
4264 outs +=
"\" variable=\"";
4267 variables.insert(arg);
4269 outs +=
" </function>\n";
4272 outs +=
" </functionList>\n";
4274 if (!scope->varlist.empty()) {
4275 outs +=
" <varlist>\n";
4276 for (std::list<Variable>::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) {
4277 outs +=
" <var id=\"";
4281 outs +=
" </varlist>\n";
4283 outs +=
" </scope>\n";
4286 outs +=
" </scopes>\n";
4289 outs +=
" <types>\n";
4291 outs +=
" <type id=\"";
4293 outs +=
"\" classScope=\"";
4296 if (type.derivedFrom.empty()) {
4302 outs +=
" <derivedFrom";
4303 outs +=
" access=\"";
4309 outs +=
" isVirtual=\"";
4312 outs +=
" nameTok=\"";
4317 outs +=
" </type>\n";
4319 outs +=
" </types>\n";
4324 variables.insert(var);
4325 outs +=
" <variables>\n";
4326 for (
const Variable *var : variables) {
4329 outs +=
" <var id=\"";
4332 outs +=
" nameToken=\"";
4335 outs +=
" typeStartToken=\"";
4338 outs +=
" typeEndToken=\"";
4341 outs +=
" access=\"";
4344 outs +=
" scope=\"";
4348 outs +=
" constness=\"";
4352 outs +=
" volatileness=\"";
4356 outs +=
" isArray=\"";
4359 outs +=
" isClass=\"";
4362 outs +=
" isConst=\"";
4365 outs +=
" isExtern=\"";
4368 outs +=
" isPointer=\"";
4371 outs +=
" isReference=\"";
4374 outs +=
" isStatic=\"";
4377 outs +=
" isVolatile=\"";
4382 outs +=
" </variables>\n";
4420 unsigned int count = 0;
4422 for (
const Token* tok = start->
next(); tok; tok = tok->
next()) {
4426 const Token* startTok = tok;
4427 const Token* endTok =
nullptr;
4428 const Token* nameTok =
nullptr;
4435 if (tok != startTok && !nameTok &&
Token::Match(tok,
"( & %var% ) [")) {
4436 nameTok = tok->
tokAt(2);
4440 nameTok = tok->
tokAt(2);
4442 tok = tok->
link()->linkAt(1);
4443 }
else if (tok != startTok && !nameTok &&
Token::Match(tok,
"( * %var% ) [")) {
4444 nameTok = tok->
tokAt(2);
4447 }
else if (tok->
varId() != 0) {
4450 }
else if (tok->
str() ==
"[") {
4453 while (tok->
next()->
str() ==
"[")
4455 }
else if (tok->
str() ==
"<") {
4465 }
while (tok->
str() !=
"," && tok->
str() !=
")" && tok->
str() !=
"=");
4467 const Token *typeTok = startTok;
4469 while (
Token::Match(typeTok,
"const|volatile|enum|struct|::"))
4470 typeTok = typeTok->
next();
4478 typeTok = typeTok->
tokAt(2);
4491 symbolDatabase->
debugMessage(nameTok,
"varid0",
"Function::addArguments found argument \'" + nameTok->
str() +
"\' with varid 0.");
4498 const ::Type *argType =
nullptr;
4503 const_cast<Token *
>(typeTok)->
type(argType);
4507 if (tok->
str() ==
"=") {
4512 }
while (tok->
str() !=
"," && tok->
str() !=
")");
4516 while (
Token::Match(startTok,
"enum|struct|const|volatile"))
4517 startTok = startTok->
next();
4519 if (startTok == nameTok)
4524 if (tok->
str() ==
")") {
4535 if (tok->
str() ==
"=") {
4537 if (tok->
strAt(1) ==
"[") {
4559 bool foundAllBaseClasses =
true;
4562 if (foundAllBaseClasses)
4569 std::vector<const Function*> result;
4574 for (std::multimap<std::string, const Function*>::const_iterator it = scope->
functionMap.find(
tokenDef->
str());
4578 if (isMemberFunction && isMemberFunction == func->
isStatic())
4580 result.push_back(func);
4582 if (isMemberFunction)
4592 if (foundAllBaseClasses)
4593 *foundAllBaseClasses =
true;
4602 if (thisName.back() !=
'>')
4604 const auto pos = thisName.find(
'<');
4605 if (pos == std::string::npos)
4607 return thisName.compare(0, pos + 1, baseName, 0, pos + 1) == 0;
4613 for (const ::Type::BaseInfo & i : baseType->derivedFrom) {
4614 const ::Type* derivedFromType = i.
type;
4616 if (!derivedFromType || !derivedFromType->classScope) {
4617 if (foundAllBaseClasses)
4618 *foundAllBaseClasses =
false;
4622 const Scope *parent = derivedFromType->classScope;
4626 for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
4627 const Function * func = it->second;
4634 while (!
Token::Match(temp1,
"virtual|public:|private:|protected:|{|}|;")) {
4635 if (temp1->
str() != temp2->
str() &&
4636 !(temp1->
type() && temp2->
type() && temp2->
type()->isDerivedFrom(temp1->
type()->name()))) {
4664 return f.isDestructor() && f.isImplicitlyVirtual();
4670 if (!derivedFromType->derivedFrom.empty() && !derivedFromType->hasCircularDependencies() && !
isDerivedFromItself(baseType->classScope->className, i.name)) {
4686 std::advance(it, num);
4697 classDef(classDef_),
4698 nestedIn(nestedIn_),
4706 classDef(classDef_),
4714 nameTok = nameTok->
next();
4717 nameTok = nameTok->
next();
4720 nameTok = nameTok->
next();
4723 nameTok = nameTok->
next();
4726 nameTok = nameTok->
next();
4727 if (nameTok->
str() ==
"class") {
4729 nameTok = nameTok->
next();
4765 const int varIndex =
varlist.size();
4766 varlist.emplace_back(token_, start_, end_, varIndex, access_, type_, scope_, settings);
4794 for (
const Token *tok = start; tok && tok != end; tok = tok->
next()) {
4796 if (tok->
next() ==
nullptr)
4800 if (tok->
str() ==
"{") {
4807 tok = tok->
tokAt(2);
4808 while (tok && tok->
str() !=
"{")
4819 tok = tok->
next()->
link()->tokAt(2);
4830 else if (tok->
str() ==
"__published:") {
4831 for (; tok; tok = tok->
next()) {
4832 if (tok->
str() ==
"{")
4843 else if (tok->
str() ==
"public:") {
4846 }
else if (tok->
str() ==
"protected:") {
4849 }
else if (tok->
str() ==
"private:") {
4856 tok = tok->
tokAt(2);
4861 else if (tok->
str() ==
"__property")
4866 while (tok->
next() &&
4884 if (tok->
str() ==
";")
4910 if (next && next->
str() ==
"{")
4911 next = next->
link();
4916 while (tok && tok->
isKeyword() &&
Token::Match(tok,
"const|constexpr|volatile|static|mutable|extern")) {
4921 const Token *typestart = tok;
4928 addVariable(tok, typestart, typeend, varaccess,
nullptr,
this, settings);
4930 return typeend->
linkAt(1);
4938 const Token *vartok =
nullptr;
4939 const Token *typetok =
nullptr;
4943 tok = vartok->
next();
4945 tok = tok->
link()->next();
4947 if (vartok->
varId() == 0) {
4949 check->
debugMessage(vartok,
"varid0",
"Scope::checkVariable found variable \'" + vartok->
str() +
"\' with varid 0.");
4953 const Type *vType =
nullptr;
4958 const_cast<Token *
>(typetok)->
type(vType);
4963 typestart = typestart->
next();
4974 return var.name() == varname;
4995 tok = tok->
tokAt(2);
5023 const bool isCPP = tok->
isCpp();
5030 if (isCPP11 && tok->
str() ==
"using")
5034 const Token* localVarTok =
nullptr;
5037 localTypeTok = localTypeTok->
linkAt(1)->
next();
5040 if (
Token::Match(tok,
"const_cast|dynamic_cast|reinterpret_cast|static_cast <"))
5047 if (
Token::Match(localVarTok,
":: %type% %name% [;=({]")) {
5048 if (localVarTok->
strAt(3) !=
"(" ||
5050 localTypeTok = localVarTok->
next();
5051 localVarTok = localVarTok->
tokAt(2);
5070 localVarTok = localVarTok->
next();
5072 if (
Token::Match(localVarTok,
"%name% ;|=") || (localVarTok && localVarTok->
varId() && localVarTok->
strAt(1) ==
":")) {
5073 vartok = localVarTok;
5074 typetok = localTypeTok;
5075 }
else if (
Token::Match(localVarTok,
"%name% )|[") && localVarTok->
str() !=
"operator") {
5076 vartok = localVarTok;
5077 typetok = localTypeTok;
5078 }
else if (localVarTok && localVarTok->
varId() &&
Token::Match(localVarTok,
"%name% (|{") &&
5080 vartok = localVarTok;
5081 typetok = localTypeTok;
5084 vartok = localVarTok;
5085 typetok = localTypeTok;
5088 return nullptr != vartok;
5096 if (tok2->
isCpp() && tok2->
str() ==
"class")
5097 tok2 = tok2->
next();
5100 tok2 = tok2->
next();
5103 if (tok2->
str() ==
":") {
5104 tok2 = tok2->
next();
5108 tok2 = tok2->
next();
5112 if (tok2->
str() ==
"{") {
5114 tok2 = tok2->
next();
5121 enumerator.
name = tok2;
5124 tok2 = tok2->
next();
5126 if (tok2->
str() ==
"=") {
5128 tok2 = tok2->
next();
5130 if (tok2->
str() ==
"}")
5133 enumerator.
start = tok2;
5137 tok2 = tok2->
link();
5138 enumerator.
end = tok2;
5139 tok2 = tok2->
next();
5141 }
else if (tok2->
str() ==
"(") {
5143 tok2 = tok2->
link()->next();
5146 if (tok2->
str() ==
",") {
5148 tok2 = tok2->
next();
5149 }
else if (tok2->
str() ==
"}") {
5156 tok2 = tok2->
next();
5158 if (tok2 && tok2->
str() !=
";" && (tok2->
isCpp() || tok2->
str() !=
")"))
5173 const Type *derivedFromType = i.
type;
5174 if (derivedFromType && derivedFromType->
classScope) {
5188 const std::string& tokStr = tok->
str();
5192 if (tok->
strAt(-1) ==
"::") {
5194 const Token *tok1 = tok;
5196 tok1 = tok1->
tokAt(-2);
5198 if (tok1->
strAt(-1) ==
"::")
5201 const Scope* temp =
nullptr;
5211 while (!temp && nested) {
5227 tok1 = tok1->
tokAt(2);
5230 tok1 = tok1->
tokAt(2);
5239 for (std::vector<Scope *>::const_iterator it = scope->
nestedList.cbegin(), end = scope->
nestedList.cend(); it != end; ++it) {
5240 enumerator = (*it)->findEnumerator(tokStr);
5249 if (tokensThatAreNotEnumeratorValues.find(tokStr) != tokensThatAreNotEnumeratorValues.end())
5257 scope = ctor->
function()->nestedIn;
5268 scope = varTok->
variable()->type()->classScope;
5273 scope = varTok->
variable()->scope();
5276 for (std::vector<Scope *>::const_iterator s = scope->
nestedList.cbegin(); s != scope->
nestedList.cend(); ++s) {
5277 enumerator = (*s)->findEnumerator(tokStr);
5286 const Type *derivedFromType = i.
type;
5287 if (derivedFromType && derivedFromType->
classScope) {
5307 for (std::vector<Scope*>::const_iterator s = scope->
nestedList.cbegin(); s != scope->
nestedList.cend(); ++s) {
5308 enumerator = (*s)->findEnumerator(tokStr);
5316 tokensThatAreNotEnumeratorValues.insert(tokStr);
5349 const Scope *scope = start;
5352 if (typeTok->
strAt(-1) !=
"::" && typeTok->
strAt(1) !=
"::") {
5392 else if (typeTok->
strAt(-1) ==
"::") {
5394 if (typeTok->
strAt(1) ==
"::")
5398 const Token *tok1 = typeTok;
5402 if (tok1->
strAt(-1) ==
"::")
5403 tok1 = tok1->
tokAt(-2);
5409 if (tok1->
strAt(-1) ==
"::") {
5438 if (tok1->
strAt(1) ==
"::")
5439 tok1 = tok1->
tokAt(2);
5474 if (s->type == Scope::eUnconditional && Token::simpleMatch(s->bodyStart->previous(),
") {"))
5477 if (s->type == Scope::eLambda && !hasEmptyCaptureList(s->bodyStart))
5479 if (s->hasInlineOrLambdaFunction())
5496 for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
5500 matches.push_back(func);
5520 if (base->
name() == name) {
5536 std::vector<const Scope*> result = {
this};
5545 result.insert(result.end(), baseScopes.cbegin(), baseScopes.cend());
5575 if (ptrequals && constEquals &&
5585 }
else if (ptrequals) {
5590 if ((takesInt && passesInt) || (takesFloat && passesFloat))
5592 else if ((takesInt && passesFloat) || (takesFloat && passesInt))
5603 if (typeToken->
str() ==
"::") {
5606 ret +=
"::" + typeToken->
strAt(1);
5607 typeToken = typeToken->
tokAt(2);
5608 if (typeToken->
str() ==
"<") {
5609 for (
const Token *tok = typeToken; tok != typeToken->
link(); tok = tok->
next())
5612 typeToken = typeToken->
link()->next();
5617 if (
Token::Match(typeToken,
"%name% const| %var%|*|&")) {
5618 return typeToken->
str();
5620 typeToken = typeToken->
next();
5626 if (!classScope || !argType)
5631 if (!f.isConstructor() || f.argCount() != 1 || !f.getArgumentVar(0))
5633 const ValueType* vt = f.getArgumentVar(0)->valueType();
5635 vt->type == argType->type &&
5636 (argType->sign == ValueType::Sign::UNKNOWN_SIGN || vt->sign == argType->sign) &&
5637 vt->pointer == argType->pointer &&
5638 (vt->constness & 1) >= (argType->constness & 1) &&
5639 (vt->volatileness & 1) >= (argType->volatileness & 1);
5647 const std::vector<const Token *> arguments =
getArguments(tok);
5649 std::vector<const Function *> matches;
5652 const std::size_t args = arguments.size();
5654 auto addMatchingFunctions = [&](
const Scope *scope) {
5655 auto range = scope->functionMap.equal_range(tok->
str());
5656 for (std::multimap<std::string, const Function *>::const_iterator it = range.first; it != range.second; ++it) {
5658 if (!isCall || args == func->
argCount() ||
5661 matches.push_back(func);
5666 addMatchingFunctions(
this);
5670 if (nestedScope->type ==
eNamespace && nestedScope->className.empty())
5671 addMatchingFunctions(nestedScope);
5674 const std::size_t numberOfMatchesNonBase = matches.size();
5681 return matches.empty() ? nullptr : matches[0];
5684 std::vector<const Function*> fallback1Func, fallback2Func;
5687 for (std::size_t i = 0; i < matches.size();) {
5688 if (i > 0 && i == numberOfMatchesNonBase && fallback1Func.empty() && !fallback2Func.empty())
5691 bool constFallback =
false;
5692 const Function * func = matches[i];
5695 if (requireConst && !func->
isConst()) {
5700 if (!requireConst || !func->
isConst()) {
5713 constFallback =
true;
5718 size_t fallback1 = 0;
5719 size_t fallback2 = 0;
5720 bool erased =
false;
5721 for (std::size_t j = 0; j < args; ++j) {
5729 if (!arguments[j]->valueType()) {
5730 const Token *vartok = arguments[j];
5733 pointer += vartok->
isUnaryOp(
"&") ? 1 : -1;
5736 if (vartok && vartok->
variable()) {
5737 const Token *callArgTypeToken = vartok->
variable()->typeStartToken();
5743 typeToken = typeToken->previous();
5746 if (typeToken->str() ==
"const")
5748 else if (typeToken->str() ==
"volatile")
5750 else if (typeToken->str() ==
"*")
5752 else if (typeToken->str() ==
"<") {
5753 if (!typeToken->link())
5755 typeToken = typeToken->link();
5757 typeToken = typeToken->next();
5764 if (!type1.empty() && type1 == type2) {
5765 ValueType callArgType = parseDecl(callArgTypeToken);
5766 callArgType.
pointer += pointer;
5767 ValueType funcArgType = parseDecl(funcArgTypeToken);
5769 callArgType.
sign = funcArgType.
sign = ValueType::Sign::SIGNED;
5770 callArgType.
type = funcArgType.
type = ValueType::Type::INT;
5786 const Variable * callarg = arguments[j]->variable();
5790 else if (funcarg->
isStlStringType() && arguments[j]->valueType() && arguments[j]->valueType()->pointer == 1 && arguments[j]->valueType()->type == ValueType::Type::CHAR)
5804 else if (arguments[j]->isCpp()) {
5805 const Token *vartok = arguments[j];
5806 if (vartok->
str() ==
".") {
5815 bool unknownDeref =
false;
5820 unknownDeref =
true;
5822 const Token* valuetok = arguments[j];
5823 if (valuetok->
str() ==
"::") {
5841 matches.erase(matches.begin() + i);
5855 if (same == hasToBe) {
5856 if (constFallback || (!requireConst && func->
isConst()))
5857 fallback1Func.emplace_back(func);
5863 if (same + fallback1 == hasToBe)
5864 fallback1Func.emplace_back(func);
5865 else if (same + fallback2 + fallback1 == hasToBe)
5866 fallback2Func.emplace_back(func);
5874 for (
const auto& fb : { fallback1Func, fallback2Func }) {
5877 if (fb.size() == 2) {
5878 if (fb[0]->isConst() && !fb[1]->isConst())
5880 if (fb[1]->isConst() && !fb[0]->isConst())
5886 auto itPure = std::find_if(matches.begin(), matches.end(), [](
const Function* m) {
5889 if (itPure != matches.end() && std::any_of(matches.begin(), matches.end(), [&](
const Function* m) {
5890 return m->isImplicitlyVirtual() && m != *itPure;
5892 matches.erase(itPure);
5895 if (matches.size() == 1)
5899 for (
const auto& fb : { fallback1Func, fallback2Func }) {
5901 for (
int i = 0; i < fb.size(); ++i) {
5902 if (std::find(matches.cbegin(), matches.cend(), fb[i]) == matches.cend())
5937 if (tok->
strAt(-1) ==
"::") {
5939 const Token *tok1 = tok;
5942 if (tok1->
strAt(-2) ==
">") {
5948 tok1 = tok1->
tokAt(-2);
5952 if (tok1->
strAt(-1) ==
"::") {
5978 while (currScope && tok1 && !(
Token::Match(tok1,
"%type% :: %name% [(),>]") ||
5980 if (tok1->
strAt(1) ==
"::")
5981 tok1 = tok1->
tokAt(2);
5982 else if (tok1->
strAt(1) ==
"<")
5997 tok1 = tok1->
tokAt(2);
5999 if (currScope && tok1) {
6044 currScope = tok->
scope();
6046 for (
const auto& ul : currScope->
usingList) {
6048 const Function* func = ul.scope->findFunction(tok);
6070 return s.className == name;
6072 return it ==
scopeList.end() ? nullptr : &*it;
6077 template<
class S,
class T,
REQUIRES(
"S must be a Scope class", std::is_convertible<S*, const Scope*> ),
REQUIRES(
"T must be a Type class", std::is_convertible<T*, const Type*> )>
6080 for (S* scope: thisScope.nestedList) {
6084 S* nestedScope = scope->findRecordInNestedList(name, isC);
6090 T * nested_type = thisScope.findType(name);
6093 if (nested_type->isTypeAlias()) {
6094 if (nested_type->typeStart == nested_type->typeEnd)
6095 return thisScope.findRecordInNestedList(nested_type->typeStart->str());
6097 return const_cast<S*
>(nested_type->classScope);
6105 return findRecordInNestedListImpl<const Scope, const Type>(*
this, name, isC);
6110 return findRecordInNestedListImpl<Scope, Type>(*
this, name, isC);
6115 template<
class S,
class T,
REQUIRES(
"S must be a Scope class", std::is_convertible<S*, const Scope*> ),
REQUIRES(
"T must be a Type class", std::is_convertible<T*, const Type*> )>
6118 auto it = thisScope.definedTypesMap.find(name);
6121 if (thisScope.definedTypesMap.end() != it)
6126 if (it != thisScope.definedTypesMap.end()) {
6127 for (S *scope : thisScope.nestedList) {
6128 if (scope->className.empty() && (scope->type == thisScope.eNamespace || scope->isClassOrStructOrUnion())) {
6129 T *t = scope->findType(name);
6142 return findTypeImpl<const Scope, const Type>(*
this, name);
6147 return findTypeImpl<Scope, Type>(*
this, name);
6155 return s->className == name;
6173 return f.type == Function::eDestructor;
6182 const Scope *scope =
nullptr;
6184 if (tok->
str() ==
"::") {
6189 else if (tok->
isName()) {
6193 while (scope && tok && tok->
isName()) {
6194 if (tok->
strAt(1) ==
"::") {
6196 tok = tok->
tokAt(2);
6214 startTok = startTok->
next();
6220 if (startTok->
isC()) {
6221 const Scope* scope = startScope;
6237 const Scope* start_scope = startScope;
6240 if (startTok->
str() ==
"::") {
6241 startTok = startTok->
next();
6245 const Token* tok = startTok;
6246 const Scope* scope = start_scope;
6248 while (scope && tok && tok->
isName()) {
6252 if (tok->
strAt(1) ==
"::")
6253 tok = tok->
tokAt(2);
6257 start_scope = start_scope->
nestedIn;
6260 scope = start_scope;
6264 const Scope* scope1{};
6269 type = scope1->definedType;
6272 }
else if (lookOutside && scope->
type == Scope::ScopeType::eNamespace) {
6281 while (startScope) {
6282 for (std::vector<Scope::UsingInfo>::const_iterator it = startScope->
usingList.cbegin();
6283 it != startScope->
usingList.cend(); ++it) {
6286 start_scope = startScope;
6288 while (scope && tok && tok->
isName()) {
6292 if (tok->
strAt(1) ==
"::")
6293 tok = tok->
tokAt(2);
6297 start_scope = start_scope->
nestedIn;
6300 scope = start_scope;
6308 type = scope1->definedType;
6329 startTok = startTok->
next();
6335 bool hasPath =
false;
6338 if (startTok->
str() ==
"::") {
6340 startTok = startTok->
next();
6344 const Token* tok = startTok;
6345 const Scope* scope = startScope;
6347 while (scope && tok && tok->
isName()) {
6352 if (tok->
strAt(1) ==
"::")
6353 tok = tok->
tokAt(2);
6365 if (hasPath || type)
6396 const Function *
function =
nullptr;
6397 const bool destructor = func->
strAt(-1) ==
"~";
6400 for (std::multimap<std::string, const Function*>::const_iterator it = range.first; it != range.second; ++it) {
6401 if (it->second->argsMatch(ns, it->second->argDef, func->
next(), path, path_length) &&
6402 it->second->isDestructor() == destructor) {
6403 function = it->second;
6411 if (func->
strAt(1) ==
"::")
6412 func = func->
tokAt(2);
6413 else if (func->
linkAt(1))
6417 if (func->
str() ==
"~")
6418 func = func->
next();
6423 return const_cast<Function *
>(
function);
6430 const std::string& iName = tok->
str();
6432 static const auto& cpp_keywords =
Keywords::getAll(Standards::cppstd_t::CPPLatest);
6433 return cpp_keywords.find(iName) != cpp_keywords.cend();
6435 static const auto& c_keywords =
Keywords::getAll(Standards::cstd_t::CLatest);
6436 return c_keywords.find(iName) != c_keywords.cend();
6443 if (size == 0 && type->
type() && type->
type()->isEnumType() && type->
type()->classScope) {
6445 const Token * enum_type = type->
type()->classScope->enumType;
6506 valuetype.
sign = ValueType::Sign::SIGNED;
6508 valuetype.
sign = ValueType::Sign::UNSIGNED;
6509 else if (valuetype.
type == ValueType::Type::CHAR)
6512 valuetype.
sign = ValueType::Sign::SIGNED;
6543 auto* valuetypePtr =
new ValueType(valuetype);
6545 valuetypePtr->setDebugPath(tok, loc);
6558 if (vt1->
type < ValueType::Type::BOOL || vt1->
type >= ValueType::Type::INT) {
6564 vt.
type = ValueType::Type::INT;
6565 vt.
sign = ValueType::Sign::SIGNED;
6605 Token *autoTok =
nullptr;
6609 autoTok = var1Tok->
tokAt(-2);
6611 autoTok = var1Tok->
tokAt(-3);
6662 while (
op1 &&
op1->str() ==
"[")
6663 op1 =
op1->astOperand1();
6667 if (!(
op1 &&
op1->variable() &&
op1->variable()->nameToken() ==
op1))
6692 if (parent->
str() ==
"*" && !parent->
astOperand2() && valuetype.
type == ValueType::Type::ITERATOR &&
6706 if (parent->
str() ==
"*" && !parent->
astOperand2() && valuetype.
type == ValueType::Type::SMART_POINTER &&
6720 while (
op1 &&
op1->str() ==
"[")
6721 op1 =
op1->astOperand1();
6723 if (
op1 &&
op1->variable() &&
op1->variable()->nameToken() ==
op1) {
6731 bool isArrayToPointerDecay =
false;
6734 child = child->astOperand2();
6736 isArrayToPointerDecay = child->variable() && child->variable()->isArray();
6740 if (!isArrayToPointerDecay)
6746 if ((parent->
str() ==
"." || parent->
str() ==
"::") &&
6749 if (!var && valuetype.
typeScope && vt1) {
6750 const std::string &name = parent->
astOperand2()->str();
6754 auto it = std::find_if(typeScope->
varlist.begin(), typeScope->
varlist.end(), [&name](
const Variable& v) {
6755 return v.nameToken()->str() == name;
6757 if (it != typeScope->
varlist.end())
6771 parent->
str() ==
":" &&
6777 Token *
const autoToken = parent->
astParent()->tokAt(isconst ? 2 : 1);
6815 typeStart = typeStart->
variable()->typeStartToken();
6824 bool setType =
false;
6826 const Type *templateArgType =
nullptr;
6829 autovt.
type = ValueType::Type::RECORD;
6834 smartPointerTypeTok = smartPointerTypeTok->
next();
6839 autovt.
type = ValueType::Type::NONSTD;
6918 const bool ternary = parent->
str() ==
":" && parent->
astParent() && parent->
astParent()->str() ==
"?";
6928 if (parent->
str() ==
"+" && vt1->
type == ValueType::Type::CONTAINER && vt2 && vt2->
isIntegral()) {
6933 if (parent->
str() ==
"+" && vt1->
isIntegral() && vt2 && vt2->
type == ValueType::Type::CONTAINER) {
6948 }
else if (ternary) {
6975 setValueType(parent,
ValueType(ValueType::Sign::SIGNED, ValueType::Type::INT, 0U, 0U,
"ptrdiff_t"));
6979 if (vt1->
type == ValueType::Type::LONGDOUBLE || (vt2 && vt2->
type == ValueType::Type::LONGDOUBLE)) {
6983 if (vt1->
type == ValueType::Type::DOUBLE || (vt2 && vt2->
type == ValueType::Type::DOUBLE)) {
6987 if (vt1->
type == ValueType::Type::FLOAT || (vt2 && vt2->
type == ValueType::Type::FLOAT)) {
6993 if (vt1->
type == ValueType::Type::ITERATOR && vt2 && vt2->
isIntegral() &&
6994 (parent->
str() ==
"+" || parent->
str() ==
"-")) {
6999 if (parent->
str() ==
"+" && vt1->
type == ValueType::Type::CONTAINER && vt2 && vt2->
type == ValueType::Type::CONTAINER && vt1->
container == vt2->
container) {
7010 if (!vt2 || vt1->
type > vt2->
type) {
7014 }
else if (vt1->
type == vt2->
type) {
7016 if (vt1->
sign == ValueType::Sign::UNSIGNED || vt2->
sign == ValueType::Sign::UNSIGNED)
7017 vt.
sign = ValueType::Sign::UNSIGNED;
7018 else if (vt1->
sign == ValueType::Sign::UNKNOWN_SIGN || vt2->
sign == ValueType::Sign::UNKNOWN_SIGN)
7019 vt.
sign = ValueType::Sign::UNKNOWN_SIGN;
7021 vt.
sign = ValueType::Sign::SIGNED;
7028 if (vt.
type < ValueType::Type::INT && !(ternary && vt.
type==ValueType::Type::BOOL)) {
7029 vt.
type = ValueType::Type::INT;
7030 vt.
sign = ValueType::Sign::SIGNED;
7050 if ((vt->type > type && (vt->type == ValueType::Type::LONG || vt->type == ValueType::Type::LONGLONG)))
7057 type = ValueType::Type::LONG;
7059 type = ValueType::Type::LONGLONG;
7073 const Token *
const previousType = type;
7074 const unsigned int pointer0 = valuetype->
pointer;
7077 valuetype->
sign = ValueType::Sign::UNKNOWN_SIGN;
7079 valuetype->
type = ValueType::Type::UNKNOWN_TYPE;
7081 valuetype->
type = ValueType::Type::SMART_POINTER;
7086 valuetype->
sign = ValueType::Sign::SIGNED;
7088 valuetype->
sign = ValueType::Sign::UNSIGNED;
7090 valuetype->
sign = defaultSignedness;
7092 if (t != ValueType::Type::UNKNOWN_TYPE)
7093 valuetype->
type = t;
7099 valuetype->
type = ValueType::Type::RECORD;
7104 if (type->
str() ==
"(") {
7113 if (valuetype->
sign == ValueType::Sign::UNKNOWN_SIGN)
7115 if (valuetype->
type == ValueType::Type::UNKNOWN_TYPE)
7124 valuetype->
sign = ValueType::Sign::SIGNED;
7126 valuetype->
sign = ValueType::Sign::UNSIGNED;
7127 if (valuetype->
type == ValueType::Type::UNKNOWN_TYPE &&
7128 type->
type() && type->
type()->isTypeAlias() && type->
type()->typeStart &&
7129 type->
type()->typeStart->str() != type->
str() && type->
type()->typeStart != previousType)
7130 parsedecl(type->
type()->typeStart, valuetype, defaultSignedness, settings);
7135 else if (settings.
clang && type->
str().size() > 2 && type->
str().find(
"::") < type->
str().find(
'<')) {
7137 std::string::size_type pos1 = 0;
7139 const std::string::size_type pos2 = type->
str().find(
"::", pos1);
7140 if (pos2 == std::string::npos) {
7141 typeTokens.
addtoken(type->
str().substr(pos1), 0, 0, 0,
false);
7144 typeTokens.
addtoken(type->
str().substr(pos1, pos2 - pos1), 0, 0, 0,
false);
7145 typeTokens.
addtoken(
"::", 0, 0, 0,
false);
7147 }
while (pos1 < type->str().size());
7152 valuetype->
type = ValueType::Type::ITERATOR;
7154 valuetype->
type = ValueType::Type::CONTAINER;
7160 valuetype->
type = (scope->
type == Scope::ScopeType::eClass) ? ValueType::Type::RECORD : ValueType::Type::NONSTD;
7164 valuetype->
type = ValueType::Type::ITERATOR;
7166 valuetype->
type = ValueType::Type::CONTAINER;
7169 if (type->
str() ==
"<" && type->
link()) {
7170 if (container->type_templateArgNo >= 0) {
7171 const Token *templateType = type->
next();
7172 for (
int j = 0; templateType && j < container->type_templateArgNo; j++)
7176 type = type->
link();
7178 type = type->
next();
7191 valuetype->
type = ValueType::Type::SMART_POINTER;
7192 type = argTok->
link();
7194 type = type->
next();
7197 std::string typestr;
7198 const Token *end = type;
7200 typestr += end->
str() +
"::";
7201 end = end->
tokAt(2);
7203 typestr += end->
str();
7209 if (t0 == ValueType::Type::LONG) {
7210 if (valuetype->
type == ValueType::Type::LONG)
7211 valuetype->
type = ValueType::Type::LONGLONG;
7212 else if (valuetype->
type == ValueType::Type::DOUBLE)
7213 valuetype->
type = ValueType::Type::LONGDOUBLE;
7215 }
else if (type->
str() ==
"auto") {
7222 if (vt->
sign != ValueType::Sign::UNKNOWN_SIGN)
7230 if (type->
str() ==
"*") {
7236 }
else if (type->
str() ==
"&") {
7238 }
else if (type->
str() ==
"&&") {
7241 if (type->
str() ==
"const")
7243 if (type->
str() ==
"volatile")
7245 type = type->
next();
7248 }
else if (!valuetype->
typeScope && (type->
str() ==
"struct" || type->
str() ==
"enum"))
7249 valuetype->
type = type->
str() ==
"struct" ? ValueType::Type::RECORD : ValueType::Type::NONSTD;
7251 if (type->
type()->classScope->type == Scope::ScopeType::eEnum) {
7252 valuetype->
sign = ValueType::Sign::SIGNED;
7255 valuetype->
type = ValueType::Type::RECORD;
7258 }
else if (type->
isName() && valuetype->
sign != ValueType::Sign::UNKNOWN_SIGN && valuetype->
pointer == 0U)
7260 else if (type->
str() ==
"*")
7262 else if (type->
str() ==
"&")
7264 else if (type->
str() ==
"&&")
7272 type = type->
next();
7273 if (type && type->
link() && type->
str() ==
"<")
7274 type = type->
link()->next();
7278 if (valuetype->
isIntegral() && valuetype->
sign == ValueType::Sign::UNKNOWN_SIGN) {
7279 if (valuetype->
type == ValueType::Type::CHAR)
7280 valuetype->
sign = defaultSignedness;
7281 else if (valuetype->
type >= ValueType::Type::SHORT)
7282 valuetype->
sign = ValueType::Sign::SIGNED;
7297 const std::string functionName(
"operator" + tok->
str());
7298 std::multimap<std::string, const Function *>::const_iterator it;
7324 if (
Token::Match(lvar->nameToken()->next(),
"; %varid% = [", lvar->declarationId()))
7325 lambda = lvar->nameToken()->tokAt(4)->function();
7327 lambda = lvar->nameToken()->tokAt(2)->function();
7328 if (lambda && lambda->retDef)
7339 for (
Token *tok = tokens; tok; tok = tok->
next())
7342 for (
Token *tok = tokens; tok; tok = tok->
next()) {
7346 const char suffix = tok->
str()[tok->
str().size() - 1];
7347 if (suffix ==
'f' || suffix ==
'F')
7348 type = ValueType::Type::FLOAT;
7349 else if (suffix ==
'L' || suffix ==
'l')
7350 type = ValueType::Type::LONGDOUBLE;
7354 const bool unsignedSuffix = (tokStr.find_last_of(
"uU") != std::string::npos);
7355 ValueType::Sign sign = unsignedSuffix ? ValueType::Sign::UNSIGNED : ValueType::Sign::SIGNED;
7358 for (std::size_t pos = tokStr.size() - 1U; pos > 0U; --pos) {
7359 const char suffix = tokStr[pos];
7360 if (suffix ==
'u' || suffix ==
'U')
7361 sign = ValueType::Sign::UNSIGNED;
7362 else if (suffix ==
'l' || suffix ==
'L')
7363 type = (type == ValueType::Type::INT) ? ValueType::Type::LONG : ValueType::Type::LONGLONG;
7364 else if (pos > 2U && suffix ==
'4' && tokStr[pos - 1] ==
'6' && tokStr[pos - 2] ==
'i') {
7365 type = ValueType::Type::LONGLONG;
7371 type = ValueType::Type::INT;
7373 type = ValueType::Type::INT;
7374 sign = ValueType::Sign::UNSIGNED;
7376 type = ValueType::Type::LONG;
7378 type = ValueType::Type::LONG;
7379 sign = ValueType::Sign::UNSIGNED;
7381 type = ValueType::Type::LONGLONG;
7383 type = ValueType::Type::LONGLONG;
7384 sign = ValueType::Sign::UNSIGNED;
7406 nonneg int const volatileness = 0U;
7407 ValueType valuetype(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, pointer, constness, volatileness);
7418 }
else if (tok->
isLong()) {
7420 valuetype.
type = ValueType::Type::WCHAR_T;
7422 valuetype.
type = ValueType::Type::INT;
7423 valuetype.
sign = ValueType::Sign::SIGNED;
7460 ValueType valuetype(ValueType::Sign::UNSIGNED, ValueType::Type::LONG, 0U);
7462 valuetype.
type = ValueType::Type::LONGLONG;
7485 valuetype.
sign = ValueType::Sign::UNSIGNED;
7487 valuetype.
sign = ValueType::Sign::SIGNED;
7520 while (typeStartToken && typeStartToken->
str() ==
"::")
7531 const std::string e = tok->
astOperand1()->expressionString();
7533 if ((e ==
"std::make_shared" || e ==
"std::make_unique") &&
Token::Match(tok->
astOperand1(),
":: %name% < %name%")) {
7544 vt.
type = ValueType::Type::SMART_POINTER;
7558 if (!typestr.empty()) {
7561 std::istringstream istr(typestr+
";");
7562 tokenList.
createTokens(istr, tok->
isCpp() ? Standards::Language::CPP : Standards::Language::C);
7571 const bool isReturnIter = typestr ==
"iterator";
7572 if (typestr.empty() || isReturnIter) {
7577 tok->
astOperand1()->astOperand1()->valueType()->container) {
7585 vt.
type = ValueType::Type::ITERATOR;
7588 tok->
astOperand1()->astOperand1()->valueType()->containerTypeToken;
7597 const auto*
const paramVariable = tok->
astOperand2()->variable();
7598 if (!paramVariable ||
7599 !paramVariable->valueType() ||
7600 !paramVariable->valueType()->container) {
7609 vt.
type = ValueType::Type::ITERATOR;
7610 vt.
container = paramVariable->valueType()->container;
7616 const std::vector<const Token*> args =
getArguments(tok);
7617 if (!args.empty()) {
7619 if (info && info->
it) {
7620 const Token* contTok = args[0];
7621 if (
Token::simpleMatch(args[0]->astOperand1(),
".") && args[0]->astOperand1()->astOperand1())
7629 if (contTok && contTok->
variable() && contTok->
variable()->valueType() && contTok->
variable()->valueType()->container) {
7631 vt.
type = ValueType::Type::ITERATOR;
7639 vt.
type = ValueType::Type::ITERATOR;
7651 std::istringstream istr(typestr+
";");
7652 if (tokenList.
createTokens(istr, tok->
isCpp() ? Standards::Language::CPP : Standards::Language::C)) {
7662 }
else if (tok->
str() ==
"return") {
7665 functionScope = functionScope->
nestedIn;
7682 typeTok = typeTok->
link()->next();
7688 vt.
type =
isIterator ? ValueType::Type::ITERATOR : ValueType::Type::CONTAINER;
7692 std::string typestr;
7694 typestr += typeTok->
str() +
"::";
7695 typeTok = typeTok->
tokAt(2);
7699 typestr += typeTok->
str();
7702 if (typeTok->
type() && typeTok->
type()->classScope) {
7703 vt.
type = ValueType::Type::RECORD;
7707 if (vt.
type == ValueType::Type::UNKNOWN_TYPE)
7709 if (vt.
type == ValueType::Type::UNKNOWN_TYPE)
7712 vt.
sign = ValueType::Sign::UNSIGNED;
7714 vt.
sign = ValueType::Sign::SIGNED;
7725 while (fscope && !fscope->
function)
7732 }
else if (tok->
isKeyword() && tok->
str() ==
"this" && tok->
scope()->isExecutable()) {
7734 while (fscope && !fscope->
function)
7738 ValueType vt(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::RECORD, 1);
7750 for (
Token *tok = tokens; tok; tok = tok->
next()) {
7756 debugMessage(tok,
"autoNoType",
"auto token with no type.");
7777 if (typestr ==
"void")
7778 return ValueType::Type::VOID;
7779 if (typestr ==
"bool" || typestr ==
"_Bool")
7780 return ValueType::Type::BOOL;
7781 if (typestr==
"char")
7782 return ValueType::Type::CHAR;
7783 if (typestr ==
"short")
7784 return ValueType::Type::SHORT;
7785 if (typestr ==
"wchar_t")
7786 return ValueType::Type::WCHAR_T;
7787 if (typestr ==
"int")
7788 return ValueType::Type::INT;
7789 if (typestr ==
"long")
7790 return longType ? ValueType::Type::LONGLONG : ValueType::Type::LONG;
7791 if (typestr ==
"float")
7792 return ValueType::Type::FLOAT;
7793 if (typestr ==
"double")
7794 return longType ? ValueType::Type::LONGDOUBLE : ValueType::Type::DOUBLE;
7795 return ValueType::Type::UNKNOWN_TYPE;
7801 if (podtype && (podtype->
sign ==
's' || podtype->
sign ==
'u')) {
7802 if (podtype->
size == 1)
7803 type = ValueType::Type::CHAR;
7805 type = ValueType::Type::INT;
7807 type = ValueType::Type::SHORT;
7809 type = ValueType::Type::LONG;
7811 type = ValueType::Type::LONGLONG;
7813 type = ValueType::Type::BOOL;
7815 type = ValueType::Type::CHAR;
7817 type = ValueType::Type::SHORT;
7819 type = ValueType::Type::INT;
7821 type = ValueType::Type::LONG;
7823 type = ValueType::Type::LONGLONG;
7825 type = ValueType::Type::UNKNOWN_INT;
7830 type = ValueType::Type::POD;
7837 if (platformType->
mType ==
"char")
7838 type = ValueType::Type::CHAR;
7839 else if (platformType->
mType ==
"short")
7840 type = ValueType::Type::SHORT;
7841 else if (platformType->
mType ==
"wchar_t")
7842 type = ValueType::Type::WCHAR_T;
7843 else if (platformType->
mType ==
"int")
7844 type = platformType->
mLong ? ValueType::Type::LONG : ValueType::Type::INT;
7845 else if (platformType->
mType ==
"long")
7846 type = platformType->
mLong ? ValueType::Type::LONGLONG : ValueType::Type::LONG;
7859 if (!podtype && (typestr ==
"size_t" || typestr ==
"std::size_t")) {
7863 type = ValueType::Type::LONG;
7865 type = ValueType::Type::LONGLONG;
7867 type = ValueType::Type::INT;
7869 type = ValueType::Type::UNKNOWN_INT;
7883 ret +=
"valueType-type=\"nonstd\"";
7886 ret +=
"valueType-type=\"pod\"";
7889 ret +=
"valueType-type=\"record\"";
7892 ret +=
"valueType-type=\"smart-pointer\"";
7895 ret +=
"valueType-type=\"container\"";
7896 ret +=
" valueType-containerId=\"";
7902 ret +=
"valueType-type=\"iterator\"";
7905 ret +=
"valueType-type=\"void\"";
7908 ret +=
"valueType-type=\"bool\"";
7911 ret +=
"valueType-type=\"char\"";
7914 ret +=
"valueType-type=\"short\"";
7917 ret +=
"valueType-type=\"wchar_t\"";
7920 ret +=
"valueType-type=\"int\"";
7923 ret +=
"valueType-type=\"long\"";
7926 ret +=
"valueType-type=\"long long\"";
7929 ret +=
"valueType-type=\"unknown int\"";
7932 ret +=
"valueType-type=\"float\"";
7935 ret +=
"valueType-type=\"double\"";
7938 ret +=
"valueType-type=\"long double\"";
7943 case Sign::UNKNOWN_SIGN:
7946 ret +=
" valueType-sign=\"signed\"";
7948 case Sign::UNSIGNED:
7949 ret +=
" valueType-sign=\"unsigned\"";
7954 ret +=
" valueType-bits=\"";
7955 ret += std::to_string(
bits);
7960 ret +=
" valueType-pointer=\"";
7961 ret += std::to_string(
pointer);
7966 ret +=
" valueType-constness=\"";
7972 ret +=
" valueType-volatileness=\"";
7978 ret +=
" valueType-reference=\"None\"";
7980 ret +=
" valueType-reference=\"LValue\"";
7982 ret +=
" valueType-reference=\"RValue\"";
7985 ret +=
" valueType-typeScope=\"";
7991 ret +=
" valueType-originalTypeName=\"";
8021 case ValueType::Type::BOOL:
8023 case ValueType::Type::CHAR:
8025 case ValueType::Type::SHORT:
8027 case ValueType::Type::WCHAR_T:
8029 case ValueType::Type::INT:
8031 case ValueType::Type::LONG:
8033 case ValueType::Type::LONGLONG:
8035 case ValueType::Type::FLOAT:
8037 case ValueType::Type::DOUBLE:
8039 case ValueType::Type::LONGDOUBLE:
8054 return std::tie(vt->type, vt->container, vt->pointer, vt->typeScope, vt->smartPointer);
8056 return tie(
this) == tie(that);
8086 ret +=
" long long";
8088 ret +=
" unknown_int";
8094 ret +=
" long double";
8095 else if ((
type == ValueType::Type::NONSTD ||
type == ValueType::Type::RECORD) &&
typeScope) {
8100 className = scope->
className +
"::" + className;
8103 ret +=
' ' + className;
8104 }
else if (
type == ValueType::Type::CONTAINER &&
container) {
8106 }
else if (
type == ValueType::Type::ITERATOR &&
container) {
8111 for (
unsigned int p = 0; p <
pointer; p++) {
8124 return ret.substr(1);
8134 debugPath.emplace_back(tok, std::move(s));
8161 if (call->
type == ValueType::Type::VOID || func->
type == ValueType::Type::VOID)
8190 if (func->
type < ValueType::Type::VOID || func->
type == ValueType::Type::UNKNOWN_INT)
8217 const bool templateVar =
8221 if (!templateVar && type1.find(
"auto") == std::string::npos && type2.find(
"auto") == std::string::npos)
bool astIsContainer(const Token *tok)
std::vector< const Token * > getArguments(const Token *ftok)
Get arguments (AST)
bool precedes(const Token *tok1, const Token *tok2)
If tok2 comes after tok1.
bool compareTokenFlags(const Token *tok1, const Token *tok2, bool macro)
Are the tokens' flags equal?
static bool match(const Token *tok, const std::string &rhs)
Library::Container::Yield astFunctionYield(const Token *tok, const Settings &settings, const Token **ftok)
const Token * findLambdaStartToken(const Token *last)
const Token * findLambdaEndToken(const Token *first)
find lambda function end token
const Token * nextAfterAstRightmostLeaf(const Token *tok)
bool isReturnScope(const Token *const endToken, const Library &library, const Token **unknownFunc, bool functionScope)
Is scope a return scope (scope will unconditionally return)
bool isCPPCast(const Token *tok)
SmallVector< ReferenceToken > followAllReferences(const Token *tok, bool temporary, bool inconclusive, ErrorPath errors, int depth)
bool succeeds(const Token *tok1, const Token *tok2)
If tok1 comes after tok2.
const Token * findAstNode(const Token *ast, const TFunc &pred)
static int sign(const T v)
static bool isIterator(const Variable *var, bool &inconclusiveType)
This is an interface, which the class responsible of error logging should implement.
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
static std::string toxml(const std::string &str)
Convert XML-sensitive characters into XML entities.
virtual void reportProgress(const std::string &filename, const char stage[], const std::size_t value)
Report progress to client.
Wrapper for error messages, provided by reportErr()
bool isInlineKeyword() const
AccessControl access
public/protected/private
Function(const Token *tok, const Scope *scope, const Token *tokDef, const Token *tokArgDef)
nonneg int initializedArgCount() const
nonneg int minArgCount() const
static std::vector< const Token * > findReturns(const Function *f)
const std::string & name() const
std::vector< const Function * > getOverloadedFunctions() const
void addArguments(const SymbolDatabase *symbolDatabase, const Scope *scope)
const Token * argDef
function argument start '(' in class definition
const Scope * functionScope
scope of function body
const Function * getOverriddenFunction(bool *foundAllBaseClasses=nullptr) const
get function in base class that is overridden
bool hasRvalRefQualifier() const
static bool returnsConst(const Function *function, bool unknown=false)
bool hasLvalRefQualifier() const
Type type
constructor, destructor, ...
bool isSafe(const Settings &settings) const
static bool returnsPointer(const Function *function, bool unknown=false)
static bool returnsReference(const Function *function, bool unknown=false, bool includeRValueRef=false)
bool argsMatch(const Scope *scope, const Token *first, const Token *second, const std::string &path, nonneg int path_length) const
@ fHasFinalSpecifier
does declaration contain 'final' specifier?
@ fHasOverrideSpecifier
does declaration contain 'override' specifier?
const Token * setFlags(const Token *tok1, const Scope *scope)
nonneg int initArgCount
number of args with default values
const Variable * getArgumentVar(nonneg int num) const
nonneg int argCount() const
const Token * throwArg
throw token
const Token * retDef
function return type token
bool isImplicitlyVirtual(bool defaultVal=false) const
check if this function is virtual in the base classes
bool hasTrailingReturnType() const
static bool returnsStandardType(const Function *function, bool unknown=false)
std::string fullName() const
const Token * constructorMemberInitialization() const
const Function * getOverriddenFunctionRecursive(const ::Type *baseType, bool *foundAllBaseClasses) const
Recursively determine if this function overrides a virtual function in a base class.
bool isEscapeFunction() const
const Token * token
function name token in implementation
const Token * arg
function argument start '('
const Scope * nestedIn
Scope the function is declared in.
bool hasOverrideSpecifier() const
bool hasVirtualSpecifier() const
const Token * tokenDef
function name token in class definition
const Token * templateDef
points to 'template <' before function
std::list< Variable > argumentList
argument list, must remain list due to clangimport usage!
void setFlag(unsigned int flag, bool state)
Set specified flag state.
static bool returnsVoid(const Function *function, bool unknown=false)
bool isDestructor() const
bool isConstructor() const
bool isStaticLocal() const
static const std::unordered_set< std::string > & getAll(Standards::cstd_t cStd)
std::vector< RangeItemRecordTypeItem > rangeItemRecordType
std::map< std::string, Function > functions
Yield getYield(const std::string &function) const
Library definitions handling.
const Container * detectContainerOrIterator(const Token *typeStart, bool *isIterator=nullptr, bool withoutStd=false) const
const SmartPointer * detectSmartPointer(const Token *tok, bool withoutStd=false) const
bool isSmartPointer(const Token *tok) const
const PodType * podtype(const std::string &name) const
const ArgumentChecks::IteratorInfo * getArgIteratorInfo(const Token *ftok, int argnr) const
std::unordered_map< std::string, SmartPointer > smartPointers
const Container * detectContainer(const Token *typeStart) const
const std::string & returnValueType(const Token *ftok) const
std::unordered_map< std::string, Function > functions
const PlatformType * platform_type(const std::string &name, const std::string &platform) const
static biguint toBigUNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
static bigint toBigNumber(const std::string &str)
for conversion of numeric literals - for atoi-like conversions please use strToInt()
static bool isFloat(const std::string &str)
static bool isDec(const std::string &str)
static bool isNullValue(const std::string &str)
Does the string represent the numerical value of 0? In case leading or trailing white space is provid...
static std::string abs(const std::string &tok)
static bool isInt(const std::string &str)
unsigned long long biguint
static std::string stripDirectoryPart(const std::string &file)
Get filename without a directory path part.
std::list< Function > functionList
bool hasInlineOrLambdaFunction() const
std::vector< UsingInfo > usingList
std::map< std::string, Type * > definedTypesMap
const Scope * findRecordInNestedList(const std::string &name, bool isC=false) const
std::list< Variable > varlist
const Token * checkVariable(const Token *tok, AccessControl varaccess, const Settings &settings)
check if statement is variable declaration and add it if it is
const Scope * findRecordInBase(const std::string &name) const
std::multimap< std::string, const Function * > functionMap
bool isVariableDeclaration(const Token *const tok, const Token *&vartok, const Token *&typetok) const
helper function for getVariableList()
std::vector< Scope * > nestedList
const Token * addEnum(const Token *tok)
Scope(const SymbolDatabase *check_, const Token *classDef_, const Scope *nestedIn_)
const Function * getDestructor() const
std::vector< Enumerator > enumeratorList
Function * function
function info for this function
const SymbolDatabase * check
void addVariable(const Token *token_, const Token *start_, const Token *end_, AccessControl access_, const Type *type_, const Scope *scope_, const Settings &settings)
const Function * findFunction(const Token *tok, bool requireConst=false) const
find a function
const Type * findType(const std::string &name) const
std::vector< const Token * > bodyStartList
const Token * classDef
class/struct/union/namespace token
void getVariableList(const Settings &settings)
initialize varlist
Scope * findInNestedListRecursive(const std::string &name)
find if name is in nested list
void setBodyStartEnd(const Token *start)
AccessControl defaultAccess() const
const Token * bodyStart
'{' token
const Token * bodyEnd
'}' token
void findFunctionInBase(const std::string &name, nonneg int args, std::vector< const Function * > &matches) const
const Scope * functionOf
scope this function belongs to
const Enumerator * findEnumerator(const std::string &name) const
void addFunction(Function func)
std::vector< const Scope * > findAssociatedScopes() const
bool isClassOrStructOrUnion() const
const Variable * getVariable(const std::string &varname) const
get variable from name
bool isExecutable() const
bool isClassOrStruct() const
This is just a container for general settings so that we don't need to pass individual values to func...
bool debugnormal
Is –debug-normal given?
SimpleEnableGroup< Severity > severity
bool debugwarnings
Is –debug-warnings given?
Standards standards
Struct contains standards settings.
bool isEnabled(T flag) const
void createSymbolDatabaseNeedInitialization()
void debugSymbolDatabase() const
const Scope * findScopeByName(const std::string &name) const
For unit testing only.
void createSymbolDatabaseSetFunctionPointers(bool firstPass)
static bool isReservedName(const Token *tok)
Whether the token is a keyword as defined in http://en.cppreference.com/w/c/keyword and http://en....
const Variable * getVariableFromVarId(nonneg int varId) const
std::vector< const Variable * > mVariableList
variable symbol table
void createSymbolDatabaseFunctionReturnTypes()
void createSymbolDatabaseSetScopePointers()
const std::vector< const Variable * > & variableList() const
SymbolDatabase(Tokenizer &tokenizer, const Settings &settings, ErrorLogger &errorLogger)
const Settings & mSettings
void addNewFunction(Scope *&scope, const Token *&tok)
void createSymbolDatabaseClassAndStructScopes()
void createSymbolDatabaseExprIds()
void validateExecutableScopes() const
const Function * findFunction(const Token *tok) const
find a function
static const Type * findVariableTypeInBase(const Scope *scope, const Token *typeTok)
void createSymbolDatabaseVariableSymbolTable()
void debugMessage(const Token *tok, const std::string &type, const std::string &msg) const
output a debug message
std::list< Type > typeList
Fast access to types.
void createSymbolDatabaseVariableInfo()
void clangSetVariables(const std::vector< const Variable * > &variableList)
void createSymbolDatabaseSetTypePointers()
void createSymbolDatabaseCopyAndMoveConstructors()
std::map< unsigned int, MemberIdMap > VarIdMap
std::list< Type > mBlankTypes
list for missing types
void createSymbolDatabaseFunctionScopes()
const Type * findTypeInNested(const Token *startTok, const Scope *startScope) const
const Scope * findScope(const Token *tok, const Scope *startScope) const
void setValueTypeInTokenList(bool reportDebugWarnings, Token *tokens=nullptr)
Set valuetype in provided tokenlist.
void createSymbolDatabaseSetVariablePointers()
ValueType::Sign mDefaultSignedness
void createSymbolDatabaseFindAllScopes()
const Type * findType(const Token *startTok, const Scope *startScope, bool lookOutside=false) const
void createSymbolDatabaseEscapeFunctions()
void validateVariables() const
Check variable list, e.g.
void printXml(std::ostream &out) const
const Enumerator * findEnumerator(const Token *tok, std::set< std::string > &tokensThatAreNotEnumeratorValues) const
void returnImplicitIntError(const Token *tok) const
void setValueType(Token *tok, const ValueType &valuetype, const SourceLocation &loc=SourceLocation::current())
void setArrayDimensionsUsingValueFlow()
Set array dimensions when valueflow analysis is completed.
void createSymbolDatabaseSetSmartPointerType()
std::vector< const Scope * > functionScopes
Fast access to function scopes.
std::map< unsigned int, unsigned int > MemberIdMap
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
bool isFunction(const Token *tok, const Scope *outerScope, const Token *&funcStart, const Token *&argStart, const Token *&declEnd) const
void createSymbolDatabaseClassInfo()
nonneg int sizeOfType(const Token *type) const
Calculates sizeof value for given type.
void printVariable(const Variable *var, const char *indent) const
void createSymbolDatabaseIncompleteVars()
ErrorLogger & mErrorLogger
Function * addGlobalFunction(Scope *&scope, const Token *&tok, const Token *argStart, const Token *funcStart)
void createSymbolDatabaseEnums()
void addClassFunction(Scope *&scope, const Token *&tok, const Token *argStart)
void fixVarId(VarIdMap &varIds, const Token *vartok, Token *membertok, const Variable *membervar)
static Function * addGlobalFunctionDecl(Scope *&scope, const Token *tok, const Token *argStart, const Token *funcStart)
std::vector< const Scope * > classAndStructScopes
Fast access to class and struct scopes.
static Function * findFunctionInScope(const Token *func, const Scope *ns, const std::string &path, nonneg int path_length)
const Scope * findNamespace(const Token *tok, const Scope *scope) const
void printOut(const char *title=nullptr) const
static bool simplifyNumericCalculations(Token *tok, bool isTemplate=true)
Simplify constant calculations such as "1+2" => "3".
std::string fileLine(const Token *tok) const
Get file:line for a given token.
const Token * back() const
get last token of list
void simplifyPlatformTypes()
Convert platform dependent types to standard types.
const std::string & getSourceFilePath() const
void simplifyStdType()
Collapse compound standard types into a single token.
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
bool createTokens(std::istream &code, const std::string &file0)
Create tokens from code.
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.
nonneg int exprId() const
bool isEnumerator() const
unsigned char bits() const
const std::string & originalName() const
static const Token * findmatch(const Token *const startTok, const char pattern[], const nonneg int varId=0)
bool hasKnownIntValue() const
MathLib::bigint getKnownIntValue() const
bool isSimplifiedTypedef() const
const Token * nextTemplateArgument() const
bool isArithmeticalOp() const
bool isIncompleteVar() const
bool isUpperCaseName() const
nonneg int progressValue() const
Get progressValue (0 - 100)
bool isControlFlowKeyword() const
void setValueType(ValueType *vt)
const ValueType * valueType() const
const std::string & strAt(int index) const
const Enumerator * enumerator() const
void astOperand1(Token *tok)
void function(const Function *f)
Associate this token with given function.
bool isCMultiChar() const
std::string expressionString() const
bool isUnaryOp(const std::string &s) const
bool isOperatorKeyword() const
bool isIncompleteConstant() const
TokenDebug getTokenDebug() const
static const Token * findsimplematch(const Token *const startTok, const char(&pattern)[count])
const Token * tokAt(int index) const
Token::Type tokType() 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
void type(const ::Type *t)
Associate this token with given type.
bool isAssignmentOp() const
bool isSplittedVarDeclEq() const
bool isStandardType() const
void variable(const Variable *v)
Associate this token with given variable.
bool isAttributeMaybeUnused() const
bool isComparisonOp() const
const Token * nextArgument() const
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
void astParent(Token *tok)
The main purpose is to tokenize the source code.
nonneg int sizeOfType(const Token *type) const
Calculates sizeof value for given type.
nonneg int newVarId()
Get new variable id.
const Token * tokens() const
nonneg int varIdCount() const
Get variable count.
TokenList list
Token list: stores all tokens.
bool isC() const
Is the code C.
NORETURN void unmatchedToken(const Token *tok) const
Syntax error.
static const Token * isFunctionHead(const Token *tok, const std::string &endsWith)
is token pointing at function head?
NORETURN void syntaxError(const Token *tok, const std::string &code=emptyString) const
Syntax error.
Information about a class type.
const Function * getFunction(const std::string &funcName) const
bool findDependency(const Type *ancestor) const
Check for dependency.
const Scope * enclosingScope
bool isDerivedFrom(const std::string &ancestor) const
bool isStructType() const
bool hasCircularDependencies(std::set< BaseInfo > *ancestors=nullptr) const
Check for circulare dependencies, i.e.
const Token * classDef
Points to "class" token.
const Token * initBaseInfo(const Token *tok, const Token *tok1)
std::vector< BaseInfo > derivedFrom
std::vector< FriendInfo > friendList
enum Type::NeedInitialization needInitialization
const std::string & type() const
bool fromLibraryType(const std::string &typestr, const Settings &settings)
enum ValueType::Type type
const Library::Container * container
If the type is a container defined in a cfg file, this is the used.
bool isConst(nonneg int indirect=0) const
nonneg int constness
bit 0=data, bit 1=*, bit 2=**
static Type typeFromString(const std::string &typestr, bool longType)
nonneg int bits
bitfield bitcount
bool isTypeEqual(const ValueType *that) const
Check if type is the same ignoring const and references.
MathLib::bigint typeSize(const Platform &platform, bool p=false) const
Reference reference
Is the outermost indirection of this type a reference or rvalue.
const Library::SmartPointer * smartPointer
Smart pointer.
nonneg int pointer
0=>not pointer, 1=>*, 2=>**, 3=>***, etc
const Token * smartPointerTypeToken
Smart pointer type token.
static MatchResult matchParameter(const ValueType *call, const ValueType *func)
nonneg int volatileness
bit 0=data, bit 1=*, bit 2=**
std::string originalTypeName
original type name as written in the source code.
const Token * containerTypeToken
The container type token.
const Scope * typeScope
if the type definition is seen this point out the type scope
static ValueType parseDecl(const Token *type, const Settings &settings)
enum ValueType::Sign sign
bool isVolatile(nonneg int indirect=0) const
ErrorPath debugPath
debug path to the type
const ::Type * smartPointerType
Smart pointer type.
void setDebugPath(const Token *tok, SourceLocation ctx, const SourceLocation &local=SourceLocation::current())
Information about a member variable.
@ fIsPointer
array variable
@ fIsReference
pointer variable
@ fIsInit
marked [[maybe_unused]]
@ fIsSmartPointer
volatile
@ fIsClass
extern variable
@ fIsExtern
const variable
@ fIsStlString
STL type ('std::')
@ fIsStlType
function argument with default value
@ fIsRValueRef
reference variable
@ fIsMaybeUnused
std::shared_ptr|unique_ptr
@ fIsVolatile
Floating point type.
@ fIsArray
user defined type
@ fIsFloatType
std::string|wstring|basic_string<T>|u16string|u32string
@ fIsStatic
mutable variable
@ fIsConst
static variable
@ fHasDefault
rvalue reference variable
bool hasDefault() const
Does variable have a default value.
bool isArgument() const
Is variable a function argument.
bool arrayDimensions(const Settings &settings, bool &isContainer)
parse and save array dimension information
const Token * mTypeStartToken
variable type start token
bool isEnumType() const
Determine whether it's an enumeration type.
Variable(const Token *name_, const Token *start_, const Token *end_, nonneg int index_, AccessControl access_, const Type *type_, const Scope *scope_, const Settings &settings)
bool isClass() const
Is variable a user defined (or unknown) type.
Variable & operator=(const Variable &var)
const Type * mType
pointer to user defined type info (for known types)
bool isArrayOrPointer() const
Is array or pointer variable.
bool isExtern() const
Is variable extern.
const Token * mNameToken
variable name token
const Type * smartPointerType() const
const Type * iteratorType() const
bool isReference() const
Is reference variable.
bool isStlStringViewType() const
nonneg int mIndex
order declared
std::string getTypeName() const
bool isRValueReference() const
Is reference variable.
AccessControl accessControl() const
bool isStlType() const
Checks if the variable is an STL type ('std::') E.g.
bool isLocal() const
Is variable local.
bool isSmartPointer() const
const Token * declEndToken() const
Get end token of variable declaration E.g.
const Type * type() const
Get Type pointer of known type.
const Scope * scope() const
Get Scope pointer of enclosing scope.
void setFlag(unsigned int flag_, bool state_)
Set specified flag state.
bool getFlag(unsigned int flag_) const
Get specified flag state.
const Scope * typeScope() const
Get Scope pointer of known type.
const Token * typeEndToken() const
Get type end token.
bool isConst() const
Is variable const.
bool isPointerArray() const
Is variable an array of pointers.
MathLib::bigint dimension(nonneg int index_) const
Get array dimension length.
bool isMember() const
Is variable a member of a user-defined type.
bool isArray() const
Is variable an array.
const Token * nameToken() const
Get name token.
AccessControl mAccess
what section is this variable declared in?
nonneg int index() const
Get index of variable in declared order.
const Scope * mScope
pointer to scope this variable is in
bool isUnsigned() const
Is variable unsigned.
nonneg int declarationId() const
Get declaration ID (varId used for variable in its declaration).
bool isMutable() const
Is variable mutable.
std::vector< Dimension > mDimensions
array dimensions
const Token * typeStartToken() const
Get type start token.
void evaluate(const Settings &settings)
fill in information, depending on Tokens given at instantiation
bool isVolatile() const
Is variable volatile.
const std::vector< Dimension > & dimensions() const
Get array dimensions.
bool isPointer() const
Is pointer variable.
bool isStlStringType() const
Checks if the variable is an STL type ('std::') E.g.
void setValueType(const ValueType &valueType)
const Token * mTypeEndToken
variable type end token
bool isStatic() const
Is variable static.
const ValueType * valueType() const
const ValueType * mValueType
#define REQUIRES(msg,...)
static const std::string emptyString
std::list< ErrorPathItem > ErrorPath
@ portability
Portability warning.
const Value * valueFlowConstantFoldAST(Token *expr, const Settings &settings)
Constant folding of expression. This can be used before the full ValueFlow has been executed (ValueFl...
Array dimension information.
const Token * tok
size token
MathLib::bigint num
(assumed) dimension length when size is a number, 0 if not known
Simple container to be thrown when internal error is detected.
enum Library::PodType::Type stdtype
bool classes
Public interface of classes.
bool externalFunctions
External functions.
bool internalFunctions
Experimental: assume that internal functions can be used in any way This is only available in the GUI...
static SourceLocation current()
const char * function_name() const
const char * file_name() const
std::uint_least32_t line() const
enum Standards::cppstd_t cpp
static const Scope * getClassScope(const Token *tok)
static bool isUnknownType(const Token *start, const Token *end)
T * findTypeImpl(S &thisScope, const std::string &name)
static bool isContainerYieldPointer(Library::Container::Yield yield)
static const char * functionTypeToString(Function::Type type)
static bool usingNamespace(const Scope *scope, const Token *first, const Token *second, int &offset)
static bool isContainerYieldElement(Library::Container::Yield yield)
static const Token * skipScopeIdentifiers(const Token *tok)
static const Scope * findEnumScopeInBase(const Scope *scope, const std::string &tokStr)
static std::string getIncompleteNameID(const Token *tok)
S * findRecordInNestedListImpl(S &thisScope, const std::string &name, bool isC)
static bool typesMatch(const Scope *first_scope, const Token *first_token, const Scope *second_scope, const Token *second_token, const Token *&new_first, const Token *&new_second)
static void checkVariableCallMatch(const Variable *callarg, const Variable *funcarg, size_t &same, size_t &fallback1, size_t &fallback2)
static const Token * parsedecl(const Token *type, ValueType *const valuetype, ValueType::Sign defaultSignedness, const Settings &settings, SourceLocation loc=SourceLocation::current())
static bool isExpression(const Token *tok)
static const Token * skipPointers(const Token *tok)
static std::string getTypeString(const Token *typeToken)
static std::string tokenType(const Token *tok)
static bool isExecutableScope(const Token *tok)
static std::string qualifiedName(const Scope *scope)
static void setAutoTokenProperties(Token *const autoTok)
static std::ostream & operator<<(std::ostream &s, Scope::ScopeType type)
static bool isEnumDefinition(const Token *tok)
static const Function * getOperatorFunction(const Token *const tok)
static const Function * getFunction(const Token *tok)
static const Token * skipPointersAndQualifiers(const Token *tok)
static const Token * getEnableIfReturnType(const Token *start)
static bool isDerivedFromItself(const std::string &thisName, const std::string &baseName)
static bool hasMatchingConstructor(const Scope *classScope, const ValueType *argType)
static bool checkReturns(const Function *function, bool unknown, bool emptyEnableIf, Predicate pred)
static bool isOperator(const Token *tokenDef)
static std::string accessControlToString(AccessControl access)
static std::string scopeToString(const Scope *scope, const Tokenizer &tokenizer)
static std::string scopeTypeToString(Scope::ScopeType type)
static ValueType::Type getEnumType(const Scope *scope, const Platform &platform)
static bool hasEmptyCaptureList(const Token *tok)
static const Type * findVariableTypeIncludingUsedNamespaces(const SymbolDatabase *symbolDatabase, const Scope *scope, const Token *typeTok)
static std::string tokenToString(const Token *tok, const Tokenizer &tokenizer)
AccessControl
Access control enumerations.
static void indent(std::string &str, const nonneg int indent1, const nonneg int indent2)
const Token * findLambdaEndTokenWithoutAST(const Token *tok)
const Token * isLambdaCaptureList(const Token *tok)
static std::string id_string(const void *p)
bool startsWith(const std::string &str, const char start[], std::size_t startlen)
bool endsWith(const std::string &str, char c)
static const char * bool_to_string(bool b)
bool contains(const Range &r, const T &x)