summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-05-20 21:59:21 +0200
committerKarsten Heimrich <karsten.heimrich@qt.io>2020-08-19 19:48:11 +0200
commit8dc7761e6d490877af18949c0177097e5c857424 (patch)
tree1bbab7de63ebb95a45b712c09486bba264b16a18 /src/corelib/serialization
parent3398eeadf617880af38fb540f26273df87ba0b1f (diff)
Fix QXmlStreamSimpleStack to work also with non POD data types
The current code is already undefined behavior, as QStringRef is not POD. It happened to work, because the destructor is empty. Fix this and rather let the compiler determine whether it needs to call any constructors or destructors. Change-Id: Idc8710df539603b0ca401a9453f2501f01beaab4 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/serialization')
-rw-r--r--src/corelib/serialization/qxmlstream.cpp6
-rw-r--r--src/corelib/serialization/qxmlstream_p.h28
-rw-r--r--src/corelib/serialization/qxmlstreamparser_p.h4
3 files changed, 24 insertions, 14 deletions
diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp
index e242340f7b..176dbfe398 100644
--- a/src/corelib/serialization/qxmlstream.cpp
+++ b/src/corelib/serialization/qxmlstream.cpp
@@ -3037,7 +3037,7 @@ bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
if (inEmptyElement) {
write("/>");
- QXmlStreamWriterPrivate::Tag &tag = tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = tagStack_pop();
lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
lastWasStartElement = false;
} else {
@@ -3496,7 +3496,7 @@ void QXmlStreamWriter::writeEndElement()
if (d->inStartElement && !d->inEmptyElement) {
d->write("/>");
d->lastWasStartElement = d->inStartElement = false;
- QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = d->tagStack_pop();
d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
return;
}
@@ -3506,7 +3506,7 @@ void QXmlStreamWriter::writeEndElement()
if (d->tagStack.isEmpty())
return;
d->lastWasStartElement = false;
- QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
+ QXmlStreamWriterPrivate::Tag tag = d->tagStack_pop();
d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
d->write("</");
if (!tag.namespaceDeclaration.prefix.isEmpty()) {
diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h
index b1e25c161e..b279701a83 100644
--- a/src/corelib/serialization/qxmlstream_p.h
+++ b/src/corelib/serialization/qxmlstream_p.h
@@ -58,14 +58,24 @@
QT_BEGIN_NAMESPACE
-template <typename T> class QXmlStreamSimpleStack {
+template <typename T> class QXmlStreamSimpleStack
+{
T *data;
qsizetype tos, cap;
public:
- inline QXmlStreamSimpleStack():data(nullptr), tos(-1), cap(0){}
- inline ~QXmlStreamSimpleStack(){ if (data) free(data); }
+ inline QXmlStreamSimpleStack()
+ : data(nullptr), tos(-1), cap(0)
+ {}
+ inline ~QXmlStreamSimpleStack()
+ {
+ if (data) {
+ std::destroy_n(data, size());
+ free(data);
+ }
+ }
- inline void reserve(qsizetype extraCapacity) {
+ inline void reserve(qsizetype extraCapacity)
+ {
if (tos + extraCapacity + 1 > cap) {
cap = qMax(tos + extraCapacity + 1, cap << 1 );
void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
@@ -74,11 +84,11 @@ public:
}
}
- inline T &push() { reserve(1); return data[++tos]; }
- inline T &rawPush() { return data[++tos]; }
+ inline T &push() { reserve(1); return rawPush(); }
+ inline T &rawPush() { return *new (data + (++tos)) T; }
inline const T &top() const { return data[tos]; }
inline T &top() { return data[tos]; }
- inline T &pop() { return data[tos--]; }
+ inline T pop() { T t = std::move(data[tos]); std::destroy_at(data + tos); --tos; return t; }
inline T &operator[](qsizetype index) { return data[index]; }
inline const T &at(qsizetype index) const { return data[index]; }
inline qsizetype size() const { return tos + 1; }
@@ -147,8 +157,8 @@ public:
QXmlStreamSimpleStack<Tag> tagStack;
- inline Tag &tagStack_pop() {
- Tag& tag = tagStack.pop();
+ inline Tag tagStack_pop() {
+ Tag tag = tagStack.pop();
tagStackStringStorageSize = tag.tagStackStringStorageSize;
namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
tagsDone = tagStack.isEmpty();
diff --git a/src/corelib/serialization/qxmlstreamparser_p.h b/src/corelib/serialization/qxmlstreamparser_p.h
index 1d28923a11..2d2dc5811d 100644
--- a/src/corelib/serialization/qxmlstreamparser_p.h
+++ b/src/corelib/serialization/qxmlstreamparser_p.h
@@ -90,7 +90,7 @@ bool QXmlStreamReaderPrivate::parse()
attributes.clear();
if (isEmptyElement) {
setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
+ Tag tag = tagStack_pop();
namespaceUri = tag.namespaceDeclaration.namespaceUri;
name = tag.name;
qualifiedName = tag.qualifiedName;
@@ -837,7 +837,7 @@ bool QXmlStreamReaderPrivate::parse()
case 238: {
setType(QXmlStreamReader::EndElement);
- Tag &tag = tagStack_pop();
+ Tag tag = tagStack_pop();
namespaceUri = tag.namespaceDeclaration.namespaceUri;
name = tag.name;