Skip to content

Commit 1def032

Browse files
Fix #13443 FP uninitMemberVar due to bad varid in template (danmar#8304)
1 parent 0fd737a commit 1def032

2 files changed

Lines changed: 41 additions & 18 deletions

File tree

lib/tokenize.cpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4246,10 +4246,13 @@ void Tokenizer::simplifyTemplates()
42464246
namespace {
42474247
/** Class used in Tokenizer::setVarIdPass1 */
42484248
class VariableMap {
4249+
public:
4250+
struct VarInfo { nonneg int id{}; bool assigned{}; };
4251+
using MapType = std::unordered_map<std::string, VarInfo>;
42494252
private:
4250-
std::unordered_map<std::string, nonneg int> mVariableId;
4251-
std::unordered_map<std::string, nonneg int> mVariableId_global;
4252-
std::stack<std::vector<std::pair<std::string, nonneg int>>> mScopeInfo;
4253+
MapType mVariableId;
4254+
MapType mVariableId_global;
4255+
std::stack<std::vector<MapType::value_type>> mScopeInfo;
42534256
mutable nonneg int mVarId{};
42544257
public:
42554258
VariableMap() = default;
@@ -4260,7 +4263,10 @@ namespace {
42604263
return mVariableId.find(varname) != mVariableId.end();
42614264
}
42624265

4263-
const std::unordered_map<std::string, nonneg int>& map(bool global) const {
4266+
const MapType& map(bool global) const {
4267+
return global ? mVariableId_global : mVariableId;
4268+
}
4269+
MapType& map(bool global) {
42644270
return global ? mVariableId_global : mVariableId;
42654271
}
42664272
nonneg int& getVarId() {
@@ -4280,8 +4286,8 @@ bool VariableMap::leaveScope()
42804286
if (mScopeInfo.empty())
42814287
return false;
42824288

4283-
for (const std::pair<std::string, nonneg int>& outerVariable : mScopeInfo.top()) {
4284-
if (outerVariable.second != 0)
4289+
for (const MapType::value_type& outerVariable : mScopeInfo.top()) {
4290+
if (outerVariable.second.id != 0)
42854291
mVariableId[outerVariable.first] = outerVariable.second;
42864292
else
42874293
mVariableId.erase(outerVariable.first);
@@ -4293,21 +4299,22 @@ bool VariableMap::leaveScope()
42934299
void VariableMap::addVariable(const std::string& varname, bool globalNamespace)
42944300
{
42954301
if (mScopeInfo.empty()) {
4296-
mVariableId[varname] = ++mVarId;
4302+
mVariableId[varname].id = ++mVarId;
42974303
if (globalNamespace)
42984304
mVariableId_global[varname] = mVariableId[varname];
42994305
return;
43004306
}
43014307
const auto it = mVariableId.find(varname);
43024308
if (it == mVariableId.end()) {
4303-
mScopeInfo.top().emplace_back(varname, 0);
4304-
mVariableId[varname] = ++mVarId;
4309+
mScopeInfo.top().emplace_back(varname, VarInfo{});
4310+
mVariableId[varname].id = ++mVarId;
43054311
if (globalNamespace)
43064312
mVariableId_global[varname] = mVariableId[varname];
43074313
return;
43084314
}
43094315
mScopeInfo.top().emplace_back(varname, it->second);
4310-
it->second = ++mVarId;
4316+
it->second.id = ++mVarId;
4317+
it->second.assigned = false;
43114318
}
43124319

43134320
/**
@@ -4524,14 +4531,14 @@ static void setVarIdStructMembers(Token *&tok1,
45244531

45254532
static void addTemplateVarIdUsage(const std::string &tokstr,
45264533
const std::map<std::string, std::set<std::string>>& templateVarUsage,
4527-
const std::unordered_map<std::string, nonneg int>& variableMap,
4534+
const VariableMap::MapType& variableMap,
45284535
std::set<nonneg int>& templateVarIdUsage) {
45294536
const auto v = templateVarUsage.find(tokstr);
45304537
if (v != templateVarUsage.end()) {
45314538
for (const std::string& varname: v->second) {
45324539
const auto it = variableMap.find(varname);
45334540
if (it != variableMap.end())
4534-
templateVarIdUsage.insert(it->second);
4541+
templateVarIdUsage.insert(it->second.id);
45354542
}
45364543
}
45374544
}
@@ -4588,7 +4595,7 @@ static bool setVarIdClassDeclaration(Token* const startToken,
45884595
} else if (initList && indentlevel == 0 && Token::Match(tok->previous(), "[,:] %name% [({]")) {
45894596
const auto it = variableMap.map(false).find(tok->str());
45904597
if (it != variableMap.map(false).end()) {
4591-
tok->varId(it->second);
4598+
tok->varId(it->second.id);
45924599
}
45934600
} else if (tok->isName() && tok->varId() <= scopeStartVarId) {
45944601
if (indentlevel > 0 || initList) {
@@ -4606,7 +4613,7 @@ static bool setVarIdClassDeclaration(Token* const startToken,
46064613
if (!inEnum) {
46074614
const auto it = variableMap.map(false).find(tok->str());
46084615
if (it != variableMap.map(false).end()) {
4609-
tok->varId(it->second);
4616+
tok->varId(it->second.id);
46104617
setVarIdStructMembers(tok, structMembers, variableMap.getVarId());
46114618
} else if (tok->str().back() == '>') {
46124619
addTemplateVarIdUsage(tok->str(), templateVarUsage, variableMap.map(false), templateVarIdUsage);
@@ -4902,7 +4909,7 @@ void Tokenizer::setVarIdPass1()
49024909
if (declTypeTok) {
49034910
for (Token *declTok = declTypeTok->linkAt(1); declTok != declTypeTok; declTok = declTok->previous()) {
49044911
if (declTok->isName() && !Token::Match(declTok->previous(), "::|.") && variableMap.hasVariable(declTok->str()))
4905-
declTok->varId(variableMap.map(false).find(declTok->str())->second);
4912+
declTok->varId(variableMap.map(false).find(declTok->str())->second.id);
49064913
}
49074914
}
49084915

@@ -4982,7 +4989,7 @@ void Tokenizer::setVarIdPass1()
49824989
Token::Match(tok->tokAt(-1), ":: %name%"))) {
49834990
const auto it = variableMap.map(false).find(tok->str());
49844991
if (it != variableMap.map(false).end())
4985-
tok->varId(it->second);
4992+
tok->varId(it->second.id);
49864993
}
49874994
tok = tok->next();
49884995
}
@@ -5057,8 +5064,11 @@ void Tokenizer::setVarIdPass1()
50575064
!Token::simpleMatch(tok->next(), ": ;") && !(tok->tokAt(-1) && Token::Match(tok->tokAt(-2), "{|, ."))) {
50585065
const auto it = variableMap.map(globalNamespace).find(tok->str());
50595066
if (it != variableMap.map(globalNamespace).end()) {
5060-
tok->varId(it->second);
5061-
setVarIdStructMembers(tok, structMembers, variableMap.getVarId());
5067+
if (!it->second.assigned || !Token::Match(tok->previous(), "%type% %name% (") || tok->previous()->isKeyword()) {
5068+
it->second.assigned = true;
5069+
tok->varId(it->second.id);
5070+
setVarIdStructMembers(tok, structMembers, variableMap.getVarId());
5071+
}
50625072
}
50635073
}
50645074
} else if (Token::Match(tok, "::|. %name%") && Token::Match(tok->previous(), ")|]|>|%name%")) {

test/testvarid.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ class TestVarID : public TestFixture {
150150
TEST_CASE(varid_in_class27);
151151
TEST_CASE(varid_in_class28);
152152
TEST_CASE(varid_in_class29);
153+
TEST_CASE(varid_in_class30);
153154
TEST_CASE(varid_namespace_1); // #7272
154155
TEST_CASE(varid_namespace_2); // #7000
155156
TEST_CASE(varid_namespace_3); // #8627
@@ -2403,6 +2404,18 @@ class TestVarID : public TestFixture {
24032404
ASSERT_EQUALS(expected, tokenize(code));
24042405
}
24052406

2407+
void varid_in_class30() {
2408+
const char code[] = "void* p;\n" // #13443
2409+
"struct S {\n"
2410+
" void p();\n"
2411+
"};\n";
2412+
const char expected[] = "1: void * p@1 ;\n"
2413+
"2: struct S {\n"
2414+
"3: void p ( ) ;\n"
2415+
"4: } ;\n";
2416+
ASSERT_EQUALS(expected, tokenize(code));
2417+
}
2418+
24062419
void varid_namespace_1() { // #7272
24072420
const char code[] = "namespace Blah {\n"
24082421
" struct foo { int x;};\n"

0 commit comments

Comments
 (0)