[libcxx-commits] [libcxx] ef843c8 - [libc++] Fix ADL for `make_error_{code, condition}`

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Fri Sep 30 14:23:55 PDT 2022


Author: Jonathan Wakely
Date: 2022-09-30T17:23:45-04:00
New Revision: ef843c8271027b89419d07ffc2aaa3abf91438ef

URL: https://github.com/llvm/llvm-project/commit/ef843c8271027b89419d07ffc2aaa3abf91438ef
DIFF: https://github.com/llvm/llvm-project/commit/ef843c8271027b89419d07ffc2aaa3abf91438ef.diff

LOG: [libc++] Fix ADL for `make_error_{code,condition}`

Implement LWG 3629, by making lookup for make_error_code and
make_error_condition only consider names found by ADL. This is achieved
by adding a block scope using-declaration for a function that will be
found by unqualified lookup, preventing unqualified lookup from
continuing to enclosing scopes (the class scope, then enclosing
namespaces). The function named by the using declaration is not
viable, so overload resolution must select a candidate found by ADL.

This fixes https://github.com/llvm/llvm-project/issues/57614

Differential Revision: https://reviews.llvm.org/D134943

Added: 
    libcxx/test/std/diagnostics/syserr/syserr.errcode/syserr.errcode.constructors/lwg3629.pass.cpp
    libcxx/test/std/diagnostics/syserr/syserr.errcode/syserr.errcode.modifiers/lwg3629.pass.cpp
    libcxx/test/std/diagnostics/syserr/syserr.errcondition/syserr.errcondition.constructors/lwg3629.pass.cpp
    libcxx/test/std/diagnostics/syserr/syserr.errcondition/syserr.errcondition.modifiers/lwg3629.pass.cpp

Modified: 
    libcxx/docs/Status/Cxx2bIssues.csv
    libcxx/include/system_error

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv
index 85a93cc52ee64..20b20b46a16db 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -186,6 +186,7 @@
 "`3721 <https://wg21.link/LWG3721>`__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","July 2022","|Complete|","16.0","|format|"
 "`3724 <https://wg21.link/LWG3724>`__","``decay-copy`` should be constrained","July 2022","|Complete|","14.0"
 "","","","",""
-"`3645 <https://wg21.link/LWG3645>`__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","Not voted in","|Complete|","14.0",""
+"`3629 <https://wg21.link/LWG3629>`__","``make_error_code`` and ``make_error_condition`` are customization points","Not voted in","|Complete|","16.0",""
 "`3631 <https://wg21.link/LWG3631>`__","``basic_format_arg(T&&)`` should use ``remove_cvref_t<T>`` throughout","Not voted in","|Complete|","15.0",""
+"`3645 <https://wg21.link/LWG3645>`__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","Not voted in","|Complete|","14.0",""
 "","","","",""

diff  --git a/libcxx/include/system_error b/libcxx/include/system_error
index f81165fb8b410..98919927bc042 100644
--- a/libcxx/include/system_error
+++ b/libcxx/include/system_error
@@ -256,6 +256,13 @@ public:
 _LIBCPP_FUNC_VIS const error_category& generic_category() _NOEXCEPT;
 _LIBCPP_FUNC_VIS const error_category& system_category() _NOEXCEPT;
 
