Permit constant evaluation of mixed __builtin_memcmp between char and

char8_t.
This commit is contained in:
Richard Smith 2020-04-05 15:35:32 -07:00
parent 7f24db0175
commit 944db8a433
2 changed files with 12 additions and 4 deletions

View File

@ -8319,6 +8319,12 @@ bool PointerExprEvaluator::VisitCallExpr(const CallExpr *E) {
return visitNonBuiltinCallExpr(E);
}
// Determine if T is a character type for which we guarantee that
// sizeof(T) == 1.
static bool isOneByteCharacterType(QualType T) {
return T->isCharType() || T->isChar8Type();
}
bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
unsigned BuiltinOp) {
switch (BuiltinOp) {
@ -8469,7 +8475,7 @@ bool PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
}
// Give up on byte-oriented matching against multibyte elements.
// FIXME: We can compare the bytes in the correct order.
if (IsRawByte && !CharTy->isCharType() && !CharTy->isChar8Type()) {
if (IsRawByte && !isOneByteCharacterType(CharTy)) {
Info.FFDiag(E, diag::note_constexpr_memchr_unsupported)
<< (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")
<< CharTy;
@ -11156,9 +11162,8 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
// For memcmp, allow comparing any arrays of '[[un]signed] char' or
// 'char8_t', but no other types.
bool IsChar = CharTy1->isCharType() && CharTy2->isCharType();
bool IsChar8 = CharTy1->isChar8Type() && CharTy2->isChar8Type();
if (IsRawByte && !IsChar && !IsChar8) {
if (IsRawByte &&
!(isOneByteCharacterType(CharTy1) && isOneByteCharacterType(CharTy2))) {
// FIXME: Consider using our bit_cast implementation to support this.
Info.FFDiag(E, diag::note_constexpr_memcmp_unsupported)
<< (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")

View File

@ -118,6 +118,9 @@ namespace StrcmpEtc {
static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0canada", 6) == -1);
static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0canada", 5) == 0);
static_assert(__builtin_memcmp(u8"\u1234", "\xE1\x88\xB4", 4) == 0);
static_assert(__builtin_memcmp(u8"\u1234", "\xE1\x88\xB3", 4) == 1);
static_assert(__builtin_bcmp("abaa", "abba", 3) != 0);
static_assert(__builtin_bcmp("abaa", "abba", 2) == 0);
static_assert(__builtin_bcmp("a\203", "a", 2) != 0);