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

Reply via email to