aboutsummaryrefslogtreecommitdiff
path: root/clang/test/AST/ByteCode/builtin-functions.cpp
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-03-08 16:52:06 +0100
committerGitHub <noreply@github.com>2025-03-08 16:52:06 +0100
commit46d218d1af5d285a646a1e5d3be6a43940fb4a9d (patch)
tree55ee83443bb8f6f3293b97a98bc64f9fe615db6e /clang/test/AST/ByteCode/builtin-functions.cpp
parentb01c71bbd4f7f7565313c38ac7a3b7377eada798 (diff)
downloadllvm-46d218d1af5d285a646a1e5d3be6a43940fb4a9d.zip
llvm-46d218d1af5d285a646a1e5d3be6a43940fb4a9d.tar.gz
llvm-46d218d1af5d285a646a1e5d3be6a43940fb4a9d.tar.bz2
[clang][bytecode] Implement __builtin_{memchr,strchr,char_memchr} (#130420)
llvm has recently started to use `__builitn_memchr` at compile time, so implement this. Still needs some work but the basics are done.
Diffstat (limited to 'clang/test/AST/ByteCode/builtin-functions.cpp')
-rw-r--r--clang/test/AST/ByteCode/builtin-functions.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 75380f9..dbff9164 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -18,6 +18,8 @@
extern "C" {
typedef decltype(sizeof(int)) size_t;
extern size_t wcslen(const wchar_t *p);
+ extern void *memchr(const void *s, int c, size_t n);
+ extern char *strchr(const char *s, int c);
}
namespace strcmp {
@@ -1351,3 +1353,119 @@ namespace Memcmp {
static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 6) == -1);
static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 5) == 0);
}
+
+namespace Memchr {
+ constexpr const char *kStr = "abca\xff\0d";
+ constexpr char kFoo[] = {'f', 'o', 'o'};
+
+ static_assert(__builtin_memchr(kStr, 'a', 0) == nullptr);
+ static_assert(__builtin_memchr(kStr, 'a', 1) == kStr);
+ static_assert(__builtin_memchr(kStr, '\0', 5) == nullptr);
+ static_assert(__builtin_memchr(kStr, '\0', 6) == kStr + 5);
+ static_assert(__builtin_memchr(kStr, '\xff', 8) == kStr + 4);
+ static_assert(__builtin_memchr(kStr, '\xff' + 256, 8) == kStr + 4);
+ static_assert(__builtin_memchr(kStr, '\xff' - 256, 8) == kStr + 4);
+ static_assert(__builtin_memchr(kFoo, 'x', 3) == nullptr);
+ static_assert(__builtin_memchr(kFoo, 'x', 4) == nullptr); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_memchr(nullptr, 'x', 3) == nullptr); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced null}}
+ static_assert(__builtin_memchr(nullptr, 'x', 0) == nullptr);
+
+
+#if defined(CHAR8_T)
+ 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); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_memchr(nullptr, u8'x', 3) == nullptr); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced null}}
+ static_assert(__builtin_memchr(nullptr, u8'x', 0) == nullptr);
+#endif
+
+ extern struct Incomplete incomplete;
+ static_assert(__builtin_memchr(&incomplete, 0, 0u) == nullptr);
+ static_assert(__builtin_memchr(&incomplete, 0, 1u) == nullptr); // both-error {{not an integral constant}} \
+ // ref-note {{read of incomplete type 'struct Incomplete'}}
+
+ const unsigned char &u1 = 0xf0;
+ auto &&i1 = (const signed char []){-128};
+ static_assert(__builtin_memchr(&u1, -(0x0f + 1), 1) == &u1);
+ static_assert(__builtin_memchr(i1, 0x80, 1) == i1);
+
+ enum class E : unsigned char {};
+ struct EPair { E e, f; };
+ constexpr EPair ee{E{240}};
+ static_assert(__builtin_memchr(&ee.e, 240, 1) == &ee.e); // both-error {{constant}} \
+ // both-note {{not supported}}
+
+ constexpr bool kBool[] = {false, true, false};
+ constexpr const bool *const kBoolPastTheEndPtr = kBool + 3;
+ static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr - 3, 1, 99) == kBool + 1); // both-error {{constant}} \
+ // both-note {{not supported}}
+ static_assert(sizeof(bool) != 1u || __builtin_memchr(kBool + 1, 0, 99) == kBoolPastTheEndPtr - 1); // both-error {{constant}} \
+ // both-note {{not supported}}
+ static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr - 3, -1, 3) == nullptr); // both-error {{constant}} \
+ // both-note {{not supported}}
+ static_assert(sizeof(bool) != 1u || __builtin_memchr(kBoolPastTheEndPtr, 0, 1) == nullptr); // both-error {{constant}} \
+ // both-note {{not supported}}
+
+ static_assert(__builtin_char_memchr(kStr, 'a', 0) == nullptr);
+ static_assert(__builtin_char_memchr(kStr, 'a', 1) == kStr);
+ static_assert(__builtin_char_memchr(kStr, '\0', 5) == nullptr);
+ static_assert(__builtin_char_memchr(kStr, '\0', 6) == kStr + 5);
+ static_assert(__builtin_char_memchr(kStr, '\xff', 8) == kStr + 4);
+ static_assert(__builtin_char_memchr(kStr, '\xff' + 256, 8) == kStr + 4);
+ static_assert(__builtin_char_memchr(kStr, '\xff' - 256, 8) == kStr + 4);
+ static_assert(__builtin_char_memchr(kFoo, 'x', 3) == nullptr);
+ static_assert(__builtin_char_memchr(kFoo, 'x', 4) == nullptr); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_char_memchr(nullptr, 'x', 3) == nullptr); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced null}}
+ static_assert(__builtin_char_memchr(nullptr, 'x', 0) == nullptr);
+
+ static_assert(*__builtin_char_memchr(kStr, '\xff', 8) == '\xff');
+ constexpr bool char_memchr_mutable() {
+ char buffer[] = "mutable";
+ *__builtin_char_memchr(buffer, 't', 8) = 'r';
+ *__builtin_char_memchr(buffer, 'm', 8) = 'd';
+ return __builtin_strcmp(buffer, "durable") == 0;
+ }
+ static_assert(char_memchr_mutable());
+
+ constexpr bool b = !memchr("hello", 'h', 3); // both-error {{constant expression}} \
+ // both-note {{non-constexpr function 'memchr' cannot be used in a constant expression}}
+
+}
+
+namespace Strchr {
+ constexpr const char *kStr = "abca\xff\0d";
+ constexpr char kFoo[] = {'f', 'o', 'o'};
+ static_assert(__builtin_strchr(kStr, 'a') == kStr);
+ static_assert(__builtin_strchr(kStr, 'b') == kStr + 1);
+ static_assert(__builtin_strchr(kStr, 'c') == kStr + 2);
+ static_assert(__builtin_strchr(kStr, 'd') == nullptr);
+ static_assert(__builtin_strchr(kStr, 'e') == nullptr);
+ static_assert(__builtin_strchr(kStr, '\0') == kStr + 5);
+ static_assert(__builtin_strchr(kStr, 'a' + 256) == nullptr);
+ static_assert(__builtin_strchr(kStr, 'a' - 256) == nullptr);
+ static_assert(__builtin_strchr(kStr, '\xff') == kStr + 4);
+ static_assert(__builtin_strchr(kStr, '\xff' + 256) == nullptr);
+ static_assert(__builtin_strchr(kStr, '\xff' - 256) == nullptr);
+ static_assert(__builtin_strchr(kFoo, 'o') == kFoo + 1);
+ static_assert(__builtin_strchr(kFoo, 'x') == nullptr); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced one-past-the-end}}
+ static_assert(__builtin_strchr(nullptr, 'x') == nullptr); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced null}}
+
+ constexpr bool a = !strchr("hello", 'h'); // both-error {{constant expression}} \
+ // both-note {{non-constexpr function 'strchr' cannot be used in a constant expression}}
+}