[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