GUI: Add handling of containers to CppcheckLibraryData

This commit is contained in:
Daniel Marjamäki 2015-09-05 20:13:26 +02:00
parent 0d7d1e8350
commit ff0f4cef16
3 changed files with 172 additions and 48 deletions

View File

@ -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>
<arg nr="2">
<not-null/>
<formatstr/>
<arg nr="2">
<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="&gt; !!::">
<type templateParameter="0"/>
<size>
@ -3867,8 +3878,7 @@
<container id="stdBasicString" startPattern="std :: basic_string &lt;" 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>

View File

@ -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();
}

View File

@ -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;