Skip to content

Commit 5fd17ab

Browse files
committed
Fix overload sets of strchr, strpbrk, strrchr, memchr and strstr from
<string.h> and wcschr, wcspbrk, wcsrchr, wmemchr, and wcsstr from <wchar.h> to provide a const-correct overload set even when the underlying C library does not. This change adds a new macro, _LIBCPP_PREFERRED_OVERLOAD, which (if defined) specifies that a given overload is a better match than an otherwise equally good function declaration without the overload. This is implemented in modern versions of Clang via __attribute__((enable_if)), and not elsewhere. We use this new macro to define overloads in the global namespace for these functions that displace the overloads provided by the C library, unless we believe the C library is already providing the correct signatures. llvm-svn: 260337
1 parent 755a4e6 commit 5fd17ab

File tree

9 files changed

+193
-57
lines changed

9 files changed

+193
-57
lines changed

libcxx/include/__config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,12 @@
237237
# endif
238238
#endif
239239

240+
#ifndef _LIBCPP_PREFERRED_OVERLOAD
241+
# if __has_attribute(__enable_if__)
242+
# define _LIBCPP_PREFERRED_OVERLOAD __attribute__ ((__enable_if__(true, "")))
243+
# endif
244+
#endif
245+
240246
#ifndef _LIBCPP_TYPE_VIS_ONLY
241247
# define _LIBCPP_TYPE_VIS_ONLY _LIBCPP_TYPE_VIS
242248
#endif

libcxx/include/cstring

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -78,30 +78,13 @@ using ::strcmp;
7878
using ::strncmp;
7979
using ::strcoll;
8080
using ::strxfrm;
81-
8281
using ::memchr;
83-
8482
using ::strchr;
85-
8683
using ::strcspn;
87-
8884
using ::strpbrk;
89-
9085
using ::strrchr;
91-
9286
using ::strspn;
93-
9487
using ::strstr;
95-
96-
// MSVCRT, GNU libc and its derivates already have the correct prototype in <string.h> #ifdef __cplusplus
97-
#if !defined(__GLIBC__) && !defined(_LIBCPP_MSVCRT) && !defined(__sun__) && !defined(_STRING_H_CPLUSPLUS_98_CONFORMANCE_)
98-
inline _LIBCPP_INLINE_VISIBILITY char* strchr( char* __s, int __c) {return ::strchr(__s, __c);}
99-
inline _LIBCPP_INLINE_VISIBILITY char* strpbrk( char* __s1, const char* __s2) {return ::strpbrk(__s1, __s2);}
100-
inline _LIBCPP_INLINE_VISIBILITY char* strrchr( char* __s, int __c) {return ::strrchr(__s, __c);}
101-
inline _LIBCPP_INLINE_VISIBILITY void* memchr( void* __s, int __c, size_t __n) {return ::memchr(__s, __c, __n);}
102-
inline _LIBCPP_INLINE_VISIBILITY char* strstr( char* __s1, const char* __s2) {return ::strstr(__s1, __s2);}
103-
#endif
104-
10588
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
10689
using ::strtok;
10790
#endif

libcxx/include/cwchar

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -157,30 +157,11 @@ using ::wcscmp;
157157
using ::wcscoll;
158158
using ::wcsncmp;
159159
using ::wcsxfrm;
160-
161-
#ifdef _LIBCPP_WCHAR_H_HAS_CONST_OVERLOADS
162160
using ::wcschr;
163161
using ::wcspbrk;
164162
using ::wcsrchr;
165163
using ::wcsstr;
166164
using ::wmemchr;
167-
#else
168-
inline _LIBCPP_INLINE_VISIBILITY const wchar_t* wcschr(const wchar_t* __s, wchar_t __c) {return ::wcschr(__s, __c);}
169-
inline _LIBCPP_INLINE_VISIBILITY wchar_t* wcschr( wchar_t* __s, wchar_t __c) {return ::wcschr(__s, __c);}
170-
171-
inline _LIBCPP_INLINE_VISIBILITY const wchar_t* wcspbrk(const wchar_t* __s1, const wchar_t* __s2) {return ::wcspbrk(__s1, __s2);}
172-
inline _LIBCPP_INLINE_VISIBILITY wchar_t* wcspbrk( wchar_t* __s1, const wchar_t* __s2) {return ::wcspbrk(__s1, __s2);}
173-
174-
inline _LIBCPP_INLINE_VISIBILITY const wchar_t* wcsrchr(const wchar_t* __s, wchar_t __c) {return ::wcsrchr(__s, __c);}
175-
inline _LIBCPP_INLINE_VISIBILITY wchar_t* wcsrchr( wchar_t* __s, wchar_t __c) {return ::wcsrchr(__s, __c);}
176-
177-
inline _LIBCPP_INLINE_VISIBILITY const wchar_t* wcsstr(const wchar_t* __s1, const wchar_t* __s2) {return ::wcsstr(__s1, __s2);}
178-
inline _LIBCPP_INLINE_VISIBILITY wchar_t* wcsstr( wchar_t* __s1, const wchar_t* __s2) {return ::wcsstr(__s1, __s2);}
179-
180-
inline _LIBCPP_INLINE_VISIBILITY const wchar_t* wmemchr(const wchar_t* __s, wchar_t __c, size_t __n) {return ::wmemchr(__s, __c, __n);}
181-
inline _LIBCPP_INLINE_VISIBILITY wchar_t* wmemchr( wchar_t* __s, wchar_t __c, size_t __n) {return ::wmemchr(__s, __c, __n);}
182-
#endif
183-
184165
using ::wcscspn;
185166
using ::wcslen;
186167
using ::wcsspn;

