|
18 | 18 | extern "C" {
|
19 | 19 | typedef decltype(sizeof(int)) size_t;
|
20 | 20 | extern size_t wcslen(const wchar_t *p);
|
| 21 | + extern void *memchr(const void *s, int c, size_t n); |
| 22 | + extern char *strchr(const char *s, int c); |
21 | 23 | }
|
22 | 24 |
|
23 | 25 | namespace strcmp {
|
@@ -1351,3 +1353,119 @@ namespace Memcmp {
|
1351 | 1353 | static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 6) == -1);
|
1352 | 1354 | static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 5) == 0);
|
1353 | 1355 | }
|
| 1356 | + |
| 1357 | +namespace Memchr { |
| 1358 | + constexpr const char *kStr = "abca\xff\0d"; |
| 1359 | + constexpr char kFoo[] = {'f', 'o', 'o'}; |
| 1360 | + |
| 1361 | + static_assert(__builtin_memchr(kStr, 'a', 0) == nullptr); |
| 1362 | + static_assert(__builtin_memchr(kStr, 'a', 1) == kStr); |
| 1363 | + static_assert(__builtin_memchr(kStr, '\0', 5) == nullptr); |
| 1364 | + static_assert(__builtin_memchr(kStr, '\0', 6) == kStr + 5); |
| 1365 | + static_assert(__builtin_memchr(kStr, '\xff', 8) == kStr + 4); |
| 1366 | + static_assert(__builtin_memchr(kStr, '\xff' + 256, 8) == kStr + 4); |
| 1367 | + static_assert(__builtin_memchr(kStr, '\xff' - 256, 8) == kStr + 4); |
| 1368 | + static_assert(__builtin_memchr(kFoo, 'x', 3) == nullptr); |
| 1369 | + static_assert(__builtin_memchr(kFoo, 'x', 4) == nullptr); // both-error {{not an integral constant}} \ |
| 1370 | + // both-note {{dereferenced one-past-the-end}} |
| 1371 | + static_assert(__builtin_memchr(nullptr, 'x', 3) == nullptr); // both-error {{not an integral constant}} \ |
| 1372 | + // both-note {{dereferenced null}} |
| 1373 | + static_assert(__builtin_memchr(nullptr, 'x', 0) == nullptr); |
| 1374 | + |
| 1375 | + |
| 1376 | +#if defined(CHAR8_T) |
| 1377 | + constexpr const char8_t *kU8Str = u8"abca\xff\0d"; |
| 1378 | + constexpr char8_t kU8Foo[] = {u8'f', u8'o', u8'o'}; |
| 1379 | + static_assert(__builtin_memchr(kU8Str, u8'a', 0) == nullptr); |
| 1380 | + static_assert(__builtin_memchr(kU8Str, u8'a', 1) == kU8Str); |
| 1381 | + static_assert(__builtin_memchr(kU8Str, u8'\0', 5) == nullptr); |
| 1382 | + static_assert(__builtin_memchr(kU8Str, u8'\0', 6) == kU8Str + 5); |
| 1383 | + static_assert(__builtin_memchr(kU8Str, u8'\xff', 8) == kU8Str + 4); |
| 1384 | + static_assert(__builtin_memchr(kU8Str, u8'\xff' + 256, 8) == kU8Str + 4); |
| 1385 | + static_assert(__builtin_memchr(kU8Str, u8'\xff' - 256, 8) == kU8Str + 4); |
| 1386 | + static_assert(__builtin_memchr(kU8Foo, u8'x', 3) == nullptr); |
| 1387 | + static_assert(__builtin_memchr(kU8Foo, u8'x', 4) == nullptr); // both-error {{not an integral constant}} \ |
| 1388 | + // both-note {{dereferenced one-past-the-end}} |
| 1389 | + static_assert(__builtin_memchr(nullptr, u8'x', 3) == nullptr); // both-error {{not an integral constant}} \ |
| 1390 | + // both-note {{dereferenced null}} |
| 1391 | + static_assert(__builtin_memchr(nullptr, u8'x', 0) == nullptr); |
| 1392 | +#endif |
| 1393 | + |
| 1394 | + extern struct Incomplete incomplete; |
| 1395 | + static_assert(__builtin_memchr(&incomplete, 0, 0u) == nullptr); |
| 1396 | + static_assert(__builtin_memchr(&incomplete, 0, 1u) == nullptr); // both-error {{not an integral constant}} \ |
| 1397 | + // ref-note {{read of incomplete type 'struct Incomplete'}} |
| 1398 | + |
| 1399 | + const unsigned char &u1 = 0xf0; |
| 1400 | + auto &&i1 = (const signed char []){-128}; |
| 1401 | + static_assert(__builtin_memchr(&u1, -(0x0f + 1), 1) == &u1); |
| 1402 | + static_assert(__builtin_memchr(i1, 0x80, 1) == i1); |
| 1403 | + |
| 1404 | + enum class E : unsigned char {}; |
| 1405 | + struct EPair { E e, f; }; |
| 1406 | + constexpr EPair ee{E{240}}; |
| 1407 | + static_assert(__builtin_memchr(&ee.e, 240, 1) == &ee.e); // both-error {{constant}} \ |
| 1408 | + // both-note {{not supported}} |
| 1409 | + |
| 1410 | + constexpr bool kBool[] = {false, true, false}; |
| 1411 | + constexpr const bool *const kBoolPastTheEndPtr = kBool + 3; |
| 1412 | + static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr - 3, 1, 99) == kBool + 1); // both-error {{constant}} \ |
| 1413 | + // both-note {{not supported}} |
| 1414 | + static_assert(sizeof(bool) != 1u || __builtin_memchr(kBool + 1, 0, 99) == kBoolPastTheEndPtr - 1); // both-error {{constant}} \ |
| 1415 | + // both-note {{not supported}} |
| 1416 | + static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr - 3, -1, 3) == nullptr); // both-error {{constant}} \ |
| 1417 | + // both-note {{not supported}} |
| 1418 | + static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr, 0, 1) == nullptr); // both-error {{constant}} \ |
| 1419 | + // both-note {{not supported}} |
| 1420 | + |
| 1421 | + static_assert(__builtin_char_memchr(kStr, 'a', 0) == nullptr); |
| 1422 | + static_assert(__builtin_char_memchr(kStr, 'a', 1) == kStr); |
| 1423 | + static_assert(__builtin_char_memchr(kStr, '\0', 5) == nullptr); |
| 1424 | + static_assert(__builtin_char_memchr(kStr, '\0', 6) == kStr + 5); |
| 1425 | + static_assert(__builtin_char_memchr(kStr, '\xff', 8) == kStr + 4); |
| 1426 | + static_assert(__builtin_char_memchr(kStr, '\xff' + 256, 8) == kStr + 4); |
| 1427 | + static_assert(__builtin_char_memchr(kStr, '\xff' - 256, 8) == kStr + 4); |
| 1428 | + static_assert(__builtin_char_memchr(kFoo, 'x', 3) == nullptr); |
| 1429 | + static_assert(__builtin_char_memchr(kFoo, 'x', 4) == nullptr); // both-error {{not an integral constant}} \ |
| 1430 | + // both-note {{dereferenced one-past-the-end}} |
| 1431 | + static_assert(__builtin_char_memchr(nullptr, 'x', 3) == nullptr); // both-error {{not an integral constant}} \ |
| 1432 | + // both-note {{dereferenced null}} |
| 1433 | + static_assert(__builtin_char_memchr(nullptr, 'x', 0) == nullptr); |
| 1434 | + |
| 1435 | + static_assert(*__builtin_char_memchr(kStr, '\xff', 8) == '\xff'); |
| 1436 | + constexpr bool char_memchr_mutable() { |
| 1437 | + char buffer[] = "mutable"; |
| 1438 | + *__builtin_char_memchr(buffer, 't', 8) = 'r'; |
| 1439 | + *__builtin_char_memchr(buffer, 'm', 8) = 'd'; |
| 1440 | + return __builtin_strcmp(buffer, "durable") == 0; |
| 1441 | + } |
| 1442 | + static_assert(char_memchr_mutable()); |
| 1443 | + |
| 1444 | + constexpr bool b = !memchr("hello", 'h', 3); // both-error {{constant expression}} \ |
| 1445 | + // both-note {{non-constexpr function 'memchr' cannot be used in a constant expression}} |
| 1446 | + |
| 1447 | +} |
| 1448 | + |
| 1449 | +namespace Strchr { |
| 1450 | + constexpr const char *kStr = "abca\xff\0d"; |
| 1451 | + constexpr char kFoo[] = {'f', 'o', 'o'}; |
| 1452 | + static_assert(__builtin_strchr(kStr, 'a') == kStr); |
| 1453 | + static_assert(__builtin_strchr(kStr, 'b') == kStr + 1); |
| 1454 | + static_assert(__builtin_strchr(kStr, 'c') == kStr + 2); |
| 1455 | + static_assert(__builtin_strchr(kStr, 'd') == nullptr); |
| 1456 | + static_assert(__builtin_strchr(kStr, 'e') == nullptr); |
| 1457 | + static_assert(__builtin_strchr(kStr, '\0') == kStr + 5); |
| 1458 | + static_assert(__builtin_strchr(kStr, 'a' + 256) == nullptr); |
| 1459 | + static_assert(__builtin_strchr(kStr, 'a' - 256) == nullptr); |
| 1460 | + static_assert(__builtin_strchr(kStr, '\xff') == kStr + 4); |
| 1461 | + static_assert(__builtin_strchr(kStr, '\xff' + 256) == nullptr); |
| 1462 | + static_assert(__builtin_strchr(kStr, '\xff' - 256) == nullptr); |
| 1463 | + static_assert(__builtin_strchr(kFoo, 'o') == kFoo + 1); |
| 1464 | + static_assert(__builtin_strchr(kFoo, 'x') == nullptr); // both-error {{not an integral constant}} \ |
| 1465 | + // both-note {{dereferenced one-past-the-end}} |
| 1466 | + static_assert(__builtin_strchr(nullptr, 'x') == nullptr); // both-error {{not an integral constant}} \ |
| 1467 | + // both-note {{dereferenced null}} |
| 1468 | + |
| 1469 | + constexpr bool a = !strchr("hello", 'h'); // both-error {{constant expression}} \ |
| 1470 | + // both-note {{non-constexpr function 'strchr' cannot be used in a constant expression}} |
| 1471 | +} |
0 commit comments