Don't change the implementation of a method depending on QT_USE_QSTRINGUILDER

This is rather evil and caused crashes in static builds, when library
and application where compiler with different settings of the
QT_USE_QSTRINGBUILDER flag.

The reason is that the implementation of QStringDecoder::operator() was
different (and returning different data) with or without the setting.
The compiler would thus create two very different versions of this method
in different .o files. When linking the app, one of the implementations
would be chosen, leading to crashes in places where the other one was
expected.

Fix this by only providing the QStringBuilder enabled version of the
methods. They return a temporary object that's converatable to a
QString/QByteArray anyway. Make sure that qdoc shows a simple signature.

As a drive by fix a compile error in a code path that didn't get hit
so far.

Change-Id: I312fa564d0bc6b464f2b4466de1d53841f7b7b0f
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Lars Knoll 2020-05-26 11:11:08 +02:00 committed by Volker Hilsheimer
parent a989c98393
commit 9980ba5ba5

View File

@ -206,7 +206,11 @@ public:
: QStringConverter(name, flags)
{}
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
#if defined(Q_QDOC)
QString operator()(const QString &);
QString operator()(QStringView);
QString operator()(const QChar *, qsizetype);
#else
template<typename T>
struct DecodedData
{
@ -218,18 +222,9 @@ public:
{ return DecodedData<const QString &>{this, str}; }
DecodedData<QStringView> operator()(QStringView in)
{ return DecodedData<QStringView>{this, in}; }
#else
QByteArray operator()(const QString &in)
{
return encode(QStringView(in));
}
QByteArray operator()(QStringView in)
{
return encode(in);
}
#endif
QByteArray operator()(const QChar *in, qsizetype length)
DecodedData<QStringView> operator()(const QChar *in, qsizetype length)
{ return (*this)(QStringView(in, length)); }
#endif
qsizetype requiredSpace(qsizetype inputLength) const
{ return iface->fromUtf16Len(inputLength); }
@ -249,14 +244,12 @@ private:
class QStringDecoder : public QStringConverter
{
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
struct View {
const char *ch;
qsizetype l;
const char *data() const { return ch; }
qsizetype length() const { return l; }
};
#endif
protected:
QSTRINGCONVERTER_CONSTEXPR QStringDecoder(const Interface *i)
@ -273,7 +266,11 @@ public:
: QStringConverter(name, f)
{}
#if defined(QT_USE_FAST_OPERATOR_PLUS) || defined(QT_USE_QSTRINGBUILDER)
#if defined(Q_QDOC)
QString operator()(const QByteArray &ba);
QString operator()(const char *in, qsizetype length);
QString operator()(const char *chars);
#else
template<typename T>
struct EncodedData
{
@ -287,13 +284,6 @@ public:
{ return EncodedData<View>{this, {in, length}}; }
EncodedData<View> operator()(const char *chars)
{ return EncodedData<View>{this, {chars, qsizetype(strlen(chars))}}; }
#else
QString operator()(const QByteArray &ba)
{ return decode(ba.data(), ba.length()); }
QString operator()(const char *in, qsizetype length)
{ return decode(in, length); }
QString operator()(const char *chars)
{ return decode(chars, strlen(chars)); }
#endif
qsizetype requiredSpace(qsizetype inputLength) const
@ -338,7 +328,7 @@ struct QConcatenable<QStringEncoder::DecodedData<T>>
static qsizetype size(const QStringEncoder::DecodedData<T> &s) { return s.encoder->requiredSpace(s.data.length()); }
static inline void appendTo(const QStringEncoder::DecodedData<T> &s, char *&out)
{
out = s.decoder->appendToBuffer(out, s.data.data(), s.data.length());
out = s.encoder->appendToBuffer(out, s.data.data(), s.data.length());
}
};