Long live Q_PRE/Q_PRE_X!

As decided with lazy consensus on the development ML¹, we'd like to
separate precondition checking from internal consistency checking.

Add a new Q_PRE/Q_PRE_X macro for the former, to leave Q_ASSERT/_X for
the latter.

As requested in review, modernize Q_PRE_X vis-a-vis Q_ASSERT_X by
skipping the `where` parameter (defaulting it to Q_FUNC_INFO).

Added as undocumented API, for now, to pick back to all active
branches without actually promising semantics different from Q_ASSERT,
a change that, realistically, will only happen for 6.10 at the
earliest. But by making the macro available to all active branches, we
avoid conflicts when picking changes back, and the change is rather
risk-less.

Apply to QStringView, to have at least one user.

¹ https://lists.qt-project.org/pipermail/development/2024-August/045588.html Items 1-3.

Pick-to: 6.8 6.5
Task-number: QTBUG-98965
Change-Id: Ia04248a64c8feba80cce10f8f5cbde580436db88
Reviewed-by: Jøger Hansegård <joger.hansegard@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit eb3df4edbc0ca04a892728e54962ad0daef4a78e)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2025-01-19 09:22:58 +01:00 committed by Qt Cherry-pick Bot
parent 97b41af2a2
commit 4a352937e3
2 changed files with 18 additions and 8 deletions

View File

@ -47,6 +47,16 @@ void qt_assert_x(const char *where, const char *what, const char *file, int line
# endif
#endif
#ifndef Q_PRE
# define Q_PRE(cond) \
Q_ASSERT(cond) /* for now... */
#endif
#ifndef Q_PRE_X
# define Q_PRE_X(cond, what) \
Q_ASSERT_X(cond, Q_FUNC_INFO, what) /* for now... */
#endif
Q_NORETURN Q_CORE_EXPORT void qt_check_pointer(const char *, int) noexcept;
Q_NORETURN Q_DECL_COLD_FUNCTION
Q_CORE_EXPORT void qBadAlloc();

View File

@ -130,9 +130,9 @@ public:
constexpr QStringView(const Char *str, qsizetype len)
#if QT_VERSION >= QT_VERSION_CHECK(7, 0, 0) || defined(QT_BOOTSTRAPPED)
: m_data(castHelper(str)),
m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len))
m_size((Q_PRE(len >= 0), Q_PRE(str || !len), len))
#else
: m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)),
: m_size((Q_PRE(len >= 0), Q_PRE(str || !len), len)),
m_data(castHelper(str))
#endif
{}
@ -404,8 +404,8 @@ public:
[[nodiscard]] const_reverse_iterator crend() const noexcept { return rend(); }
[[nodiscard]] constexpr bool empty() const noexcept { return size() == 0; }
[[nodiscard]] constexpr QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); }
[[nodiscard]] constexpr QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); }
[[nodiscard]] constexpr QChar front() const { return Q_PRE(!empty()), QChar(m_data[0]); }
[[nodiscard]] constexpr QChar back() const { return Q_PRE(!empty()), QChar(m_data[m_size - 1]); }
[[nodiscard]] Q_IMPLICIT operator std::u16string_view() const noexcept
{ return std::u16string_view(m_data, size_t(m_size)); }
@ -441,10 +441,10 @@ private:
Q_ALWAYS_INLINE constexpr void verify([[maybe_unused]] qsizetype pos = 0,
[[maybe_unused]] qsizetype n = 1) const
{
Q_ASSERT(pos >= 0);
Q_ASSERT(pos <= size());
Q_ASSERT(n >= 0);
Q_ASSERT(n <= size() - pos);
Q_PRE(pos >= 0);
Q_PRE(pos <= size());
Q_PRE(n >= 0);
Q_PRE(n <= size() - pos);
}
constexpr int compare_single_char_helper(int diff) const noexcept