[clang] 7f24db0 - Add documentation and testing for

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


Author: Richard Smith
Date: 2020-04-05T15:24:49-07:00
New Revision: 7f24db01751da6953782630bb42dcca8a111590b

URL: https://github.com/llvm/llvm-project/commit/7f24db01751da6953782630bb42dcca8a111590b
DIFF: https://github.com/llvm/llvm-project/commit/7f24db01751da6953782630bb42dcca8a111590b.diff

LOG: Add documentation and testing for
2c88a485c71155c19e512f22c54e63ee337282a3.

Also extend it to cover memchr for consistency.

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 6dcfd1a49f06..f83d7cff9c87 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -2368,8 +2368,8 @@ constant expressions in C++11 onwards (where a cast from ``void*`` to ``char*``
 is disallowed in general).
 
 Constant evaluation support for the ``__builtin_mem*`` functions is provided
-only for arrays of ``char``, ``signed char``, or ``unsigned char``, despite
-these functions accepting an argument of type ``const void*``.
+only for arrays of ``char``, ``signed char``, ``unsigned char``, or ``char8_t``,
+despite these functions accepting an argument of type ``const void*``.
 
 Support for constant expression evaluation for the above builtins can be detected
 with ``__has_feature(cxx_constexpr_string_builtins)``.

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 7508bcbc365d..a10a4dab6dff 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8469,7 +8469,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()) {
+    if (IsRawByte && !CharTy->isCharType() && !CharTy->isChar8Type()) {
       Info.FFDiag(E, diag::note_constexpr_memchr_unsupported)
           << (std::string("'") + Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")
           << CharTy;

diff  --git a/clang/test/SemaCXX/constexpr-string.cpp b/clang/test/SemaCXX/constexpr-string.cpp
index 79ac3bf2cc4d..b9f90adf7b76 100644
--- a/clang/test/SemaCXX/constexpr-string.cpp
+++ b/clang/test/SemaCXX/constexpr-string.cpp
@@ -107,6 +107,17 @@ namespace StrcmpEtc {
   static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 6) == -1);
   static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 5) == 0);
 
+  static_assert(__builtin_memcmp(u8"abaa", u8"abba", 3) == -1);
+  static_assert(__builtin_memcmp(u8"abaa", u8"abba", 2) == 0);
+  static_assert(__builtin_memcmp(u8"a\203", u8"a", 2) == 1);
+  static_assert(__builtin_memcmp(u8"a\203", u8"a\003", 2) == 1);
+  static_assert(__builtin_memcmp(0, 0, 0) == 0);
+  static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0banana", 100) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+  static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0canada", 100) == -1); // FIXME: Should we reject this?
+  static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0canada", 7) == -1);
+  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_bcmp("abaa", "abba", 3) != 0);
   static_assert(__builtin_bcmp("abaa", "abba", 2) == 0);
   static_assert(__builtin_bcmp("a\203", "a", 2) != 0);
@@ -373,6 +384,20 @@ namespace StrchrEtc {
   static_assert(__builtin_memchr(nullptr, 'x', 3) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
   static_assert(__builtin_memchr(nullptr, 'x', 0) == nullptr); // FIXME: Should we reject this?
 
+  constexpr const char8_t *kU8Str = u8"abca\xff\0d";
+  constexpr char8_t kU8Foo[] = {u8'f', u8'o', u8'o'};
+  static_assert(__builtin_memchr(kU8Str, u8'a', 0) == nullptr);
+  static_assert(__builtin_memchr(kU8Str, u8'a', 1) == kU8Str);
+  static_assert(__builtin_memchr(kU8Str, u8'\0', 5) == nullptr);
+  static_assert(__builtin_memchr(kU8Str, u8'\0', 6) == kU8Str + 5);
+  static_assert(__builtin_memchr(kU8Str, u8'\xff', 8) == kU8Str + 4);
+  static_assert(__builtin_memchr(kU8Str, u8'\xff' + 256, 8) == kU8Str + 4);
+  static_assert(__builtin_memchr(kU8Str, u8'\xff' - 256, 8) == kU8Str + 4);
+  static_assert(__builtin_memchr(kU8Foo, u8'x', 3) == nullptr);
+  static_assert(__builtin_memchr(kU8Foo, u8'x', 4) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
+  static_assert(__builtin_memchr(nullptr, u8'x', 3) == nullptr); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
+  static_assert(__builtin_memchr(nullptr, u8'x', 0) == nullptr); // FIXME: Should we reject this?
+
   extern struct Incomplete incomplete;
   static_assert(__builtin_memchr(&incomplete, 0, 0u) == nullptr);
   static_assert(__builtin_memchr(&incomplete, 0, 1u) == nullptr); // expected-error {{not an integral constant}} expected-note {{read of incomplete type 'struct Incomplete'}}


        


More information about the cfe-commits mailing list