[libcxx-commits] [libcxx] c2df707 - [libc++] Suppress -Wctad-maybe-unsupported on types w/o deduction guides

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Mon Oct 3 11:05:23 PDT 2022


Author: Louis Dionne
Date: 2022-10-03T14:05:08-04:00
New Revision: c2df70766647b39d302ab5ab952980e0b3b4d725

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

LOG: [libc++] Suppress -Wctad-maybe-unsupported on types w/o deduction guides

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 patch adds a dummy deduction guide to those types to suppress
-Wctad-maybe-unsupported (which gets emitted in user code).

This is a re-application of the original patch by Eric Fiselier in
fcd549a7d828 which had been reverted due to reasons lost at this point.
I also added the macro to a few more types. Reviving this patch was
prompted by the discussion on https://llvm.org/D133425.

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

Added: 
    libcxx/test/std/iterators/predef.iterators/counted.iterator/implicit_ctad.pass.cpp
    libcxx/test/std/iterators/predef.iterators/insert.iterators/back.insert.iterator/implicit_ctad.pass.cpp
    libcxx/test/std/iterators/predef.iterators/insert.iterators/front.insert.iterator/implicit_ctad.pass.cpp
    libcxx/test/std/iterators/predef.iterators/move.iterators/move.iterator/implicit_ctad.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.all/range.owning.view/implicit_ctad.pass.cpp
    libcxx/test/std/strings/string.view/string.view.deduct/implicit.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.guard/implicit_ctad.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.scoped/implicit_ctad.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp
    libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.unique/implicit_ctad.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bm/implicit_ctad.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/implicit_ctad.pass.cpp
    libcxx/test/std/utilities/function.objects/func.search/func.search.default/implicit_ctad.pass.cpp
    libcxx/test/std/utilities/function.objects/operations.implicit_ctad.pass.cpp
    libcxx/test/std/utilities/variant/variant.variant/implicit_ctad.pass.cpp

Modified: 
    libcxx/CMakeLists.txt
    libcxx/include/__config
    libcxx/include/__format/format_args.h
    libcxx/include/__format/format_context.h
    libcxx/include/__format/format_functions.h
    libcxx/include/__format/format_to_n_result.h
    libcxx/include/__format/parser_std_format_spec.h
    libcxx/include/__format/unicode.h
    libcxx/include/__functional/boyer_moore_searcher.h
    libcxx/include/__functional/default_searcher.h
    libcxx/include/__functional/operations.h
    libcxx/include/__iterator/back_insert_iterator.h
    libcxx/include/__iterator/counted_iterator.h
    libcxx/include/__iterator/front_insert_iterator.h
    libcxx/include/__iterator/move_iterator.h
    libcxx/include/__mutex_base
    libcxx/include/__ranges/owning_view.h
    libcxx/include/__ranges/range_adaptor.h
    libcxx/include/__utility/transaction.h
    libcxx/include/mutex
    libcxx/include/shared_mutex
    libcxx/include/string_view
    libcxx/src/filesystem/operations.cpp
    libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_back.pass.cpp
    libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h
    libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
    libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h
    libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/iter_swap.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp
    libcxx/test/std/ranges/range.adaptors/range.join.view/types.h
    libcxx/test/std/ranges/range.factories/range.iota.view/types.h
    libcxx/test/std/thread/thread.semaphore/ctor.compile.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.context/format.context/advance_to.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.context/format.context/arg.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.context/format.context/ctor.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.context/format.context/locale.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.context/format.context/out.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/advance_to.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/begin.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/ctor.pass.cpp
    libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/end.pass.cpp
    libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp
    libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
    libcxx/test/support/callable_types.h
    libcxx/test/support/test_iterators.h
    libcxx/utils/libcxx/test/params.py

Removed: 
    


################################################################################
diff  --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt
index 95847fb5b6294..a515615f08f60 100644
--- a/libcxx/CMakeLists.txt
+++ b/libcxx/CMakeLists.txt
@@ -584,7 +584,6 @@ function(cxx_add_warning_flags target)
       -Wno-user-defined-literals
       -Wno-covered-switch-default
       -Wno-suggest-override
-      -Wno-ctad-maybe-unsupported
     )
     if (LIBCXX_TARGETING_CLANG_CL)
       target_add_compile_flags_if_supported(${target} PRIVATE

diff  --git a/libcxx/include/__config b/libcxx/include/__config
index 460c4754f1436..94c54d9e9f4a1 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -1199,6 +1199,17 @@ _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_END_NAMESPACE_STD
 #    endif
 #  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 <class _Tag = void>                                                                                       \
+    _ClassName(typename _Tag::__allow_ctad) -> _ClassName<_Tag>
+#else
+#  define _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(_ClassName) static_assert(true, "")
+#endif
+
 #endif // __cplusplus
 
 #endif // _LIBCPP___CONFIG

diff  --git a/libcxx/include/__format/format_args.h b/libcxx/include/__format/format_args.h
index d90dc50acbd11..8b8fbde92fe67 100644
--- a/libcxx/include/__format/format_args.h
+++ b/libcxx/include/__format/format_args.h
@@ -71,6 +71,7 @@ class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_args {
     const basic_format_arg<_Context>* __args_;
   };
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_format_args);
 
 #endif //_LIBCPP_STD_VER > 17
 

diff  --git a/libcxx/include/__format/format_context.h b/libcxx/include/__format/format_context.h
index b9a41db05d51e..a2c79d9ec0651 100644
--- a/libcxx/include/__format/format_context.h
+++ b/libcxx/include/__format/format_context.h
@@ -50,8 +50,8 @@ __format_context_create(
     _OutIt __out_it,
     basic_format_args<basic_format_context<_OutIt, _CharT>> __args,
     optional<_VSTD::locale>&& __loc = nullopt) {
-  return _VSTD::basic_format_context(_VSTD::move(__out_it), __args,
-                                     _VSTD::move(__loc));
+  return _VSTD::basic_format_context<_OutIt, _CharT>(_VSTD::move(__out_it), __args,
+                                                     _VSTD::move(__loc));
 }
 #else
 template <class _OutIt, class _CharT>
@@ -59,7 +59,7 @@ _LIBCPP_HIDE_FROM_ABI basic_format_context<_OutIt, _CharT>
 __format_context_create(
     _OutIt __out_it,
     basic_format_args<basic_format_context<_OutIt, _CharT>> __args) {
-  return _VSTD::basic_format_context(_VSTD::move(__out_it), __args);
+  return _VSTD::basic_format_context<_OutIt, _CharT>(_VSTD::move(__out_it), __args);
 }
 #endif
 

