GUI: Add handling of containers to CppcheckLibraryData
This commit is contained in:
parent
0d7d1e8350
commit
ff0f4cef16
90
cfg/std.cfg
90
cfg/std.cfg
|
@ -2321,9 +2321,9 @@
|
|||
<minsize type="argvalue" arg="3"/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
<not-bool/>
|
||||
<valid>0:</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- wchar_t * wmemcpy(wchar_t *ct, const wchar_t *cs, size_t n);-->
|
||||
|
@ -2340,9 +2340,9 @@
|
|||
<minsize type="argvalue" arg="3"/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
<not-bool/>
|
||||
<valid>0:</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- void * memmove(void *ct, const void *cs, size_t n); -->
|
||||
|
@ -2359,9 +2359,9 @@
|
|||
<minsize type="argvalue" arg="3"/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
<not-bool/>
|
||||
<valid>0:</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- wchar_t * wmemmove(wchar_t *ct, const wchar_t *cs, size_t n); -->
|
||||
|
@ -2378,9 +2378,9 @@
|
|||
<minsize type="argvalue" arg="3"/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
<not-bool/>
|
||||
<valid>0:</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- void *memset(void *s, int c, size_t n); -->
|
||||
|
@ -2395,9 +2395,9 @@
|
|||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
<not-bool/>
|
||||
<valid>0:</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- wchar_t *wmemset(wchar_t *s, wchar_t c, size_t n); -->
|
||||
|
@ -2412,9 +2412,9 @@
|
|||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="3">
|
||||
<not-uninit/>
|
||||
<not-bool/>
|
||||
<valid>0:</valid>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- time_t mktime(struct tm *tp); -->
|
||||
|
@ -2754,24 +2754,24 @@
|
|||
<leak-ignore/>
|
||||
<formatstr scan="true"/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<formatstr/>
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- int vsscanf(const char *s, const char *format, va_list arg); -->
|
||||
<function name="vsscanf,std::vsscanf">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<formatstr scan="true"/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<formatstr scan="true"/>
|
||||
<arg nr="2">
|
||||
<formatstr/>
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="3"/>
|
||||
</function>
|
||||
|
@ -2779,15 +2779,15 @@
|
|||
<function name="vswscanf,std::vswscanf">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<formatstr scan="true"/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<formatstr scan="true"/>
|
||||
<arg nr="2">
|
||||
<formatstr/>
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="3"/>
|
||||
</function>
|
||||
|
@ -2797,9 +2797,9 @@
|
|||
<leak-ignore/>
|
||||
<formatstr scan="true"/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<formatstr/>
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2"/>
|
||||
</function>
|
||||
|
@ -2850,16 +2850,6 @@
|
|||
<leak-ignore/>
|
||||
<arg nr="1"/>
|
||||
</function>
|
||||
<memory>
|
||||
<dealloc>free</dealloc>
|
||||
<alloc init="false">malloc</alloc>
|
||||
<alloc init="true">calloc</alloc>
|
||||
</memory>
|
||||
<resource>
|
||||
<dealloc>fclose</dealloc>
|
||||
<alloc init="true">fopen</alloc>
|
||||
<alloc init="true">tmpfile</alloc>
|
||||
</resource>
|
||||
<!-- char * strcat(char *deststr, const char *srcstr); -->
|
||||
<function name="strcat,std::strcat">
|
||||
<noreturn>false</noreturn>
|
||||
|
@ -3392,9 +3382,8 @@
|
|||
</function>
|
||||
<!-- char *strtok(char *s, const char *ct); -->
|
||||
<function name="strtok">
|
||||
<!-- strtok may modify the first argument, so using the return value is not mandatory -->
|
||||
<noreturn>false</noreturn>
|
||||
<pure/>
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
|
@ -3591,13 +3580,13 @@
|
|||
<function name="sprintf">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<formatstr/>
|
||||
<arg nr="1">
|
||||
<minsize type="strlen" arg="2"/>
|
||||
</arg>
|
||||
<formatstr/>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
<formatstr/>
|
||||
<not-null/>
|
||||
</arg>
|
||||
</function>
|
||||
<!-- int swprintf(wchar_t *s, size_t n, const wchar_t *format, ...); -->
|
||||
|
@ -3783,17 +3772,39 @@
|
|||
</function>
|
||||
<!-- struct tmx *zonetime(const time_t *tp, int zone); -->
|
||||
<function name="zonetime">
|
||||
<use-retval/>
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<use-retval/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
<not-null/>
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
</function>
|
||||
<!--Not part of standard, but widely supported by runtime libraries-->
|
||||
<function name="itoa">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="3"/>
|
||||
</function>
|
||||
<memory>
|
||||
<alloc>malloc</alloc>
|
||||
<alloc init="true">calloc</alloc>
|
||||
<dealloc>free</dealloc>
|
||||
</memory>
|
||||
<resource>
|
||||
<alloc init="true">fopen</alloc>
|
||||
<alloc init="true">tmpfile</alloc>
|
||||
<dealloc>fclose</dealloc>
|
||||
</resource>
|
||||
<container id="stdContainer" endPattern="> !!::">
|
||||
<type templateParameter="0"/>
|
||||
<size>
|
||||
|
@ -3867,8 +3878,7 @@
|
|||
<container id="stdBasicString" startPattern="std :: basic_string <" inherits="stdAllString">
|
||||
<type templateParameter="0"/>
|
||||
</container>
|
||||
<container id="stdString" startPattern="std :: string|wstring|u16string|u32string" endPattern="" inherits="stdAllString">
|
||||
</container>
|
||||
<container id="stdString" startPattern="std :: string|wstring|u16string|u32string" inherits="stdAllString"/>
|
||||
<podtype name="int8_t" sign="s" size="1"/>
|
||||
<podtype name="int16_t" sign="s" size="2"/>
|
||||
<podtype name="int32_t" sign="s" size="4"/>
|
||||
|
@ -3919,16 +3929,4 @@
|
|||
<podtype name="mbstate_t"/>
|
||||
<podtype name="wint_t"/>
|
||||
<podtype name="jmp_buf"/>
|
||||
<!--Not part of standard, but widely supported by runtime libraries-->
|
||||
<function name="itoa">
|
||||
<noreturn>false</noreturn>
|
||||
<leak-ignore/>
|
||||
<arg nr="1">
|
||||
<not-uninit/>
|
||||
</arg>
|
||||
<arg nr="2">
|
||||
<not-null/>
|
||||
</arg>
|
||||
<arg nr="3"/>
|
||||
</function>
|
||||
</def>
|
||||
|
|
|
@ -27,6 +27,52 @@ CppcheckLibraryData::CppcheckLibraryData()
|
|||
{
|
||||
}
|
||||
|
||||
static CppcheckLibraryData::Container loadContainer(QXmlStreamReader &xmlReader)
|
||||
{
|
||||
CppcheckLibraryData::Container container;
|
||||
container.id = xmlReader.attributes().value("id").toString();
|
||||
container.inherits = xmlReader.attributes().value("inherits").toString();
|
||||
container.startPattern = xmlReader.attributes().value("startPattern").toString();
|
||||
container.endPattern = xmlReader.attributes().value("endPattern").toString();
|
||||
|
||||
QXmlStreamReader::TokenType type;
|
||||
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
|
||||
xmlReader.name().toString() != "container") {
|
||||
if (type != QXmlStreamReader::StartElement)
|
||||
continue;
|
||||
const QString elementName = xmlReader.name().toString();
|
||||
if (elementName == "type") {
|
||||
container.type.templateParameter = xmlReader.attributes().value("templateParameter").toString();
|
||||
container.type.string = xmlReader.attributes().value("string").toString();
|
||||
} else if (elementName == "size" || elementName == "access" || elementName == "other") {
|
||||
const QString indexOperator = xmlReader.attributes().value("indexOperator").toString();
|
||||
if (elementName == "access" && indexOperator == "array-like")
|
||||
container.access_arrayLike = true;
|
||||
const QString templateParameter = xmlReader.attributes().value("templateParameter").toString();
|
||||
if (elementName == "size" && !templateParameter.isEmpty())
|
||||
container.size_templateParameter = templateParameter.toInt();
|
||||
for (;;) {
|
||||
type = xmlReader.readNext();
|
||||
if (xmlReader.name().toString() == elementName)
|
||||
break;
|
||||
if (type != QXmlStreamReader::StartElement)
|
||||
continue;
|
||||
struct CppcheckLibraryData::Container::Function function;
|
||||
function.name = xmlReader.attributes().value("name").toString();
|
||||
function.action = xmlReader.attributes().value("action").toString();
|
||||
function.yields = xmlReader.attributes().value("yields").toString();
|
||||
if (elementName == "size")
|
||||
container.sizeFunctions.append(function);
|
||||
else if (elementName == "access")
|
||||
container.accessFunctions.append(function);
|
||||
else
|
||||
container.otherFunctions.append(function);
|
||||
};
|
||||
}
|
||||
}
|
||||
return container;
|
||||
}
|
||||
|
||||
static CppcheckLibraryData::Define loadDefine(const QXmlStreamReader &xmlReader)
|
||||
{
|
||||
CppcheckLibraryData::Define define;
|
||||
|
@ -148,6 +194,8 @@ bool CppcheckLibraryData::open(QIODevice &file)
|
|||
comments.append(xmlReader.text().toString());
|
||||
break;
|
||||
case QXmlStreamReader::StartElement:
|
||||
if (xmlReader.name() == "container")
|
||||
containers.append(loadContainer(xmlReader));
|
||||
if (xmlReader.name() == "define")
|
||||
defines.append(loadDefine(xmlReader));
|
||||
else if (xmlReader.name() == "function")
|
||||
|
@ -166,6 +214,53 @@ bool CppcheckLibraryData::open(QIODevice &file)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void writeContainerFunctions(QXmlStreamWriter &xmlWriter, const QString name, int extra, const QList<struct CppcheckLibraryData::Container::Function> &functions)
|
||||
{
|
||||
if (functions.isEmpty() && extra <= 0)
|
||||
return;
|
||||
xmlWriter.writeStartElement(name);
|
||||
if (extra > 0) {
|
||||
if (name == "access")
|
||||
xmlWriter.writeAttribute("indexOperator", "array-like");
|
||||
else if (name == "size")
|
||||
xmlWriter.writeAttribute("templateParameter", QString::number(extra));
|
||||
}
|
||||
foreach(const CppcheckLibraryData::Container::Function &function, functions) {
|
||||
xmlWriter.writeStartElement("function");
|
||||
xmlWriter.writeAttribute("name", function.name);
|
||||
if (!function.action.isEmpty())
|
||||
xmlWriter.writeAttribute("action", function.action);
|
||||
if (!function.yields.isEmpty())
|
||||
xmlWriter.writeAttribute("yields", function.yields);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
static void writeContainer(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData::Container &container)
|
||||
{
|
||||
xmlWriter.writeStartElement("container");
|
||||
xmlWriter.writeAttribute("id", container.id);
|
||||
if (!container.startPattern.isEmpty())
|
||||
xmlWriter.writeAttribute("startPattern", container.startPattern);
|
||||
if (!container.endPattern.isEmpty())
|
||||
xmlWriter.writeAttribute("endPattern", container.endPattern);
|
||||
if (!container.inherits.isEmpty())
|
||||
xmlWriter.writeAttribute("inherits", container.inherits);
|
||||
if (!container.type.templateParameter.isEmpty() || !container.type.string.isEmpty()) {
|
||||
xmlWriter.writeStartElement("type");
|
||||
if (!container.type.templateParameter.isEmpty())
|
||||
xmlWriter.writeAttribute("templateParameter", container.type.templateParameter);
|
||||
if (!container.type.string.isEmpty())
|
||||
xmlWriter.writeAttribute("string", container.type.string);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
writeContainerFunctions(xmlWriter, "size", container.size_templateParameter, container.sizeFunctions);
|
||||
writeContainerFunctions(xmlWriter, "access", container.access_arrayLike, container.accessFunctions);
|
||||
writeContainerFunctions(xmlWriter, "other", 0, container.otherFunctions);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
static void writeFunction(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData::Function &function)
|
||||
{
|
||||
foreach(const QString &comment, function.comments) {
|
||||
|
@ -273,13 +368,17 @@ QString CppcheckLibraryData::toString() const
|
|||
writeMemoryResource(xmlWriter, mr);
|
||||
}
|
||||
|
||||
foreach(const Container &container, containers) {
|
||||
writeContainer(xmlWriter, container);
|
||||
}
|
||||
|
||||
foreach(const PodType &podtype, podtypes) {
|
||||
xmlWriter.writeStartElement("podtype");
|
||||
xmlWriter.writeAttribute("name", podtype.name);
|
||||
if (!podtype.size.isEmpty())
|
||||
xmlWriter.writeAttribute("size", podtype.size);
|
||||
if (!podtype.sign.isEmpty())
|
||||
xmlWriter.writeAttribute("sign", podtype.sign);
|
||||
if (!podtype.size.isEmpty())
|
||||
xmlWriter.writeAttribute("size", podtype.size);
|
||||
xmlWriter.writeEndElement();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,32 @@ class CppcheckLibraryData {
|
|||
public:
|
||||
CppcheckLibraryData();
|
||||
|
||||
struct Container {
|
||||
Container() : access_arrayLike(false), size_templateParameter(-1) {}
|
||||
|
||||
QString id;
|
||||
QString inherits;
|
||||
QString startPattern;
|
||||
QString endPattern;
|
||||
|
||||
bool access_arrayLike;
|
||||
int size_templateParameter;
|
||||
|
||||
struct {
|
||||
QString templateParameter;
|
||||
QString string;
|
||||
} type;
|
||||
|
||||
struct Function {
|
||||
QString name;
|
||||
QString yields;
|
||||
QString action;
|
||||
};
|
||||
QList<struct Function> accessFunctions;
|
||||
QList<struct Function> otherFunctions;
|
||||
QList<struct Function> sizeFunctions;
|
||||
};
|
||||
|
||||
struct Define {
|
||||
QString name;
|
||||
QString value;
|
||||
|
@ -101,6 +127,7 @@ public:
|
|||
bool open(QIODevice &file);
|
||||
QString toString() const;
|
||||
|
||||
QList<struct Container> containers;
|
||||
QList<struct Define> defines;
|
||||
QList<struct Function> functions;
|
||||
QList<struct MemoryResource> memoryresource;
|
||||
|
|
Loading…
Reference in New Issue