Improvement: Set varId for variables with global scope operator :: Refactorization: Moved internal class from tokenize.h to tokenize.cpp (#4184)
Merged from LCppC.
This commit is contained in:
parent
c9b85010f9
commit
99ce89c003
197
lib/tokenize.cpp
197
lib/tokenize.cpp
|
@ -3424,14 +3424,85 @@ void Tokenizer::simplifyTemplates()
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::string,int> &variableId, bool executableScope, bool cpp, bool c)
|
||||
/** Class used in Tokenizer::setVarIdPass1 */
|
||||
class VariableMap {
|
||||
private:
|
||||
std::map<std::string, nonneg int> mVariableId;
|
||||
std::map<std::string, nonneg int> mVariableId_global;
|
||||
std::stack<std::vector<std::pair<std::string, nonneg int>>> mScopeInfo;
|
||||
mutable nonneg int mVarId;
|
||||
public:
|
||||
VariableMap() : mVarId(0) {}
|
||||
void enterScope();
|
||||
bool leaveScope();
|
||||
void addVariable(const std::string& varname, bool globalNamespace);
|
||||
bool hasVariable(const std::string& varname) const {
|
||||
return mVariableId.find(varname) != mVariableId.end();
|
||||
}
|
||||
std::map<std::string, nonneg int>::const_iterator find(const std::string& varname, bool global) const {
|
||||
return map(global).find(varname);
|
||||
}
|
||||
std::map<std::string, nonneg int>::const_iterator end() const {
|
||||
return mVariableId.end();
|
||||
}
|
||||
const std::map<std::string, nonneg int>& map(bool global) const {
|
||||
return global ? mVariableId_global : mVariableId;
|
||||
}
|
||||
nonneg int* getVarId() const {
|
||||
return &mVarId;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void VariableMap::enterScope()
|
||||
{
|
||||
mScopeInfo.push(std::vector<std::pair<std::string, nonneg int>>());
|
||||
}
|
||||
|
||||
bool VariableMap::leaveScope()
|
||||
{
|
||||
if (mScopeInfo.empty())
|
||||
return false;
|
||||
|
||||
for (const std::pair<std::string, nonneg int>& outerVariable : mScopeInfo.top()) {
|
||||
if (outerVariable.second != 0)
|
||||
mVariableId[outerVariable.first] = outerVariable.second;
|
||||
else
|
||||
mVariableId.erase(outerVariable.first);
|
||||
}
|
||||
mScopeInfo.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
void VariableMap::addVariable(const std::string& varname, bool globalNamespace)
|
||||
{
|
||||
if (mScopeInfo.empty()) {
|
||||
mVariableId[varname] = ++mVarId;
|
||||
if (globalNamespace)
|
||||
mVariableId_global[varname] = mVariableId[varname];
|
||||
return;
|
||||
}
|
||||
std::map<std::string, nonneg int>::iterator it = mVariableId.find(varname);
|
||||
if (it == mVariableId.end()) {
|
||||
mScopeInfo.top().push_back(std::pair<std::string, nonneg int>(varname, 0));
|
||||
mVariableId[varname] = ++mVarId;
|
||||
if (globalNamespace)
|
||||
mVariableId_global[varname] = mVariableId[varname];
|
||||
return;
|
||||
}
|
||||
mScopeInfo.top().push_back(std::pair<std::string, nonneg int>(varname, it->second));
|
||||
it->second = ++mVarId;
|
||||
}
|
||||
|
||||
|
||||
static bool setVarIdParseDeclaration(const Token **tok, const VariableMap& variableMap, bool executableScope, bool cpp, bool c)
|
||||
{
|
||||
const Token *tok2 = *tok;
|
||||
if (!tok2->isName())
|
||||
return false;
|
||||
|
||||
int typeCount = 0;
|
||||
int singleNameCount = 0;
|
||||
nonneg int typeCount = 0;
|
||||
nonneg int singleNameCount = 0;
|
||||
bool hasstruct = false; // Is there a "struct" or "class"?
|
||||
bool bracket = false;
|
||||
bool ref = false;
|
||||
|
@ -3450,7 +3521,7 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
|
|||
singleNameCount = 0;
|
||||
} else if (Token::Match(tok2, "const|extern")) {
|
||||
// just skip "const", "extern"
|
||||
} else if (!hasstruct && variableId.find(tok2->str()) != variableId.end() && tok2->previous()->str() != "::") {
|
||||
} else if (!hasstruct && variableMap.find(tok2->str(), false) != variableMap.end() && tok2->previous()->str() != "::") {
|
||||
++typeCount;
|
||||
tok2 = tok2->next();
|
||||
if (!tok2 || tok2->str() != "::")
|
||||
|
@ -3554,17 +3625,17 @@ static bool setVarIdParseDeclaration(const Token **tok, const std::map<std::stri
|
|||
|
||||
|
||||
void Tokenizer::setVarIdStructMembers(Token **tok1,
|
||||
std::map<int, std::map<std::string, int>>& structMembers,
|
||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||
nonneg int *varId) const
|
||||
{
|
||||
Token *tok = *tok1;
|
||||
|
||||
if (Token::Match(tok, "%name% = { . %name% =|{")) {
|
||||
const int struct_varid = tok->varId();
|
||||
const nonneg int struct_varid = tok->varId();
|
||||
if (struct_varid == 0)
|
||||
return;
|
||||
|
||||
std::map<std::string, int>& members = structMembers[struct_varid];
|
||||
std::map<std::string, nonneg int>& members = structMembers[struct_varid];
|
||||
|
||||
tok = tok->tokAt(3);
|
||||
while (tok->str() != "}") {
|
||||
|
@ -3572,7 +3643,7 @@ void Tokenizer::setVarIdStructMembers(Token **tok1,
|
|||
tok = tok->link();
|
||||
if (Token::Match(tok->previous(), "[,{] . %name% =|{")) {
|
||||
tok = tok->next();
|
||||
const std::map<std::string, int>::iterator it = members.find(tok->str());
|
||||
const std::map<std::string, nonneg int>::iterator it = members.find(tok->str());
|
||||
if (it == members.end()) {
|
||||
members[tok->str()] = ++(*varId);
|
||||
tok->varId(*varId);
|
||||
|
@ -3593,7 +3664,7 @@ void Tokenizer::setVarIdStructMembers(Token **tok1,
|
|||
tok = tok->tokAt(3);
|
||||
continue;
|
||||
}
|
||||
const int struct_varid = tok->varId();
|
||||
const nonneg int struct_varid = tok->varId();
|
||||
tok = tok->tokAt(2);
|
||||
if (struct_varid == 0)
|
||||
continue;
|
||||
|
@ -3605,8 +3676,8 @@ void Tokenizer::setVarIdStructMembers(Token **tok1,
|
|||
if (TemplateSimplifier::templateParameters(tok->next()) > 0)
|
||||
break;
|
||||
|
||||
std::map<std::string, int>& members = structMembers[struct_varid];
|
||||
const std::map<std::string, int>::iterator it = members.find(tok->str());
|
||||
std::map<std::string, nonneg int>& members = structMembers[struct_varid];
|
||||
const std::map<std::string, nonneg int>::iterator it = members.find(tok->str());
|
||||
if (it == members.end()) {
|
||||
members[tok->str()] = ++(*varId);
|
||||
tok->varId(*varId);
|
||||
|
@ -3622,7 +3693,7 @@ void Tokenizer::setVarIdStructMembers(Token **tok1,
|
|||
void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
||||
const VariableMap &variableMap,
|
||||
const nonneg int scopeStartVarId,
|
||||
std::map<int, std::map<std::string,int>>& structMembers)
|
||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers)
|
||||
{
|
||||
// end of scope
|
||||
const Token * const endToken = startToken->link();
|
||||
|
@ -3663,7 +3734,7 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
|||
--indentlevel;
|
||||
inEnum = false;
|
||||
} else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %name% [({]")) {
|
||||
const std::map<std::string, int>::const_iterator it = variableMap.find(tok->str());
|
||||
const std::map<std::string, nonneg int>::const_iterator it = variableMap.find(tok->str(), false);
|
||||
if (it != variableMap.end()) {
|
||||
tok->varId(it->second);
|
||||
}
|
||||
|
@ -3681,7 +3752,7 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
|||
}
|
||||
|
||||
if (!inEnum) {
|
||||
const std::map<std::string, int>::const_iterator it = variableMap.find(tok->str());
|
||||
const std::map<std::string, nonneg int>::const_iterator it = variableMap.find(tok->str(), false);
|
||||
if (it != variableMap.end()) {
|
||||
tok->varId(it->second);
|
||||
setVarIdStructMembers(&tok, structMembers, variableMap.getVarId());
|
||||
|
@ -3700,8 +3771,8 @@ void Tokenizer::setVarIdClassDeclaration(const Token * const startToken,
|
|||
void Tokenizer::setVarIdClassFunction(const std::string &classname,
|
||||
Token * const startToken,
|
||||
const Token * const endToken,
|
||||
const std::map<std::string, int> &varlist,
|
||||
std::map<int, std::map<std::string, int>>& structMembers,
|
||||
const std::map<std::string, nonneg int> &varlist,
|
||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||
nonneg int *varId_)
|
||||
{
|
||||
for (Token *tok2 = startToken; tok2 && tok2 != endToken; tok2 = tok2->next()) {
|
||||
|
@ -3716,7 +3787,7 @@ void Tokenizer::setVarIdClassFunction(const std::string &classname,
|
|||
if (Token::Match(tok2, "%name% ::"))
|
||||
continue;
|
||||
|
||||
const std::map<std::string,int>::const_iterator it = varlist.find(tok2->str());
|
||||
const std::map<std::string, nonneg int>::const_iterator it = varlist.find(tok2->str());
|
||||
if (it != varlist.end()) {
|
||||
tok2->varId(it->second);
|
||||
setVarIdStructMembers(&tok2, structMembers, varId_);
|
||||
|
@ -3755,7 +3826,7 @@ void Tokenizer::setVarIdPass1()
|
|||
const std::unordered_set<std::string>& notstart = (isC()) ? notstart_c : notstart_cpp;
|
||||
|
||||
VariableMap variableMap;
|
||||
std::map<int, std::map<std::string, int>> structMembers;
|
||||
std::map<nonneg int, std::map<std::string, nonneg int>> structMembers;
|
||||
|
||||
std::stack<VarIdScopeInfo> scopeStack;
|
||||
|
||||
|
@ -3817,8 +3888,8 @@ void Tokenizer::setVarIdPass1()
|
|||
|
||||
const Token * const startToken = (tok->str() == "{") ? tok : tok->link();
|
||||
|
||||
// parse anonymous unions as part of the current scope
|
||||
if (!Token::Match(startToken->previous(), "union|struct|enum {") &&
|
||||
// parse anonymous namespaces as part of the current scope
|
||||
if (!Token::Match(startToken->previous(), "union|struct|enum|namespace {") &&
|
||||
!(initlist && Token::Match(startToken->previous(), "%name%|>|>>") && Token::Match(startToken->link(), "} ,|{"))) {
|
||||
|
||||
if (tok->str() == "{") {
|
||||
|
@ -3918,7 +3989,7 @@ void Tokenizer::setVarIdPass1()
|
|||
Token::simpleMatch(tok2->link(), "] =")) {
|
||||
while (tok2 && tok2->str() != "]") {
|
||||
if (Token::Match(tok2, "%name% [,]]"))
|
||||
variableMap.addVariable(tok2->str());
|
||||
variableMap.addVariable(tok2->str(), false);
|
||||
tok2 = tok2->next();
|
||||
}
|
||||
continue;
|
||||
|
@ -3926,7 +3997,7 @@ void Tokenizer::setVarIdPass1()
|
|||
}
|
||||
|
||||
try { /* Ticket #8151 */
|
||||
decl = setVarIdParseDeclaration(&tok2, variableMap.map(), scopeStack.top().isExecutable, isCPP(), isC());
|
||||
decl = setVarIdParseDeclaration(&tok2, variableMap, scopeStack.top().isExecutable, isCPP(), isC());
|
||||
} catch (const Token * errTok) {
|
||||
syntaxError(errTok);
|
||||
}
|
||||
|
@ -3935,7 +4006,7 @@ void Tokenizer::setVarIdPass1()
|
|||
if (Token *declTypeTok = Token::findsimplematch(tok, "decltype (", tok2)) {
|
||||
for (Token *declTok = declTypeTok->linkAt(1); declTok != declTypeTok; declTok = declTok->previous()) {
|
||||
if (declTok->isName() && !Token::Match(declTok->previous(), "::|.") && variableMap.hasVariable(declTok->str()))
|
||||
declTok->varId(variableMap.find(declTok->str())->second);
|
||||
declTok->varId(variableMap.find(declTok->str(), false)->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3994,14 +4065,14 @@ void Tokenizer::setVarIdPass1()
|
|||
decl = false;
|
||||
|
||||
if (decl) {
|
||||
variableMap.addVariable(prev2->str());
|
||||
variableMap.addVariable(prev2->str(), scopeStack.size() <= 1);
|
||||
|
||||
if (Token::simpleMatch(tok->previous(), "for (") && Token::Match(prev2, "%name% [=,]")) {
|
||||
for (const Token *tok3 = prev2->next(); tok3 && tok3->str() != ";"; tok3 = tok3->next()) {
|
||||
if (Token::Match(tok3, "[([]"))
|
||||
tok3 = tok3->link();
|
||||
if (Token::Match(tok3, ", %name% [,=;]"))
|
||||
variableMap.addVariable(tok3->next()->str());
|
||||
variableMap.addVariable(tok3->next()->str(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4014,7 +4085,7 @@ void Tokenizer::setVarIdPass1()
|
|||
while (tok != end) {
|
||||
if (tok->isName() && !(Token::simpleMatch(tok->next(), "<") &&
|
||||
Token::Match(tok->tokAt(-1), ":: %name%"))) {
|
||||
const std::map<std::string, int>::const_iterator it = variableMap.find(tok->str());
|
||||
const std::map<std::string, nonneg int>::const_iterator it = variableMap.find(tok->str(), false);
|
||||
if (it != variableMap.end())
|
||||
tok->varId(it->second);
|
||||
}
|
||||
|
@ -4032,9 +4103,14 @@ void Tokenizer::setVarIdPass1()
|
|||
if (Token::Match(tok->previous(), "struct|enum|union") || (isCPP() && tok->strAt(-1) == "class"))
|
||||
continue;
|
||||
|
||||
bool globalNamespace = false;
|
||||
if (!isC()) {
|
||||
if (tok->previous() && tok->previous()->str() == "::")
|
||||
if (tok->previous() && tok->previous()->str() == "::") {
|
||||
if (Token::Match(tok->tokAt(-2), ")|]|%name%"))
|
||||
continue;
|
||||
else
|
||||
globalNamespace = true;
|
||||
}
|
||||
if (tok->next() && tok->next()->str() == "::")
|
||||
continue;
|
||||
if (Token::simpleMatch(tok->tokAt(-2), ":: template"))
|
||||
|
@ -4074,13 +4150,13 @@ void Tokenizer::setVarIdPass1()
|
|||
}
|
||||
|
||||
if (!scopeStack.top().isEnum || !(Token::Match(tok->previous(), "{|,") && Token::Match(tok->next(), ",|=|}"))) {
|
||||
const std::map<std::string, int>::const_iterator it = variableMap.find(tok->str());
|
||||
if (it != variableMap.end()) {
|
||||
const std::map<std::string, nonneg int>::const_iterator it = variableMap.find(tok->str(), globalNamespace);
|
||||
if (it != variableMap.map(globalNamespace).end()) {
|
||||
tok->varId(it->second);
|
||||
setVarIdStructMembers(&tok, structMembers, variableMap.getVarId());
|
||||
}
|
||||
}
|
||||
} else if (Token::Match(tok, "::|. %name%")) {
|
||||
} else if (Token::Match(tok, "::|. %name%") && Token::Match(tok->previous(), ")|]|>|%name%")) {
|
||||
// Don't set varid after a :: or . token
|
||||
tok = tok->next();
|
||||
} else if (tok->str() == ":" && Token::Match(tok->tokAt(-2), "class %type%")) {
|
||||
|
@ -4193,7 +4269,7 @@ static Token * matchMemberFunctionName(const Member &func, const std::list<Scope
|
|||
|
||||
void Tokenizer::setVarIdPass2()
|
||||
{
|
||||
std::map<int, std::map<std::string, int>> structMembers;
|
||||
std::map<nonneg int, std::map<std::string, nonneg int>> structMembers;
|
||||
|
||||
// Member functions and variables in this source
|
||||
std::list<Member> allMemberFunctions;
|
||||
|
@ -4225,15 +4301,18 @@ void Tokenizer::setVarIdPass2()
|
|||
}
|
||||
|
||||
Token* const tok1 = tok;
|
||||
if (Token::Match(tok->previous(), "!!:: %name% :: ~| %name%"))
|
||||
if (Token::Match(tok, "%name% :: ~| %name%"))
|
||||
tok = tok->next();
|
||||
else if (Token::Match(tok->previous(), "!!:: %name% <") && Token::Match(tok->next()->findClosingBracket(),"> :: ~| %name%"))
|
||||
else if (Token::Match(tok, "%name% <") && Token::Match(tok->next()->findClosingBracket(),"> :: ~| %name%"))
|
||||
tok = tok->next()->findClosingBracket()->next();
|
||||
else if (usingnamespaces.empty() || tok->varId() || !tok->isName() || tok->isStandardType() || tok->tokType() == Token::eKeyword || tok->tokType() == Token::eBoolean ||
|
||||
Token::Match(tok->previous(), ".|namespace|class|struct|&|&&|*|> %name%") || Token::Match(tok->previous(), "%type%| %name% ( %type%|)") || Token::Match(tok, "public:|private:|protected:") ||
|
||||
(!tok->next() && Token::Match(tok->previous(), "}|; %name%")))
|
||||
continue;
|
||||
|
||||
if (tok->strAt(-1) == "::" && tok->tokAt(-2) && tok->tokAt(-2)->isName())
|
||||
continue;
|
||||
|
||||
while (Token::Match(tok, ":: ~| %name%")) {
|
||||
tok = tok->next();
|
||||
if (tok->str() == "~")
|
||||
|
@ -4257,7 +4336,7 @@ void Tokenizer::setVarIdPass2()
|
|||
std::list<ScopeInfo2> scopeInfo;
|
||||
|
||||
// class members..
|
||||
std::map<std::string, std::map<std::string, int>> varsByClass;
|
||||
std::map<std::string, std::map<std::string, nonneg int>> varsByClass;
|
||||
for (Token *tok = list.front(); tok; tok = tok->next()) {
|
||||
while (tok->str() == "}" && !scopeInfo.empty() && tok == scopeInfo.back().bodyEnd)
|
||||
scopeInfo.pop_back();
|
||||
|
@ -4288,7 +4367,7 @@ void Tokenizer::setVarIdPass2()
|
|||
for (const Token *it : classnameTokens)
|
||||
classname += (classname.empty() ? "" : " :: ") + it->str();
|
||||
|
||||
std::map<std::string, int> &thisClassVars = varsByClass[scopeName2 + classname];
|
||||
std::map<std::string, nonneg int> &thisClassVars = varsByClass[scopeName2 + classname];
|
||||
while (Token::Match(tokStart, ":|::|,|%name%")) {
|
||||
if (Token::Match(tokStart, "%name% <")) {
|
||||
tokStart = tokStart->next()->findClosingBracket();
|
||||
|
@ -4314,7 +4393,7 @@ void Tokenizer::setVarIdPass2()
|
|||
break;
|
||||
scopeName3.erase(pos + 4);
|
||||
}
|
||||
const std::map<std::string, int>& baseClassVars = varsByClass[baseClassName];
|
||||
const std::map<std::string, nonneg int>& baseClassVars = varsByClass[baseClassName];
|
||||
thisClassVars.insert(baseClassVars.begin(), baseClassVars.end());
|
||||
}
|
||||
tokStart = tokStart->next();
|
||||
|
@ -4406,7 +4485,7 @@ void Tokenizer::setVarIdPass2()
|
|||
break;
|
||||
|
||||
// set varid
|
||||
const std::map<std::string, int>::const_iterator varpos = thisClassVars.find(tok3->str());
|
||||
const std::map<std::string, nonneg int>::const_iterator varpos = thisClassVars.find(tok3->str());
|
||||
if (varpos != thisClassVars.end())
|
||||
tok3->varId(varpos->second);
|
||||
|
||||
|
@ -12415,50 +12494,6 @@ void Tokenizer::simplifyNamespaceAliases()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Tokenizer::VariableMap::VariableMap() : mVarId(0) {}
|
||||
|
||||
void Tokenizer::VariableMap::enterScope()
|
||||
{
|
||||
mScopeInfo.push(std::list<std::pair<std::string, int>>());
|
||||
}
|
||||
|
||||
bool Tokenizer::VariableMap::leaveScope()
|
||||
{
|
||||
if (mScopeInfo.empty())
|
||||
return false;
|
||||
|
||||
for (const std::pair<std::string, int> &outerVariable : mScopeInfo.top()) {
|
||||
if (outerVariable.second != 0)
|
||||
mVariableId[outerVariable.first] = outerVariable.second;
|
||||
else
|
||||
mVariableId.erase(outerVariable.first);
|
||||
}
|
||||
mScopeInfo.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Tokenizer::VariableMap::addVariable(const std::string &varname)
|
||||
{
|
||||
if (mScopeInfo.empty()) {
|
||||
mVariableId[varname] = ++mVarId;
|
||||
return;
|
||||
}
|
||||
std::map<std::string, int>::iterator it = mVariableId.find(varname);
|
||||
if (it == mVariableId.end()) {
|
||||
mScopeInfo.top().push_back(std::pair<std::string, int>(varname, 0));
|
||||
mVariableId[varname] = ++mVarId;
|
||||
return;
|
||||
}
|
||||
mScopeInfo.top().push_back(std::pair<std::string, int>(varname, it->second));
|
||||
it->second = ++mVarId;
|
||||
}
|
||||
|
||||
bool Tokenizer::VariableMap::hasVariable(const std::string &varname) const
|
||||
{
|
||||
return mVariableId.find(varname) != mVariableId.end();
|
||||
}
|
||||
|
||||
bool Tokenizer::hasIfdef(const Token *start, const Token *end) const
|
||||
{
|
||||
if (!mPreprocessor)
|
||||
|
|
|
@ -40,6 +40,7 @@ class Token;
|
|||
class TemplateSimplifier;
|
||||
class ErrorLogger;
|
||||
class Preprocessor;
|
||||
class VariableMap;
|
||||
|
||||
namespace simplecpp {
|
||||
class TokenList;
|
||||
|
@ -59,33 +60,6 @@ class CPPCHECKLIB Tokenizer {
|
|||
friend class TestSimplifyTemplate;
|
||||
friend class TemplateSimplifier;
|
||||
|
||||
/** Class used in Tokenizer::setVarIdPass1 */
|
||||
class VariableMap {
|
||||
private:
|
||||
std::map<std::string, int> mVariableId;
|
||||
std::stack<std::list<std::pair<std::string,int>>> mScopeInfo;
|
||||
mutable nonneg int mVarId;
|
||||
public:
|
||||
VariableMap();
|
||||
void enterScope();
|
||||
bool leaveScope();
|
||||
void addVariable(const std::string &varname);
|
||||
bool hasVariable(const std::string &varname) const;
|
||||
std::map<std::string,int>::const_iterator find(const std::string &varname) const {
|
||||
return mVariableId.find(varname);
|
||||
}
|
||||
std::map<std::string,int>::const_iterator end() const {
|
||||
return mVariableId.end();
|
||||
}
|
||||
const std::map<std::string,int> &map() const {
|
||||
return mVariableId;
|
||||
}
|
||||
nonneg int *getVarId() const {
|
||||
return &mVarId;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
Tokenizer();
|
||||
Tokenizer(const Settings * settings, ErrorLogger *errorLogger);
|
||||
|
@ -798,17 +772,17 @@ private:
|
|||
void setVarIdClassDeclaration(const Token * const startToken,
|
||||
const VariableMap &variableMap,
|
||||
const nonneg int scopeStartVarId,
|
||||
std::map<int, std::map<std::string,int>>& structMembers);
|
||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers);
|
||||
|
||||
void setVarIdStructMembers(Token **tok1,
|
||||
std::map<int, std::map<std::string, int>>& structMembers,
|
||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||
nonneg int *varId) const;
|
||||
|
||||
void setVarIdClassFunction(const std::string &classname,
|
||||
Token * const startToken,
|
||||
const Token * const endToken,
|
||||
const std::map<std::string,int> &varlist,
|
||||
std::map<int, std::map<std::string,int>>& structMembers,
|
||||
const std::map<std::string, nonneg int> &varlist,
|
||||
std::map<nonneg int, std::map<std::string, nonneg int>>& structMembers,
|
||||
nonneg int *varId_);
|
||||
|
||||
/**
|
||||
|
|
|
@ -743,7 +743,7 @@ static void setTokenValue(Token* tok, ValueFlow::Value value, const Settings* se
|
|||
if (parent->isUnaryOp("&")) {
|
||||
pvalue.indirect++;
|
||||
setTokenValue(parent, pvalue, settings);
|
||||
} else if (Token::Match(parent, ". %var%") && parent->astOperand1() == tok) {
|
||||
} else if (Token::Match(parent, ". %var%") && parent->astOperand1() == tok && parent->astOperand2()) {
|
||||
if (parent->originalName() == "->" && pvalue.indirect > 0)
|
||||
pvalue.indirect--;
|
||||
setTokenValue(parent->astOperand2(), pvalue, settings);
|
||||
|
|
|
@ -178,6 +178,7 @@ private:
|
|||
TEST_CASE(varid_for_auto_cpp17);
|
||||
TEST_CASE(varid_not); // #9689 'not x'
|
||||
TEST_CASE(varid_declInIfCondition);
|
||||
TEST_CASE(varid_globalScope);
|
||||
|
||||
TEST_CASE(varidclass1);
|
||||
TEST_CASE(varidclass2);
|
||||
|
@ -2859,6 +2860,29 @@ private:
|
|||
"}"));
|
||||
}
|
||||
|
||||
void varid_globalScope() {
|
||||
const char code1[] = "int a[5];\n"
|
||||
"namespace Z { struct B { int a[5]; } b; }\n"
|
||||
"void f() {\n"
|
||||
" int a[5];\n"
|
||||
" memset(a, 123, 5);\n"
|
||||
" memset(::a, 123, 5);\n"
|
||||
" memset(Z::b.a, 123, 5);\n"
|
||||
" memset(::Z::b.a, 123, 5);\n"
|
||||
"}";
|
||||
|
||||
const char exp1[] = "1: int a@1 [ 5 ] ;\n"
|
||||
"2: namespace Z { struct B { int a@2 [ 5 ] ; } ; struct B b@3 ; }\n"
|
||||
"3: void f ( ) {\n"
|
||||
"4: int a@4 [ 5 ] ;\n"
|
||||
"5: memset ( a@4 , 123 , 5 ) ;\n"
|
||||
"6: memset ( :: a@1 , 123 , 5 ) ;\n"
|
||||
"7: memset ( Z :: b@3 . a , 123 , 5 ) ;\n"
|
||||
"8: memset ( :: Z :: b@3 . a , 123 , 5 ) ;\n"
|
||||
"9: }\n";
|
||||
ASSERT_EQUALS(exp1, tokenize(code1));
|
||||
}
|
||||
|
||||
void varidclass1() {
|
||||
const std::string actual = tokenize(
|
||||
"class Fred\n"
|
||||
|
|
Loading…
Reference in New Issue