On Monday, November 04, 2013 12:24:37 Marc Mutz wrote: > The issue is with the casts to enums in some of the QFlags operators, IIRC, > but the log I cited is old and the line numbers might not match anymore.
I've dug up attached attempt to fix the issue, with which I am, however, not pleased enough to even bother putting it up on Gerrit.
From c924820e87f4a15b0ad730c03cf1a4ae865e363d Mon Sep 17 00:00:00 2001 From: Marc Mutz <[email protected]> Date: Mon, 16 Sep 2013 22:24:45 +0200 Subject: [PATCH] Q(UrlTwo)Flags: avoid undefined behavior Loading an enum with a value that isn't in the enum is undefined, according to Clang's usan. So provide a private ctor that takes int, but disambiguate with a separate bool dummy argument so as not to break code that uses the Zero constructor: QUrlTwoFlags f = 0; // OK, calls QUrlTwoFlags(Zero) Change-Id: I5f27e22c4d831482fcbba88b97cb124fb005e3fd --- src/corelib/global/qflags.h | 19 +++++++++++-------- src/corelib/io/qurl.h | 28 +++++++++++++++------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h index 5b7edba..dc853aa 100644 --- a/src/corelib/global/qflags.h +++ b/src/corelib/global/qflags.h @@ -97,6 +97,9 @@ public: inline QFlags(const QFlags &other); inline QFlags &operator=(const QFlags &other); #endif +private: + Q_DECL_CONSTEXPR inline QFlags(Int ii, bool) : i(ii) {} +public: Q_DECL_CONSTEXPR inline QFlags(Enum f) : i(Int(f)) {} Q_DECL_CONSTEXPR inline QFlags(Zero = 0) : i(0) {} Q_DECL_CONSTEXPR inline QFlags(QFlag f) : i(f) {} @@ -111,14 +114,14 @@ public: Q_DECL_CONSTEXPR inline operator Int() const { return i; } - Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(Enum(i | f.i)); } - Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(Enum(i | Int(f))); } - Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(Enum(i ^ f.i)); } - Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(Enum(i ^ Int(f))); } - Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(Enum(i & mask)); } - Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(Enum(i & mask)); } - Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(Enum(i & Int(f))); } - Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(Enum(~i)); } + Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const { return QFlags(i | f.i, true); } + Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const { return QFlags(i | Int(f), true); } + Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const { return QFlags(i ^ f.i, true); } + Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const { return QFlags(i ^ Int(f), true); } + Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const { return QFlags(i & mask, true); } + Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const { return QFlags(i & mask, true); } + Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const { return QFlags(i & Int(f), true); } + Q_DECL_CONSTEXPR inline QFlags operator~() const { return QFlags(~i, true); } Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h index e7edb43..4e4ebdd 100644 --- a/src/corelib/io/qurl.h +++ b/src/corelib/io/qurl.h @@ -67,6 +67,8 @@ class QUrlTwoFlags { int i; typedef int QUrlTwoFlags:: *Zero; + Q_DECL_CONSTEXPR inline QUrlTwoFlags(int ii, bool) // disambiguate: don't break flags=0 via Zero below + : i(ii) {} public: Q_DECL_CONSTEXPR inline QUrlTwoFlags(E1 f) : i(f) {} Q_DECL_CONSTEXPR inline QUrlTwoFlags(E2 f) : i(f) {} @@ -84,33 +86,33 @@ public: inline QUrlTwoFlags &operator^=(E1 f) { i ^= f; return *this; } inline QUrlTwoFlags &operator^=(E2 f) { i ^= f; return *this; } - Q_DECL_CONSTEXPR inline operator QFlags<E1>() const { return E1(i); } - Q_DECL_CONSTEXPR inline operator QFlags<E2>() const { return E2(i); } + Q_DECL_CONSTEXPR inline operator QFlags<E1>() const { return QFlags<E1>(QFlag(i)); } + Q_DECL_CONSTEXPR inline operator QFlags<E2>() const { return QFlags<E2>(QFlag(i)); } Q_DECL_CONSTEXPR inline operator int() const { return i; } Q_DECL_CONSTEXPR inline bool operator!() const { return !i; } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(QUrlTwoFlags f) const - { return QUrlTwoFlags(E1(i | f.i)); } + { return QUrlTwoFlags(i | f.i, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E1 f) const - { return QUrlTwoFlags(E1(i | f)); } + { return QUrlTwoFlags(i | f, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator|(E2 f) const - { return QUrlTwoFlags(E2(i | f)); } + { return QUrlTwoFlags(i | f, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(QUrlTwoFlags f) const - { return QUrlTwoFlags(E1(i ^ f.i)); } + { return QUrlTwoFlags(i ^ f.i, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E1 f) const - { return QUrlTwoFlags(E1(i ^ f)); } + { return QUrlTwoFlags(i ^ f, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator^(E2 f) const - { return QUrlTwoFlags(E2(i ^ f)); } + { return QUrlTwoFlags(i ^ f, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(int mask) const - { return QUrlTwoFlags(E1(i & mask)); } + { return QUrlTwoFlags(i & mask, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(uint mask) const - { return QUrlTwoFlags(E1(i & mask)); } + { return QUrlTwoFlags(i & mask, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E1 f) const - { return QUrlTwoFlags(E1(i & f)); } + { return QUrlTwoFlags(i & f, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator&(E2 f) const - { return QUrlTwoFlags(E2(i & f)); } + { return QUrlTwoFlags(i & f, true); } Q_DECL_CONSTEXPR inline QUrlTwoFlags operator~() const - { return QUrlTwoFlags(E1(~i)); } + { return QUrlTwoFlags(~i, true); } inline bool testFlag(E1 f) const { return (i & f) == f && (f != 0 || i == int(f)); } inline bool testFlag(E2 f) const { return (i & f) == f && (f != 0 || i == int(f)); } -- 1.7.9.5
_______________________________________________ Development mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/development