+namespace __adl_only {
+    // Those cause ADL to trigger but they are not viable candidates,
+    // so they are never actually selected.
+    void make_error_condition() = delete;
+    void make_error_code() = delete;
+} // namespace __adl_only
+
 class _LIBCPP_TYPE_VIS error_condition
 {
     int __val_;
@@ -273,7 +280,10 @@ public:
         error_condition(_Ep __e,
               typename enable_if<is_error_condition_enum<_Ep>::value>::type* = nullptr
                                                                      ) _NOEXCEPT
-            {*this = make_error_condition(__e);}
+            {
+                using __adl_only::make_error_condition;
+                *this = make_error_condition(__e);
+            }
 
     _LIBCPP_INLINE_VISIBILITY
     void assign(int __val, const error_category& __cat) _NOEXCEPT
@@ -290,7 +300,11 @@ public:
             error_condition&
         >::type
         operator=(_Ep __e) _NOEXCEPT
-            {*this = make_error_condition(__e); return *this;}
+            {
+                using __adl_only::make_error_condition;
+                *this = make_error_condition(__e);
+                return *this;
+            }
 
     _LIBCPP_INLINE_VISIBILITY
     void clear() _NOEXCEPT
@@ -336,7 +350,10 @@ public:
         error_code(_Ep __e,
                    typename enable_if<is_error_code_enum<_Ep>::value>::type* = nullptr
                                                                      ) _NOEXCEPT
-            {*this = make_error_code(__e);}
+            {
+                using __adl_only::make_error_code;
+                *this = make_error_code(__e);
+            }
 
     _LIBCPP_INLINE_VISIBILITY
     void assign(int __val, const error_category& __cat) _NOEXCEPT
@@ -353,7 +370,11 @@ public:
             error_code&
         >::type
         operator=(_Ep __e) _NOEXCEPT
-            {*this = make_error_code(__e); return *this;}
+            {
+                using __adl_only::make_error_code;
+                *this = make_error_code(__e);
+                return *this;
+            }
 
     _LIBCPP_INLINE_VISIBILITY
     void clear() _NOEXCEPT

diff  --git a/libcxx/test/std/diagnostics/syserr/syserr.errcode/syserr.errcode.constructors/lwg3629.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcode/syserr.errcode.constructors/lwg3629.pass.cpp
new file mode 100644
index 0000000000000..edf1541e383c0
--- /dev/null
+++ b/libcxx/test/std/diagnostics/syserr/syserr.errcode/syserr.errcode.constructors/lwg3629.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <system_error>
+
+// class error_code
+
+// template <ErrorCodeEnum E> error_code(E e);
+
+// Regression test for https://github.com/llvm/llvm-project/issues/57614
+
+int make_error_code; // It's important that this comes before <system_error>
+
+#include <system_error>
+#include <cassert>
+#include <type_traits>
+
+namespace user {
+  enum Err {};
+
+  std::error_code make_error_code(Err) { return std::error_code(42, std::generic_category()); }
+}
+
+namespace std {
+  template <>
+  struct is_error_code_enum<user::Err> : true_type {};
+}
+
+int main(int, char**) {
+  std::error_code e((user::Err()));
+  assert(e.value() == 42);
+  assert(e.category() == std::generic_category());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/diagnostics/syserr/syserr.errcode/syserr.errcode.modifiers/lwg3629.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcode/syserr.errcode.modifiers/lwg3629.pass.cpp
new file mode 100644
index 0000000000000..715d8c763e1da
--- /dev/null
+++ b/libcxx/test/std/diagnostics/syserr/syserr.errcode/syserr.errcode.modifiers/lwg3629.pass.cpp
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <system_error>
+
+// class error_code
+
+// template <ErrorCodeEnum E> error_code& operator=(E e);
+
+// Regression test for https://github.com/llvm/llvm-project/issues/57614
+
+int make_error_code; // It's important that this comes before <system_error>
+
+#include <system_error>
+#include <cassert>
+#include <type_traits>
+
+namespace user {
+  enum Err {};
+
+  std::error_code make_error_code(Err) { return std::error_code(42, std::generic_category()); }
+}
+
+namespace std {
+  template <>
+  struct is_error_code_enum<user::Err> : true_type {};
+}
+
+int main(int, char**) {
+  std::error_code e;
+  e = user::Err();
+  assert(e.value() == 42);
+  assert(e.category() == std::generic_category());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/diagnostics/syserr/syserr.errcondition/syserr.errcondition.constructors/lwg3629.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcondition/syserr.errcondition.constructors/lwg3629.pass.cpp
new file mode 100644
index 0000000000000..3a7dfba62886d
--- /dev/null
+++ b/libcxx/test/std/diagnostics/syserr/syserr.errcondition/syserr.errcondition.constructors/lwg3629.pass.cpp
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <system_error>
+
+// class error_condition
+
+// template <ErrorCodeEnum E> error_condition(E e);
+
+// Regression test for https://github.com/llvm/llvm-project/issues/57614
+
+int make_error_condition; // It's important that this comes before <system_error>
+
+#include <system_error>
+#include <cassert>
+#include <type_traits>
+
+namespace user {
+  enum Err {};
+
+  std::error_condition make_error_condition(Err) { return std::error_condition(42, std::generic_category()); }
+}
+
+namespace std {
+  template <>
+  struct is_error_condition_enum<user::Err> : true_type {};
+}
+
+int main(int, char**) {
+  std::error_condition e((user::Err()));
+  assert(e.value() == 42);
+  assert(e.category() == std::generic_category());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/diagnostics/syserr/syserr.errcondition/syserr.errcondition.modifiers/lwg3629.pass.cpp b/libcxx/test/std/diagnostics/syserr/syserr.errcondition/syserr.errcondition.modifiers/lwg3629.pass.cpp
new file mode 100644
index 0000000000000..95b6f6e2d22d6
--- /dev/null
+++ b/libcxx/test/std/diagnostics/syserr/syserr.errcondition/syserr.errcondition.modifiers/lwg3629.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <system_error>
+
+// class error_condition
+
+// template <ErrorCodeEnum E> error_condition& operator=(E e);
+
+// Regression test for https://github.com/llvm/llvm-project/issues/57614
+
+int make_error_condition; // It's important that this comes before <system_error>
+
+#include <system_error>
+#include <cassert>
+#include <type_traits>
+
+#include "test_macros.h"
+
+namespace user {
+  enum Err {};
+
+  std::error_condition make_error_condition(Err) { return std::error_condition(42, std::generic_category()); }
+}
+
+namespace std {
+  template <>
+  struct is_error_condition_enum<user::Err> : true_type {};
+}
+
+int main(int, char**) {
+  std::error_condition e;
+  e = user::Err();
+  assert(e.value() == 42);
+  assert(e.category() == std::generic_category());
+  return 0;
+}


        


More information about the libcxx-commits mailing list