@@ -30,6 +30,7 @@ extern "C" {
3030 extern wchar_t *wcschr (const wchar_t *s, wchar_t c);
3131 extern int wcscmp (const wchar_t *s1, const wchar_t *s2);
3232 extern int wcsncmp (const wchar_t *s1, const wchar_t *s2, size_t n);
33+ extern wchar_t *wmemcpy (wchar_t *d, const wchar_t *s, size_t n);
3334}
3435
3536namespace strcmp {
@@ -1592,6 +1593,67 @@ namespace WMemChr {
15921593 // both-note {{non-constexpr function 'wcschr' cannot be used in a constant expression}}
15931594}
15941595
1596+ namespace WMemCpy {
1597+ template <typename T>
1598+ constexpr T result (T (&arr)[4]) {
1599+ return arr[0 ] * 1000 + arr[1 ] * 100 + arr[2 ] * 10 + arr[3 ];
1600+ }
1601+ constexpr int test_wmemcpy (int a, int b, int n) {
1602+ wchar_t arr[4 ] = {1 , 2 , 3 , 4 };
1603+ __builtin_wmemcpy (arr + a, arr + b, n);
1604+ // both-note@-1 2{{overlapping memory regions}}
1605+ // both-note@-2 {{source is not a contiguous array of at least 2 elements of type 'wchar_t'}}
1606+ // both-note@-3 {{destination is not a contiguous array of at least 3 elements of type 'wchar_t'}}
1607+ return result (arr);
1608+ }
1609+ static_assert (test_wmemcpy(1 , 2 , 1 ) == 1334 );
1610+ static_assert (test_wmemcpy(2 , 1 , 1 ) == 1224 );
1611+ static_assert (test_wmemcpy(0 , 1 , 2 ) == 2334 ); // both-error {{constant}} both-note {{in call}}
1612+ static_assert (test_wmemcpy(1 , 0 , 2 ) == 1124 ); // both-error {{constant}} both-note {{in call}}
1613+ static_assert (test_wmemcpy(1 , 2 , 1 ) == 1334 );
1614+ static_assert (test_wmemcpy(0 , 3 , 1 ) == 4234 );
1615+ static_assert (test_wmemcpy(0 , 3 , 2 ) == 4234 ); // both-error {{constant}} both-note {{in call}}
1616+ static_assert (test_wmemcpy(2 , 0 , 3 ) == 4234 ); // both-error {{constant}} both-note {{in call}}
1617+
1618+ wchar_t global;
1619+ constexpr wchar_t *null = 0 ;
1620+ static_assert (__builtin_wmemcpy(&global, null, sizeof (wchar_t ))); // both-error {{}} \
1621+ // both-note {{source of 'wmemcpy' is nullptr}}
1622+ static_assert (__builtin_wmemcpy(null, &global, sizeof (wchar_t ))); // both-error {{}} \
1623+ // both-note {{destination of 'wmemcpy' is nullptr}}
1624+ }
1625+
1626+ namespace WMemMove {
1627+ template <typename T>
1628+ constexpr T result (T (&arr)[4]) {
1629+ return arr[0 ] * 1000 + arr[1 ] * 100 + arr[2 ] * 10 + arr[3 ];
1630+ }
1631+
1632+ constexpr int test_wmemmove (int a, int b, int n) {
1633+ wchar_t arr[4 ] = {1 , 2 , 3 , 4 };
1634+ __builtin_wmemmove (arr + a, arr + b, n);
1635+ // both-note@-1 {{source is not a contiguous array of at least 2 elements of type 'wchar_t'}}
1636+ // both-note@-2 {{destination is not a contiguous array of at least 3 elements of type 'wchar_t'}}
1637+ return result (arr);
1638+ }
1639+
1640+ static_assert (test_wmemmove(1 , 2 , 1 ) == 1334 );
1641+ static_assert (test_wmemmove(2 , 1 , 1 ) == 1224 );
1642+ static_assert (test_wmemmove(0 , 1 , 2 ) == 2334 );
1643+ static_assert (test_wmemmove(1 , 0 , 2 ) == 1124 );
1644+ static_assert (test_wmemmove(1 , 2 , 1 ) == 1334 );
1645+ static_assert (test_wmemmove(0 , 3 , 1 ) == 4234 );
1646+ static_assert (test_wmemmove(0 , 3 , 2 ) == 4234 ); // both-error {{constant}} both-note {{in call}}
1647+ static_assert (test_wmemmove(2 , 0 , 3 ) == 4234 ); // both-error {{constant}} both-note {{in call}}
1648+
1649+ wchar_t global;
1650+ constexpr wchar_t *null = 0 ;
1651+ static_assert (__builtin_wmemmove(&global, null, sizeof (wchar_t ))); // both-error {{}} \
1652+ // both-note {{source of 'wmemmove' is nullptr}}
1653+ static_assert (__builtin_wmemmove(null, &global, sizeof (wchar_t ))); // both-error {{}} \
1654+ // both-note {{destination of 'wmemmove' is nullptr}}
1655+ }
1656+
15951657namespace Invalid {
15961658 constexpr int test () { // both-error {{never produces a constant expression}}
15971659 __builtin_abort (); // both-note 2{{subexpression not valid in a constant expression}}
0 commit comments