Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 71 additions & 7 deletions gui/cppchecklibrarydata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static CppcheckLibraryData::Container loadContainer(QXmlStreamReader &xmlReader)
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") {
} else if (elementName == "size" || elementName == "access" || elementName == "other" || elementName == "rangeItemRecordType") {
const QString indexOperator = xmlReader.attributes().value("indexOperator").toString();
if (elementName == "access" && indexOperator == "array-like")
container.access_arrayLike = true;
Expand All @@ -82,7 +82,12 @@ static CppcheckLibraryData::Container loadContainer(QXmlStreamReader &xmlReader)
container.sizeFunctions.append(function);
else if (elementName == "access")
container.accessFunctions.append(function);
else
else if (elementName == "rangeItemRecordType") {
struct CppcheckLibraryData::Container::RangeItemRecordType rangeItemRecordType;
rangeItemRecordType.name = xmlReader.attributes().value("name").toString();
rangeItemRecordType.templateParameter = xmlReader.attributes().value("templateParameter").toString();
container.rangeItemRecordTypeList.append(rangeItemRecordType);
} else
container.otherFunctions.append(function);
}
} else {
Expand All @@ -105,9 +110,23 @@ static QString loadUndefine(const QXmlStreamReader &xmlReader)
return xmlReader.attributes().value("name").toString();
}

static QString loadSmartPointer(const QXmlStreamReader &xmlReader)
static CppcheckLibraryData::SmartPointer loadSmartPointer(QXmlStreamReader &xmlReader)
{
return xmlReader.attributes().value("class-name").toString();
CppcheckLibraryData::SmartPointer smartPointer;
smartPointer.name = xmlReader.attributes().value("class-name").toString();
QXmlStreamReader::TokenType type;
while ((type = xmlReader.readNext()) != QXmlStreamReader::EndElement ||
xmlReader.name().toString() != "smart-pointer") {
if (type != QXmlStreamReader::StartElement)
continue;
const QString elementName = xmlReader.name().toString();
if (elementName == "unique") {
smartPointer.unique = true;
} else {
unhandledElement(xmlReader);
}
}
return smartPointer;
}

static CppcheckLibraryData::TypeChecks loadTypeChecks(QXmlStreamReader &xmlReader)
Expand Down Expand Up @@ -210,6 +229,20 @@ static CppcheckLibraryData::Function loadFunction(QXmlStreamReader &xmlReader, c
function.warn.reason = xmlReader.attributes().value("reason").toString();
function.warn.alternatives = xmlReader.attributes().value("alternatives").toString();
function.warn.msg = xmlReader.readElementText();
} else if (elementName == "not-overlapping-data") {
const QStringList attributeList {"ptr1-arg", "ptr2-arg", "size-arg", "strlen-arg"};
for (const QString &attr : attributeList) {
if (xmlReader.attributes().hasAttribute(attr)) {
function.notOverlappingDataArgs[attr] = xmlReader.attributes().value(attr).toString();
}
}
} else if (elementName == "container") {
const QStringList attributeList {"action", "yields"};
for (const QString &attr : attributeList) {
if (xmlReader.attributes().hasAttribute(attr)) {
function.containerAttributes[attr] = xmlReader.attributes().value(attr).toString();
}
}
} else {
unhandledElement(xmlReader);
}
Expand Down Expand Up @@ -493,6 +526,20 @@ static void writeContainerFunctions(QXmlStreamWriter &xmlWriter, const QString &
xmlWriter.writeEndElement();
}

static void writeContainerRangeItemRecords(QXmlStreamWriter &xmlWriter, const QList<struct CppcheckLibraryData::Container::RangeItemRecordType> &rangeItemRecords)
{
if (rangeItemRecords.isEmpty())
return;
xmlWriter.writeStartElement("rangeItemRecordType");
for (const CppcheckLibraryData::Container::RangeItemRecordType &item : rangeItemRecords) {
xmlWriter.writeStartElement("member");
xmlWriter.writeAttribute("name", item.name);
xmlWriter.writeAttribute("templateParameter", item.templateParameter);
xmlWriter.writeEndElement();
}
xmlWriter.writeEndElement();
}

