| 1711 | } |
| 1712 | |
| 1713 | void SymbolDatabase::createSymbolDatabaseExprIds() |
| 1714 | { |
| 1715 | // Find highest varId |
| 1716 | nonneg int maximumVarId = 0; |
| 1717 | for (const Token* tok = mTokenizer.list.front(); tok; tok = tok->next()) { |
| 1718 | maximumVarId = std::max(tok->varId(), maximumVarId); |
| 1719 | } |
| 1720 | nonneg int id = maximumVarId + 1; |
| 1721 | // Find incomplete vars that are used in constant context |
| 1722 | std::unordered_map<std::string, nonneg int> unknownConstantIds; |
| 1723 | const Token* inConstExpr = nullptr; |
| 1724 | for (const Token* tok = mTokenizer.list.front(); tok != mTokenizer.list.back(); tok = tok->next()) { |
| 1725 | if (Token::Match(tok, "decltype|sizeof|typeof (") && tok->linkAt(1)) { |
| 1726 | tok = tok->linkAt(1)->previous(); |
| 1727 | } else if (tok == inConstExpr) { |
| 1728 | inConstExpr = nullptr; |
| 1729 | } else if (inConstExpr) { |
| 1730 | if (!tok->isIncompleteVar()) |
| 1731 | continue; |
| 1732 | if (!isExpression(tok->astParent())) |
| 1733 | continue; |
| 1734 | const std::string& name = getIncompleteNameID(tok); |
| 1735 | if (unknownConstantIds.count(name) > 0) |
| 1736 | continue; |
| 1737 | unknownConstantIds[name] = id++; |
| 1738 | } else if (tok->link() && tok->str() == "<") { |
| 1739 | inConstExpr = tok->link(); |
| 1740 | } else if (Token::Match(tok, "%var% [") && tok->variable() && tok->variable()->nameToken() == tok) { |
| 1741 | inConstExpr = tok->linkAt(1); |
| 1742 | } |
| 1743 | } |
| 1744 | |
| 1745 | auto exprScopes = functionScopes; // functions + global lambdas + namespaces |
| 1746 | std::copy_if(scopeList.front().nestedList.begin(), scopeList.front().nestedList.end(), std::back_inserter(exprScopes), [](const Scope* scope) { |
| 1747 | return scope && (scope->type == ScopeType::eLambda || scope->type == ScopeType::eNamespace); |
| 1748 | }); |
| 1749 | |
| 1750 | for (const Scope * scope : exprScopes) { |
| 1751 | std::unordered_map<std::string, nonneg int> unknownIds; |
| 1752 | // Assign IDs to incomplete vars which are part of an expression |
| 1753 | // Such variables should be assumed global |
| 1754 | for (auto* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { |
| 1755 | if (!tok->isIncompleteVar()) |
| 1756 | continue; |
| 1757 | if (!isExpression(tok->astParent())) |
| 1758 | continue; |
| 1759 | const std::string& name = getIncompleteNameID(tok); |
| 1760 | nonneg int sid = 0; |
| 1761 | if (unknownConstantIds.count(name) > 0) { |
| 1762 | sid = unknownConstantIds.at(name); |
| 1763 | tok->isIncompleteConstant(true); |
| 1764 | } else if (unknownIds.count(name) == 0) { |
| 1765 | sid = id++; |
| 1766 | unknownIds[name] = sid; |
| 1767 | } else { |
| 1768 | sid = unknownIds.at(name); |
| 1769 | } |
| 1770 | assert(sid > 0); |
no test coverage detected