diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index a10a4dab6dff7..35232bebbb3a1 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -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) + "'") diff --git a/clang/test/SemaCXX/constexpr-string.cpp b/clang/test/SemaCXX/constexpr-string.cpp index b9f90adf7b76c..f33627e812b22 100644 --- a/clang/test/SemaCXX/constexpr-string.cpp +++ b/clang/test/SemaCXX/constexpr-string.cpp @@ -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);