Skip to content

Commit 7492666

Browse files
authored
[clang][bytecode] Implement __builtin_wmemchr (#132254)
1 parent 3520dc5 commit 7492666

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2039,11 +2039,23 @@ static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,
20392039
}
20402040
}
20412041

2042-
uint64_t DesiredVal =
2043-
Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2042+
uint64_t DesiredVal;
2043+
if (ID == Builtin::BIwmemchr || ID == Builtin::BI__builtin_wmemchr ||
2044+
ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr) {
2045+
// wcschr and wmemchr are given a wchar_t to look for. Just use it.
2046+
DesiredVal = Desired.getZExtValue();
2047+
} else {
2048+
DesiredVal = Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2049+
}
2050+
20442051
bool StopAtZero =
20452052
(ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr);
20462053

2054+
PrimType ElemT =
2055+
IsRawByte
2056+
? PT_Sint8
2057+
: *S.getContext().classify(Ptr.getFieldDesc()->getElemQualType());
2058+
20472059
size_t Index = Ptr.getIndex();
20482060
size_t Step = 0;
20492061
for (;;) {
@@ -2053,7 +2065,10 @@ static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,
20532065
if (!CheckLoad(S, OpPC, ElemPtr))
20542066
return false;
20552067

2056-
unsigned char V = static_cast<unsigned char>(ElemPtr.deref<char>());
2068+
uint64_t V;
2069+
INT_TYPE_SWITCH_NO_BOOL(
2070+
ElemT, { V = static_cast<uint64_t>(ElemPtr.deref<T>().toUnsigned()); });
2071+
20572072
if (V == DesiredVal) {
20582073
S.Stk.push<Pointer>(ElemPtr);
20592074
return true;
@@ -2556,11 +2571,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
25562571
case Builtin::BI__builtin_memchr:
25572572
case Builtin::BIstrchr:
25582573
case Builtin::BI__builtin_strchr:
2574+
case Builtin::BIwmemchr:
2575+
case Builtin::BI__builtin_wmemchr:
25592576
#if 0
25602577
case Builtin::BIwcschr:
25612578
case Builtin::BI__builtin_wcschr:
2562-
case Builtin::BImemchr:
2563-
case Builtin::BI__builtin_wmemchr:
25642579
#endif
25652580
case Builtin::BI__builtin_char_memchr:
25662581
if (!interp__builtin_memchr(S, OpPC, Frame, F, Call))

clang/test/AST/ByteCode/builtin-functions.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern "C" {
2020
extern size_t wcslen(const wchar_t *p);
2121
extern void *memchr(const void *s, int c, size_t n);
2222
extern char *strchr(const char *s, int c);
23+
extern wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n);
2324
}
2425

2526
namespace strcmp {
@@ -1489,3 +1490,26 @@ namespace Strchr {
14891490
constexpr bool a = !strchr("hello", 'h'); // both-error {{constant expression}} \
14901491
// both-note {{non-constexpr function 'strchr' cannot be used in a constant expression}}
14911492
}
1493+
1494+
namespace WMemChr {
1495+
constexpr const wchar_t *kStr = L"abca\xffff\0dL";
1496+
constexpr wchar_t kFoo[] = {L'f', L'o', L'o'};
1497+
1498+
static_assert(__builtin_wmemchr(kStr, L'a', 0) == nullptr);
1499+
static_assert(__builtin_wmemchr(kStr, L'a', 1) == kStr);
1500+
static_assert(__builtin_wmemchr(kStr, L'\0', 5) == nullptr);
1501+
static_assert(__builtin_wmemchr(kStr, L'\0', 6) == kStr + 5);
1502+
static_assert(__builtin_wmemchr(kStr, L'\xffff', 8) == kStr + 4);
1503+
static_assert(__builtin_wmemchr(kFoo, L'x', 3) == nullptr);
1504+
static_assert(__builtin_wmemchr(kFoo, L'x', 4) == nullptr); // both-error {{not an integral constant}} \
1505+
// both-note {{dereferenced one-past-the-end}}
1506+
static_assert(__builtin_wmemchr(nullptr, L'x', 3) == nullptr); // both-error {{not an integral constant}} \
1507+
// both-note {{dereferenced null}}
1508+
static_assert(__builtin_wmemchr(nullptr, L'x', 0) == nullptr);
1509+
1510+
constexpr bool b = !wmemchr(L"hello", L'h', 3); // both-error {{constant expression}} \
1511+
// both-note {{non-constexpr function 'wmemchr' cannot be used in a constant expression}}
1512+
1513+
constexpr wchar_t kStr2[] = {L'f', L'o', L'\xffff', L'o'};
1514+
static_assert(__builtin_wmemchr(kStr2, L'\xffff', 4) == kStr2 + 2);
1515+
}

0 commit comments

Comments
 (0)