Skip to content

Commit b49a10b

Browse files
Mark templates users shouldn't specialize with no_specializations attributes (#5536)
Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 135c5d7 commit b49a10b

23 files changed

+547
-280
lines changed

stl/inc/__msvc_chrono.hpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,20 @@ _STL_DISABLE_CLANG_WARNINGS
2525
#pragma push_macro("new")
2626
#undef new
2727

28+
// TRANSITION, non-_Ugly attribute tokens
29+
#pragma push_macro("msvc")
30+
#pragma push_macro("no_specializations")
31+
#undef msvc
32+
#undef no_specializations
33+
2834
_STD_BEGIN
2935
namespace chrono {
3036
_EXPORT_STD template <class _Rep>
3137
struct treat_as_floating_point : is_floating_point<_Rep> {}; // tests for floating-point type
3238

3339
_EXPORT_STD template <class _Rep>
34-
constexpr bool treat_as_floating_point_v = treat_as_floating_point<_Rep>::value;
40+
_NO_SPECIALIZATIONS_OF_VARIABLE_TEMPLATES constexpr bool treat_as_floating_point_v =
41+
treat_as_floating_point<_Rep>::value;
3542

3643
_EXPORT_STD template <class _Rep>
3744
struct duration_values { // gets arithmetic properties of a type
@@ -53,7 +60,7 @@ namespace chrono {
5360

5461
#if _HAS_CXX20
5562
_EXPORT_STD template <class _Clock>
56-
constexpr bool is_clock_v = requires {
63+
_NO_SPECIALIZATIONS_OF_VARIABLE_TEMPLATES constexpr bool is_clock_v = requires {
5764
typename _Clock::rep;
5865
typename _Clock::period;
5966
typename _Clock::duration;
@@ -62,7 +69,7 @@ namespace chrono {
6269
_Clock::now();
6370
};
6471
_EXPORT_STD template <class _Clock>
65-
struct is_clock : bool_constant<is_clock_v<_Clock>> {};
72+
struct _NO_SPECIALIZATIONS_CITING("N5014 [time.traits.is.clock]/2") is_clock : bool_constant<is_clock_v<_Clock>> {};
6673

6774
template <class _Clock>
6875
constexpr bool _Is_clock_v = is_clock_v<_Clock>;
@@ -688,6 +695,10 @@ namespace chrono {
688695
} // namespace chrono
689696
_STD_END
690697

698+
// TRANSITION, non-_Ugly attribute tokens
699+
#pragma pop_macro("no_specializations")
700+
#pragma pop_macro("msvc")
701+
691702
#pragma pop_macro("new")
692703
_STL_RESTORE_CLANG_WARNINGS
693704
#pragma warning(pop)

stl/inc/__msvc_formatter.hpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ _STL_DISABLE_CLANG_WARNINGS
5858
#pragma push_macro("new")
5959
#undef new
6060

61+
// TRANSITION, non-_Ugly attribute tokens
62+
#pragma push_macro("msvc")
63+
#pragma push_macro("no_specializations")
64+
#undef msvc
65+
#undef no_specializations
66+
6167
_STD_BEGIN
6268
#if _HAS_CXX23
6369
#define _FMT_P2286_BEGIN inline namespace __p2286 {
@@ -90,7 +96,7 @@ enum class _Basic_format_arg_type : uint8_t {
9096
static_assert(static_cast<int>(_Basic_format_arg_type::_Custom_type) < 16, "must fit in 4-bit bitfield");
9197

9298
#if _HAS_CXX23
93-
_EXPORT_STD template <class _Ty>
99+
_EXPORT_STD template <class _Ty> // specializations allowed by N5014 [format.formatter.locking]/1
94100
constexpr bool enable_nonlocking_formatter_optimization = false;
95101

96102
_NODISCARD consteval bool _Is_debug_enabled_fmt_type(_Basic_format_arg_type _Ty) {
@@ -126,7 +132,7 @@ struct _Dynamic_format_specs : _Basic_format_specs<_CharT> {
126132
[[noreturn]] inline void _Throw_format_error(const char* _Message);
127133

128134
_EXPORT_STD template <class _CharT>
129-
class basic_format_parse_context;
135+
class _NO_SPECIALIZATIONS_CITING("N5014 [format.parse.ctx]/2") basic_format_parse_context;
130136

131137
template <class _CharT>
132138
concept _Format_supported_charT = _Is_any_of_v<_CharT, char, wchar_t>;
@@ -328,7 +334,7 @@ struct _Invalid_format_kind {
328334
};
329335

330336
_EXPORT_STD template <class _Ty>
331-
constexpr _Invalid_format_kind<_Ty> format_kind;
337+
constexpr _Invalid_format_kind<_Ty> format_kind; // specializations allowed by N5014 [format.range.fmtkind]/3
332338

333339
template <class _Ty>
334340
constexpr bool _Is_two_tuple = false;
@@ -442,6 +448,10 @@ struct _Fill_align_and_width_formatter {
442448
#endif // _HAS_CXX23
443449
_STD_END
444450

451+
// TRANSITION, non-_Ugly attribute tokens
452+
#pragma pop_macro("no_specializations")
453+
#pragma pop_macro("msvc")
454+
445455
#pragma pop_macro("new")
446456
_STL_RESTORE_CLANG_WARNINGS
447457
#pragma warning(pop)

stl/inc/__msvc_iter_core.hpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ _STL_DISABLE_CLANG_WARNINGS
1616
#pragma push_macro("new")
1717
#undef new
1818

19+
// TRANSITION, non-_Ugly attribute tokens
20+
#pragma push_macro("msvc")
21+
#pragma push_macro("no_specializations")
22+
#undef msvc
23+
#undef no_specializations
24+
1925
_STD_BEGIN
2026
template <class _Ty, class _Alloc, class = void>
2127
struct _Has_allocator_type : false_type {}; // tests for suitable _Ty::allocator_type
@@ -34,7 +40,7 @@ _EXPORT_STD template <class _Ty, class _Alloc>
3440
struct uses_allocator : _Has_allocator_type<_Ty, _Alloc>::type {};
3541

3642
_EXPORT_STD template <class _Ty, class _Alloc>
37-
constexpr bool uses_allocator_v = uses_allocator<_Ty, _Alloc>::value;
43+
_NO_SPECIALIZATIONS_OF_VARIABLE_TEMPLATES constexpr bool uses_allocator_v = uses_allocator<_Ty, _Alloc>::value;
3844

3945
// from <iterator>
4046
_EXPORT_STD struct input_iterator_tag {};
@@ -406,7 +412,7 @@ concept input_or_output_iterator = requires(_It __i) {
406412
_EXPORT_STD template <class _Se, class _It>
407413
concept sentinel_for = semiregular<_Se> && input_or_output_iterator<_It> && _Weakly_equality_comparable_with<_Se, _It>;
408414

409-
_EXPORT_STD template <class _Se, class _It>
415+
_EXPORT_STD template <class _Se, class _It> // specializations allowed by N5014 [iterator.concept.sizedsentinel]/3
410416
constexpr bool disable_sized_sentinel_for = false;
411417

412418
_EXPORT_STD template <class _Se, class _It>
@@ -542,6 +548,10 @@ struct _Meta_find_unique_index_<_List<_First, _Rest...>, _Ty> {
542548
};
543549
_STD_END
544550

551+
// TRANSITION, non-_Ugly attribute tokens
552+
#pragma pop_macro("no_specializations")
553+
#pragma pop_macro("msvc")
554+
545555
#pragma pop_macro("new")
546556
_STL_RESTORE_CLANG_WARNINGS
547557
#pragma warning(pop)

stl/inc/__msvc_ranges_tuple_formatter.hpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ _STL_DISABLE_CLANG_WARNINGS
6161
#pragma push_macro("new")
6262
#undef new
6363

64+
// TRANSITION, non-_Ugly attribute tokens
65+
#pragma push_macro("msvc")
66+
#pragma push_macro("no_specializations")
67+
#undef msvc
68+
#undef no_specializations
69+
6470
_STD_BEGIN
6571
_EXPORT_STD template <class, class>
6672
class vector;
@@ -93,7 +99,7 @@ template <class _CharT>
9399
class _Compile_time_parse_context;
94100

95101
_EXPORT_STD template <class _CharT>
96-
class basic_format_parse_context {
102+
class _NO_SPECIALIZATIONS_CITING("N5014 [format.parse.ctx]/2") basic_format_parse_context {
97103
public:
98104
using char_type = _CharT;
99105
using const_iterator = basic_string_view<_CharT>::const_iterator;
@@ -229,7 +235,7 @@ struct _Format_handler;
229235
_FMT_P2286_END
230236

231237
_EXPORT_STD template <class _Context>
232-
class basic_format_arg {
238+
class _NO_SPECIALIZATIONS_CITING("N5014 [format.arg]/2") basic_format_arg {
233239
public:
234240
using _CharType = _Context::char_type;
235241

@@ -674,7 +680,7 @@ class _Lazy_locale {
674680

675681
_EXPORT_STD template <class _Out, class _CharT>
676682
requires output_iterator<_Out, const _CharT&>
677-
class basic_format_context {
683+
class _NO_SPECIALIZATIONS_CITING("N5014 [format.context]/2") basic_format_context {
678684
private:
679685
_Out _OutputIt;
680686
basic_format_args<basic_format_context> _Args;
@@ -1256,6 +1262,10 @@ struct formatter<tuple<_Types...>, _CharT> : _Tuple_formatter_base<tuple<_Types.
12561262
#endif // _HAS_CXX23
12571263
_STD_END
12581264

1265+
// TRANSITION, non-_Ugly attribute tokens
1266+
#pragma pop_macro("no_specializations")
1267+
#pragma pop_macro("msvc")
1268+
12591269
#pragma pop_macro("new")
12601270
_STL_RESTORE_CLANG_WARNINGS
12611271
#pragma warning(pop)

stl/inc/compare

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ _STL_DISABLE_CLANG_WARNINGS
2020
#pragma push_macro("new")
2121
#undef new
2222

23+
// TRANSITION, non-_Ugly attribute tokens
24+
#pragma push_macro("msvc")
25+
#pragma push_macro("no_specializations")
26+
#undef msvc
27+
#undef no_specializations
28+
2329
_STD_BEGIN
2430
void _Literal_zero_is_expected();
2531

@@ -321,7 +327,7 @@ using compare_three_way_result_t =
321327
decltype(_STD declval<const remove_reference_t<_Ty1>&>() <=> _STD declval<const remove_reference_t<_Ty2>&>());
322328

323329
_EXPORT_STD template <class _Ty1, class _Ty2 = _Ty1>
324-
struct compare_three_way_result {};
330+
struct _NO_SPECIALIZATIONS_CITING("N5014 [cmp.result]/1") compare_three_way_result {};
325331

326332
template <class _Ty1, class _Ty2>
327333
requires requires { typename compare_three_way_result_t<_Ty1, _Ty2>; }
@@ -841,6 +847,10 @@ inline namespace _Cpos {
841847
}
842848
_STD_END
843849

850+
// TRANSITION, non-_Ugly attribute tokens
851+
#pragma pop_macro("no_specializations")
852+
#pragma pop_macro("msvc")
853+
844854
#pragma pop_macro("new")
845855
_STL_RESTORE_CLANG_WARNINGS
846856
#pragma warning(pop)

stl/inc/coroutine

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ _STL_DISABLE_CLANG_WARNINGS
3232
#pragma push_macro("new")
3333
#undef new
3434

35+
// TRANSITION, non-_Ugly attribute tokens
36+
#pragma push_macro("msvc")
37+
#pragma push_macro("no_specializations")
38+
#undef msvc
39+
#undef no_specializations
40+
3541
_STD_BEGIN
3642

3743
template <class _Ret, class = void>
@@ -46,7 +52,7 @@ _EXPORT_STD template <class _Ret, class...>
4652
struct coroutine_traits : _Coroutine_traits<_Ret> {};
4753

4854
_EXPORT_STD template <class = void>
49-
struct coroutine_handle;
55+
struct _NO_SPECIALIZATIONS_CITING("N5014 [coroutine.handle.general]/2") coroutine_handle;
5056

5157
template <>
5258
struct coroutine_handle<void> {
@@ -93,7 +99,7 @@ private:
9399
};
94100

95101
_EXPORT_STD template <class _CoroPromise>
96-
struct coroutine_handle {
102+
struct _NO_SPECIALIZATIONS_CITING("N5014 [coroutine.handle.general]/2") coroutine_handle {
97103
constexpr coroutine_handle() noexcept = default;
98104
constexpr coroutine_handle(nullptr_t) noexcept {}
99105

@@ -255,6 +261,10 @@ _EXPORT_STD struct suspend_always {
255261

256262
_STD_END
257263

264+
// TRANSITION, non-_Ugly attribute tokens
265+
#pragma pop_macro("no_specializations")
266+
#pragma pop_macro("msvc")
267+
258268
#pragma pop_macro("new")
259269
_STL_RESTORE_CLANG_WARNINGS
260270
#pragma warning(pop)

stl/inc/functional

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ _STL_DISABLE_CLANG_WARNINGS
2828
#pragma push_macro("new")
2929
#undef new
3030

31+
// TRANSITION, non-_Ugly attribute tokens
32+
#pragma push_macro("msvc")
33+
#pragma push_macro("no_specializations")
34+
#undef msvc
35+
#undef no_specializations
36+
3137
_STD_BEGIN
3238
// plus, minus, and multiplies are defined in <xutility>
3339

@@ -301,13 +307,13 @@ _STL_RESTORE_DEPRECATED_WARNING
301307

302308
#if _HAS_AUTO_PTR_ETC
303309
_EXPORT_STD template <class _Arg, class _Result>
304-
struct unary_function { // base class for unary functions
310+
struct _NO_SPECIALIZATIONS_CITING("N4140 [depr.base]/1") unary_function { // base class for unary functions
305311
using argument_type = _Arg;
306312
using result_type = _Result;
307313
};
308314

309315
_EXPORT_STD template <class _Arg1, class _Arg2, class _Result>
310-
struct binary_function { // base class for binary functions
316+
struct _NO_SPECIALIZATIONS_CITING("N4140 [depr.base]/1") binary_function { // base class for binary functions
311317
using first_argument_type = _Arg1;
312318
using second_argument_type = _Arg2;
313319
using result_type = _Result;
@@ -2008,7 +2014,7 @@ template <class _Tx>
20082014
struct is_placeholder<const volatile _Tx> : is_placeholder<_Tx>::type {}; // ignore cv-qualifiers
20092015

20102016
_EXPORT_STD template <class _Ty>
2011-
constexpr int is_placeholder_v = is_placeholder<_Ty>::value;
2017+
_NO_SPECIALIZATIONS_OF_VARIABLE_TEMPLATES constexpr int is_placeholder_v = is_placeholder<_Ty>::value;
20122018

20132019
template <class _Ret, class _Fx, class... _Types>
20142020
class _Binder;
@@ -2029,7 +2035,7 @@ template <class _Tx>
20292035
struct is_bind_expression<const volatile _Tx> : is_bind_expression<_Tx>::type {}; // ignore cv-qualifiers
20302036

20312037
_EXPORT_STD template <class _Ty>
2032-
constexpr bool is_bind_expression_v = is_bind_expression<_Ty>::value;
2038+
_NO_SPECIALIZATIONS_OF_VARIABLE_TEMPLATES constexpr bool is_bind_expression_v = is_bind_expression<_Ty>::value;
20332039

20342040
template <class _Cv_TiD, bool = _Is_specialization_v<remove_cv_t<_Cv_TiD>, reference_wrapper>,
20352041
bool = is_bind_expression_v<_Cv_TiD>, int = is_placeholder_v<_Cv_TiD>>
@@ -3160,6 +3166,10 @@ namespace _DEPRECATE_TR1_NAMESPACE tr1 {
31603166

31613167
_STD_END
31623168

3169+
// TRANSITION, non-_Ugly attribute tokens
3170+
#pragma pop_macro("no_specializations")
3171+
#pragma pop_macro("msvc")
3172+
31633173
#pragma pop_macro("new")
31643174
_STL_RESTORE_CLANG_WARNINGS
31653175
#pragma warning(pop)

stl/inc/generator

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@ _STL_DISABLE_CLANG_WARNINGS
2727
#undef new
2828

2929
// TRANSITION, non-_Ugly attribute tokens
30+
#pragma push_macro("msvc")
31+
#pragma push_macro("no_specializations")
3032
#pragma push_macro("empty_bases")
33+
#undef msvc
34+
#undef no_specializations
3135
#undef empty_bases
3236

3337
_STD_BEGIN
@@ -40,7 +44,7 @@ template <class _Alloc>
4044
constexpr bool _Stateless_allocator = default_initializable<_Alloc> && allocator_traits<_Alloc>::is_always_equal::value;
4145

4246
_EXPORT_STD template <class _Rty, class _Vty = void, class _Alloc = void>
43-
class generator;
47+
class _NO_SPECIALIZATIONS_CITING("N5014 [coro.generator.class]/4") generator;
4448

4549
namespace _Gen_detail {
4650
template <class _Alloc>
@@ -518,7 +522,8 @@ namespace _Gen_detail {
518522
} // namespace _Gen_detail
519523

520524
_EXPORT_STD template <class _Rty, class _Vty, class _Alloc>
521-
class generator : public _RANGES view_interface<generator<_Rty, _Vty, _Alloc>> {
525+
class _NO_SPECIALIZATIONS_CITING("N5014 [coro.generator.class]/4") generator
526+
: public _RANGES view_interface<generator<_Rty, _Vty, _Alloc>> {
522527
private:
523528
static_assert(_Gen_detail::_Valid_allocator<_Alloc>,
524529
"generator allocators must use raw pointers (N4988 [coro.generator.class]/1.1)");
@@ -603,6 +608,8 @@ _STD_END
603608

604609
// TRANSITION, non-_Ugly attribute tokens
605610
#pragma pop_macro("empty_bases")
611+
#pragma pop_macro("no_specializations")
612+
#pragma pop_macro("msvc")
606613

607614
#pragma pop_macro("new")
608615
_STL_RESTORE_CLANG_WARNINGS

stl/inc/initializer_list

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@ _STL_DISABLE_CLANG_WARNINGS
1616
#pragma push_macro("new")
1717
#undef new
1818

19+
// TRANSITION, non-_Ugly attribute tokens
20+
#pragma push_macro("msvc")
21+
#pragma push_macro("no_specializations")
22+
#undef msvc
23+
#undef no_specializations
24+
1925
_STD_BEGIN
2026
_EXPORT_STD template <class _Elem>
21-
class initializer_list {
27+
class _NO_SPECIALIZATIONS_CITING("N5014 [initializer.list.syn]/2") initializer_list {
2228
public:
2329
using value_type = _Elem;
2430
using reference = const _Elem&;
@@ -60,6 +66,11 @@ _NODISCARD constexpr const _Elem* end(initializer_list<_Elem> _Ilist) noexcept {
6066
return _Ilist.end();
6167
}
6268
_STD_END
69+
70+
// TRANSITION, non-_Ugly attribute tokens
71+
#pragma pop_macro("no_specializations")
72+
#pragma pop_macro("msvc")
73+
6374
#pragma pop_macro("new")
6475
_STL_RESTORE_CLANG_WARNINGS
6576
#pragma warning(pop)

0 commit comments

Comments
 (0)