Fix http://llvm.org/bugs/show_bug.cgi?id=11428.  Fix provided by Alberto Ganesh Barbati

llvm-svn: 145698
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: 75689c1018ffcacb3d4771297f439822882313c6
diff --git a/include/__config b/include/__config
index 0f6c77d..5e0db7c 100644
--- a/include/__config
+++ b/include/__config
@@ -160,6 +160,10 @@
 #define _LIBCPP_NO_RTTI
 #endif
 
+#if !(__has_feature(cxx_strong_enums))
+#define _LIBCPP_HAS_NO_STRONG_ENUMS
+#endif
+
 #if !(__has_feature(cxx_decltype))
 #define _LIBCPP_HAS_NO_DECLTYPE
 #endif
@@ -223,6 +227,7 @@
 
 #if __has_feature(objc_arc_weak)
 #define _LIBCPP_HAS_OBJC_ARC_WEAK
+#define _LIBCPP_HAS_NO_STRONG_ENUMS
 #endif
 
 #if !(__has_feature(cxx_constexpr))
@@ -371,6 +376,18 @@
 #define __has_feature(__x) 0
 #endif
 
+#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS
+#define _LIBCPP_DECLARE_STRONG_ENUM(x) struct _LIBCPP_VISIBLE x { enum _
+#define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x) \
+    _ __v_; \
+    _LIBCPP_ALWAYS_INLINE x(_ __v) : __v_(__v) {} \
+    _LIBCPP_ALWAYS_INLINE operator int() const {return __v_;} \
+    };
+#else  // _LIBCPP_HAS_NO_STRONG_ENUMS
+#define _LIBCPP_DECLARE_STRONG_ENUM(x) enum class _LIBCPP_VISIBLE x
+#define _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(x)
+#endif  // _LIBCPP_HAS_NO_STRONG_ENUMS
+
 #if __APPLE__ || __FreeBSD__ || _WIN32
 #define _LIBCPP_LOCALE__L_EXTENSIONS 1
 #endif
diff --git a/include/future b/include/future
index 0e61869..aae707e 100644
--- a/include/future
+++ b/include/future
@@ -377,56 +377,40 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 //enum class future_errc
-struct _LIBCPP_VISIBLE future_errc
+_LIBCPP_DECLARE_STRONG_ENUM(future_errc)
 {
-enum _ {
     broken_promise,
     future_already_retrieved,
     promise_already_satisfied,
     no_state
 };
-
-    _ __v_;
-
-    _LIBCPP_INLINE_VISIBILITY future_errc(_ __v) : __v_(__v) {}
-    _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;}
-
-};
+_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_errc)
 
 template <>
 struct _LIBCPP_VISIBLE is_error_code_enum<future_errc> : public true_type {};
 
+#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS
+template <>
+struct _LIBCPP_VISIBLE is_error_code_enum<future_errc::_> : public true_type { };
+#endif
+
 //enum class launch
-struct _LIBCPP_VISIBLE launch
+_LIBCPP_DECLARE_STRONG_ENUM(launch)
 {
-enum _ {
     async = 1,
     deferred = 2,
     any = async | deferred
 };
-
-    _ __v_;
-
-    _LIBCPP_INLINE_VISIBILITY launch(_ __v) : __v_(__v) {}
-    _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;}
-
-};
+_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(launch)
 
 //enum class future_status
-struct _LIBCPP_VISIBLE future_status
+_LIBCPP_DECLARE_STRONG_ENUM(future_status)
 {
-enum _ {
     ready,
     timeout,
     deferred
 };
-
-    _ __v_;
-
-    _LIBCPP_INLINE_VISIBILITY future_status(_ __v) : __v_(__v) {}
-    _LIBCPP_INLINE_VISIBILITY operator int() const {return __v_;}
-
-};
+_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_status)
 
 _LIBCPP_VISIBLE
 const error_category& future_category();
@@ -2252,10 +2236,10 @@
     typedef __async_func<typename decay<_Fp>::type, typename decay<_Args>::type...> _BF;
     typedef typename _BF::_Rp _Rp;
     future<_Rp> __r;
