[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