libcxx/include/string.h

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// -*- C++ -*-
2+
//===--------------------------- string.h ---------------------------------===//
3+
//
4+
// The LLVM Compiler Infrastructure
5+
//
6+
// This file is distributed under the University of Illinois Open Source
7+
// License. See LICENSE.TXT for details.
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
#ifndef _LIBCPP_STRING_H
12+
#define _LIBCPP_STRING_H
13+
14+
/*
15+
string.h synopsis
16+
17+
Macros:
18+
19+
NULL
20+
21+
Types:
22+
23+
size_t
24+
25+
void* memcpy(void* restrict s1, const void* restrict s2, size_t n);
26+
void* memmove(void* s1, const void* s2, size_t n);
27+
char* strcpy (char* restrict s1, const char* restrict s2);
28+
char* strncpy(char* restrict s1, const char* restrict s2, size_t n);
29+
char* strcat (char* restrict s1, const char* restrict s2);
30+
char* strncat(char* restrict s1, const char* restrict s2, size_t n);
31+
int memcmp(const void* s1, const void* s2, size_t n);
32+
int strcmp (const char* s1, const char* s2);
33+
int strncmp(const char* s1, const char* s2, size_t n);
34+
int strcoll(const char* s1, const char* s2);
35+
size_t strxfrm(char* restrict s1, const char* restrict s2, size_t n);
36+
const void* memchr(const void* s, int c, size_t n);
37+
void* memchr( void* s, int c, size_t n);
38+
const char* strchr(const char* s, int c);
39+
char* strchr( char* s, int c);
40+
size_t strcspn(const char* s1, const char* s2);
41+
const char* strpbrk(const char* s1, const char* s2);
42+
char* strpbrk( char* s1, const char* s2);
43+
const char* strrchr(const char* s, int c);
44+
char* strrchr( char* s, int c);
45+
size_t strspn(const char* s1, const char* s2);
46+
const char* strstr(const char* s1, const char* s2);
47+
char* strstr( char* s1, const char* s2);
48+
char* strtok(char* restrict s1, const char* restrict s2);
49+
void* memset(void* s, int c, size_t n);
50+
char* strerror(int errnum);
51+
size_t strlen(const char* s);
52+
53+
*/
54+
55+
#include <__config>
56+
57+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
58+
#pragma GCC system_header
59+
#endif
60+
61+
#include_next <string.h>
62+
63+
// MSVCRT, GNU libc and its derivates already have the correct prototype in
64+
// <string.h> if __cplusplus is defined. This macro can be defined by users if
65+
// their C library provides the right signature.
66+
#if defined(__GLIBC__) || defined(_LIBCPP_MSVCRT) || defined(__sun__) || \
67+
defined(_STRING_H_CPLUSPLUS_98_CONFORMANCE_)
68+
#define _LIBCPP_STRING_H_HAS_CONST_OVERLOADS
69+
#endif
70+
71+
#if defined(__cplusplus) && !defined(_LIBCPP_STRING_H_HAS_CONST_OVERLOADS) && defined(_LIBCPP_PREFERRED_OVERLOAD)
72+
extern "C++" {
73+
inline _LIBCPP_INLINE_VISIBILITY
74+
char* __libcpp_strchr(const char* __s, int __c) {return (char*)strchr(__s, __c);}
75+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
76+
const char* strchr(const char* __s, int __c) {return __libcpp_strchr(__s, __c);}
77+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
78+
char* strchr( char* __s, int __c) {return __libcpp_strchr(__s, __c);}
79+
80+
inline _LIBCPP_INLINE_VISIBILITY
81+
char* __libcpp_strpbrk(const char* __s1, const char* __s2) {return (char*)strpbrk(__s1, __s2);}
82+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
83+
const char* strpbrk(const char* __s1, const char* __s2) {return __libcpp_strpbrk(__s1, __s2);}
84+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
85+
char* strpbrk( char* __s1, const char* __s2) {return __libcpp_strpbrk(__s1, __s2);}
86+
87+
inline _LIBCPP_INLINE_VISIBILITY
88+
char* __libcpp_strrchr(const char* __s, int __c) {return (char*)strrchr(__s, __c);}
89+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
90+
const char* strrchr(const char* __s, int __c) {return __libcpp_strrchr(__s, __c);}
91+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
92+
char* strrchr( char* __s, int __c) {return __libcpp_strrchr(__s, __c);}
93+
94+
inline _LIBCPP_INLINE_VISIBILITY
95+
void* __libcpp_memchr(const void* __s, int __c, size_t __n) {return (void*)memchr(__s, __c, __n);}
96+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
97+
const void* memchr(const void* __s, int __c, size_t __n) {return __libcpp_memchr(__s, __c, __n);}
98+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
99+
void* memchr( void* __s, int __c, size_t __n) {return __libcpp_memchr(__s, __c, __n);}
100+
101+
inline _LIBCPP_INLINE_VISIBILITY
102+
char* __libcpp_strstr(const char* __s1, const char* __s2) {return (char*)strstr(__s1, __s2);}
103+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
104+
const char* strstr(const char* __s1, const char* __s2) {return __libcpp_strstr(__s1, __s2);}
105+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
106+
char* strstr( char* __s1, const char* __s2) {return __libcpp_strstr(__s1, __s2);}
107+
}
108+
#endif
109+
110+
#endif // _LIBCPP_STRING_H

