diff options
author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2019-05-13 14:33:57 +0200 |
---|---|---|
committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2019-05-19 14:24:52 +0200 |
commit | 8845caa057cfcf54f7d46621adb3393c13747ffb (patch) | |
tree | 5aebf32e9d1abe6b4e93067c83d6e3204f944fd1 /src/corelib/tools/qstring.h | |
parent | c7167509acdba006fe6da4ec1866acb214c18197 (diff) |
QCharRef/QByteRef: warn when triggering the resizing operator= behavior
The whole reason of QCharRef/QByteRef existence is to have a magic
operator=. This operator= delays the actual detach up to
the moment something is written into the Ref, thus avoiding
spurious detaches to the underlying string/byte array.
operator= has also an extra feature, it allows this code to
succeed:
QString s("abc");
s[10] = 'z';
assert(s == "abc z");
This last behavior is *extremely* surprising.
The problem with all of this is that this extra convenience is
outweighted by the massive pessimization in the codegen for
operator[]; by the maintenance burden (QChar APIs need to be
mirrored in QCharRef, etc.), and, for the automatic resize, by the
fact that it's an super-niche use case.
Cherry on top, std::basic_string does not do that, and no Qt or std
container does that. In other words: any other container-like class
exhibits UB for out of bounds access.
We can't just go and change behavior, though. This is something
coming all the way back from Qt 2 (maybe even Qt 1), which means we
can't deprecate it at short notice.
This patch simply adds a warning in debug builds in case the special
resizing behavior is triggered. While at it, removes some code
duplication in QByteRef.
[ChangeLog][QtCore][QString] The behavior of operator[] to allow
implicit resizing of the string has been deprecated, and will be
removed in a future version of Qt.
[ChangeLog][QtCore][QByteArray] The behavior of operator[] to allow
implicit detaching and resizing of the byte array has been
deprecated, and will be removed in a future version of Qt.
Change-Id: I3b5c5191167f12a606bcf6e513e6f304b220d675
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Diffstat (limited to 'src/corelib/tools/qstring.h')
-rw-r--r-- | src/corelib/tools/qstring.h | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 1abb91eabe..1feb8e186c 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1060,10 +1060,29 @@ public: // all this is not documented: We just say "like QChar" and let it be. inline operator QChar() const - { return i < s.d->size ? s.d->data()[i] : 0; } + { + using namespace QtPrivate::DeprecatedRefClassBehavior; + if (Q_LIKELY(i < s.d->size)) + return s.d->data()[i]; +#ifdef QT_DEBUG + warn(EmittingClass::QCharRef); +#endif + return 0; + } inline QCharRef &operator=(QChar c) - { if (i >= s.d->size) s.resize(i + 1, QLatin1Char(' ')); else s.detach(); - s.d->data()[i] = c.unicode(); return *this; } + { + using namespace QtPrivate::DeprecatedRefClassBehavior; + if (Q_UNLIKELY(i >= s.d->size)) { +#ifdef QT_DEBUG + warn(EmittingClass::QCharRef); +#endif + s.resize(i + 1, QLatin1Char(' ')); + } else { + s.detach(); + } + s.d->data()[i] = c.unicode(); + return *this; + } // An operator= for each QChar cast constructors #ifndef QT_NO_CAST_FROM_ASCII |