Index: libc/src/string/aarch64/memcmp.cpp =================================================================== --- libc/src/string/aarch64/memcmp.cpp +++ libc/src/string/aarch64/memcmp.cpp @@ -14,20 +14,21 @@ namespace __llvm_libc { namespace aarch64 { -static int memcmp_impl(const char *lhs, const char *rhs, size_t count) { +static int memcmp_impl(const char *lhs, const char *rhs, + size_t count) noexcept { if (count == 0) return 0; if (count == 1) return ThreeWayCompare<_1>(lhs, rhs); - else if (count == 2) + if (count == 2) return ThreeWayCompare<_2>(lhs, rhs); - else if (count == 3) + if (count == 3) return ThreeWayCompare<_3>(lhs, rhs); - else if (count < 8) + if (count < 8) return ThreeWayCompare>(lhs, rhs, count); - else if (count < 16) + if (count < 16) return ThreeWayCompare>(lhs, rhs, count); - else if (count < 128) { + if (count < 128) { if (Equals<_16>(lhs, rhs)) { if (count < 32) return ThreeWayCompare>(lhs, rhs, count); @@ -49,11 +50,11 @@ } // namespace aarch64 LLVM_LIBC_FUNCTION(int, memcmp, - (const void *lhs, const void *rhs, size_t count)) { + (const void *lhs, const void *rhs, size_t count)) +noexcept { - const char *_lhs = reinterpret_cast(lhs); - const char *_rhs = reinterpret_cast(rhs); - return aarch64::memcmp_impl(_lhs, _rhs, count); + return aarch64::memcmp_impl(reinterpret_cast(lhs), + reinterpret_cast(rhs), count); } } // namespace __llvm_libc Index: libc/src/string/aarch64/memcpy.cpp =================================================================== --- libc/src/string/aarch64/memcpy.cpp +++ libc/src/string/aarch64/memcpy.cpp @@ -42,7 +42,7 @@ // with little change on the code side. // This implementation has been tuned for Neoverse-N1. static void memcpy_aarch64(char *__restrict dst, const char *__restrict src, - size_t count) { + size_t count) noexcept { if (count == 0) return; if (count == 1) @@ -68,7 +68,8 @@ LLVM_LIBC_FUNCTION(void *, memcpy, (void *__restrict dst, const void *__restrict src, - size_t size)) { + size_t size)) +noexcept { memcpy_aarch64(reinterpret_cast(dst), reinterpret_cast(src), size); return dst; Index: libc/src/string/memchr.cpp =================================================================== --- libc/src/string/memchr.cpp +++ libc/src/string/memchr.cpp @@ -15,9 +15,10 @@ namespace __llvm_libc { // TODO: Look at performance benefits of comparing words. -LLVM_LIBC_FUNCTION(void *, memchr, (const void *src, int c, size_t n)) { +LLVM_LIBC_FUNCTION(void *, memchr, (const void *src, int c, size_t n)) noexcept{ return internal::find_first_character( - reinterpret_cast(src), c, n); + reinterpret_cast(src), + static_cast(c), n); } } // namespace __llvm_libc Index: libc/src/string/memcmp.cpp =================================================================== --- libc/src/string/memcmp.cpp +++ libc/src/string/memcmp.cpp @@ -14,7 +14,7 @@ // TODO: It is a simple implementation, an optimized version is preparing. LLVM_LIBC_FUNCTION(int, memcmp, - (const void *lhs, const void *rhs, size_t count)) { + (const void *lhs, const void *rhs, size_t count)) noexcept { const unsigned char *_lhs = reinterpret_cast(lhs); const unsigned char *_rhs = reinterpret_cast(rhs); for (size_t i = 0; i < count; ++i) Index: libc/src/string/memcpy.cpp =================================================================== --- libc/src/string/memcpy.cpp +++ libc/src/string/memcpy.cpp @@ -31,7 +31,7 @@ // - As compilers and processors get better, the generated code is improved // with little change on the code side. static void memcpy_impl(char *__restrict dst, const char *__restrict src, - size_t count) { + size_t count) noexcept { // Use scalar strategies (_1, _2, _3 ...) using namespace __llvm_libc::scalar; @@ -60,7 +60,7 @@ LLVM_LIBC_FUNCTION(void *, memcpy, (void *__restrict dst, const void *__restrict src, - size_t size)) { + size_t size)) noexcept { memcpy_impl(reinterpret_cast(dst), reinterpret_cast(src), size); return dst; Index: libc/src/string/memmove.cpp =================================================================== --- libc/src/string/memmove.cpp +++ libc/src/string/memmove.cpp @@ -15,22 +15,25 @@ namespace __llvm_libc { -static inline void move_byte_forward(char *dest_m, const char *src_m, - size_t count) { - for (size_t offset = 0; count; --count, ++offset) +static inline void move_byte_forward(unsigned char *dest_m, + const unsigned char *src_m, size_t count) noexcept { + for (size_t offset = 0; offset != count; ++offset) dest_m[offset] = src_m[offset]; } -static inline void move_byte_backward(char *dest_m, const char *src_m, - size_t count) { - for (size_t offset = count - 1; count; --count, --offset) - dest_m[offset] = src_m[offset]; +static inline void move_byte_backward(unsigned char *dest_m, + const unsigned char *src_m, + size_t count) noexcept { + if (count != 0) { // Avoid underflow + for (size_t offset = count - 1; offset != 0; --offset) + dest_m[offset] = src_m[offset]; + } } LLVM_LIBC_FUNCTION(void *, memmove, - (void *dest, const void *src, size_t count)) { - char *dest_c = reinterpret_cast(dest); - const char *src_c = reinterpret_cast(src); + (void *dest, const void *src, size_t count)) noexcept { + unsigned char *dest_c = reinterpret_cast(dest); + const unsigned char *src_c = reinterpret_cast(src); // If the distance between src_c and dest_c is equal to or greater // than count (integerAbs(src_c - dest_c) >= count), they would not overlap. @@ -58,7 +61,7 @@ // TODO: Optimize `move_byte_xxx(...)` functions. if (dest_c < src_c) move_byte_forward(dest_c, src_c, count); - if (dest_c > src_c) + else if (dest_c > src_c) move_byte_backward(dest_c, src_c, count); return dest; } Index: libc/src/string/memory_utils/elements.h =================================================================== --- libc/src/string/memory_utils/elements.h +++ libc/src/string/memory_utils/elements.h @@ -26,44 +26,46 @@ // Fixed-size copies from 'src' to 'dst'. template -void Copy(char *__restrict dst, const char *__restrict src) { +void Copy(char *__restrict dst, const char *__restrict src) noexcept { Element::Copy(dst, src); } // Runtime-size copies from 'src' to 'dst'. template -void Copy(char *__restrict dst, const char *__restrict src, size_t size) { +void Copy(char *__restrict dst, const char *__restrict src, + size_t size) noexcept { Element::Copy(dst, src, size); } // Fixed-size equality between 'lhs' and 'rhs'. -template bool Equals(const char *lhs, const char *rhs) { +template +bool Equals(const char *lhs, const char *rhs) noexcept { return Element::Equals(lhs, rhs); } // Runtime-size equality between 'lhs' and 'rhs'. template -bool Equals(const char *lhs, const char *rhs, size_t size) { +bool Equals(const char *lhs, const char *rhs, size_t size) noexcept { return Element::Equals(lhs, rhs, size); } // Fixed-size three-way comparison between 'lhs' and 'rhs'. template -int ThreeWayCompare(const char *lhs, const char *rhs) { +int ThreeWayCompare(const char *lhs, const char *rhs) noexcept { return Element::ThreeWayCompare(lhs, rhs); } // Runtime-size three-way comparison between 'lhs' and 'rhs'. template -int ThreeWayCompare(const char *lhs, const char *rhs, size_t size) { +int ThreeWayCompare(const char *lhs, const char *rhs, size_t size) noexcept { return Element::ThreeWayCompare(lhs, rhs, size); } // Fixed-size initialization. template -void SplatSet(char *dst, const unsigned char value) { +void SplatSet(char *dst, const unsigned char value) noexcept { Element::SplatSet(dst, value); } // Runtime-size initialization. template -void SplatSet(char *dst, const unsigned char value, size_t size) { +void SplatSet(char *dst, const unsigned char value, size_t size) noexcept { Element::SplatSet(dst, value, size); } @@ -76,14 +78,14 @@ template struct Repeated { static constexpr size_t kSize = ElementCount * Element::kSize; - static void Copy(char *__restrict dst, const char *__restrict src) { + static void Copy(char *__restrict dst, const char *__restrict src) noexcept { for (size_t i = 0; i < ElementCount; ++i) { const size_t offset = i * Element::kSize; Element::Copy(dst + offset, src + offset); } } - static bool Equals(const char *lhs, const char *rhs) { + static bool Equals(const char *lhs, const char *rhs) noexcept { for (size_t i = 0; i < ElementCount; ++i) { const size_t offset = i * Element::kSize; if (!Element::Equals(lhs + offset, rhs + offset)) @@ -92,18 +94,17 @@ return true; } - static int ThreeWayCompare(const char *lhs, const char *rhs) { + static int ThreeWayCompare(const char *lhs, const char *rhs) noexcept { for (size_t i = 0; i < ElementCount; ++i) { const size_t offset = i * Element::kSize; // We make the assumption that 'Equals' si cheaper than 'ThreeWayCompare'. - if (Element::Equals(lhs + offset, rhs + offset)) - continue; - return Element::ThreeWayCompare(lhs + offset, rhs + offset); + if (!Element::Equals(lhs + offset, rhs + offset)) + return Element::ThreeWayCompare(lhs + offset, rhs + offset); } return 0; } - static void SplatSet(char *dst, const unsigned char value) { + static void SplatSet(char *dst, const unsigned char value) noexcept { for (size_t i = 0; i < ElementCount; ++i) { const size_t offset = i * Element::kSize; Element::SplatSet(dst + offset, value); @@ -119,25 +120,25 @@ template struct Chained { static constexpr size_t kSize = Head::kSize + Chained::kSize; - static void Copy(char *__restrict dst, const char *__restrict src) { + static void Copy(char *__restrict dst, const char *__restrict src) noexcept { Chained::Copy(dst + Head::kSize, src + Head::kSize); __llvm_libc::Copy(dst, src); } - static bool Equals(const char *lhs, const char *rhs) { + static bool Equals(const char *lhs, const char *rhs) noexcept { if (!__llvm_libc::Equals(lhs, rhs)) return false; return Chained::Equals(lhs + Head::kSize, rhs + Head::kSize); } - static int ThreeWayCompare(const char *lhs, const char *rhs) { - if (__llvm_libc::Equals(lhs, rhs)) - return Chained::ThreeWayCompare(lhs + Head::kSize, - rhs + Head::kSize); - return __llvm_libc::ThreeWayCompare(lhs, rhs); + static int ThreeWayCompare(const char *lhs, const char *rhs) noexcept { + if (!__llvm_libc::Equals(lhs, rhs)) + return __llvm_libc::ThreeWayCompare(lhs, rhs); + return Chained::ThreeWayCompare(lhs + Head::kSize, + rhs + Head::kSize); } - static void SplatSet(char *dst, const unsigned char value) { + static void SplatSet(char *dst, const unsigned char value) noexcept { Chained::SplatSet(dst + Head::kSize, value); __llvm_libc::SplatSet(dst, value); } @@ -168,23 +169,25 @@ // Precondition: `size >= T::kSize`. template struct Tail { static void Copy(char *__restrict dst, const char *__restrict src, - size_t size) { + size_t size) noexcept { return T::Copy(dst + offset(size), src + offset(size)); } - static bool Equals(const char *lhs, const char *rhs, size_t size) { + static bool Equals(const char *lhs, const char *rhs, size_t size) noexcept { return T::Equals(lhs + offset(size), rhs + offset(size)); } - static int ThreeWayCompare(const char *lhs, const char *rhs, size_t size) { + static int ThreeWayCompare(const char *lhs, const char *rhs, + size_t size) noexcept { return T::ThreeWayCompare(lhs + offset(size), rhs + offset(size)); } - static void SplatSet(char *dst, const unsigned char value, size_t size) { + static void SplatSet(char *dst, const unsigned char value, + size_t size) noexcept { return T::SplatSet(dst + offset(size), value); } - static size_t offset(size_t size) { return size - T::kSize; } + static size_t offset(size_t size) noexcept { return size - T::kSize; } }; // Perform the operation on the first and last 'T::kSize' bytes of the buffer. @@ -199,24 +202,26 @@ // Precondition: `size >= T::kSize && size <= 2 x T::kSize`. template struct HeadTail { static void Copy(char *__restrict dst, const char *__restrict src, - size_t size) { + size_t size) noexcept { T::Copy(dst, src); Tail::Copy(dst, src, size); } - static bool Equals(const char *lhs, const char *rhs, size_t size) { + static bool Equals(const char *lhs, const char *rhs, size_t size) noexcept { if (!T::Equals(lhs, rhs)) return false; return Tail::Equals(lhs, rhs, size); } - static int ThreeWayCompare(const char *lhs, const char *rhs, size_t size) { + static int ThreeWayCompare(const char *lhs, const char *rhs, + size_t size) noexcept { if (!T::Equals(lhs, rhs)) return T::ThreeWayCompare(lhs, rhs); return Tail::ThreeWayCompare(lhs, rhs, size); } - static void SplatSet(char *dst, const unsigned char value, size_t size) { + static void SplatSet(char *dst, const unsigned char value, + size_t size) noexcept { T::SplatSet(dst, value); Tail::SplatSet(dst, value, size); } @@ -356,7 +361,7 @@ template struct Builtin { static constexpr size_t kSize = Size; - static void Copy(char *__restrict dst, const char *__restrict src) { + static void Copy(char *__restrict dst, const char *__restrict src) noexcept { #if LLVM_LIBC_HAVE_MEMORY_SANITIZER || LLVM_LIBC_HAVE_ADDRESS_SANITIZER ForLoopCopy(dst, src); #elif __has_builtin(__builtin_memcpy_inline) @@ -376,15 +381,15 @@ #define LLVM_LIBC_MEMCMP __builtin_memcmp #endif - static bool Equals(const char *lhs, const char *rhs) { + static bool Equals(const char *lhs, const char *rhs) noexcept { return LLVM_LIBC_MEMCMP(lhs, rhs, kSize) == 0; } - static int ThreeWayCompare(const char *lhs, const char *rhs) { + static int ThreeWayCompare(const char *lhs, const char *rhs) noexcept { return LLVM_LIBC_MEMCMP(lhs, rhs, kSize); } - static void SplatSet(char *dst, const unsigned char value) { + static void SplatSet(char *dst, const unsigned char value) noexcept { __builtin_memset(dst, value, kSize); } @@ -392,7 +397,8 @@ // Copies `kSize` bytes from `src` to `dst` using a for loop. // This code requires the use of `-fno-buitin-memcpy` to prevent the compiler // from turning the for-loop back into `__builtin_memcpy`. - static void ForLoopCopy(char *__restrict dst, const char *__restrict src) { + static void ForLoopCopy(char *__restrict dst, + const char *__restrict src) noexcept { for (size_t i = 0; i < kSize; ++i) dst[i] = src[i]; } @@ -418,58 +424,62 @@ template struct Scalar { static constexpr size_t kSize = sizeof(T); - static void Copy(char *__restrict dst, const char *__restrict src) { + static void Copy(char *__restrict dst, const char *__restrict src) noexcept { Store(dst, Load(src)); } - static bool Equals(const char *lhs, const char *rhs) { + static bool Equals(const char *lhs, const char *rhs) noexcept { return Load(lhs) == Load(rhs); } - static int ThreeWayCompare(const char *lhs, const char *rhs) { + static int ThreeWayCompare(const char *lhs, const char *rhs) noexcept { return ScalarThreeWayCompare(Load(lhs), Load(rhs)); } - static void SplatSet(char *dst, const unsigned char value) { + static void SplatSet(char *dst, const unsigned char value) noexcept { Store(dst, GetSplattedValue(value)); } static int ScalarThreeWayCompare(T a, T b); private: - static T Load(const char *ptr) { + static T Load(const char *ptr) noexcept { T value; builtin::Builtin::Copy(reinterpret_cast(&value), ptr); return value; } - static void Store(char *ptr, T value) { + static void Store(char *ptr, T value) noexcept { builtin::Builtin::Copy(ptr, reinterpret_cast(&value)); } - static T GetSplattedValue(const unsigned char value) { + static T GetSplattedValue(const unsigned char value) noexcept { return T(~0) / T(0xFF) * T(value); } }; template <> -inline int Scalar::ScalarThreeWayCompare(uint8_t a, uint8_t b) { +inline int Scalar::ScalarThreeWayCompare(uint8_t a, + uint8_t b) noexcept { const int16_t la = Endian::ToBigEndian(a); const int16_t lb = Endian::ToBigEndian(b); return la - lb; } template <> -inline int Scalar::ScalarThreeWayCompare(uint16_t a, uint16_t b) { +inline int Scalar::ScalarThreeWayCompare(uint16_t a, + uint16_t b) noexcept { const int32_t la = Endian::ToBigEndian(a); const int32_t lb = Endian::ToBigEndian(b); return la - lb; } template <> -inline int Scalar::ScalarThreeWayCompare(uint32_t a, uint32_t b) { +inline int Scalar::ScalarThreeWayCompare(uint32_t a, + uint32_t b) noexcept { const uint32_t la = Endian::ToBigEndian(a); const uint32_t lb = Endian::ToBigEndian(b); return la > lb ? 1 : la < lb ? -1 : 0; } template <> -inline int Scalar::ScalarThreeWayCompare(uint64_t a, uint64_t b) { +inline int Scalar::ScalarThreeWayCompare(uint64_t a, + uint64_t b) noexcept { const uint64_t la = Endian::ToBigEndian(a); const uint64_t lb = Endian::ToBigEndian(b); return la > lb ? 1 : la < lb ? -1 : 0; Index: libc/src/string/memory_utils/memset_utils.h =================================================================== --- libc/src/string/memory_utils/memset_utils.h +++ libc/src/string/memory_utils/memset_utils.h @@ -48,7 +48,7 @@ // may waste up to 31 Bytes. Benchmarks showed that SetAlignedBlocks<64> was not // superior for sizes that mattered. inline static void GeneralPurposeMemset(char *dst, unsigned char value, - size_t count) { + size_t count) noexcept { #if defined(__i386__) || defined(__x86_64__) using namespace ::__llvm_libc::x86; #else Index: libc/src/string/memory_utils/utils.h =================================================================== --- libc/src/string/memory_utils/utils.h +++ libc/src/string/memory_utils/utils.h @@ -72,11 +72,11 @@ } // Returns the offset from `ptr` to the next cache line. -static inline intptr_t offset_to_next_cache_line(const void *ptr) { +static inline intptr_t offset_to_next_cache_line(const void *ptr) noexcept { return offset_to_next_aligned(ptr); } -template static T *assume_aligned(T *ptr) { +template static T *assume_aligned(T *ptr) noexcept { return reinterpret_cast(__builtin_assume_aligned(ptr, alignment)); } Index: libc/src/string/memrchr.cpp =================================================================== --- libc/src/string/memrchr.cpp +++ libc/src/string/memrchr.cpp @@ -12,13 +12,13 @@ namespace __llvm_libc { -LLVM_LIBC_FUNCTION(void *, memrchr, (const void *src, int c, size_t n)) { +LLVM_LIBC_FUNCTION(void *, memrchr, (const void *src, int c, size_t n)) +noexcept { const unsigned char *str = reinterpret_cast(src); - const unsigned char ch = c; + const unsigned char ch = static_cast(c); for (; n != 0; --n) { - const unsigned char *s = str + n - 1; - if (*s == ch) - return const_cast(s); + if (*(--str) == ch) + return const_cast(str); } return nullptr; } Index: libc/src/string/strcat.cpp =================================================================== --- libc/src/string/strcat.cpp +++ libc/src/string/strcat.cpp @@ -15,7 +15,7 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(char *, strcat, - (char *__restrict dest, const char *__restrict src)) { + (char *__restrict dest, const char *__restrict src)) noexcept { __llvm_libc::strcpy(dest + internal::string_length(dest), src); return dest; } Index: libc/src/string/strchr.cpp =================================================================== --- libc/src/string/strchr.cpp +++ libc/src/string/strchr.cpp @@ -13,13 +13,13 @@ namespace __llvm_libc { // TODO: Look at performance benefits of comparing words. -LLVM_LIBC_FUNCTION(char *, strchr, (const char *src, int c)) { - unsigned char *str = - const_cast(reinterpret_cast(src)); - const unsigned char ch = c; - for (; *str && *str != ch; ++str) - ; - return *str == ch ? reinterpret_cast(str) : nullptr; +LLVM_LIBC_FUNCTION(char *, strchr, (const char *src, int c)) noexcept { + const char ch = static_cast(c); + for (; *src != ch; ++src) + if (*src == '\0') + return nullptr; + + return const_cast(src); } } // namespace __llvm_libc Index: libc/src/string/strcmp.cpp =================================================================== --- libc/src/string/strcmp.cpp +++ libc/src/string/strcmp.cpp @@ -13,7 +13,7 @@ namespace __llvm_libc { // TODO: Look at benefits for comparing words at a time. -LLVM_LIBC_FUNCTION(int, strcmp, (const char *left, const char *right)) { +LLVM_LIBC_FUNCTION(int, strcmp, (const char *left, const char *right)) noexcept { for (; *left && *left == *right; ++left, ++right) ; return *reinterpret_cast(left) - Index: libc/src/string/strcpy.cpp =================================================================== --- libc/src/string/strcpy.cpp +++ libc/src/string/strcpy.cpp @@ -15,7 +15,8 @@ namespace __llvm_libc { LLVM_LIBC_FUNCTION(char *, strcpy, - (char *__restrict dest, const char *__restrict src)) { + (char *__restrict dest, const char *__restrict src)) +noexcept { return reinterpret_cast( __llvm_libc::memcpy(dest, src, internal::string_length(src) + 1)); } Index: libc/src/string/strcspn.cpp =================================================================== --- libc/src/string/strcspn.cpp +++ libc/src/string/strcspn.cpp @@ -13,7 +13,8 @@ namespace __llvm_libc { -LLVM_LIBC_FUNCTION(size_t, strcspn, (const char *src, const char *segment)) { +LLVM_LIBC_FUNCTION(size_t, strcspn, (const char *src, const char *segment)) +noexcept { return internal::complementary_span(src, segment); } Index: libc/src/string/string_utils.h =================================================================== --- libc/src/string/string_utils.h +++ libc/src/string/string_utils.h @@ -17,31 +17,33 @@ // Returns the length of a string, denoted by the first occurrence // of a null terminator. -static inline size_t string_length(const char *src) { - size_t length; - for (length = 0; *src; ++src, ++length) +static inline size_t string_length(const char *src) noexcept { + const char *const initial = src; + for (; *src != '\0'; ++src) ; - return length; + return src - initial; } // Returns the first occurrence of 'ch' within the first 'n' characters of // 'src'. If 'ch' is not found, returns nullptr. static inline void *find_first_character(const unsigned char *src, - unsigned char ch, size_t n) { - for (; n && *src != ch; --n, ++src) - ; - return n ? const_cast(src) : nullptr; + unsigned char ch, size_t n) noexcept { + for (; n != 0; --n, ++src) + if (*src == ch) + return const_cast(src); + return nullptr; } // Returns the maximum length span that contains only characters not found in // 'segment'. If no characters are found, returns the length of 'src'. -static inline size_t complementary_span(const char *src, const char *segment) { - const char *initial = src; +static inline size_t complementary_span(const char *src, + const char *segment) noexcept { + const char *const initial = src; cpp::Bitset<256> bitset; - for (; *segment; ++segment) + for (; *segment != '\0'; ++segment) bitset.set(*segment); - for (; *src && !bitset.test(*src); ++src) + for (; *src != '\0' && !bitset.test(*src); ++src) ; return src - initial; } @@ -57,24 +59,23 @@ // terminating character is reached, returns a nullptr. static inline char *string_token(char *__restrict src, const char *__restrict delimiter_string, - char **__restrict saveptr) { + char **__restrict saveptr) noexcept { cpp::Bitset<256> delimiter_set; - for (; *delimiter_string; ++delimiter_string) + for (; *delimiter_string != '\0'; ++delimiter_string) delimiter_set.set(*delimiter_string); src = src ? src : *saveptr; - for (; *src && delimiter_set.test(*src); ++src) + for (; *src != '\0' && delimiter_set.test(*src); ++src) ; - if (!*src) { + if (*src == '\0') { *saveptr = src; return nullptr; } char *token = src; - for (; *src && !delimiter_set.test(*src); ++src) + for (; *src != '\0' && !delimiter_set.test(*src); ++src) ; - if (*src) { - *src = '\0'; - ++src; + if (*src != '\0') { + *src++ = '\0'; } *saveptr = src; return token; Index: libc/src/string/strlen.cpp =================================================================== --- libc/src/string/strlen.cpp +++ libc/src/string/strlen.cpp @@ -15,7 +15,7 @@ // TODO: investigate the performance of this function. // There might be potential for compiler optimization. -LLVM_LIBC_FUNCTION(size_t, strlen, (const char *src)) { +LLVM_LIBC_FUNCTION(size_t, strlen, (const char *src)) noexcept { return internal::string_length(src); } Index: libc/src/string/strncpy.cpp =================================================================== --- libc/src/string/strncpy.cpp +++ libc/src/string/strncpy.cpp @@ -15,7 +15,8 @@ LLVM_LIBC_FUNCTION(char *, strncpy, (char *__restrict dest, const char *__restrict src, - size_t n)) { + size_t n)) +noexcept { size_t i = 0; // Copy up until \0 is found. for (; i < n && src[i] != '\0'; ++i) Index: libc/src/string/strnlen.cpp =================================================================== --- libc/src/string/strnlen.cpp +++ libc/src/string/strnlen.cpp @@ -14,7 +14,7 @@ namespace __llvm_libc { -LLVM_LIBC_FUNCTION(size_t, strnlen, (const char *src, size_t n)) { +LLVM_LIBC_FUNCTION(size_t, strnlen, (const char *src, size_t n)) noexcept { const void *temp = internal::find_first_character( reinterpret_cast(src), '\0', n); return temp ? reinterpret_cast(temp) - src : n; Index: libc/src/string/strpbrk.cpp =================================================================== --- libc/src/string/strpbrk.cpp +++ libc/src/string/strpbrk.cpp @@ -13,7 +13,8 @@ namespace __llvm_libc { -LLVM_LIBC_FUNCTION(char *, strpbrk, (const char *src, const char *breakset)) { +LLVM_LIBC_FUNCTION(char *, strpbrk, (const char *src, const char *breakset)) +noexcept { src += internal::complementary_span(src, breakset); return *src ? const_cast(src) : nullptr; } Index: libc/src/string/strrchr.cpp =================================================================== --- libc/src/string/strrchr.cpp +++ libc/src/string/strrchr.cpp @@ -12,13 +12,13 @@ namespace __llvm_libc { -LLVM_LIBC_FUNCTION(char *, strrchr, (const char *src, int c)) { - const char ch = c; +LLVM_LIBC_FUNCTION(char *, strrchr, (const char *src, int c)) noexcept { + const char ch = static_cast(c); char *last_occurrence = nullptr; do { if (*src == ch) last_occurrence = const_cast(src); - } while (*src++); + } while (*src++ != '\0'); return last_occurrence; } Index: libc/src/string/strspn.cpp =================================================================== --- libc/src/string/strspn.cpp +++ libc/src/string/strspn.cpp @@ -14,7 +14,8 @@ namespace __llvm_libc { -LLVM_LIBC_FUNCTION(size_t, strspn, (const char *src, const char *segment)) { +LLVM_LIBC_FUNCTION(size_t, strspn, (const char *src, const char *segment)) +noexcept { const char *initial = src; cpp::Bitset<256> bitset; Index: libc/src/string/strstr.cpp =================================================================== --- libc/src/string/strstr.cpp +++ libc/src/string/strstr.cpp @@ -15,7 +15,8 @@ // TODO: This is a simple brute force implementation. This can be // improved upon using well known string matching algorithms. -LLVM_LIBC_FUNCTION(char *, strstr, (const char *haystack, const char *needle)) { +LLVM_LIBC_FUNCTION(char *, strstr, (const char *haystack, const char *needle)) +noexcept { for (size_t i = 0; haystack[i]; ++i) { size_t j; for (j = 0; haystack[i + j] && haystack[i + j] == needle[j]; ++j) Index: libc/src/string/strtok.cpp =================================================================== --- libc/src/string/strtok.cpp +++ libc/src/string/strtok.cpp @@ -17,7 +17,8 @@ LLVM_LIBC_FUNCTION(char *, strtok, (char *__restrict src, - const char *__restrict delimiter_string)) { + const char *__restrict delimiter_string)) +noexcept { return internal::string_token(src, delimiter_string, &strtok_str); } Index: libc/src/string/strtok_r.cpp =================================================================== --- libc/src/string/strtok_r.cpp +++ libc/src/string/strtok_r.cpp @@ -16,7 +16,8 @@ LLVM_LIBC_FUNCTION(char *, strtok_r, (char *__restrict src, const char *__restrict delimiter_string, - char **__restrict saveptr)) { + char **__restrict saveptr)) +noexcept { return internal::string_token(src, delimiter_string, saveptr); } Index: libc/src/string/x86_64/memcpy.cpp =================================================================== --- libc/src/string/x86_64/memcpy.cpp +++ libc/src/string/x86_64/memcpy.cpp @@ -63,7 +63,7 @@ // - As compilers and processors get better, the generated code is improved // with little change on the code side. static void memcpy_x86(char *__restrict dst, const char *__restrict src, - size_t count) { + size_t count) noexcept { // Use x86 strategies (_1, _2, _3 ...) using namespace __llvm_libc::x86;