diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-05-20 21:59:21 +0200 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@qt.io> | 2020-08-19 19:48:11 +0200 |
commit | 8dc7761e6d490877af18949c0177097e5c857424 (patch) | |
tree | 1bbab7de63ebb95a45b712c09486bba264b16a18 /src/corelib/serialization | |
parent | 3398eeadf617880af38fb540f26273df87ba0b1f (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.cpp | 6 | ||||
-rw-r--r-- | src/corelib/serialization/qxmlstream_p.h | 28 | ||||
-rw-r--r-- | src/corelib/serialization/qxmlstreamparser_p.h | 4 |
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; |