diff mbox series

[5/8] libstdc++: Consistently use noexcept, constexpr, nodiscard on bitmask ops

Message ID 20240227114528.1350601-5-jwakely@redhat.com
State New
Headers show
Series [1/8] libstdc++: Add more [[nodiscard]] to <stacktrace> | expand

Commit Message

Jonathan Wakely Feb. 27, 2024, 11:42 a.m. UTC
Tested x86_64-linux. Reviews invited.

-- >8 --

The bitwise operators for combining bitmask types such as std::launch
are not consistently annotated with noexcept, constexpr, and nodiscard.

This is the subject of LWG 3977, although the proposed resolution
doesn't work. We can make the changes in libstdc++ anyway though.

libstdc++-v3/ChangeLog:

	* include/bits/atomic_base.h (operator|, operator&): Add
	noexcept.
	* include/bits/fs_fwd.h (operator&, operator|, operator^)
	(operator~): Add nodiscard to overloads for copy_options, perms,
	perm_options, and directory_options.
	* include/bits/ios_base.h (operator&, operator|, operator^)
	(operator~): Add nodiscard and noexcept to overloads for
	_Ios_Fmtflags, _Ios_Openmode, and _Ios_Iostate.
	(operator|=, operator&=, operator^=): Add constexpr for C++14.
	* include/bits/regex_constants.h (operator&, operator|, operator^)
	(operator~): Add nodiscard and noexcept to overloads for
	syntax_option_type and match_flag_type.
	(operator|=, operator&=, operator^=): Add noexcept.
	* include/std/charconv (operator&, operator|, operator^)
	(operator~): Add nodiscard to overloads for chars_format.
	* include/std/future (operator&, operator|, operator^)
	(operator~): Add nodiscard for overloads for launch.
	(operator&=, operator|=, operator^=): Add constexpr for C++14.
	* include/experimental/bits/fs_fwd.h  (operator&, operator|)
	(operator^, operator~): Add nodiscard to overloads for
	copy_options, perms, and directory_options.
	* testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc:
	Add dg-warning for nodiscard warnings.
	* testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc:
	Likewise.
	* testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc:
	Likewise.
	* testsuite/27_io/filesystem/operations/bitmask_types.cc:
	New test.
---
 libstdc++-v3/include/bits/atomic_base.h       |  4 +-
 libstdc++-v3/include/bits/fs_fwd.h            | 16 ++++
 libstdc++-v3/include/bits/ios_base.h          | 89 ++++++++++++-------
 libstdc++-v3/include/bits/regex_constants.h   | 52 ++++++-----
 .../include/experimental/bits/fs_fwd.h        | 12 +++
 libstdc++-v3/include/std/charconv             |  4 +
 libstdc++-v3/include/std/future               |  7 ++
 .../filesystem/operations/bitmask_types.cc    | 56 ++++++++++++
 .../types/fmtflags/bitmask_operators.cc       |  4 +
 .../types/iostate/bitmask_operators.cc        |  4 +
 .../types/openmode/bitmask_operators.cc       |  4 +
 11 files changed, 194 insertions(+), 58 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/27_io/filesystem/operations/bitmask_types.cc
diff mbox series

Patch

diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index d3a2c4f3805..b857b441169 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -100,13 +100,13 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// @endcond
 
   constexpr memory_order
-  operator|(memory_order __m, __memory_order_modifier __mod)
+  operator|(memory_order __m, __memory_order_modifier __mod) noexcept
   {
     return memory_order(int(__m) | int(__mod));
   }
 
   constexpr memory_order
-  operator&(memory_order __m, __memory_order_modifier __mod)
+  operator&(memory_order __m, __memory_order_modifier __mod) noexcept
   {
     return memory_order(int(__m) & int(__mod));
   }
diff --git a/libstdc++-v3/include/bits/fs_fwd.h b/libstdc++-v3/include/bits/fs_fwd.h
index 6208e799b84..7e2bc30df30 100644
--- a/libstdc++-v3/include/bits/fs_fwd.h
+++ b/libstdc++-v3/include/bits/fs_fwd.h
@@ -91,6 +91,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 
   /// @{
   /// @relates copy_options