static void writeContainer(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData::Container &container)
{
xmlWriter.writeStartElement("container");
Expand All @@ -519,6 +566,7 @@ static void writeContainer(QXmlStreamWriter &xmlWriter, const CppcheckLibraryDat
writeContainerFunctions(xmlWriter, "size", container.size_templateParameter, container.sizeFunctions);
writeContainerFunctions(xmlWriter, "access", container.access_arrayLike?1:-1, container.accessFunctions);
writeContainerFunctions(xmlWriter, "other", -1, container.otherFunctions);
writeContainerRangeItemRecords(xmlWriter, container.rangeItemRecordTypeList);
xmlWriter.writeEndElement();
}

Expand Down Expand Up @@ -632,7 +680,20 @@ static void writeFunction(QXmlStreamWriter &xmlWriter, const CppcheckLibraryData

xmlWriter.writeEndElement();
}

if (!function.notOverlappingDataArgs.isEmpty()) {
xmlWriter.writeStartElement("not-overlapping-data");
foreach (const QString value, function.notOverlappingDataArgs) {
xmlWriter.writeAttribute(function.notOverlappingDataArgs.key(value), value);
}
xmlWriter.writeEndElement();
}
if (!function.containerAttributes.isEmpty()) {
xmlWriter.writeStartElement("container");
foreach (const QString value, function.containerAttributes) {
xmlWriter.writeAttribute(function.containerAttributes.key(value), value);
}
xmlWriter.writeEndElement();
}
xmlWriter.writeEndElement();
}

Expand Down Expand Up @@ -835,9 +896,12 @@ QString CppcheckLibraryData::toString() const
writeTypeChecks(xmlWriter, check);
}

for (const QString &smartPtr : smartPointers) {
for (const SmartPointer &smartPtr : smartPointers) {
xmlWriter.writeStartElement("smart-pointer");
xmlWriter.writeAttribute("class-name", smartPtr);
xmlWriter.writeAttribute("class-name", smartPtr.name);
if (smartPtr.unique) {
xmlWriter.writeEmptyElement("unique");
}
xmlWriter.writeEndElement();
}

Expand Down
21 changes: 20 additions & 1 deletion gui/cppchecklibrarydata.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <QList>
#include <QString>
#include <QStringList>
#include <QMap>

class QIODevice;

Expand All @@ -47,6 +48,11 @@ class CppcheckLibraryData {
QString string;
} type;

struct RangeItemRecordType {
QString name;
QString templateParameter;
};

struct Function {
QString name;
QString yields;
Expand All @@ -55,6 +61,7 @@ class CppcheckLibraryData {
QList<struct Function> accessFunctions;
QList<struct Function> otherFunctions;
QList<struct Function> sizeFunctions;
QList<struct RangeItemRecordType> rangeItemRecordTypeList;
};

struct Define {
Expand Down Expand Up @@ -130,6 +137,9 @@ class CppcheckLibraryData {
msg.isEmpty();
}
} warn;

QMap<QString, QString> notOverlappingDataArgs;
QMap<QString, QString> containerAttributes;
};

struct MemoryResource {
Expand Down Expand Up @@ -219,6 +229,15 @@ class CppcheckLibraryData {
QList<Exporter> exporter;
};

struct SmartPointer {
SmartPointer() :
unique {false}
{}

QString name;
bool unique;
};

void clear() {
containers.clear();
defines.clear();
Expand Down Expand Up @@ -258,7 +277,7 @@ class CppcheckLibraryData {
QList<TypeChecks> typeChecks;
QList<struct PlatformType> platformTypes;
QStringList undefines;
QStringList smartPointers;
QList<struct SmartPointer> smartPointers;
QList<struct Reflection> reflections;
QList<struct Markup> markups;
};
Expand Down
9 changes: 9 additions & 0 deletions gui/test/cppchecklibrarydata/files/container_valid.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<def format="2">
<container id="stdMultiMap">
<rangeItemRecordType>
<member name="first" templateParameter="0"/>
<member name="second" templateParameter="1"/>
</rangeItemRecordType>
</container>
</def>
4 changes: 3 additions & 1 deletion gui/test/cppchecklibrarydata/files/smartptr_valid.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<?xml version="1.0"?>
<def format="2">
<smart-pointer class-name="wxObjectDataPtr"/>
<smart-pointer class-name="wxScopedArray"/>
<smart-pointer class-name="wxScopedArray">
<unique/>
</smart-pointer>
<smart-pointer class-name="wxScopedPtr"/>
</def>
1 change: 1 addition & 0 deletions gui/test/cppchecklibrarydata/resources.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
<file>files/markup_mandatory_attribute_missing.cfg</file>
<file>files/markup_valid.cfg</file>
<file>files/markup_unhandled_element.cfg</file>
<file>files/container_valid.cfg</file>
</qresource>
</RCC>
54 changes: 50 additions & 4 deletions gui/test/cppchecklibrarydata/testcppchecklibrarydata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,12 @@ void TestCppcheckLibraryData::smartPointerValid()
// Do size and content checks against swapped data.
QCOMPARE(libraryData.smartPointers.size(), 3);

QCOMPARE(libraryData.smartPointers[0], QString("wxObjectDataPtr"));
QCOMPARE(libraryData.smartPointers[1], QString("wxScopedArray"));
QCOMPARE(libraryData.smartPointers[2], QString("wxScopedPtr"));
QCOMPARE(libraryData.smartPointers[0].name, QString("wxObjectDataPtr"));
QCOMPARE(libraryData.smartPointers[0].unique, false);
QCOMPARE(libraryData.smartPointers[1].name, QString("wxScopedArray"));
QCOMPARE(libraryData.smartPointers[1].unique, true);
QCOMPARE(libraryData.smartPointers[2].name, QString("wxScopedPtr"));
QCOMPARE(libraryData.smartPointers[2].unique, false);

// Save library data to file
saveCfgFile(TempCfgFile, libraryData);
Expand All @@ -199,7 +202,10 @@ void TestCppcheckLibraryData::smartPointerValid()
// Verify no data got lost or modified
QCOMPARE(libraryData.smartPointers.size(), fileLibraryData.smartPointers.size());
QCOMPARE(libraryData.smartPointers.size(), 3);
QCOMPARE(libraryData.smartPointers, fileLibraryData.smartPointers);
for (int idx=0; idx < libraryData.smartPointers.size(); idx++) {
QCOMPARE(libraryData.smartPointers[idx].name, fileLibraryData.smartPointers[idx].name);
QCOMPARE(libraryData.smartPointers[idx].unique, fileLibraryData.smartPointers[idx].unique);
}
}

void TestCppcheckLibraryData::platformTypeValid()
Expand Down Expand Up @@ -543,6 +549,46 @@ void TestCppcheckLibraryData::markupValid()
}
}

