SymbolDatabase: Do not set wrong type for std::map etc items in range for loop

This commit is contained in:
Daniel Marjamäki 2021-12-11 15:16:54 +01:00
parent 54b54567cf
commit 77434d093e
6 changed files with 41 additions and 2 deletions

View File

@ -453,6 +453,14 @@
</optional>
<empty/>
</element>
<element name="rangeItemRecordType">
<oneOrMore>
<element name="member">
<attribute name="name"><ref name="DATA-NAME"/></attribute>
<attribute name="templateParameter"><data type="integer"/></attribute>
</element>
</oneOrMore>
</element>
<element name="size">
<optional>
<attribute name="templateParameter"><data type="integer"/></attribute>

View File

@ -8230,6 +8230,10 @@ initializer list (7) string& replace (const_iterator i1, const_iterator i2, init
</container>
<container id="stdMultiMap" startPattern="std :: multimap|unordered_multimap &lt;" inherits="stdContainer">
<type templateParameter="1" associative="std-like"/>
<rangeItemRecordType>
<member name="first" templateParameter="0"/>
<member name="second" templateParameter="1"/>
</rangeItemRecordType>
<access>
<function name="at" yields="at_index"/>
<function name="count" action="find"/>

View File

@ -506,6 +506,15 @@ Library::Error Library::load(const tinyxml2::XMLDocument &doc)
if (unstableType.find("insert") != std::string::npos)
container.unstableInsert = true;
}
} else if (containerNodeName == "rangeItemRecordType") {
for (const tinyxml2::XMLElement* memberNode = node->FirstChildElement(); memberNode; memberNode = memberNode->NextSiblingElement()) {
const char *memberName = memberNode->Attribute("name");
const char *memberTemplateParameter = memberNode->Attribute("templateParameter");
struct Container::RangeItemRecordTypeItem member;
member.name = memberName ? memberName : "";
member.templateParameter = memberTemplateParameter ? std::atoi(memberTemplateParameter) : -1;
container.rangeItemRecordType.emplace_back(member);
}
} else
unknown_elements.insert(containerNodeName);
}

View File

@ -246,9 +246,14 @@ public:
Action action;
Yield yield;
};
struct RangeItemRecordTypeItem {
std::string name;
int templateParameter;
};
std::string startPattern, startPattern2, endPattern, itEndPattern;
std::map<std::string, Function> functions;
int type_templateArgNo;
std::vector<RangeItemRecordTypeItem> rangeItemRecordType;
int size_templateArgNo;
bool arrayLike_indexOp;
bool stdStringLike;

View File

@ -6008,7 +6008,10 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
bool setType = false;
ValueType autovt;
const Type *templateArgType = nullptr; // container element type / smart pointer type
if (vt2->containerTypeToken) {
if (!vt2->container->rangeItemRecordType.empty()) {
setType = true;
autovt.type = ValueType::Type::RECORD;
} else if (vt2->containerTypeToken) {
if (mSettings->library.isSmartPointer(vt2->containerTypeToken)) {
const Token *smartPointerTypeTok = vt2->containerTypeToken;
while (Token::Match(smartPointerTypeTok, "%name%|::"))
@ -6023,7 +6026,6 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
setType = true;
templateArgType = vt2->containerTypeToken->type();
}
}
if (setType) {

View File

@ -478,6 +478,7 @@ private:
TEST_CASE(auto13);
TEST_CASE(auto14);
TEST_CASE(auto15); // C++17 auto deduction from braced-init-list
TEST_CASE(auto16);
TEST_CASE(unionWithConstructor);
@ -8354,6 +8355,16 @@ private:
ASSERT_EQUALS(ValueType::Type::DOUBLE, var2->valueType()->type);
}
void auto16() {
GET_SYMBOL_DB("void foo(std::map<std::string, bool> x) {\n"
" for (const auto& i: x) {}\n"
"}\n");
ASSERT_EQUALS(3, db->variableList().size());
const Variable *i = db->variableList().back();
ASSERT(i->valueType());
ASSERT_EQUALS(ValueType::Type::RECORD, i->valueType()->type);
}
void unionWithConstructor() {
GET_SYMBOL_DB("union Fred {\n"
" Fred(int x) : i(x) { }\n"