Skip to content

Commit 8b60ba7

Browse files
committed
[libc++] Add availability markup for std::to_chars on Apple platforms
Summary: Otherwise, one gets link errors when trying to back-deploy to older platforms. rdar://problem/57854364 Reviewers: lichray, EricWF Subscribers: christof, jkorous, dexonsmith, libcxx-commits Tags: #libc Differential Revision: https://reviews.llvm.org/D74626
1 parent e580552 commit 8b60ba7

File tree

6 files changed

+152
-66
lines changed

6 files changed

+152
-66
lines changed

libcxx/include/__config

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,6 +1430,8 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
14301430
_Pragma("clang attribute pop") \
14311431
_Pragma("clang attribute pop") \
14321432
_Pragma("clang attribute pop")
1433+
# define _LIBCPP_AVAILABILITY_TO_CHARS \
1434+
_LIBCPP_AVAILABILITY_FILESYSTEM
14331435
#else
14341436
# define _LIBCPP_AVAILABILITY_SHARED_MUTEX
14351437
# define _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS
@@ -1444,6 +1446,7 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
14441446
# define _LIBCPP_AVAILABILITY_FILESYSTEM
14451447
# define _LIBCPP_AVAILABILITY_FILESYSTEM_PUSH
14461448
# define _LIBCPP_AVAILABILITY_FILESYSTEM_POP
1449+
# define _LIBCPP_AVAILABILITY_TO_CHARS
14471450
#endif
14481451

14491452
// Define availability that depends on _LIBCPP_NO_EXCEPTIONS.

libcxx/include/charconv

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ namespace std {
7373
7474
*/
7575

76+
#include <__config>
7677
#include <__errc>
7778
#include <type_traits>
7879
#include <limits>
@@ -92,8 +93,8 @@ _LIBCPP_PUSH_MACROS
9293
_LIBCPP_BEGIN_NAMESPACE_STD
9394

9495
namespace __itoa {
95-
_LIBCPP_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer);
96-
_LIBCPP_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer);
96+
_LIBCPP_AVAILABILITY_TO_CHARS _LIBCPP_FUNC_VIS char* __u64toa(uint64_t __value, char* __buffer);
97+
_LIBCPP_AVAILABILITY_TO_CHARS _LIBCPP_FUNC_VIS char* __u32toa(uint32_t __value, char* __buffer);
9798
}
9899

99100
#ifndef _LIBCPP_CXX03_LANG
@@ -167,6 +168,7 @@ struct _LIBCPP_HIDDEN __traits_base
167168
}
168169
#endif
169170

171+
_LIBCPP_AVAILABILITY_TO_CHARS
170172
static _LIBCPP_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p)
171173
{
172174
return __u64toa(__v, __p);
@@ -189,6 +191,7 @@ struct _LIBCPP_HIDDEN
189191
}
190192
#endif
191193

194+
_LIBCPP_AVAILABILITY_TO_CHARS
192195
static _LIBCPP_INLINE_VISIBILITY char* __convert(_Tp __v, char* __p)
193196
{
194197
return __u32toa(__v, __p);
@@ -292,6 +295,7 @@ __to_unsigned(_Tp __x)
292295
}
293296

294297
template <typename _Tp>
298+
_LIBCPP_AVAILABILITY_TO_CHARS
295299
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
296300
__to_chars_itoa(char* __first, char* __last, _Tp __value, true_type)
297301
{
@@ -306,6 +310,7 @@ __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type)
306310
}
307311

308312
template <typename _Tp>
313+
_LIBCPP_AVAILABILITY_TO_CHARS
309314
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
310315
__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type)
311316
{
@@ -337,6 +342,7 @@ __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type)
337342
}
338343

339344
template <typename _Tp>
345+
_LIBCPP_AVAILABILITY_TO_CHARS
340346
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
341347
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base,
342348
true_type)
@@ -352,6 +358,7 @@ __to_chars_integral(char* __first, char* __last, _Tp __value, int __base,
352358
}
353359

354360
template <typename _Tp>
361+
_LIBCPP_AVAILABILITY_TO_CHARS
355362
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
356363
__to_chars_integral(char* __first, char* __last, _Tp __value, int __base,
357364
false_type)
@@ -380,13 +387,15 @@ __to_chars_integral(char* __first, char* __last, _Tp __value, int __base,
380387
}
381388

382389
template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
390+
_LIBCPP_AVAILABILITY_TO_CHARS
383391
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
384392
to_chars(char* __first, char* __last, _Tp __value)
385393
{
386394
return __to_chars_itoa(__first, __last, __value, is_signed<_Tp>());
387395
}
388396

