[clang] 944db8a - Permit constant evaluation of mixed __builtin_memcmp between char and

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Sun Apr 5 15:37:42 PDT 2020


Author: Richard Smith
Date: 2020-04-05T15:35:32-07:00
New Revision: 944db8a433f591e514219c12fa33b7e8fdd5e883

URL: https://github.com/llvm/llvm-project/commit/944db8a433f591e514219c12fa33b7e8fdd5e883
DIFF: https://github.com/llvm/llvm-project/commit/944db8a433f591e514219c12fa33b7e8fdd5e883.diff

LOG: Permit constant evaluation of mixed __builtin_memcmp between char and
char8_t.

Added: 
    

Modified: 
    clang/lib/AST/ExprConstant.cpp
    clang/test/SemaCXX/constexpr-string.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index a10a4dab6dff..35232bebbb3a 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 b9f90adf7b76..f33627e812b2 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);


        


More information about the cfe-commits mailing list