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>
bb10
Lars Knoll 2020-05-20 21:59:21 +02:00 committed by Karsten Heimrich
parent 3398eeadf6
commit 8dc7761e6d
3 changed files with 24 additions and 14 deletions

View File

@ -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()) {

View File

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

View File

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