void TestCppcheckLibraryData::containerValid()
{
// Load library data from file
loadCfgFile(":/files/container_valid.cfg", fileLibraryData, result);
QCOMPARE(result.isNull(), true);

// Swap library data read from file to other object
libraryData.swap(fileLibraryData);

// Do size and content checks against swapped data.
QCOMPARE(libraryData.containers.size(), 1);

QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList.size(), 2);
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList[0].name, QString("first"));
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList[0].templateParameter, QString("0"));
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList[1].name, QString("second"));
QCOMPARE(libraryData.containers[0].rangeItemRecordTypeList[1].templateParameter, QString("1"));

// Save library data to file
saveCfgFile(TempCfgFile, libraryData);

fileLibraryData.clear();
QCOMPARE(fileLibraryData.containers.size(), 0);

// Reload library data from file
loadCfgFile(TempCfgFile, fileLibraryData, result, true);
QCOMPARE(result.isNull(), true);

// Verify no data got lost or modified
QCOMPARE(libraryData.containers.size(), fileLibraryData.containers.size());
for (int idx=0; idx < libraryData.containers.size(); idx++) {
CppcheckLibraryData::Container lhs = libraryData.containers[idx];
CppcheckLibraryData::Container rhs = fileLibraryData.containers[idx];
for (int num=0; num < lhs.rangeItemRecordTypeList.size(); num++) {
QCOMPARE(lhs.rangeItemRecordTypeList[num].name, rhs.rangeItemRecordTypeList[num].name);
QCOMPARE(lhs.rangeItemRecordTypeList[num].templateParameter, rhs.rangeItemRecordTypeList[num].templateParameter);
}
}
}

void TestCppcheckLibraryData::loadCfgFile(QString filename, CppcheckLibraryData &data, QString &res, bool removeFile)
{
QFile file(filename);
Expand Down
1 change: 1 addition & 0 deletions gui/test/cppchecklibrarydata/testcppchecklibrarydata.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ private slots:
void undefineValid();
void reflectionValid();
void markupValid();
void containerValid();

private:
void loadCfgFile(QString filename, CppcheckLibraryData &data, QString &res, bool removeFile = false);
Expand Down