libcxx/include/wchar.h

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len,
118118

119119
#include_next <wchar.h>
120120

121-
// Let <cwchar> know if we have const-correct overloads for wcschr and friends.
121+
// Determine whether we have const-correct overloads for wcschr and friends.
122122
#if defined(_WCHAR_H_CPLUSPLUS_98_CONFORMANCE_)
123123
# define _LIBCPP_WCHAR_H_HAS_CONST_OVERLOADS 1
124124
#elif defined(__GLIBC_PREREQ)
@@ -127,6 +127,45 @@ size_t wcsrtombs(char* restrict dst, const wchar_t** restrict src, size_t len,
127127
# endif
128128
#endif
129129

130+
#if defined(__cplusplus) && !defined(_LIBCPP_WCHAR_H_HAS_CONST_OVERLOADS) && defined(_LIBCPP_PREFERRED_OVERLOAD)
131+
extern "C++" {
132+
inline _LIBCPP_INLINE_VISIBILITY
133+
wchar_t* __libcpp_wcschr(const wchar_t* __s, wchar_t __c) {return (wchar_t*)wcschr(__s, __c);}
134+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
135+
const wchar_t* wcschr(const wchar_t* __s, wchar_t __c) {return __libcpp_wcschr(__s, __c);}
136+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
137+
wchar_t* wcschr( wchar_t* __s, wchar_t __c) {return __libcpp_wcschr(__s, __c);}
138+
139+
inline _LIBCPP_INLINE_VISIBILITY
140+
wchar_t* __libcpp_wcspbrk(const wchar_t* __s1, const wchar_t* __s2) {return (wchar_t*)wcspbrk(__s1, __s2);}
141+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
142+
const wchar_t* wcspbrk(const wchar_t* __s1, const wchar_t* __s2) {return __libcpp_wcspbrk(__s1, __s2);}
143+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
144+
wchar_t* wcspbrk( wchar_t* __s1, const wchar_t* __s2) {return __libcpp_wcspbrk(__s1, __s2);}
145+
146+
inline _LIBCPP_INLINE_VISIBILITY
147+
wchar_t* __libcpp_wcsrchr(const wchar_t* __s, wchar_t __c) {return (wchar_t*)wcsrchr(__s, __c);}
148+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
149+
const wchar_t* wcsrchr(const wchar_t* __s, wchar_t __c) {return __libcpp_wcsrchr(__s, __c);}
150+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
151+
wchar_t* wcsrchr( wchar_t* __s, wchar_t __c) {return __libcpp_wcsrchr(__s, __c);}
152+
153+
inline _LIBCPP_INLINE_VISIBILITY
154+
wchar_t* __libcpp_wcsstr(const wchar_t* __s1, const wchar_t* __s2) {return (wchar_t*)wcsstr(__s1, __s2);}
155+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
156+
const wchar_t* wcsstr(const wchar_t* __s1, const wchar_t* __s2) {return __libcpp_wcsstr(__s1, __s2);}
157+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
158+
wchar_t* wcsstr( wchar_t* __s1, const wchar_t* __s2) {return __libcpp_wcsstr(__s1, __s2);}
159+
160+
inline _LIBCPP_INLINE_VISIBILITY
161+
wchar_t* __libcpp_wmemchr(const wchar_t* __s, wchar_t __c, size_t __n) {return (wchar_t*)wmemchr(__s, __c, __n);}
162+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
163+
const wchar_t* wmemchr(const wchar_t* __s, wchar_t __c, size_t __n) {return __libcpp_wmemchr(__s, __c, __n);}
164+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_PREFERRED_OVERLOAD
165+
wchar_t* wmemchr( wchar_t* __s, wchar_t __c, size_t __n) {return __libcpp_wmemchr(__s, __c, __n);}
166+
}
167+
#endif
168+
130169
#if defined(__cplusplus) && (defined(_LIBCPP_MSVCRT) || defined(__MINGW32__))
131170
extern "C++" {
132171
#include <support/win32/support.h> // pull in *swprintf defines

libcxx/test/std/depr/depr.c.headers/string_h.pass.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,15 @@ int main()
4747
static_assert((std::is_same<decltype(memset(vp, 0, s)), void*>::value), "");
4848
static_assert((std::is_same<decltype(strerror(0)), char*>::value), "");
4949
static_assert((std::is_same<decltype(strlen(cpc)), size_t>::value), "");
50+
51+
// These tests fail on systems whose C library doesn't provide a correct overload
52+
// set for strchr, strpbrk, strrchr, strstr, and memchr, unless the compiler is
53+
// a suitably recent version of Clang.
54+
#if !defined(__APPLE__) || defined(_LIBCPP_PREFERRED_OVERLOAD)
55+
static_assert((std::is_same<decltype(strchr(cpc, 0)), const char*>::value), "");
56+
static_assert((std::is_same<decltype(strpbrk(cpc, cpc)), const char*>::value), "");
57+
static_assert((std::is_same<decltype(strrchr(cpc, 0)), const char*>::value), "");
58+
static_assert((std::is_same<decltype(strstr(cpc, cpc)), const char*>::value), "");
59+
static_assert((std::is_same<decltype(memchr(vpc, 0, s)), const void*>::value), "");
60+
#endif
5061
}

libcxx/test/std/depr/depr.c.headers/wchar_h.pass.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
// <wchar.h>
1111

12-
1312
#include <wchar.h>
1413
#include <type_traits>
1514

@@ -82,19 +81,14 @@ int main()
8281
static_assert((std::is_same<decltype(wcscoll(L"", L"")), int>::value), "");
8382
static_assert((std::is_same<decltype(wcsncmp(L"", L"", s)), int>::value), "");
8483
static_assert((std::is_same<decltype(wcsxfrm(ws, L"", s)), size_t>::value), "");
85-
// const wchar_t* wcschr((const wchar_t*)0, L' ') - See below
8684
static_assert((std::is_same<decltype(wcschr((wchar_t*)0, L' ')), wchar_t*>::value), "");
8785
static_assert((std::is_same<decltype(wcscspn(L"", L"")), size_t>::value), "");
8886
static_assert((std::is_same<decltype(wcslen(L"")), size_t>::value), "");
89-
// const wchar_t* wcspbrk((const wchar_t*)0, L"") - See below
9087
static_assert((std::is_same<decltype(wcspbrk((wchar_t*)0, L"")), wchar_t*>::value), "");
91-
// const wchar_t* wcsrchr((const wchar_t*)0, L' ') - See below
9288
static_assert((std::is_same<decltype(wcsrchr((wchar_t*)0, L' ')), wchar_t*>::value), "");
9389
static_assert((std::is_same<decltype(wcsspn(L"", L"")), size_t>::value), "");
94-
// const wchar_t* wcsstr((const wchar_t*)0, L"") - See below
9590
static_assert((std::is_same<decltype(wcsstr((wchar_t*)0, L"")), wchar_t*>::value), "");
9691
static_assert((std::is_same<decltype(wcstok(ws, L"", (wchar_t**)0)), wchar_t*>::value), "");
97-
// const wchar_t* wmemchr((const wchar_t*)0, L' ', s) - See below
9892
static_assert((std::is_same<decltype(wmemchr((wchar_t*)0, L' ', s)), wchar_t*>::value), "");
9993
static_assert((std::is_same<decltype(wmemcmp(L"", L"", s)), int>::value), "");
10094
static_assert((std::is_same<decltype(wmemcpy(ws, L"", s)), wchar_t*>::value), "");
@@ -110,10 +104,10 @@ int main()
110104
static_assert((std::is_same<decltype(mbsrtowcs(ws, (const char**)0, s, &mb)), size_t>::value), "");
111105
static_assert((std::is_same<decltype(wcsrtombs(ns, (const wchar_t**)0, s, &mb)), size_t>::value), "");
112106

113-
// This test fails on systems whose C library doesn't provide a correct overload
114-
// set for wcschr, wcspbrk, wcsrchr, wcsstr, and wmemchr. There's no way for
115-
// libc++ to fix that on the C library's behalf.
116-
#ifndef __APPLE__
107+
// These tests fail on systems whose C library doesn't provide a correct overload
108+
// set for wcschr, wcspbrk, wcsrchr, wcsstr, and wmemchr, unless the compiler is
109+
// a suitably recent version of Clang.
110+
#if !defined(__APPLE__) || defined(_LIBCPP_PREFERRED_OVERLOAD)
117111
static_assert((std::is_same<decltype(wcschr((const wchar_t*)0, L' ')), const wchar_t*>::value), "");
118112
static_assert((std::is_same<decltype(wcspbrk((const wchar_t*)0, L"")), const wchar_t*>::value), "");
119113
static_assert((std::is_same<decltype(wcsrchr((const wchar_t*)0, L' ')), const wchar_t*>::value), "");

libcxx/test/std/strings/c.strings/cstring.pass.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,28 @@ int main()
3434
static_assert((std::is_same<decltype(std::strncmp(cpc, cpc, s)), int>::value), "");
3535
static_assert((std::is_same<decltype(std::strcoll(cpc, cpc)), int>::value), "");
3636
static_assert((std::is_same<decltype(std::strxfrm(cp, cpc, s)), std::size_t>::value), "");
37-
// static_assert((std::is_same<decltype(std::memchr(vpc, 0, s)), const void*>::value), "");
3837
static_assert((std::is_same<decltype(std::memchr(vp, 0, s)), void*>::value), "");
39-
// static_assert((std::is_same<decltype(std::strchr(cpc, 0)), const char*>::value), "");
4038
static_assert((std::is_same<decltype(std::strchr(cp, 0)), char*>::value), "");
4139
static_assert((std::is_same<decltype(std::strcspn(cpc, cpc)), std::size_t>::value), "");
42-
// static_assert((std::is_same<decltype(std::strpbrk(cpc, cpc)), const char*>::value), "");
4340
static_assert((std::is_same<decltype(std::strpbrk(cp, cpc)), char*>::value), "");
44-
// static_assert((std::is_same<decltype(std::strrchr(cpc, 0)), const char*>::value), "");
4541
static_assert((std::is_same<decltype(std::strrchr(cp, 0)), char*>::value), "");
4642
static_assert((std::is_same<decltype(std::strspn(cpc, cpc)), std::size_t>::value), "");
47-
// static_assert((std::is_same<decltype(std::strstr(cpc, cpc)), const char*>::value), "");
4843
static_assert((std::is_same<decltype(std::strstr(cp, cpc)), char*>::value), "");
4944
#ifndef _LIBCPP_HAS_NO_THREAD_UNSAFE_C_FUNCTIONS
5045
static_assert((std::is_same<decltype(std::strtok(cp, cpc)), char*>::value), "");
5146
#endif
5247
static_assert((std::is_same<decltype(std::memset(vp, 0, s)), void*>::value), "");
5348
static_assert((std::is_same<decltype(std::strerror(0)), char*>::value), "");
5449
static_assert((std::is_same<decltype(std::strlen(cpc)), std::size_t>::value), "");
50+
51+
// These tests fail on systems whose C library doesn't provide a correct overload
52+
// set for strchr, strpbrk, strrchr, strstr, and memchr, unless the compiler is
53+
// a suitably recent version of Clang.
54+
#if !defined(__APPLE__) || defined(_LIBCPP_PREFERRED_OVERLOAD)
55+
static_assert((std::is_same<decltype(std::memchr(vpc, 0, s)), const void*>::value), "");
56+
static_assert((std::is_same<decltype(std::strchr(cpc, 0)), const char*>::value), "");
57+
static_assert((std::is_same<decltype(std::strpbrk(cpc, cpc)), const char*>::value), "");
58+
static_assert((std::is_same<decltype(std::strrchr(cpc, 0)), const char*>::value), "");
59+
static_assert((std::is_same<decltype(std::strstr(cpc, cpc)), const char*>::value), "");
60+
#endif
5561
}

0 commit comments

Comments
 (0)