-    if (__policy & launch::async)
+    if (int(__policy) & int(launch::async))
         __r = _VSTD::__make_async_assoc_state<_Rp>(_BF(__decay_copy(_VSTD::forward<_Fp>(__f)),
                                                      __decay_copy(_VSTD::forward<_Args>(__args))...));
-    else if (__policy & launch::deferred)
+    else if (int(__policy) & int(launch::deferred))
         __r = _VSTD::__make_deferred_assoc_state<_Rp>(_BF(__decay_copy(_VSTD::forward<_Fp>(__f)),
                                                         __decay_copy(_VSTD::forward<_Args>(__args))...));
     return __r;
diff --git a/include/ios b/include/ios
index 7ea63a3..3aa066b 100644
--- a/include/ios
+++ b/include/ios
@@ -373,21 +373,19 @@
 };
 
 //enum class io_errc
-struct _LIBCPP_VISIBLE io_errc
+_LIBCPP_DECLARE_STRONG_ENUM(io_errc)
 {
-enum _ {
     stream = 1
 };
-    _ __v_;
-
-    _LIBCPP_ALWAYS_INLINE io_errc(_ __v) : __v_(__v) {}
-    _LIBCPP_ALWAYS_INLINE operator int() const {return __v_;}
-};
+_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(io_errc)
 
 template <>
 struct _LIBCPP_VISIBLE is_error_code_enum<io_errc> : public true_type { };
+
+#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS
 template <>
 struct _LIBCPP_VISIBLE is_error_code_enum<io_errc::_> : public true_type { };
+#endif
 
 _LIBCPP_VISIBLE
 const error_category& iostream_category();
diff --git a/include/support/win32/support.h b/include/support/win32/support.h
index 38ea51e..209f720 100644
--- a/include/support/win32/support.h
+++ b/include/support/win32/support.h
@@ -31,7 +31,7 @@
                    size_t nmc, size_t len, mbstate_t *__restrict ps );
 size_t wcsnrtombs( char *__restrict dst, const wchar_t **__restrict src,
                    size_t nwc, size_t len, mbstate_t *__restrict ps );
-				   
+
 #if defined(_MSC_VER)
 #define snprintf _snprintf
 
@@ -91,8 +91,8 @@
 _LIBCPP_ALWAYS_INLINE int __builtin_ctzll( unsigned long long x )
 {
     DWORD r = 0;
-	_BitScanReverse64(&r, x);
-	return static_cast<int>(r);
+    _BitScanReverse64(&r, x);
+    return static_cast<int>(r);
 }
 _LIBCPP_ALWAYS_INLINE int __builtin_clz( unsigned int x )
 {
@@ -106,8 +106,8 @@
 _LIBCPP_ALWAYS_INLINE int __builtin_clzll( unsigned long long x )
 {
     DWORD r = 0;
-	_BitScanForward64(&r, x);
-	return static_cast<int>(r);
+    _BitScanForward64(&r, x);
+    return static_cast<int>(r);
 }
 #endif // !__clang__
 #endif // _MSC_VER
diff --git a/include/system_error b/include/system_error
index c9a8097..971be33 100644
--- a/include/system_error
+++ b/include/system_error
@@ -245,9 +245,8 @@
 // for them:
 
 //enum class errc
-struct errc
+_LIBCPP_DECLARE_STRONG_ENUM(errc)
 {
-enum _ {
     address_family_not_supported        = EAFNOSUPPORT,
     address_in_use                      = EADDRINUSE,
     address_not_available               = EADDRNOTAVAIL,
@@ -343,23 +342,17 @@
     value_too_large                     = EOVERFLOW,
     wrong_protocol_type                 = EPROTOTYPE
 };
-
-    _ __v_;
-
-    _LIBCPP_ALWAYS_INLINE
-    errc(_ __v) : __v_(__v) {}
-    _LIBCPP_ALWAYS_INLINE
-    operator int() const {return __v_;}
-
-};
+_LIBCPP_DECLARE_STRONG_ENUM_EPILOG(errc)
 
 template <>
 struct _LIBCPP_VISIBLE is_error_condition_enum<errc>
     : true_type { };
 
+#ifdef _LIBCPP_HAS_NO_STRONG_ENUMS
 template <>
 struct _LIBCPP_VISIBLE is_error_condition_enum<errc::_>
     : true_type { };
+#endif
 
 class error_condition;
 class error_code;