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.9 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>
This commit is contained in:
Marc Mutz 2025-01-19 09:22:58 +01:00
parent 3223c06d43
commit eb3df4edbc
2 changed files with 18 additions and 8 deletions

View File

@ -48,6 +48,16 @@ inline bool qt_no_assert_x(bool, const char *, const char *) noexcept { return f
# 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