+  [[nodiscard]]
   constexpr copy_options
   operator&(copy_options __x, copy_options __y) noexcept
   {
@@ -99,6 +100,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) & static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr copy_options
   operator|(copy_options __x, copy_options __y) noexcept
   {
@@ -107,6 +109,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) | static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr copy_options
   operator^(copy_options __x, copy_options __y) noexcept
   {
@@ -115,6 +118,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr copy_options
   operator~(copy_options __x) noexcept
   {
@@ -161,6 +165,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 
   /// @{
   /// @relates perms
+  [[nodiscard]]
   constexpr perms
   operator&(perms __x, perms __y) noexcept
   {
@@ -169,6 +174,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) & static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr perms
   operator|(perms __x, perms __y) noexcept
   {
@@ -177,6 +183,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) | static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr perms
   operator^(perms __x, perms __y) noexcept
   {
@@ -185,6 +192,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr perms
   operator~(perms __x) noexcept
   {
@@ -215,6 +223,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 
   /// @{
   /// @relates perm_options
+  [[nodiscard]]
   constexpr perm_options
   operator&(perm_options __x, perm_options __y) noexcept
   {
@@ -223,6 +232,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) & static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr perm_options
   operator|(perm_options __x, perm_options __y) noexcept
   {
@@ -231,6 +241,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) | static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr perm_options
   operator^(perm_options __x, perm_options __y) noexcept
   {
@@ -239,6 +250,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr perm_options
   operator~(perm_options __x) noexcept
   {
@@ -266,6 +278,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 
   /// @{
   /// @relates directory_options
+  [[nodiscard]]
   constexpr directory_options
   operator&(directory_options __x, directory_options __y) noexcept
   {
@@ -274,6 +287,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) & static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr directory_options
   operator|(directory_options __x, directory_options __y) noexcept
   {
@@ -282,6 +296,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) | static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr directory_options
   operator^(directory_options __x, directory_options __y) noexcept
   {
@@ -290,6 +305,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
   }
 
+  [[nodiscard]]
   constexpr directory_options
   operator~(directory_options __x) noexcept
   {
diff --git a/libstdc++-v3/include/bits/ios_base.h b/libstdc++-v3/include/bits/ios_base.h
index f0019649c3d..b69151c49ad 100644
--- a/libstdc++-v3/include/bits/ios_base.h
+++ b/libstdc++-v3/include/bits/ios_base.h
@@ -79,32 +79,39 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _S_ios_fmtflags_min = ~__INT_MAX__
     };
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Fmtflags
-  operator&(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Fmtflags
+  operator&(_Ios_Fmtflags __a, _Ios_Fmtflags __b) _GLIBCXX_NOTHROW
   { return _Ios_Fmtflags(static_cast<int>(__a) & static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Fmtflags
-  operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Fmtflags
+  operator|(_Ios_Fmtflags __a, _Ios_Fmtflags __b) _GLIBCXX_NOTHROW
   { return _Ios_Fmtflags(static_cast<int>(__a) | static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Fmtflags
-  operator^(_Ios_Fmtflags __a, _Ios_Fmtflags __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Fmtflags
+  operator^(_Ios_Fmtflags __a, _Ios_Fmtflags __b) _GLIBCXX_NOTHROW
   { return _Ios_Fmtflags(static_cast<int>(__a) ^ static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Fmtflags
-  operator~(_Ios_Fmtflags __a)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Fmtflags
+  operator~(_Ios_Fmtflags __a) _GLIBCXX_NOTHROW
   { return _Ios_Fmtflags(~static_cast<int>(__a)); }
 
+  _GLIBCXX14_CONSTEXPR
   inline const _Ios_Fmtflags&
-  operator|=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b)
+  operator|=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b) _GLIBCXX_NOTHROW
   { return __a = __a | __b; }
 
+  _GLIBCXX14_CONSTEXPR
   inline const _Ios_Fmtflags&
-  operator&=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b)
+  operator&=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b) _GLIBCXX_NOTHROW
   { return __a = __a & __b; }
 
+  _GLIBCXX14_CONSTEXPR
   inline const _Ios_Fmtflags&
-  operator^=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b)
+  operator^=(_Ios_Fmtflags& __a, _Ios_Fmtflags __b) _GLIBCXX_NOTHROW
   { return __a = __a ^ __b; }
 
 
@@ -122,32 +129,39 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _S_ios_openmode_min = ~__INT_MAX__
     };
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Openmode
-  operator&(_Ios_Openmode __a, _Ios_Openmode __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Openmode
+  operator&(_Ios_Openmode __a, _Ios_Openmode __b) _GLIBCXX_NOTHROW
   { return _Ios_Openmode(static_cast<int>(__a) & static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Openmode
-  operator|(_Ios_Openmode __a, _Ios_Openmode __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Openmode
+  operator|(_Ios_Openmode __a, _Ios_Openmode __b) _GLIBCXX_NOTHROW
   { return _Ios_Openmode(static_cast<int>(__a) | static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Openmode
-  operator^(_Ios_Openmode __a, _Ios_Openmode __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Openmode
+  operator^(_Ios_Openmode __a, _Ios_Openmode __b) _GLIBCXX_NOTHROW
   { return _Ios_Openmode(static_cast<int>(__a) ^ static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Openmode
-  operator~(_Ios_Openmode __a)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Openmode
+  operator~(_Ios_Openmode __a) _GLIBCXX_NOTHROW
   { return _Ios_Openmode(~static_cast<int>(__a)); }
 
+  _GLIBCXX14_CONSTEXPR
   inline const _Ios_Openmode&
-  operator|=(_Ios_Openmode& __a, _Ios_Openmode __b)
+  operator|=(_Ios_Openmode& __a, _Ios_Openmode __b) _GLIBCXX_NOTHROW
   { return __a = __a | __b; }
 
+  _GLIBCXX14_CONSTEXPR
   inline const _Ios_Openmode&
-  operator&=(_Ios_Openmode& __a, _Ios_Openmode __b)
+  operator&=(_Ios_Openmode& __a, _Ios_Openmode __b) _GLIBCXX_NOTHROW
   { return __a = __a & __b; }
 
+  _GLIBCXX14_CONSTEXPR
   inline const _Ios_Openmode&
-  operator^=(_Ios_Openmode& __a, _Ios_Openmode __b)
+  operator^=(_Ios_Openmode& __a, _Ios_Openmode __b) _GLIBCXX_NOTHROW
   { return __a = __a ^ __b; }
 
 
@@ -162,32 +176,39 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _S_ios_iostate_min = ~__INT_MAX__
     };
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Iostate
-  operator&(_Ios_Iostate __a, _Ios_Iostate __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Iostate
+  operator&(_Ios_Iostate __a, _Ios_Iostate __b) _GLIBCXX_NOTHROW
   { return _Ios_Iostate(static_cast<int>(__a) & static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Iostate
-  operator|(_Ios_Iostate __a, _Ios_Iostate __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Iostate
+  operator|(_Ios_Iostate __a, _Ios_Iostate __b) _GLIBCXX_NOTHROW
   { return _Ios_Iostate(static_cast<int>(__a) | static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Iostate
-  operator^(_Ios_Iostate __a, _Ios_Iostate __b)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Iostate
+  operator^(_Ios_Iostate __a, _Ios_Iostate __b) _GLIBCXX_NOTHROW
   { return _Ios_Iostate(static_cast<int>(__a) ^ static_cast<int>(__b)); }
 
-  inline _GLIBCXX_CONSTEXPR _Ios_Iostate
-  operator~(_Ios_Iostate __a)
+  _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+  inline _Ios_Iostate
+  operator~(_Ios_Iostate __a) _GLIBCXX_NOTHROW
   { return _Ios_Iostate(~static_cast<int>(__a)); }
 
+  _GLIBCXX14_CONSTEXPR
   inline const _Ios_Iostate&
-  operator|=(_Ios_Iostate& __a, _Ios_Iostate __b)
+  operator|=(_Ios_Iostate& __a, _Ios_Iostate __b) _GLIBCXX_NOTHROW
   { return __a = __a | __b; }
 
+  _GLIBCXX14_CONSTEXPR
   inline const _Ios_Iostate&
-  operator&=(_Ios_Iostate& __a, _Ios_Iostate __b)
+  operator&=(_Ios_Iostate& __a, _Ios_Iostate __b) _GLIBCXX_NOTHROW
   { return __a = __a & __b; }
 
-  inline const  _Ios_Iostate&
-  operator^=(_Ios_Iostate& __a, _Ios_Iostate __b)
+  _GLIBCXX14_CONSTEXPR
+  inline const _Ios_Iostate&
+  operator^=(_Ios_Iostate& __a, _Ios_Iostate __b) _GLIBCXX_NOTHROW
   { return __a = __a ^ __b; }
 
 
diff --git a/libstdc++-v3/include/bits/regex_constants.h b/libstdc++-v3/include/bits/regex_constants.h
index 5e567ec2027..437895f1dc3 100644
--- a/libstdc++-v3/include/bits/regex_constants.h
+++ b/libstdc++-v3/include/bits/regex_constants.h
@@ -186,44 +186,48 @@  namespace regex_constants
    */
   _GLIBCXX17_INLINE constexpr syntax_option_type __polynomial = _S_polynomial;
 
-  constexpr inline syntax_option_type
-  operator&(syntax_option_type __a, syntax_option_type __b)
+  [[__nodiscard__]]
+  constexpr syntax_option_type
+  operator&(syntax_option_type __a, syntax_option_type __b) noexcept
   {
     return (syntax_option_type)(static_cast<unsigned int>(__a)
 				& static_cast<unsigned int>(__b));
   }
 
-  constexpr inline syntax_option_type
-  operator|(syntax_option_type __a, syntax_option_type __b)
+  [[__nodiscard__]]
+  constexpr syntax_option_type
+  operator|(syntax_option_type __a, syntax_option_type __b) noexcept
   {
     return (syntax_option_type)(static_cast<unsigned int>(__a)
 				| static_cast<unsigned int>(__b));
   }
 
-  constexpr inline syntax_option_type
-  operator^(syntax_option_type __a, syntax_option_type __b)
+  [[__nodiscard__]]
+  constexpr syntax_option_type
+  operator^(syntax_option_type __a, syntax_option_type __b) noexcept
   {
     return (syntax_option_type)(static_cast<unsigned int>(__a)
 				^ static_cast<unsigned int>(__b));
   }
 
-  constexpr inline syntax_option_type
-  operator~(syntax_option_type __a)
+  [[__nodiscard__]]
+  constexpr syntax_option_type
+  operator~(syntax_option_type __a) noexcept
   { return (syntax_option_type)(~static_cast<unsigned int>(__a)); }
 
   _GLIBCXX14_CONSTEXPR
   inline syntax_option_type&
-  operator&=(syntax_option_type& __a, syntax_option_type __b)
+  operator&=(syntax_option_type& __a, syntax_option_type __b) noexcept
   { return __a = __a & __b; }
 
   _GLIBCXX14_CONSTEXPR
   inline syntax_option_type&
-  operator|=(syntax_option_type& __a, syntax_option_type __b)
+  operator|=(syntax_option_type& __a, syntax_option_type __b) noexcept
   { return __a = __a | __b; }
 
   _GLIBCXX14_CONSTEXPR
   inline syntax_option_type&
-  operator^=(syntax_option_type& __a, syntax_option_type __b)
+  operator^=(syntax_option_type& __a, syntax_option_type __b) noexcept
   { return __a = __a ^ __b; }
 
   ///@}
@@ -367,44 +371,48 @@  namespace regex_constants
    */
   _GLIBCXX17_INLINE constexpr match_flag_type format_first_only = _S_first_only;
 
-  constexpr inline match_flag_type
-  operator&(match_flag_type __a, match_flag_type __b)
+  [[__nodiscard__]]
+  constexpr match_flag_type
+  operator&(match_flag_type __a, match_flag_type __b) noexcept
   {
     return (match_flag_type)(static_cast<unsigned int>(__a)
 				& static_cast<unsigned int>(__b));
   }
 
-  constexpr inline match_flag_type
-  operator|(match_flag_type __a, match_flag_type __b)
+  [[__nodiscard__]]
+  constexpr match_flag_type
+  operator|(match_flag_type __a, match_flag_type __b) noexcept
   {
     return (match_flag_type)(static_cast<unsigned int>(__a)
 				| static_cast<unsigned int>(__b));
   }
 
-  constexpr inline match_flag_type
-  operator^(match_flag_type __a, match_flag_type __b)
+  [[__nodiscard__]]
+  constexpr match_flag_type
+  operator^(match_flag_type __a, match_flag_type __b) noexcept
   {
     return (match_flag_type)(static_cast<unsigned int>(__a)
 				^ static_cast<unsigned int>(__b));
   }
 
-  constexpr inline match_flag_type
-  operator~(match_flag_type __a)
+  [[__nodiscard__]]
+  constexpr match_flag_type
+  operator~(match_flag_type __a) noexcept
   { return (match_flag_type)(~static_cast<unsigned int>(__a)); }
 
   _GLIBCXX14_CONSTEXPR
   inline match_flag_type&
-  operator&=(match_flag_type& __a, match_flag_type __b)
+  operator&=(match_flag_type& __a, match_flag_type __b) noexcept
   { return __a = __a & __b; }
 
   _GLIBCXX14_CONSTEXPR
   inline match_flag_type&
-  operator|=(match_flag_type& __a, match_flag_type __b)
+  operator|=(match_flag_type& __a, match_flag_type __b) noexcept
   { return __a = __a | __b; }
 
   _GLIBCXX14_CONSTEXPR
   inline match_flag_type&
-  operator^=(match_flag_type& __a, match_flag_type __b)
+  operator^=(match_flag_type& __a, match_flag_type __b) noexcept
   { return __a = __a ^ __b; }
 
   ///@}
diff --git a/libstdc++-v3/include/experimental/bits/fs_fwd.h b/libstdc++-v3/include/experimental/bits/fs_fwd.h
index a5b8feaaa4a..565f2e43692 100644
--- a/libstdc++-v3/include/experimental/bits/fs_fwd.h
+++ b/libstdc++-v3/include/experimental/bits/fs_fwd.h
@@ -102,6 +102,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 
   /// @{
   /// @relates copy_options
+  [[__nodiscard__]]
   constexpr copy_options
   operator&(copy_options __x, copy_options __y) noexcept
   {
@@ -110,6 +111,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) & static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr copy_options
   operator|(copy_options __x, copy_options __y) noexcept
   {
@@ -118,6 +120,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) | static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr copy_options
   operator^(copy_options __x, copy_options __y) noexcept
   {
@@ -126,6 +129,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr copy_options
   operator~(copy_options __x) noexcept
   {
@@ -174,6 +178,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 
   /// @{
   /// @relates std::experimental::filesystem::perms
+  [[__nodiscard__]]
   constexpr perms
   operator&(perms __x, perms __y) noexcept
   {
@@ -182,6 +187,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) & static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr perms
   operator|(perms __x, perms __y) noexcept
   {
@@ -190,6 +196,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) | static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr perms
   operator^(perms __x, perms __y) noexcept
   {
@@ -198,6 +205,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr perms
   operator~(perms __x) noexcept
   {
@@ -225,6 +233,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 
   /// @{
   /// @relates directory_options
+  [[__nodiscard__]]
   constexpr directory_options
   operator&(directory_options __x, directory_options __y) noexcept
   {
@@ -233,6 +242,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) & static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr directory_options
   operator|(directory_options __x, directory_options __y) noexcept
   {
@@ -241,6 +251,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) | static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr directory_options
   operator^(directory_options __x, directory_options __y) noexcept
   {
@@ -249,6 +260,7 @@  _GLIBCXX_END_NAMESPACE_CXX11
 	static_cast<__utype>(__x) ^ static_cast<__utype>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr directory_options
   operator~(directory_options __x) noexcept
   {
diff --git a/libstdc++-v3/include/std/charconv b/libstdc++-v3/include/std/charconv
index 21c387973f1..e516e3b2da8 100644
--- a/libstdc++-v3/include/std/charconv
+++ b/libstdc++-v3/include/std/charconv
@@ -622,18 +622,22 @@  namespace __detail
     scientific = 1, fixed = 2, hex = 4, general = fixed | scientific
   };
 
+  [[nodiscard]]
   constexpr chars_format
   operator|(chars_format __lhs, chars_format __rhs) noexcept
   { return (chars_format)((unsigned)__lhs | (unsigned)__rhs); }
 
+  [[nodiscard]]
   constexpr chars_format
   operator&(chars_format __lhs, chars_format __rhs) noexcept
   { return (chars_format)((unsigned)__lhs & (unsigned)__rhs); }
 
+  [[nodiscard]]
   constexpr chars_format
   operator^(chars_format __lhs, chars_format __rhs) noexcept
   { return (chars_format)((unsigned)__lhs ^ (unsigned)__rhs); }
 
+  [[nodiscard]]
   constexpr chars_format
   operator~(chars_format __fmt) noexcept
   { return (chars_format)~(unsigned)__fmt; }
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index 1cba04a0e5a..9e75ae98b13 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -152,33 +152,40 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     deferred = 2
   };
 
+  [[__nodiscard__]]
   constexpr launch operator&(launch __x, launch __y) noexcept
   {
     return static_cast<launch>(
 	static_cast<int>(__x) & static_cast<int>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr launch operator|(launch __x, launch __y) noexcept
   {
     return static_cast<launch>(
 	static_cast<int>(__x) | static_cast<int>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr launch operator^(launch __x, launch __y) noexcept
   {
     return static_cast<launch>(
 	static_cast<int>(__x) ^ static_cast<int>(__y));
   }
 
+  [[__nodiscard__]]
   constexpr launch operator~(launch __x) noexcept
   { return static_cast<launch>(~static_cast<int>(__x)); }
 
+  _GLIBCXX14_CONSTEXPR
   inline launch& operator&=(launch& __x, launch __y) noexcept
   { return __x = __x & __y; }
 
+  _GLIBCXX14_CONSTEXPR
   inline launch& operator|=(launch& __x, launch __y) noexcept
   { return __x = __x | __y; }
 
+  _GLIBCXX14_CONSTEXPR
   inline launch& operator^=(launch& __x, launch __y) noexcept
   { return __x = __x ^ __y; }
 
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/bitmask_types.cc b/libstdc++-v3/testsuite/27_io/filesystem/operations/bitmask_types.cc
new file mode 100644
index 00000000000..aa3d36e1c45
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/bitmask_types.cc
@@ -0,0 +1,56 @@ 
+// { dg-do compile { target c++17 } }
+#include <filesystem>
+
+namespace fs = std::filesystem;
+
+void
+test_copy_options()
+{
+  using T = fs::copy_options;
+  constexpr T val = T::none;
+  constexpr T all = ((val | val) & val) ^ ~val;
+  static_assert( noexcept(((val | val) & val) ^ ~val) );
+  val & val; // { dg-warning "ignoring return value" }
+  val | val; // { dg-warning "ignoring return value" }
+  val ^ val; // { dg-warning "ignoring return value" }
+  ~val;      // { dg-warning "ignoring return value" }
+}
+
+void
+test_perms()
+{
+  using T = fs::perms;
+  constexpr T val = T::none;
+  constexpr T all = ((val | val) & val) ^ ~val;
+  static_assert( noexcept(((val | val) & val) ^ ~val) );
+  val & val; // { dg-warning "ignoring return value" }
+  val | val; // { dg-warning "ignoring return value" }
+  val ^ val; // { dg-warning "ignoring return value" }
+  ~val;      // { dg-warning "ignoring return value" }
+}
+
+void
+test_perm_options()
+{
+  using T = fs::perm_options;
+  constexpr T val = T::replace;
+  constexpr T all = ((val | val) & val) ^ ~val;
+  static_assert( noexcept(((val | val) & val) ^ ~val) );
+  val & val; // { dg-warning "ignoring return value" }
+  val | val; // { dg-warning "ignoring return value" }
+  val ^ val; // { dg-warning "ignoring return value" }
+  ~val;      // { dg-warning "ignoring return value" }
+}
+
+void
+test_directory_options()
+{
+  using T = fs::directory_options;
+  constexpr T val = T::none;
+  constexpr T all = ((val | val) & val) ^ ~val;
+  static_assert( noexcept(((val | val) & val) ^ ~val) );
+  val & val; // { dg-warning "ignoring return value" }
+  val | val; // { dg-warning "ignoring return value" }
+  val ^ val; // { dg-warning "ignoring return value" }
+  ~val;      // { dg-warning "ignoring return value" }
+}
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc
index 64ef31d9cd0..604d2aa6b5a 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/types/fmtflags/bitmask_operators.cc
@@ -27,3 +27,7 @@  int main()
 {
   __gnu_test::bitmask_operators<std::ios_base::fmtflags>();
 }
+// { dg-warning "ignoring return value.*operator\\|" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator&" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator\\^" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator~" "" { target c++17 } 0 }
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc
index 218cf8b8a95..a98435867ed 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/types/iostate/bitmask_operators.cc
@@ -27,3 +27,7 @@  int main()
 {
   __gnu_test::bitmask_operators<std::ios_base::iostate>();
 }
+// { dg-warning "ignoring return value.*operator\\|" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator&" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator\\^" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator~" "" { target c++17 } 0 }
diff --git a/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc b/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc
index b5f1e781676..6d024217362 100644
--- a/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc
+++ b/libstdc++-v3/testsuite/27_io/ios_base/types/openmode/bitmask_operators.cc
@@ -27,3 +27,7 @@  int main()
 {
   __gnu_test::bitmask_operators<std::ios_base::openmode>();
 }
+// { dg-warning "ignoring return value.*operator\\|" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator&" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator\\^" "" { target c++17 } 0 }
+// { dg-warning "ignoring return value.*operator~" "" { target c++17 } 0 }