diff  --git a/libcxx/include/__format/format_functions.h b/libcxx/include/__format/format_functions.h
index a197e3c79cd93..37621bc84798e 100644
--- a/libcxx/include/__format/format_functions.h
+++ b/libcxx/include/__format/format_functions.h
@@ -239,7 +239,7 @@ template <class _CharT, class _ParseCtx, class _Ctx>
 _LIBCPP_HIDE_FROM_ABI constexpr const _CharT*
 __handle_replacement_field(const _CharT* __begin, const _CharT* __end,
                            _ParseCtx& __parse_ctx, _Ctx& __ctx) {
-  __format::__parse_number_result __r =
+  __format::__parse_number_result<_CharT> __r =
       __format::__parse_arg_id(__begin, __end, __parse_ctx);
 
   bool __parse = *__r.__ptr == _CharT(':');
@@ -393,12 +393,12 @@ requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
         basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
   if constexpr (same_as<_OutIt, _FormatOutIt>)
     return _VSTD::__format::__vformat_to(
-        basic_format_parse_context{__fmt, __args.__size()},
+        basic_format_parse_context<_CharT>{__fmt, __args.__size()},
         _VSTD::__format_context_create(_VSTD::move(__out_it), __args));
   else {
     __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
     _VSTD::__format::__vformat_to(
-        basic_format_parse_context{__fmt, __args.__size()},
+        basic_format_parse_context<_CharT>{__fmt, __args.__size()},
         _VSTD::__format_context_create(__buffer.__make_output_iterator(),
                                        __args));
     return _VSTD::move(__buffer).__out_it();
@@ -473,7 +473,7 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it,
                                                                 basic_string_view<_CharT> __fmt,
                                                                 basic_format_args<_Context> __args) {
   __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
-  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
+  _VSTD::__format::__vformat_to(basic_format_parse_context<_CharT>{__fmt, __args.__size()},
                                 _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
   return _VSTD::move(__buffer).__result();
 }
@@ -496,7 +496,7 @@ format_to_n(_OutIt __out_it, iter_
diff erence_t<_OutIt> __n, wformat_string<_Args
 template <class _CharT>
 _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(basic_string_view<_CharT> __fmt, auto __args) {
   __format::__formatted_size_buffer<_CharT> __buffer;
-  _VSTD::__format::__vformat_to(basic_format_parse_context{__fmt, __args.__size()},
+  _VSTD::__format::__vformat_to(basic_format_parse_context<_CharT>{__fmt, __args.__size()},
                                 _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args));
   return _VSTD::move(__buffer).__result();
 }
@@ -524,13 +524,13 @@ requires(output_iterator<_OutIt, const _CharT&>) _LIBCPP_HIDE_FROM_ABI _OutIt
         basic_format_args<basic_format_context<_FormatOutIt, _CharT>> __args) {
   if constexpr (same_as<_OutIt, _FormatOutIt>)
     return _VSTD::__format::__vformat_to(
-        basic_format_parse_context{__fmt, __args.__size()},
+        basic_format_parse_context<_CharT>{__fmt, __args.__size()},
         _VSTD::__format_context_create(_VSTD::move(__out_it), __args,
                                        _VSTD::move(__loc)));
   else {
     __format::__format_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it)};
     _VSTD::__format::__vformat_to(
-        basic_format_parse_context{__fmt, __args.__size()},
+        basic_format_parse_context<_CharT>{__fmt, __args.__size()},
         _VSTD::__format_context_create(__buffer.__make_output_iterator(),
                                        __args, _VSTD::move(__loc)));
     return _VSTD::move(__buffer).__out_it();
@@ -610,7 +610,7 @@ _LIBCPP_HIDE_FROM_ABI format_to_n_result<_OutIt> __vformat_to_n(_OutIt __out_it,
                                                                 basic_format_args<_Context> __args) {
   __format::__format_to_n_buffer<_OutIt, _CharT> __buffer{_VSTD::move(__out_it), __n};
   _VSTD::__format::__vformat_to(
-      basic_format_parse_context{__fmt, __args.__size()},
+      basic_format_parse_context<_CharT>{__fmt, __args.__size()},
       _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
   return _VSTD::move(__buffer).__result();
 }
@@ -637,7 +637,7 @@ template <class _CharT>
 _LIBCPP_HIDE_FROM_ABI size_t __vformatted_size(locale __loc, basic_string_view<_CharT> __fmt, auto __args) {
   __format::__formatted_size_buffer<_CharT> __buffer;
   _VSTD::__format::__vformat_to(
-      basic_format_parse_context{__fmt, __args.__size()},
+      basic_format_parse_context<_CharT>{__fmt, __args.__size()},
       _VSTD::__format_context_create(__buffer.__make_output_iterator(), __args, _VSTD::move(__loc)));
   return _VSTD::move(__buffer).__result();
 }

diff  --git a/libcxx/include/__format/format_to_n_result.h b/libcxx/include/__format/format_to_n_result.h
index 25caa1c9e98d1..f1ed9a0982ab5 100644
--- a/libcxx/include/__format/format_to_n_result.h
+++ b/libcxx/include/__format/format_to_n_result.h
@@ -26,6 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS format_to_n_result {
   _OutIt out;
   iter_
diff erence_t<_OutIt> size;
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(format_to_n_result);
 
 #endif //_LIBCPP_STD_VER > 17
 

diff  --git a/libcxx/include/__format/parser_std_format_spec.h b/libcxx/include/__format/parser_std_format_spec.h
index 128f1d9c38d5c..4b2cb2be03c53 100644
--- a/libcxx/include/__format/parser_std_format_spec.h
+++ b/libcxx/include/__format/parser_std_format_spec.h
@@ -54,7 +54,7 @@ __parse_arg_id(const _CharT* __begin, const _CharT* __end, auto& __parse_ctx) {
   if (__begin == __end)
     __throw_format_error("End of input while parsing format-spec arg-id");
 
-  __format::__parse_number_result __r =
+  __format::__parse_number_result<_CharT> __r =
       __format::__parse_arg_id(__begin, __end, __parse_ctx);
 
   if (__r.__ptr == __end || *__r.__ptr != _CharT('}'))
@@ -422,7 +422,7 @@ class _LIBCPP_TEMPLATE_VIS __parser {
       __throw_format_error("A format-spec width field shouldn't have a leading zero");
 
     if (*__begin == _CharT('{')) {
-      __format::__parse_number_result __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx);
+      __format::__parse_number_result<_CharT> __r = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx);
       __width_as_arg_ = true;
       __width_ = __r.__value;
       __begin = __r.__ptr;
@@ -432,7 +432,7 @@ class _LIBCPP_TEMPLATE_VIS __parser {
     if (*__begin < _CharT('0') || *__begin > _CharT('9'))
       return false;
 
-    __format::__parse_number_result __r = __format::__parse_number(__begin, __end);
+    __format::__parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end);
     __width_ = __r.__value;
     _LIBCPP_ASSERT(__width_ != 0, "A zero value isn't allowed and should be impossible, "
                                   "due to validations in this function");
@@ -450,7 +450,7 @@ class _LIBCPP_TEMPLATE_VIS __parser {
       __throw_format_error("End of input while parsing format-spec precision");
 
     if (*__begin == _CharT('{')) {
-      __format::__parse_number_result __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx);
+      __format::__parse_number_result<_CharT> __arg_id = __format_spec::__parse_arg_id(++__begin, __end, __parse_ctx);
       __precision_as_arg_ = true;
       __precision_ = __arg_id.__value;
       __begin = __arg_id.__ptr;
@@ -460,7 +460,7 @@ class _LIBCPP_TEMPLATE_VIS __parser {
     if (*__begin < _CharT('0') || *__begin > _CharT('9'))
       __throw_format_error("The format-spec precision field doesn't contain a value or arg-id");
 
-    __format::__parse_number_result __r = __format::__parse_number(__begin, __end);
+    __format::__parse_number_result<_CharT> __r = __format::__parse_number(__begin, __end);
     __precision_ = __r.__value;
     __precision_as_arg_ = false;
     __begin = __r.__ptr;
@@ -879,7 +879,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr __column_width_result<_CharT> __estimate_column_
   }
 
   ptr
diff _t __ascii_size = __it - __str.begin();
-  __column_width_result __result =
+  __column_width_result<_CharT> __result =
       __detail::__estimate_column_width_grapheme_clustering(__it, __str.end(), __maximum, __rounding);
 
   __result.__width_ += __ascii_size;

diff  --git a/libcxx/include/__format/unicode.h b/libcxx/include/__format/unicode.h
index 3316217f4a1e6..83ca01b954ecb 100644
--- a/libcxx/include/__format/unicode.h
+++ b/libcxx/include/__format/unicode.h
@@ -328,6 +328,9 @@ class __extended_grapheme_cluster_view {
   }
 };
 
+template <class _CharT>
+__extended_grapheme_cluster_view(const _CharT*, const _CharT*) -> __extended_grapheme_cluster_view<_CharT>;
+
 } // namespace __unicode
 
 #  endif //  _LIBCPP_HAS_NO_UNICODE

diff  --git a/libcxx/include/__functional/boyer_moore_searcher.h b/libcxx/include/__functional/boyer_moore_searcher.h
index 20e554408ff01..a6750893ee57f 100644
--- a/libcxx/include/__functional/boyer_moore_searcher.h
+++ b/libcxx/include/__functional/boyer_moore_searcher.h
@@ -223,6 +223,7 @@ class _LIBCPP_TEMPLATE_VIS boyer_moore_searcher {
     }
   }
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(boyer_moore_searcher);
 
 template <class _RandomAccessIterator1,
           class _Hash = hash<typename iterator_traits<_RandomAccessIterator1>::value_type>,
@@ -303,6 +304,7 @@ class _LIBCPP_TEMPLATE_VIS boyer_moore_horspool_searcher {
     return std::make_pair(__l, __l);
   }
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(boyer_moore_horspool_searcher);
 
 _LIBCPP_END_NAMESPACE_STD
 

diff  --git a/libcxx/include/__functional/default_searcher.h b/libcxx/include/__functional/default_searcher.h
index 0e0f5afc569b3..e4151e589f78a 100644
--- a/libcxx/include/__functional/default_searcher.h
+++ b/libcxx/include/__functional/default_searcher.h
@@ -48,6 +48,7 @@ class _LIBCPP_TEMPLATE_VIS default_searcher {
     _ForwardIterator __last_;
     _BinaryPredicate __pred_;
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(default_searcher);
 
 #endif // _LIBCPP_STD_VER > 14
 

diff  --git a/libcxx/include/__functional/operations.h b/libcxx/include/__functional/operations.h
index 1f29094cd8f78..8a781efbdbbbe 100644
--- a/libcxx/include/__functional/operations.h
+++ b/libcxx/include/__functional/operations.h
@@ -36,6 +36,7 @@ struct _LIBCPP_TEMPLATE_VIS plus
     _Tp operator()(const _Tp& __x, const _Tp& __y) const
         {return __x + __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(plus);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -64,6 +65,7 @@ struct _LIBCPP_TEMPLATE_VIS minus
     _Tp operator()(const _Tp& __x, const _Tp& __y) const
         {return __x - __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(minus);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -92,6 +94,7 @@ struct _LIBCPP_TEMPLATE_VIS multiplies
     _Tp operator()(const _Tp& __x, const _Tp& __y) const
         {return __x * __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(multiplies);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -120,6 +123,7 @@ struct _LIBCPP_TEMPLATE_VIS divides
     _Tp operator()(const _Tp& __x, const _Tp& __y) const
         {return __x / __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(divides);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -148,6 +152,7 @@ struct _LIBCPP_TEMPLATE_VIS modulus
     _Tp operator()(const _Tp& __x, const _Tp& __y) const
         {return __x % __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(modulus);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -176,6 +181,7 @@ struct _LIBCPP_TEMPLATE_VIS negate
     _Tp operator()(const _Tp& __x) const
         {return -__x;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(negate);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -206,6 +212,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_and
     _Tp operator()(const _Tp& __x, const _Tp& __y) const
         {return __x & __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_and);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -230,6 +237,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_not
     _Tp operator()(const _Tp& __x) const
         {return ~__x;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_not);
 
 template <>
 struct _LIBCPP_TEMPLATE_VIS bit_not<void>
@@ -257,6 +265,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_or
     _Tp operator()(const _Tp& __x, const _Tp& __y) const
         {return __x | __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_or);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -285,6 +294,7 @@ struct _LIBCPP_TEMPLATE_VIS bit_xor
     _Tp operator()(const _Tp& __x, const _Tp& __y) const
         {return __x ^ __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(bit_xor);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -315,6 +325,7 @@ struct _LIBCPP_TEMPLATE_VIS equal_to
     bool operator()(const _Tp& __x, const _Tp& __y) const
         {return __x == __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(equal_to);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -343,6 +354,7 @@ struct _LIBCPP_TEMPLATE_VIS not_equal_to
     bool operator()(const _Tp& __x, const _Tp& __y) const
         {return __x != __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(not_equal_to);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -371,6 +383,7 @@ struct _LIBCPP_TEMPLATE_VIS less
     bool operator()(const _Tp& __x, const _Tp& __y) const
         {return __x < __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -399,6 +412,7 @@ struct _LIBCPP_TEMPLATE_VIS less_equal
     bool operator()(const _Tp& __x, const _Tp& __y) const
         {return __x <= __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(less_equal);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -427,6 +441,7 @@ struct _LIBCPP_TEMPLATE_VIS greater_equal
     bool operator()(const _Tp& __x, const _Tp& __y) const
         {return __x >= __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater_equal);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -455,6 +470,7 @@ struct _LIBCPP_TEMPLATE_VIS greater
     bool operator()(const _Tp& __x, const _Tp& __y) const
         {return __x > __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(greater);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -485,6 +501,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_and
     bool operator()(const _Tp& __x, const _Tp& __y) const
         {return __x && __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_and);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -513,6 +530,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_not
     bool operator()(const _Tp& __x) const
         {return !__x;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_not);
 
 #if _LIBCPP_STD_VER > 11
 template <>
@@ -541,6 +559,7 @@ struct _LIBCPP_TEMPLATE_VIS logical_or
     bool operator()(const _Tp& __x, const _Tp& __y) const
         {return __x || __y;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(logical_or);
 
 #if _LIBCPP_STD_VER > 11
 template <>

diff  --git a/libcxx/include/__iterator/back_insert_iterator.h b/libcxx/include/__iterator/back_insert_iterator.h
index da58b860e3832..4c00a7e397962 100644
--- a/libcxx/include/__iterator/back_insert_iterator.h
+++ b/libcxx/include/__iterator/back_insert_iterator.h
@@ -58,6 +58,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
 
     _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Container* __get_container() const { return container; }
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(back_insert_iterator);
 
 template <class _Container>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20

diff  --git a/libcxx/include/__iterator/counted_iterator.h b/libcxx/include/__iterator/counted_iterator.h
index 28b3e36bdc000..aab2c51f33a84 100644
--- a/libcxx/include/__iterator/counted_iterator.h
+++ b/libcxx/include/__iterator/counted_iterator.h
@@ -288,6 +288,7 @@ class counted_iterator
     return ranges::iter_swap(__x.__current_, __y.__current_);
   }
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(counted_iterator);
 
 template<input_iterator _Iter>
   requires same_as<_ITER_TRAITS<_Iter>, iterator_traits<_Iter>>

diff  --git a/libcxx/include/__iterator/front_insert_iterator.h b/libcxx/include/__iterator/front_insert_iterator.h
index a104b5fc5f1cc..e278359d870d6 100644
--- a/libcxx/include/__iterator/front_insert_iterator.h
+++ b/libcxx/include/__iterator/front_insert_iterator.h
@@ -56,6 +56,7 @@ _LIBCPP_SUPPRESS_DEPRECATED_POP
     _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 <class _Container>
 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20

diff  --git a/libcxx/include/__iterator/move_iterator.h b/libcxx/include/__iterator/move_iterator.h
index b02bd81bfc81a..b4f2f9ec3d5ca 100644
--- a/libcxx/include/__iterator/move_iterator.h
+++ b/libcxx/include/__iterator/move_iterator.h
@@ -222,6 +222,7 @@ class _LIBCPP_TEMPLATE_VIS move_iterator
 
     _Iter __current_;
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(move_iterator);
 
 template <class _Iter1, class _Iter2>
 inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX17

diff  --git a/libcxx/include/__mutex_base b/libcxx/include/__mutex_base
index ac0d090b7d194..82d9fa6ecbacf 100644
--- a/libcxx/include/__mutex_base
+++ b/libcxx/include/__mutex_base
@@ -103,6 +103,7 @@ private:
     lock_guard(lock_guard const&) = delete;
     lock_guard& operator=(lock_guard const&) = delete;
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(lock_guard);
 
 template <class _Mutex>
 class _LIBCPP_TEMPLATE_VIS unique_lock
@@ -195,6 +196,7 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     mutex_type* mutex() const _NOEXCEPT {return __m_;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(unique_lock);
 
 template <class _Mutex>
 void

diff  --git a/libcxx/include/__ranges/owning_view.h b/libcxx/include/__ranges/owning_view.h
index 22450baec5795..71d8146d13a85 100644
--- a/libcxx/include/__ranges/owning_view.h
+++ b/libcxx/include/__ranges/owning_view.h
@@ -68,6 +68,7 @@ namespace ranges {
     _LIBCPP_HIDE_FROM_ABI constexpr auto data() const requires contiguous_range<const _Rp>
       { return ranges::data(__r_); }
   };
+  _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(owning_view);
 
   template<class _Tp>
   inline constexpr bool enable_borrowed_range<owning_view<_Tp>> = enable_borrowed_range<_Tp>;

diff  --git a/libcxx/include/__ranges/range_adaptor.h b/libcxx/include/__ranges/range_adaptor.h
index edb32541c651a..c287a193a57db 100644
--- a/libcxx/include/__ranges/range_adaptor.h
+++ b/libcxx/include/__ranges/range_adaptor.h
@@ -41,6 +41,7 @@ template <class _Fn>
 struct __range_adaptor_closure_t : _Fn, __range_adaptor_closure<__range_adaptor_closure_t<_Fn>> {
     constexpr explicit __range_adaptor_closure_t(_Fn&& __f) : _Fn(std::move(__f)) { }
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__range_adaptor_closure_t);
 
 template <class _Tp>
 concept _RangeAdaptorClosure = derived_from<remove_cvref_t<_Tp>, __range_adaptor_closure<remove_cvref_t<_Tp>>>;

diff  --git a/libcxx/include/__utility/transaction.h b/libcxx/include/__utility/transaction.h
index 37f829b1fcec5..dc65c349d13c7 100644
--- a/libcxx/include/__utility/transaction.h
+++ b/libcxx/include/__utility/transaction.h
@@ -85,6 +85,7 @@ struct __transaction {
     _Rollback __rollback_;
     bool __completed_;
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(__transaction);
 
 template <class _Rollback>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __transaction<_Rollback> __make_transaction(_Rollback __rollback) {

diff  --git a/libcxx/include/mutex b/libcxx/include/mutex
index 139a7f5b93edc..d0b53ba75d834 100644
--- a/libcxx/include/mutex
+++ b/libcxx/include/mutex
@@ -542,6 +542,7 @@ private:
 
     _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
index e6773651ac619..6919898f66f4f 100644
--- a/libcxx/include/shared_mutex
+++ b/libcxx/include/shared_mutex
@@ -432,6 +432,7 @@ public:
     _LIBCPP_INLINE_VISIBILITY
     mutex_type* mutex() const _NOEXCEPT {return __m_;}
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(shared_lock);
 
 template <class _Mutex>
 void

diff  --git a/libcxx/include/string_view b/libcxx/include/string_view
index c3df8c4926024..2941f714fa7c7 100644
--- a/libcxx/include/string_view
+++ b/libcxx/include/string_view
@@ -726,6 +726,7 @@ private:
     const   value_type* __data_;
     size_type           __size_;
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(basic_string_view);
 
 #if _LIBCPP_STD_VER > 17
 template <class _CharT, class _Traits>

diff  --git a/libcxx/src/filesystem/operations.cpp b/libcxx/src/filesystem/operations.cpp
index 61c643cb6e662..fc14778f3f7a8 100644
--- a/libcxx/src/filesystem/operations.cpp
+++ b/libcxx/src/filesystem/operations.cpp
@@ -1408,6 +1408,7 @@ struct scope_exit {
 private:
   Cleanup cleanup_;
 };
+_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(scope_exit);
 
 uintmax_t remove_all_impl(int parent_directory, const path& p, error_code& ec) {
   // First, try to open the path as a directory.

diff  --git a/libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_back.pass.cpp b/libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_back.pass.cpp
index abeff44f03358..de7d78fc0f024 100644
--- a/libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_back.pass.cpp
+++ b/libcxx/test/libcxx/utilities/function.objects/func.bind.partial/bind_back.pass.cpp
@@ -320,7 +320,7 @@ constexpr bool test() {
   // Test properties of the constructor of the unspecified-type returned by __bind_back.
   {
     {
-      MoveOnlyCallable value(true);
+      MoveOnlyCallable<bool> value(true);
       auto ret = std::__bind_back(std::move(value), 1);
       assert(ret());
       assert(ret(1, 2, 3));
@@ -337,7 +337,7 @@ constexpr bool test() {
       static_assert(!std::is_copy_assignable<RetT>::value);
     }
     {
-      CopyCallable value(true);
+      CopyCallable<bool> value(true);
       auto ret = std::__bind_back(value, 1);
       assert(ret());
       assert(ret(1, 2, 3));

diff  --git a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h
index 433731e5dd686..3ab4924e24115 100644
--- a/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h
+++ b/libcxx/test/std/iterators/iterator.primitives/range.iter.ops/types.h
@@ -54,4 +54,7 @@ class assignable_sentinel {
     decltype(base(std::declval<It>())) base_;
 };
 
+template <class It>
+assignable_sentinel(const It&) -> assignable_sentinel<It>;
+
 #endif // TEST_STD_ITERATORS_ITERATOR_PRIMITIVES_RANGE_ITER_OPS_TYPES_H

diff  --git a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
index 5443a5bb58906..31ec0100e2eee 100644
--- a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
@@ -50,6 +50,9 @@ class iterator_wrapper {
   I base_ = I{};
 };
 
+template <class I>
+iterator_wrapper(I) -> iterator_wrapper<I>;
+
 template <typename It, typename Out>
 constexpr void unqualified_lookup_move(It first_, It last_, Out result_first_, Out result_last_) {
   auto first = ::check_unqualified_lookup::unqualified_lookup_wrapper{std::move(first_)};

diff  --git a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h
index 7c3719aa519e3..30d913ccc4401 100644
--- a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/unqualified_lookup_wrapper.h
@@ -43,6 +43,9 @@ class unqualified_lookup_wrapper {
   I base_ = I{};
 };
 
+template <class It>
+unqualified_lookup_wrapper(It) -> unqualified_lookup_wrapper<It>;
+
 enum unscoped_enum { a, b, c };
 constexpr unscoped_enum iter_move(unscoped_enum& e) noexcept(false) { return e; }
 

diff  --git a/libcxx/test/std/iterators/predef.iterators/counted.iterator/implicit_ctad.pass.cpp b/libcxx/test/std/iterators/predef.iterators/counted.iterator/implicit_ctad.pass.cpp
new file mode 100644
index 0000000000000..2786dfbb7a60f
--- /dev/null
+++ b/libcxx/test/std/iterators/predef.iterators/counted.iterator/implicit_ctad.pass.cpp
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17
+
+// counted_iterator
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <iterator>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  int array[] = {1, 2, 3};
+  int* p = array;
+  std::counted_iterator iter(p, 3);
+  ASSERT_SAME_TYPE(decltype(iter), std::counted_iterator<int*>);
+
+  return 0;
+}

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
index 0000000000000..10729e0029d08
--- /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
+
+// <iterator>
+
+// back_insert_iterator
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <iterator>
+#include <string>
+#include <vector>
+
+#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::string>);
+  }
+  {
+    std::vector<int> v;
+    std::back_insert_iterator it(v);
+    std::back_insert_iterator copy(it);
+    ASSERT_SAME_TYPE(decltype(it), std::back_insert_iterator<std::vector<int>>);
+    ASSERT_SAME_TYPE(decltype(copy), std::back_insert_iterator<std::vector<int>>);
+  }
+
+  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
index 0000000000000..f91d472e9ea2d
--- /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
+
+// <iterator>
+
+// front_insert_iterator
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <deque>
+#include <iterator>
+#include <string>
+
+#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::string>);
+  }
+  {
+    std::deque<int> v;
+    std::front_insert_iterator it(v);
+    std::front_insert_iterator copy(it);
+    ASSERT_SAME_TYPE(decltype(it), std::front_insert_iterator<std::deque<int>>);
+    ASSERT_SAME_TYPE(decltype(copy), std::front_insert_iterator<std::deque<int>>);
+  }
+
+  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
index 0000000000000..e5744465daa9b
--- /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
+
+// <iterator>
+
+// move_iterator
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <iterator>
+
+#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<int*>);
+
+  return 0;
+}

diff  --git a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/iter_swap.pass.cpp b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/iter_swap.pass.cpp
index aaad0eb51e2f8..d01ee2a1b85a1 100644
--- a/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/iter_swap.pass.cpp
+++ b/libcxx/test/std/iterators/predef.iterators/reverse.iterators/reverse.iter.nonmember/iter_swap.pass.cpp
@@ -31,8 +31,8 @@ constexpr bool test() {
     constexpr int N = 3;
     int a[N] = {0, 1, 2};
 
-    std::reverse_iterator rb(a + N);
-    std::reverse_iterator re(a + 1);
+    std::reverse_iterator<int*> rb(a + N);
+    std::reverse_iterator<int*> re(a + 1);
     assert(a[0] == 0);
     assert(a[2] == 2);
 

diff  --git a/libcxx/test/std/ranges/range.adaptors/range.all/range.owning.view/implicit_ctad.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.all/range.owning.view/implicit_ctad.pass.cpp
new file mode 100644
index 0000000000000..11b3dc76da550
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.all/range.owning.view/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: c++03, c++11, c++14, c++17
+
+// owning_view
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <ranges>
+#include <utility>
+
+#include "test_macros.h"
+
+struct Range {
+  int* begin();
+  int* end();
+};
+
+int main(int, char**) {
+  Range r;
+  std::ranges::owning_view view{std::move(r)};
+  ASSERT_SAME_TYPE(decltype(view), std::ranges::owning_view<Range>);
+
+  return 0;
+}

diff  --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp
index 44f67d1e99021..ddcf66bfe775e 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/arrow.pass.cpp
@@ -103,8 +103,8 @@ constexpr bool test() {
 
   {
     // Copyable input iterator with arrow.
-    ValueView<Box> children[4] = {ValueView(buffer[0]), ValueView(buffer[1]), ValueView(buffer[2]),
-                                  ValueView(buffer[3])};
+    using BoxView = ValueView<Box>;
+    ValueView<Box> children[4] = {BoxView(buffer[0]), BoxView(buffer[1]), BoxView(buffer[2]), BoxView(buffer[3])};
     std::ranges::join_view jv(ValueView<ValueView<Box>>{children});
     assert(jv.begin()->x == 1111);
     static_assert(HasArrow<decltype(jv.begin())>);

diff  --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp
index 057f75b9e5252..f46edd3562ba1 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.join.view/iterator/increment.pass.cpp
@@ -37,8 +37,9 @@ constexpr bool test() {
   }
 
   {
-    ValueView<int> children[4] = {ValueView(buffer1[0]), ValueView(buffer1[1]), ValueView(buffer2[0]), ValueView(buffer2[1])};
-    std::ranges::join_view jv(ValueView<ValueView<int>>{children});
+    using IntView = ValueView<int>;
+    IntView children[4] = {IntView(buffer1[0]), IntView(buffer1[1]), IntView(buffer2[0]), IntView(buffer2[1])};
+    std::ranges::join_view jv(ValueView<IntView>{children});
     auto iter = jv.begin();
     for (int i = 1; i < 17; ++i) {
       assert(*iter == i);
@@ -152,8 +153,9 @@ constexpr bool test() {
   }
 
   {
-    ValueView<int> children[4] = {ValueView(buffer1[0]), ValueView(buffer1[1]), ValueView(buffer2[0]), ValueView(buffer2[1])};
-    std::ranges::join_view jv(ValueView<ValueView<int>>{children});
+    using IntView = ValueView<int>;
+    IntView children[4] = {IntView(buffer1[0]), IntView(buffer1[1]), IntView(buffer2[0]), IntView(buffer2[1])};
+    std::ranges::join_view jv(ValueView<IntView>{children});
     auto iter = jv.begin();
     for (int i = 2; i < 17; ++i) {
       assert(*++iter == i);

diff  --git a/libcxx/test/std/ranges/range.adaptors/range.join.view/types.h b/libcxx/test/std/ranges/range.adaptors/range.join.view/types.h
index 1b4007bce0123..d33653858074b 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.join.view/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.join.view/types.h
@@ -75,6 +75,9 @@ struct ParentView : std::ranges::view_base {
   constexpr const_sentinel end() const { return const_sentinel(const_iterator(ptr_ + size_)); }
 };
 
+template <class T>
+ParentView(T*) -> ParentView<T>;
+
 struct CopyableChild : std::ranges::view_base {
   int* ptr_;
   unsigned size_;

diff  --git a/libcxx/test/std/ranges/range.factories/range.iota.view/types.h b/libcxx/test/std/ranges/range.factories/range.iota.view/types.h
index a6eb1b4d537aa..b9ef3e21de51a 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/types.h
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/types.h
@@ -88,6 +88,8 @@ struct IntComparableWith {
   constexpr IntComparableWith  operator++(int) { auto tmp = *this; ++value_; return tmp; }
   constexpr IntComparableWith  operator--() { --value_; return *this; }
 };
+template <class T>
+IntComparableWith(T) -> IntComparableWith<T>;
 
 template<class T>
 struct IntSentinelWith {
@@ -123,6 +125,8 @@ struct IntSentinelWith {
   constexpr IntSentinelWith  operator++(int) { auto tmp = *this; ++value_; return tmp; }
   constexpr IntSentinelWith  operator--() { --value_; return *this; }
 };
+template <class T>
+IntSentinelWith(T) -> IntSentinelWith<T>;
 
 struct NotIncrementable {
   using 
diff erence_type = int;

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
index 0000000000000..c76c4a01c696c
--- /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
+
+// <string_view>
+
+// basic_string_view
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <string_view>
+
+#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<char>);
+  }
+#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<wchar_t>);
+  }
+#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
index 0000000000000..b754417334821
--- /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
+
+// <mutex>
+
+// lock_guard
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <mutex>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  std::mutex mutex;
+  {
+    std::lock_guard lock(mutex);
+    ASSERT_SAME_TYPE(decltype(lock), std::lock_guard<std::mutex>);
+  }
+
+  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
index 0000000000000..7305b48c53a9f
--- /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
+
+// <mutex>
+
+// scoped_lock
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <mutex>
+
+#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::mutex>);
+  }
+  {
+    std::scoped_lock lock(m1, m2);
+    ASSERT_SAME_TYPE(decltype(lock), std::scoped_lock<std::mutex, std::recursive_mutex>);
+  }
+  {
+    std::scoped_lock lock(m1, m2, m3);
+    ASSERT_SAME_TYPE(decltype(lock), std::scoped_lock<std::mutex, std::recursive_mutex, std::recursive_timed_mutex>);
+  }
+
+  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
index 0000000000000..3fa4373c70173
--- /dev/null
+++ b/libcxx/test/std/thread/thread.mutex/thread.lock/thread.lock.shared/implicit_ctad.pass.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// dylib support for shared_mutex was added in macosx10.12
+// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx10.{{9|10|11}}
+
+// <shared_mutex>
+
+// shared_lock
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <shared_mutex>
+
+#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<std::shared_mutex>);
+  }
+
+  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
index 0000000000000..ffe651c6b7442
--- /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
+
+// <mutex>
+
+// unique_lock
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <mutex>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  std::mutex mutex;
+  {
+    std::unique_lock lock(mutex);
+    ASSERT_SAME_TYPE(decltype(lock), std::unique_lock<std::mutex>);
+  }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/thread/thread.semaphore/ctor.compile.pass.cpp b/libcxx/test/std/thread/thread.semaphore/ctor.compile.pass.cpp
index 9ffee4df04977..28ccc0124d489 100644
--- a/libcxx/test/std/thread/thread.semaphore/ctor.compile.pass.cpp
+++ b/libcxx/test/std/thread/thread.semaphore/ctor.compile.pass.cpp
@@ -27,5 +27,5 @@ static_assert(!std::is_convertible<int, std::counting_semaphore<>>::value, "");
 #if TEST_STD_VER > 17
 // Test constexpr-constructibility. (But not destructibility.)
 constinit std::binary_semaphore bs(1);
-constinit std::counting_semaphore cs(1);
+constinit std::counting_semaphore<> cs(1);
 #endif

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/advance_to.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/advance_to.pass.cpp
index da6b5d16417ca..fe2ce9d5a62a2 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/advance_to.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/advance_to.pass.cpp
@@ -24,7 +24,7 @@ void test(
     std::basic_format_args<std::basic_format_context<OutIt, CharT>> args) {
   {
     std::basic_string<CharT> str[3];
-    std::basic_format_context context =
+    std::basic_format_context<OutIt, CharT> context =
         test_format_context_create(OutIt{str[0]}, args);
     context.out() = CharT('a');
     context.advance_to(OutIt{str[1]});

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/arg.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/arg.pass.cpp
index 17d8908b2a238..abd9315612c07 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/arg.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/arg.pass.cpp
@@ -28,7 +28,7 @@ void test() {
   std::basic_format_args args = store;
 
   std::basic_string<CharT> output;
-  const std::basic_format_context context =
+  const std::basic_format_context<OutIt, CharT> context =
       test_format_context_create(OutIt{output}, args);
   LIBCPP_ASSERT(args.__size() == 4);
   ASSERT_NOEXCEPT(context.arg(0));

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/ctor.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/ctor.pass.cpp
index 0b86c342f621d..f2d24503db818 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/ctor.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/ctor.pass.cpp
@@ -55,8 +55,7 @@ void test() {
   {
     std::basic_string<CharT> output;
     OutIt out_it{output};
-    std::basic_format_context context =
-        test_format_context_create(out_it, args);
+    std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args);
     LIBCPP_ASSERT(args.__size() == 4);
 
     assert(test_basic_format_arg(context.arg(0), true));
@@ -80,8 +79,7 @@ void test() {
   {
     std::basic_string<CharT> output;
     OutIt out_it{output};
-    std::basic_format_context context =
-        test_format_context_create(out_it, args, en_US);
+    std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args, en_US);
 
     LIBCPP_ASSERT(args.__size() == 4);
     assert(test_basic_format_arg(context.arg(0), true));
@@ -101,8 +99,7 @@ void test() {
   {
     std::basic_string<CharT> output;
     OutIt out_it{output};
-    std::basic_format_context context =
-        test_format_context_create(out_it, args, fr_FR);
+    std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args, fr_FR);
 
     LIBCPP_ASSERT(args.__size() == 4);
     assert(test_basic_format_arg(context.arg(0), true));

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/locale.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/locale.pass.cpp
index a8752bfc3043b..6a91789437926 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/locale.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/locale.pass.cpp
@@ -39,8 +39,7 @@ void test() {
   {
     std::basic_string<CharT> output;
     OutIt out_it{output};
-    std::basic_format_context context =
-        test_format_context_create(out_it, args, en_US);
+    std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args, en_US);
     assert(args.__size() == 4);
     assert(test_basic_format_arg(context.arg(0), true));
     assert(test_basic_format_arg(context.arg(1), CharT('a')));
@@ -59,8 +58,7 @@ void test() {
   {
     std::basic_string<CharT> output;
     OutIt out_it{output};
-    std::basic_format_context context =
-        test_format_context_create(out_it, args, fr_FR);
+    std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args, fr_FR);
     assert(args.__size() == 4);
     assert(test_basic_format_arg(context.arg(0), true));
     assert(test_basic_format_arg(context.arg(1), CharT('a')));

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/out.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/out.pass.cpp
index 928f668c9f649..b7080e1aa7309 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/out.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.context/format.context/out.pass.cpp
@@ -25,8 +25,7 @@ void test(
   {
     std::basic_string<CharT> str;
     OutIt out_it{str};
-    std::basic_format_context context =
-        test_format_context_create(out_it, args);
+    std::basic_format_context<OutIt, CharT> context = test_format_context_create(out_it, args);
     context.out() = CharT('a');
     context.out() = CharT('b');
     context.out() = CharT('c');

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp
index bb0402aae6e20..da886d37fceb1 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.bool.pass.cpp
@@ -44,7 +44,7 @@ void test(StringT expected, StringViewT fmt, bool arg) {
   auto out = std::back_inserter(result);
   using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
 
-  std::basic_format_context format_ctx =
+  FormatCtxT format_ctx =
       test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
   formatter.format(arg, format_ctx);
   assert(result == expected);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp
index 5b5d2a6169616..dc9abd8d63481 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.c_string.pass.cpp
@@ -43,7 +43,7 @@ void test(StringT expected, StringViewT fmt, const CharT* a) {
   using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
 
   auto* arg = const_cast<T>(a);
-  std::basic_format_context format_ctx =
+  FormatCtxT format_ctx =
       test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
   formatter.format(arg, format_ctx);
   assert(result == expected);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp
index cc84948c73dc1..22c78549ddbf4 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char.pass.cpp
@@ -43,7 +43,7 @@ void test(StringT expected, StringViewT fmt, ArgumentT arg) {
   auto out = std::back_inserter(result);
   using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
 
-  std::basic_format_context format_ctx =
+  FormatCtxT format_ctx =
       test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
   formatter.format(arg, format_ctx);
   assert(result == expected);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp
index 93fb9360b5d9d..9f9ad98edc753 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.char_array.pass.cpp
@@ -58,7 +58,7 @@ struct Tester {
     // Note not too found of this hack
     Str* data = reinterpret_cast<Str*>(const_cast<CharT*>(buffer.c_str()));
 
-    std::basic_format_context format_ctx =
+    FormatCtxT format_ctx =
         test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(*data));
     formatter.format(*data, format_ctx);
     assert(result == expected);
@@ -79,6 +79,9 @@ struct Tester {
   }
 };
 
+template <size_t N>
+Tester(const char (&)[N]) -> Tester<N>;
+
 template <Tester t, class CharT>
 void test_helper_wrapper(std::basic_string<CharT> expected, std::basic_string<CharT> fmt) {
   t.test_termination_condition(expected, fmt);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp
index 65749b7f636f3..39930c347a454 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.const_char_array.pass.cpp
@@ -60,7 +60,7 @@ struct Tester {
     // Note not too found of this hack
     Str* data = reinterpret_cast<Str*>(buffer.c_str());
 
-    std::basic_format_context format_ctx =
+    FormatCtxT format_ctx =
         test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(*data));
     formatter.format(*data, format_ctx);
     assert(result == expected);
@@ -82,6 +82,9 @@ struct Tester {
   }
 };
 
+template <size_t N>
+Tester(const char (&)[N]) -> Tester<N>;
+
 template <Tester t, class CharT>
 void test_helper_wrapper(std::basic_string<CharT> expected,
                          std::basic_string<CharT> fmt) {

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp
index 9c4d56d102ef4..123d0ac36fa3a 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.floating_point.pass.cpp
@@ -53,7 +53,7 @@ void test(std::basic_string_view<CharT> fmt, ArithmeticT arg, std::basic_string<
   auto out = std::back_inserter(result);
   using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
 
-  std::basic_format_context format_ctx =
+  FormatCtxT format_ctx =
       test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
   formatter.format(arg, format_ctx);
 

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp
index 986352ee16a23..f8ffbd2a6ff2d 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.handle.pass.cpp
@@ -47,7 +47,7 @@ void test(std::string expected, std::string_view fmt, color arg) {
   auto out = std::back_inserter(result);
   using FormatCtxT = std::basic_format_context<decltype(out), char>;
 
-  std::basic_format_context format_ctx =
+  FormatCtxT format_ctx =
       test_format_context_create<decltype(out), char>(out, std::make_format_args<FormatCtxT>(arg));
   formatter.format(arg, format_ctx);
   assert(result == expected);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp
index d91b75bb54359..316667ae60075 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.pointer.pass.cpp
@@ -49,7 +49,7 @@ void test(StringT expected, StringViewT fmt, PointerT arg) {
   auto out = std::back_inserter(result);
   using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
 
-  std::basic_format_context format_ctx =
+  FormatCtxT format_ctx =
       test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
   formatter.format(arg, format_ctx);
 

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp
index 949af08e26c8d..07f5be400739c 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.signed_integral.pass.cpp
@@ -51,7 +51,7 @@ void test(StringT expected, StringViewT fmt, ArithmeticT arg) {
   auto out = std::back_inserter(result);
   using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
 
-  std::basic_format_context format_ctx =
+  FormatCtxT format_ctx =
       test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
   formatter.format(arg, format_ctx);
   assert(result == expected);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp
index 16cbac4f4b0ae..aa4c9a6b4d24f 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.string.pass.cpp
@@ -51,7 +51,7 @@ void test(StringT expected, StringViewT fmt, StringT a) {
   using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
 
   ArgumentT arg = a;
-  std::basic_format_context format_ctx = test_format_context_create<decltype(out), CharT>(
+  FormatCtxT format_ctx = test_format_context_create<decltype(out), CharT>(
       out, std::make_format_args<FormatCtxT>(std::forward<ArgumentT>(arg)));
   formatter.format(arg, format_ctx);
   assert(result == expected);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp
index 320b7e7d9022f..11025afadb6bf 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.formatter.spec/formatter.unsigned_integral.pass.cpp
@@ -51,7 +51,7 @@ void test(StringT expected, StringViewT fmt, ArithmeticT arg) {
   auto out = std::back_inserter(result);
   using FormatCtxT = std::basic_format_context<decltype(out), CharT>;
 
-  std::basic_format_context format_ctx =
+  FormatCtxT format_ctx =
       test_format_context_create<decltype(out), CharT>(out, std::make_format_args<FormatCtxT>(arg));
   formatter.format(arg, format_ctx);
   assert(result == expected);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/advance_to.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/advance_to.pass.cpp
index 6b4afcb6561de..66dacd44bb116 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/advance_to.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/advance_to.pass.cpp
@@ -35,7 +35,7 @@ constexpr void test(const CharT* fmt) {
   }
   {
     std::basic_string_view view{fmt};
-    std::basic_format_parse_context context(view);
+    std::basic_format_parse_context<CharT> context(view);
 
     context.advance_to(context.begin() + 1);
     assert(std::to_address(context.begin()) == fmt + 1);

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/begin.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/begin.pass.cpp
index 63122dc50b76c..85d9e20b9bc27 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/begin.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/begin.pass.cpp
@@ -28,7 +28,7 @@ constexpr void test(const CharT* fmt) {
   }
   {
     std::basic_string_view view{fmt};
-    std::basic_format_parse_context context(view);
+    std::basic_format_parse_context<CharT> context(view);
     assert(context.begin() == view.begin());
     ASSERT_NOEXCEPT(context.begin());
   }

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/ctor.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/ctor.pass.cpp
index 2a06751ec547f..90a102973f045 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/ctor.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/ctor.pass.cpp
@@ -40,9 +40,9 @@ constexpr void test(const CharT* fmt) {
       !std::is_move_assignable_v<std::basic_format_parse_context<CharT> >);
 
   ASSERT_NOEXCEPT(
-      std::basic_format_parse_context{std::basic_string_view<CharT>{}});
+      std::basic_format_parse_context<CharT>{std::basic_string_view<CharT>{}});
   ASSERT_NOEXCEPT(
-      std::basic_format_parse_context{std::basic_string_view<CharT>{}, 42});
+      std::basic_format_parse_context<CharT>{std::basic_string_view<CharT>{}, 42});
 
   {
     std::basic_format_parse_context<CharT> context(fmt);
@@ -51,7 +51,7 @@ constexpr void test(const CharT* fmt) {
   }
   {
     std::basic_string_view view{fmt};
-    std::basic_format_parse_context context(view);
+    std::basic_format_parse_context<CharT> context(view);
     assert(context.begin() == view.begin());
     assert(context.end() == view.end());
   }

diff  --git a/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/end.pass.cpp b/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/end.pass.cpp
index e135418dc5b85..917d856741b28 100644
--- a/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/end.pass.cpp
+++ b/libcxx/test/std/utilities/format/format.formatter/format.parse.ctx/end.pass.cpp
@@ -28,7 +28,7 @@ constexpr void test(const CharT* fmt) {
   }
   {
     std::basic_string_view view{fmt};
-    std::basic_format_parse_context context(view);
+    std::basic_format_parse_context<CharT> context(view);
     assert(context.end() == view.end());
     ASSERT_NOEXCEPT(context.end());
   }

diff  --git a/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp
index d449265a2d040..6eb4e4a46e82f 100644
--- a/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.bind_front/bind_front.pass.cpp
@@ -317,7 +317,7 @@ constexpr bool test() {
   // Test properties of the constructor of the unspecified-type returned by bind_front.
   {
     {
-      MoveOnlyCallable value(true);
+      MoveOnlyCallable<bool> value(true);
       auto ret = std::bind_front(std::move(value), 1);
       assert(ret());
       assert(ret(1, 2, 3));
@@ -334,7 +334,7 @@ constexpr bool test() {
       static_assert(!std::is_copy_assignable<RetT>::value);
     }
     {
-      CopyCallable value(true);
+      CopyCallable<bool> value(true);
       auto ret = std::bind_front(value, 1);
       assert(ret());
       assert(ret(1, 2, 3));

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/implicit_ctad.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/implicit_ctad.pass.cpp
new file mode 100644
index 0000000000000..863b4a5c2569f
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bm/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: c++98, c++03, c++11, c++14
+
+// <functional>
+
+// boyer_moore_searcher
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <functional>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  {
+    char const* str = "hello";
+    std::boyer_moore_searcher searcher(str, str + 3);
+    ASSERT_SAME_TYPE(decltype(searcher), std::boyer_moore_searcher<char const*, std::hash<char>, std::equal_to<>>);
+  }
+  {
+    struct myhash : std::hash<char> { };
+    char const* str = "hello";
+    std::boyer_moore_searcher searcher(str, str + 3, myhash{}, std::not_equal_to<>());
+    ASSERT_SAME_TYPE(decltype(searcher), std::boyer_moore_searcher<char const*, myhash, std::not_equal_to<>>);
+  }
+  {
+    struct myhash : std::hash<char> { };
+    char const* str = "hello";
+    std::boyer_moore_searcher searcher(str, str + 3, myhash{});
+    ASSERT_SAME_TYPE(decltype(searcher), std::boyer_moore_searcher<char const*, myhash, std::equal_to<>>);
+  }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/implicit_ctad.pass.cpp b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/implicit_ctad.pass.cpp
new file mode 100644
index 0000000000000..778f6d3bd2cb1
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/func.search/func.search.bmh/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: c++98, c++03, c++11, c++14
+
+// <functional>
+
+// boyer_moore_horspool_searcher
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <functional>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  {
+    char const* str = "hello";
+    std::boyer_moore_horspool_searcher searcher(str, str + 3);
+    ASSERT_SAME_TYPE(decltype(searcher), std::boyer_moore_horspool_searcher<char const*, std::hash<char>, std::equal_to<>>);
+  }
+  {
+    struct myhash : std::hash<char> { };
+    char const* str = "hello";
+    std::boyer_moore_horspool_searcher searcher(str, str + 3, myhash{}, std::not_equal_to<>());
+    ASSERT_SAME_TYPE(decltype(searcher), std::boyer_moore_horspool_searcher<char const*, myhash, std::not_equal_to<>>);
+  }
+  {
+    struct myhash : std::hash<char> { };
+    char const* str = "hello";
+    std::boyer_moore_horspool_searcher searcher(str, str + 3, myhash{});
+    ASSERT_SAME_TYPE(decltype(searcher), std::boyer_moore_horspool_searcher<char const*, myhash, std::equal_to<>>);
+  }
+
+  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
index 0000000000000..3c9029566d929
--- /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
+
+// <functional>
+
+// default searcher
+
+// Make sure that the implicitly-generated CTAD works.
+
+#include <functional>
+
+#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*, std::equal_to<>>);
+  }
+  {
+    char const* str = "hello";
+    std::default_searcher searcher(str, str + 3, std::not_equal_to<>());
+    ASSERT_SAME_TYPE(decltype(searcher), std::default_searcher<char const*, std::not_equal_to<>>);
+  }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/function.objects/operations.implicit_ctad.pass.cpp b/libcxx/test/std/utilities/function.objects/operations.implicit_ctad.pass.cpp
new file mode 100644
index 0000000000000..03c46d232c38b
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/operations.implicit_ctad.pass.cpp
@@ -0,0 +1,98 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <functional>
+
+// Make sure that we can use CTAD with operations in <functional>
+
+#include <functional>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+    {
+        std::plus f;
+        ASSERT_SAME_TYPE(decltype(f), std::plus<>);
+    }
+    {
+        std::minus f;
+        ASSERT_SAME_TYPE(decltype(f), std::minus<>);
+    }
+    {
+        std::multiplies f;
+        ASSERT_SAME_TYPE(decltype(f), std::multiplies<>);
+    }
+    {
+        std::divides f;
+        ASSERT_SAME_TYPE(decltype(f), std::divides<>);
+    }
+    {
+        std::modulus f;
+        ASSERT_SAME_TYPE(decltype(f), std::modulus<>);
+    }
+    {
+        std::negate f;
+        ASSERT_SAME_TYPE(decltype(f), std::negate<>);
+    }
+    {
+        std::bit_and f;
+        ASSERT_SAME_TYPE(decltype(f), std::bit_and<>);
+    }
+    {
+        std::bit_not f;
+        ASSERT_SAME_TYPE(decltype(f), std::bit_not<>);
+    }
+    {
+        std::bit_or f;
+        ASSERT_SAME_TYPE(decltype(f), std::bit_or<>);
+    }
+    {
+        std::bit_xor f;
+        ASSERT_SAME_TYPE(decltype(f), std::bit_xor<>);
+    }
+    {
+        std::equal_to f;
+        ASSERT_SAME_TYPE(decltype(f), std::equal_to<>);
+    }
+    {
+        std::not_equal_to f;
+        ASSERT_SAME_TYPE(decltype(f), std::not_equal_to<>);
+    }
+    {
+        std::less f;
+        ASSERT_SAME_TYPE(decltype(f), std::less<>);
+    }
+    {
+        std::less_equal f;
+        ASSERT_SAME_TYPE(decltype(f), std::less_equal<>);
+    }
+    {
+        std::greater_equal f;
+        ASSERT_SAME_TYPE(decltype(f), std::greater_equal<>);
+    }
+    {
+        std::greater f;
+        ASSERT_SAME_TYPE(decltype(f), std::greater<>);
+    }
+    {
+        std::logical_and f;
+        ASSERT_SAME_TYPE(decltype(f), std::logical_and<>);
+    }
+    {
+        std::logical_not f;
+        ASSERT_SAME_TYPE(decltype(f), std::logical_not<>);
+    }
+    {
+        std::logical_or f;
+        ASSERT_SAME_TYPE(decltype(f), std::logical_or<>);
+    }
+
+    return 0;
+}

diff  --git a/libcxx/test/std/utilities/variant/variant.variant/implicit_ctad.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/implicit_ctad.pass.cpp
new file mode 100644
index 0000000000000..514c1f87faad0
--- /dev/null
+++ b/libcxx/test/std/utilities/variant/variant.variant/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: c++03, c++11, c++14
+
+// <variant>
+
+// template <class ...Types> class variant;
+
+// Make sure that the implicitly-generated CTAD works.
+
+// We make sure that it is not ill-formed, however we still produce a warning for
+// this one because explicit construction from a variant using CTAD is ambiguous
+// (in the sense that the programer intent is not clear).
+// ADDITIONAL_COMPILE_FLAGS: -Wno-ctad-maybe-unsupported
+
+#include <variant>
+
+#include "test_macros.h"
+
+int main(int, char**) {
+  // This is the motivating example from P0739R0
+  {
+    std::variant<int, double> v1(3);
+    std::variant v2 = v1;
+    ASSERT_SAME_TYPE(decltype(v2), std::variant<int, double>);
+  }
+
+  {
+    std::variant<int, double> v1(3);
+    std::variant v2 = std::variant(v1); // Technically valid, but intent is ambiguous!
+    ASSERT_SAME_TYPE(decltype(v2), std::variant<int, double>);
+  }
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
index 39a7b9bd18335..b328ba4cbe8ad 100644
--- a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
+++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
@@ -253,11 +253,5 @@ int main(int, char**) {
   test_copy_ctor_valueless_by_exception();
   test_copy_ctor_sfinae();
   test_constexpr_copy_ctor();
-  { // This is the motivating example from P0739R0
-    std::variant<int, double> v1(3);
-    std::variant v2 = v1;
-    (void)v2;
-  }
-
   return 0;
 }

diff  --git a/libcxx/test/support/callable_types.h b/libcxx/test/support/callable_types.h
index 9bc27249c7a8b..1e0e5d9f13915 100644
--- a/libcxx/test/support/callable_types.h
+++ b/libcxx/test/support/callable_types.h
@@ -18,7 +18,7 @@
 
 constexpr bool returns_true() { return true; }
 
-template <class Ret = bool>
+template <class Ret>
 struct MoveOnlyCallable {
   MoveOnlyCallable(MoveOnlyCallable const&) = delete;
   constexpr MoveOnlyCallable(MoveOnlyCallable&& other)
@@ -32,7 +32,7 @@ struct MoveOnlyCallable {
   Ret value;
 };
 
-template <class Ret = bool>
+template <class Ret>
 struct CopyCallable {
   constexpr CopyCallable(CopyCallable const& other)
       : value(other.value) {}
@@ -48,7 +48,7 @@ struct CopyCallable {
 };
 
 
-template <class Ret = bool>
+template <class Ret>
 struct ConstCallable {
   constexpr ConstCallable(ConstCallable const& other)
       : value(other.value) {}
@@ -65,7 +65,7 @@ struct ConstCallable {
 
 
 
-template <class Ret = bool>
+template <class Ret>
 struct NoExceptCallable {
   constexpr NoExceptCallable(NoExceptCallable const& other)
       : value(other.value) {}

diff  --git a/libcxx/test/support/test_iterators.h b/libcxx/test/support/test_iterators.h
index d3c2e4d7b611d..d5381b5de1dfc 100644
--- a/libcxx/test/support/test_iterators.h
+++ b/libcxx/test/support/test_iterators.h
@@ -53,6 +53,11 @@ class cpp17_output_iterator
     template <class T>
     void operator,(T const &) = delete;
 };
+#if TEST_STD_VER > 14
+template <class It>
+cpp17_output_iterator(It) -> cpp17_output_iterator<It>;
+#endif
+
 #if TEST_STD_VER > 17
    static_assert(std::output_iterator<cpp17_output_iterator<int*>, int>);
 #endif
@@ -94,6 +99,11 @@ class cpp17_input_iterator
     template <class T>
     void operator,(T const &) = delete;
 };
+#if TEST_STD_VER > 14
+template <class It>
+cpp17_input_iterator(It) -> cpp17_input_iterator<It>;
+#endif
+
 #if TEST_STD_VER > 17
    static_assert(std::input_iterator<cpp17_input_iterator<int*>>);
 #endif
@@ -133,6 +143,10 @@ class forward_iterator
     template <class T>
     void operator,(T const &) = delete;
 };
+#if TEST_STD_VER > 14
+template <class It>
+forward_iterator(It) -> forward_iterator<It>;
+#endif
 
 template <class It>
 class bidirectional_iterator
@@ -171,6 +185,10 @@ class bidirectional_iterator
     template <class T>
     void operator,(T const &) = delete;
 };
+#if TEST_STD_VER > 14
+template <class It>
+bidirectional_iterator(It) -> bidirectional_iterator<It>;
+#endif
 
 template <class It>
 class random_access_iterator
@@ -221,6 +239,10 @@ class random_access_iterator
     template <class T>
     void operator,(T const &) = delete;
 };
+#if TEST_STD_VER > 14
+template <class It>
+random_access_iterator(It) -> random_access_iterator<It>;
+#endif
 
 #if TEST_STD_VER > 17
 
@@ -310,6 +332,8 @@ class cpp20_random_access_iterator {
   template <class T>
   void operator,(T const&) = delete;
 };
+template <class It>
+cpp20_random_access_iterator(It) -> cpp20_random_access_iterator<It>;
 
 static_assert(std::random_access_iterator<cpp20_random_access_iterator<int*>>);
 
@@ -368,6 +392,8 @@ class contiguous_iterator
     template <class T>
     void operator,(T const &) = delete;
 };
+template <class It>
+contiguous_iterator(It) -> contiguous_iterator<It>;
 
 template <class It>
 class three_way_contiguous_iterator
@@ -418,6 +444,8 @@ class three_way_contiguous_iterator
     template <class T>
     void operator,(T const &) = delete;
 };
+template <class It>
+three_way_contiguous_iterator(It) -> three_way_contiguous_iterator<It>;
 #endif // TEST_STD_VER > 17
 
 template <class Iter> // ADL base() for everything else (including pointers)
@@ -627,6 +655,9 @@ class cpp20_input_iterator
     template <class T>
     void operator,(T const &) = delete;
 };
+template <class It>
+cpp20_input_iterator(It) -> cpp20_input_iterator<It>;
+
 static_assert(std::input_iterator<cpp20_input_iterator<int*>>);
 
 template<std::input_or_output_iterator>
@@ -660,6 +691,8 @@ class cpp20_output_iterator {
   template <class T>
   void operator,(T const&) = delete;
 };
+template <class It>
+cpp20_output_iterator(It) -> cpp20_output_iterator<It>;
 
 static_assert(std::output_iterator<cpp20_output_iterator<int*>, int>);
 
@@ -815,6 +848,8 @@ class stride_counting_iterator {
     
diff erence_type stride_count_ = 0;
     
diff erence_type stride_displacement_ = 0;
 };
+template <class It>
+stride_counting_iterator(It) -> stride_counting_iterator<It>;
 
 #endif // TEST_STD_VER > 17
 
@@ -829,6 +864,8 @@ class sentinel_wrapper {
 private:
     decltype(base(std::declval<It>())) base_;
 };
+template <class It>
+sentinel_wrapper(It) -> sentinel_wrapper<It>;
 
 template <class It>
 class sized_sentinel {
@@ -842,6 +879,8 @@ class sized_sentinel {
 private:
     decltype(base(std::declval<It>())) base_;
 };
+template <class It>
+sized_sentinel(It) -> sized_sentinel<It>;
 
 namespace adl {
 
@@ -1211,6 +1250,8 @@ struct ProxyIterator : ProxyIteratorBase<Base> {
     return x.base_ - y.base_;
   }
 };
+template <class Base>
+ProxyIterator(Base) -> ProxyIterator<Base>;
 
 static_assert(std::indirectly_readable<ProxyIterator<int*>>);
 static_assert(std::indirectly_writable<ProxyIterator<int*>, Proxy<int>>);
@@ -1229,6 +1270,8 @@ struct ProxySentinel {
     return p.base_ == sent.base_;
   }
 };
+template <class BaseSent>
+ProxySentinel(BaseSent) -> ProxySentinel<BaseSent>;
 
 template <std::ranges::input_range Base>
   requires std::ranges::view<Base>

diff  --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index e33aac575ba50..74a4ec24201d5 100644
--- 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',


        


More information about the libcxx-commits mailing list