389397
template <typename _Tp, typename enable_if<is_integral<_Tp>::value, int>::type = 0>
398+
_LIBCPP_AVAILABILITY_TO_CHARS
390399
inline _LIBCPP_INLINE_VISIBILITY to_chars_result
391400
to_chars(char* __first, char* __last, _Tp __value, int __base)
392401
{
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++98, c++03
10+
// REQUIRES: availability=macosx10.7 || availability=macosx10.8 || availability=macosx10.9 || availability=macosx10.10 || availability=macosx10.11 || availability=macosx10.12 || availability=macosx10.13 || availability=macosx10.14
11+
12+
// Test the availability markup on std::to_chars.
13+
14+
#include <charconv>
15+
16+
int main(int, char**)
17+
{
18+
char buf[100];
19+
int int_value = 33;
20+
long long_value = 33;
21+
int base = 2;
22+
std::to_chars(buf, buf + 100, int_value); // expected-error{{is unavailable: introduced in}}
23+
std::to_chars(buf, buf + 100, int_value, base); // expected-error{{is unavailable: introduced in}}
24+
25+
std::to_chars(buf, buf + 100, long_value); // expected-error{{is unavailable: introduced in}}
26+
std::to_chars(buf, buf + 100, long_value, base); // expected-error{{is unavailable: introduced in}}
27+
}

libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp

Lines changed: 12 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -10,52 +10,20 @@
1010
// UNSUPPORTED: !libc++ && c++11
1111
// UNSUPPORTED: !libc++ && c++14
1212

13-
// XFAIL: with_system_cxx_lib=macosx10.14
14-
// XFAIL: with_system_cxx_lib=macosx10.13
15-
// XFAIL: with_system_cxx_lib=macosx10.12
16-
// XFAIL: with_system_cxx_lib=macosx10.11
17-
// XFAIL: with_system_cxx_lib=macosx10.10
18-
// XFAIL: with_system_cxx_lib=macosx10.9
19-
// XFAIL: with_system_cxx_lib=macosx10.8
20-
// XFAIL: with_system_cxx_lib=macosx10.7
21-
2213
// <charconv>
2314

2415
// from_chars_result from_chars(const char* first, const char* last,
2516
// Integral& value, int base = 10)
2617

18+
#include <charconv>
2719
#include "test_macros.h"
2820
#include "charconv_test_helpers.h"
2921

3022
template <typename T>
31-
struct test_basics : roundtrip_test_base<T>
23+
struct test_basics
3224
{
33-
using roundtrip_test_base<T>::test;
34-
3525
void operator()()
3626
{
37-
test(0);
38-
test(42);
39-
test(32768);
40-
test(0, 10);
41-
test(42, 10);
42-
test(32768, 10);
43-
test(0xf, 16);
44-
test(0xdeadbeaf, 16);
45-
test(0755, 8);
46-
47-
for (int b = 2; b < 37; ++b)
48-
{
49-
using xl = std::numeric_limits<T>;
50-
51-
test(1, b);
52-
test(-1, b);
53-
test(xl::lowest(), b);
54-
test((xl::max)(), b);
55-
test((xl::max)() / 2, b);
56-
}
57-
58-
using std::from_chars;
5927
std::from_chars_result r;
6028
T x;
6129

@@ -65,7 +33,7 @@ struct test_basics : roundtrip_test_base<T>
6533
// the expected form of the subject sequence is a sequence of
6634
// letters and digits representing an integer with the radix
6735
// specified by base (C11 7.22.1.4/3)
68-
r = from_chars(s, s + sizeof(s), x);
36+
r = std::from_chars(s, s + sizeof(s), x);
6937
assert(r.ec == std::errc{});
7038
assert(r.ptr == s + 3);
7139
assert(x == 1);
@@ -76,22 +44,22 @@ struct test_basics : roundtrip_test_base<T>
7644

7745
// The letters from a (or A) through z (or Z) are ascribed the
7846
// values 10 through 35; (C11 7.22.1.4/3)
79-
r = from_chars(s, s + sizeof(s), x, 36);
47+
r = std::from_chars(s, s + sizeof(s), x, 36);
8048
assert(r.ec == std::errc::result_out_of_range);
8149
// The member ptr of the return value points to the first character
8250
// not matching the pattern
8351
assert(r.ptr == s + sizeof(s) - 2);
8452
assert(x == 1);
8553

8654
// no "0x" or "0X" prefix shall appear if the value of base is 16
87-
r = from_chars(s, s + sizeof(s), x, 16);
55+
r = std::from_chars(s, s + sizeof(s), x, 16);
8856
assert(r.ec == std::errc{});
8957
assert(r.ptr == s + 1);
9058
assert(x == 0);
9159

9260
// only letters and digits whose ascribed values are less than that
9361
// of base are permitted. (C11 7.22.1.4/3)
94-
r = from_chars(s + 2, s + sizeof(s), x, 12);
62+
r = std::from_chars(s + 2, s + sizeof(s), x, 12);
9563
// If the parsed value is not in the range representable by the type
9664
// of value,
9765
if (!fits_in<T>(1150))
@@ -115,46 +83,26 @@ struct test_basics : roundtrip_test_base<T>
11583
};
11684

11785
template <typename T>
118-
struct test_signed : roundtrip_test_base<T>
86+
struct test_signed
11987
{
120-
using roundtrip_test_base<T>::test;
121-
12288
void operator()()
12389
{
124-
test(-1);
125-
test(-12);
126-
test(-1, 10);
127-
test(-12, 10);
128-
test(-21734634, 10);
129-
test(-2647, 2);
130-
test(-0xcc1, 16);
131-
132-
for (int b = 2; b < 37; ++b)
133-
{
134-
using xl = std::numeric_limits<T>;
135-
136-
test(0, b);
137-
test(xl::lowest(), b);
138-
test((xl::max)(), b);
139-
}
140-
141-
using std::from_chars;
14290
std::from_chars_result r;
14391
T x;
14492

14593
{
14694
// If the pattern allows for an optional sign,
14795
// but the string has no digit characters following the sign,
14896
char s[] = "- 9+12";
149-
r = from_chars(s, s + sizeof(s), x);
97+
r = std::from_chars(s, s + sizeof(s), x);
15098
// no characters match the pattern.
15199
assert(r.ptr == s);
152100
assert(r.ec == std::errc::invalid_argument);
153101
}
154102

155103
{
156104
char s[] = "9+12";
157-
r = from_chars(s, s + sizeof(s), x);
105+
r = std::from_chars(s, s + sizeof(s), x);
158106
assert(r.ec == std::errc{});
159107
// The member ptr of the return value points to the first character
160108
// not matching the pattern,
@@ -164,7 +112,7 @@ struct test_signed : roundtrip_test_base<T>
164112

165113
{
166114
char s[] = "12";
167-
r = from_chars(s, s + 2, x);
115+
r = std::from_chars(s, s + 2, x);
168116
assert(r.ec == std::errc{});
169117
// or has the value last if all characters match.
170118
assert(r.ptr == s + 2);
@@ -175,7 +123,7 @@ struct test_signed : roundtrip_test_base<T>
175123
// '-' is the only sign that may appear
176124
char s[] = "+30";
177125
// If no characters match the pattern,
178-
r = from_chars(s, s + sizeof(s), x);
126+
r = std::from_chars(s, s + sizeof(s), x);
179127
// value is unmodified,
180128
assert(x == 12);
181129
// the member ptr of the return value is first and
@@ -191,5 +139,5 @@ int main(int, char**)
191139
run<test_basics>(integrals);
192140
run<test_signed>(all_signed);
193141

194-
return 0;
142+
return 0;
195143
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++98, c++03
10+
// UNSUPPORTED: !libc++ && c++11
11+
// UNSUPPORTED: !libc++ && c++14
12+
13+
// The roundtrip test uses to_chars, which requires functions in the dylib
14+
// that were introduced in Mac OS 10.15.
15+
//
16+
// XFAIL: with_system_cxx_lib=macosx10.14
17+
// XFAIL: with_system_cxx_lib=macosx10.13
18+
// XFAIL: with_system_cxx_lib=macosx10.12
19+
// XFAIL: with_system_cxx_lib=macosx10.11
20+
// XFAIL: with_system_cxx_lib=macosx10.10
21+
// XFAIL: with_system_cxx_lib=macosx10.9
22+
// XFAIL: with_system_cxx_lib=macosx10.8
23+
// XFAIL: with_system_cxx_lib=macosx10.7
24+
25+
// <charconv>
26+
27+
// from_chars_result from_chars(const char* first, const char* last,
28+
// Integral& value, int base = 10)
29+
30+
#include <charconv>
31+
#include "test_macros.h"
32+
#include "charconv_test_helpers.h"
33+
34+
template <typename T>
35+
struct test_basics : roundtrip_test_base<T>
36+
{
37+
using roundtrip_test_base<T>::test;
38+
39+
void operator()()
40+
{
41+
test(0);
42+
test(42);
43+
test(32768);
44+
test(0, 10);
45+
test(42, 10);
46+
test(32768, 10);
47+
test(0xf, 16);
48+
test(0xdeadbeaf, 16);
49+
test(0755, 8);
50+
51+
for (int b = 2; b < 37; ++b)
52+
{
53+
using xl = std::numeric_limits<T>;
54+
55+
test(1, b);
56+
test(-1, b);
57+
test(xl::lowest(), b);
58+
test((xl::max)(), b);
59+
test((xl::max)() / 2, b);
60+
}
61+
}
62+
};
63+
64+
template <typename T>
65+
struct test_signed : roundtrip_test_base<T>
66+
{
67+
using roundtrip_test_base<T>::test;
68+
69+
void operator()()
70+
{
71+
test(-1);
72+
test(-12);
73+
test(-1, 10);
74+
test(-12, 10);
75+
test(-21734634, 10);
76+
test(-2647, 2);
77+
test(-0xcc1, 16);
78+
79+
for (int b = 2; b < 37; ++b)
80+
{
81+
using xl = std::numeric_limits<T>;
82+
83+
test(0, b);
84+
test(xl::lowest(), b);
85+
test((xl::max)(), b);
86+
}
87+
}
88+
};
89+
90+
int main(int, char**)
91+
{
92+
run<test_basics>(integrals);
93+
run<test_signed>(all_signed);
94+
95+
return 0;
96+
}

0 commit comments

Comments
 (0)