diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1207,6 +1207,17 @@ # define _LIBCPP_PACKED # endif +// There are a handful of standard library types that are intended to support CTAD but don't need any +// explicit deduction guides to do so. This macro is used to mark them as such, which suppresses the +// '-Wctad-maybe-unsupported' compiler warning when CTAD is used in user code with these classes. +#if _LIBCPP_STD_VER >= 17 +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) \ + template \ + _ClassName(typename _Tag::__allow_ctad)->_ClassName +#else +# define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "") +#endif + #endif // __cplusplus #endif // _LIBCPP___CONFIG diff --git a/libcxx/include/__functional/default_searcher.h b/libcxx/include/__functional/default_searcher.h --- a/libcxx/include/__functional/default_searcher.h +++ b/libcxx/include/__functional/default_searcher.h @@ -48,6 +48,7 @@ _ForwardIterator __last_; _BinaryPredicate __pred_; }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(default_searcher); #endif // _LIBCPP_STD_VER > 14 diff --git a/libcxx/include/__iterator/back_insert_iterator.h b/libcxx/include/__iterator/back_insert_iterator.h --- a/libcxx/include/__iterator/back_insert_iterator.h +++ b/libcxx/include/__iterator/back_insert_iterator.h @@ -58,6 +58,7 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Container* __get_container() const { return container; } }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(back_insert_iterator); template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 diff --git a/libcxx/include/__iterator/front_insert_iterator.h b/libcxx/include/__iterator/front_insert_iterator.h --- a/libcxx/include/__iterator/front_insert_iterator.h +++ b/libcxx/include/__iterator/front_insert_iterator.h @@ -56,6 +56,7 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 front_insert_iterator& operator++() {return *this;} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 front_insert_iterator operator++(int) {return *this;} }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(front_insert_iterator); template inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 diff --git a/libcxx/include/__iterator/move_iterator.h b/libcxx/include/__iterator/move_iterator.h --- a/libcxx/include/__iterator/move_iterator.h +++ b/libcxx/include/__iterator/move_iterator.h @@ -222,6 +222,7 @@ _Iter __current_; }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_iterator); template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17 diff --git a/libcxx/include/__mutex_base b/libcxx/include/__mutex_base --- a/libcxx/include/__mutex_base +++ b/libcxx/include/__mutex_base @@ -103,6 +103,7 @@ lock_guard(lock_guard const&) = delete; lock_guard& operator=(lock_guard const&) = delete; }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard); template class _LIBCPP_TEMPLATE_VIS unique_lock @@ -195,6 +196,7 @@ _LIBCPP_INLINE_VISIBILITY mutex_type* mutex() const _NOEXCEPT {return __m_;} }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock); template void diff --git a/libcxx/include/mutex b/libcxx/include/mutex --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -542,6 +542,7 @@ _MutexTuple __t_; }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scoped_lock); #endif // _LIBCPP_STD_VER > 14 #endif // !_LIBCPP_HAS_NO_THREADS diff --git a/libcxx/include/shared_mutex b/libcxx/include/shared_mutex --- a/libcxx/include/shared_mutex +++ b/libcxx/include/shared_mutex @@ -432,6 +432,7 @@ _LIBCPP_INLINE_VISIBILITY mutex_type* mutex() const _NOEXCEPT {return __m_;} }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(shared_lock); template void diff --git a/libcxx/include/string_view b/libcxx/include/string_view --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -726,6 +726,7 @@ const value_type* __data_; size_type __size_; }; +_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_string_view); #if _LIBCPP_STD_VER > 17 template diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/implicit_ctad.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/implicit_ctad.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/implicit_ctad.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// back_insert_iterator + +// Make sure that the implicitly-generated CTAD works. + +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + { + std::string s; + std::back_insert_iterator it(s); + ASSERT_SAME_TYPE(decltype(it), std::back_insert_iterator); + } + { + std::vector v; + std::back_insert_iterator it(v); + std::back_insert_iterator copy(it); + ASSERT_SAME_TYPE(decltype(it), std::back_insert_iterator>); + ASSERT_SAME_TYPE(decltype(copy), std::back_insert_iterator>); + } + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/implicit_ctad.pass.cpp b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/implicit_ctad.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/implicit_ctad.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// front_insert_iterator + +// Make sure that the implicitly-generated CTAD works. + +#include +#include +#include + +#include "test_macros.h" + +int main(int, char**) { + { + std::string s; + std::front_insert_iterator it(s); + ASSERT_SAME_TYPE(decltype(it), std::front_insert_iterator); + } + { + std::deque v; + std::front_insert_iterator it(v); + std::front_insert_iterator copy(it); + ASSERT_SAME_TYPE(decltype(it), std::front_insert_iterator>); + ASSERT_SAME_TYPE(decltype(copy), std::front_insert_iterator>); + } + + return 0; +} diff --git a/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/implicit_ctad.pass.cpp b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/implicit_ctad.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/implicit_ctad.pass.cpp @@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// move_iterator + +// Make sure that the implicitly-generated CTAD works. + +#include + +#include "test_macros.h" + +int main(int, char**) { + int* it = nullptr; + std::move_iterator move_it(it); + ASSERT_SAME_TYPE(decltype(move_it), std::move_iterator); + + return 0; +} diff --git a/libcxx/test/std/strings/string.view/string.view.deduct/implicit.pass.cpp b/libcxx/test/std/strings/string.view/string.view.deduct/implicit.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/strings/string.view/string.view.deduct/implicit.pass.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// basic_string_view + +// Make sure that the implicitly-generated CTAD works. + +#include + +#include "test_macros.h" + +int main(int, char**) { + { + char const* str = "hello world"; + std::basic_string_view sv(str); + ASSERT_SAME_TYPE(decltype(sv), std::basic_string_view); + } +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + { + wchar_t const* str = L"hello world"; + std::basic_string_view sv(str); + ASSERT_SAME_TYPE(decltype(sv), std::basic_string_view); + } +#endif + + return 0; +} diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-threads +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// lock_guard + +// Make sure that the implicitly-generated CTAD works. + +#include + +#include "test_macros.h" + +int main(int, char**) { + std::mutex mutex; + { + std::lock_guard lock(mutex); + ASSERT_SAME_TYPE(decltype(lock), std::lock_guard); + } + + return 0; +} + diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/implicit_ctad.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/implicit_ctad.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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-threads +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// scoped_lock + +// Make sure that the implicitly-generated CTAD works. + +#include + +#include "test_macros.h" + +int main(int, char**) { + std::mutex m1; + std::recursive_mutex m2; + std::recursive_timed_mutex m3; + { + std::scoped_lock lock(m1); + ASSERT_SAME_TYPE(decltype(lock), std::scoped_lock); + } + { + std::scoped_lock lock(m1, m2); + ASSERT_SAME_TYPE(decltype(lock), std::scoped_lock); + } + { + std::scoped_lock lock(m1, m2, m3); + ASSERT_SAME_TYPE(decltype(lock), std::scoped_lock); + } + + return 0; +} + diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-threads +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// shared_lock + +// Make sure that the implicitly-generated CTAD works. + +#include + +#include "test_macros.h" + +int main(int, char**) { + std::shared_mutex mutex; + { + std::shared_lock lock(mutex); + ASSERT_SAME_TYPE(decltype(lock), std::shared_lock); + } + + return 0; +} diff --git a/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp @@ -0,0 +1,30 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: no-threads +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// unique_lock + +// Make sure that the implicitly-generated CTAD works. + +#include + +#include "test_macros.h" + +int main(int, char**) { + std::mutex mutex; + { + std::unique_lock lock(mutex); + ASSERT_SAME_TYPE(decltype(lock), std::unique_lock); + } + + return 0; +} diff --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.default/implicit_ctad.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.default/implicit_ctad.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.default/implicit_ctad.pass.cpp @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14 + +// + +// default searcher + +// Make sure that the implicitly-generated CTAD works. + +#include + +#include "test_macros.h" + +int main(int, char**) { + { + char const* str = "hello"; + std::default_searcher searcher(str, str + 3); + ASSERT_SAME_TYPE(decltype(searcher), std::default_searcher>); + } + { + char const* str = "hello"; + std::default_searcher searcher(str, str + 3, std::not_equal_to<>()); + ASSERT_SAME_TYPE(decltype(searcher), std::default_searcher>); + } + + return 0; +} diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py --- a/libcxx/utils/libcxx/test/params.py +++ b/libcxx/utils/libcxx/test/params.py @@ -13,6 +13,7 @@ _warningFlags = [ '-Werror', '-Wall', + '-Wctad-maybe-unsupported', '-Wextra', '-Wshadow', '-Wundef',