From: Jonathan Wakely Date: Fri, 30 Sep 2022 13:22:01 +0000 (-0400) Subject: [libc++] Fix ADL for `make_error_{code,condition}` X-Git-Tag: upstream/17.0.6~31926 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ef843c8271027b89419d07ffc2aaa3abf91438ef;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv index 85a93cc..20b20b4 100644 --- a/libcxx/docs/Status/Cxx2bIssues.csv +++ b/libcxx/docs/Status/Cxx2bIssues.csv @@ -186,6 +186,7 @@ "`3721 `__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","July 2022","|Complete|","16.0","|format|" "`3724 `__","``decay-copy`` should be constrained","July 2022","|Complete|","14.0" "","","","","" -"`3645 `__","``resize_and_overwrite`` is overspecified to call its callback with lvalues","Not voted in","|Complete|","14.0","" +"`3629 `__","``make_error_code`` and ``make_error_condition`` are customization points","Not voted in","|Complete|","16.0","" "`3631 `__","``basic_format_arg(T&&)`` should use ``remove_cvref_t`` throughout","Not voted in","|Complete|","15.0","" +"`3645 `__","``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 f81165f..9891992 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::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::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 0000000..edf1541 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// class error_code + +// template 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 + +#include +#include +#include + +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 : 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 0000000..715d8c7 --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// class error_code + +// template 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 + +#include +#include +#include + +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 : 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 0000000..3a7dfba --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// class error_condition + +// template 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 + +#include +#include +#include + +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 : 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 0000000..95b6f6e --- /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 +// +//===----------------------------------------------------------------------===// + +// + +// class error_condition + +// template 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 + +#include +#include +#include + +#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 : 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; +}