[clang] Reapply "[clang][bytecode] Implement __builtin_{wcscmp,wcsncmp} (#132… (PR #132963)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 25 10:41:49 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
…723)"
This reverts commit 1e2ad6793ac205607e7c809283cf69e1cc36a69a.
Fix the previous commit on big-endian hosts by _not_ falling through to the `uint8_t` code path.
---
Full diff: https://github.com/llvm/llvm-project/pull/132963.diff
2 Files Affected:
- (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+40-13)
- (modified) clang/test/AST/ByteCode/builtin-functions.cpp (+46)
``````````diff
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index d7de4c09e2614..4d125e4c202d2 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -212,11 +212,13 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
const Pointer &A = getParam<Pointer>(Frame, 0);
const Pointer &B = getParam<Pointer>(Frame, 1);
- if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp)
+ if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||
+ ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)
diagnoseNonConstexprBuiltin(S, OpPC, ID);
uint64_t Limit = ~static_cast<uint64_t>(0);
- if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp)
+ if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||
+ ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp)
Limit = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))
.getZExtValue();
@@ -231,12 +233,22 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
if (A.isDummy() || B.isDummy())
return false;
+ bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||
+ ID == Builtin::BI__builtin_wcscmp ||
+ ID == Builtin::BI__builtin_wcsncmp;
assert(A.getFieldDesc()->isPrimitiveArray());
assert(B.getFieldDesc()->isPrimitiveArray());
+ assert(getElemType(A).getTypePtr() == getElemType(B).getTypePtr());
+ PrimType ElemT = *S.getContext().classify(getElemType(A));
+
+ auto returnResult = [&](int V) -> bool {
+ pushInteger(S, V, Call->getType());
+ return true;
+ };
+
unsigned IndexA = A.getIndex();
unsigned IndexB = B.getIndex();
- int32_t Result = 0;
uint64_t Steps = 0;
for (;; ++IndexA, ++IndexB, ++Steps) {
@@ -248,22 +260,33 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
!CheckRange(S, OpPC, PB, AK_Read)) {
return false;
}
+
+ if (IsWide) {
+ INT_TYPE_SWITCH(ElemT, {
+ T CA = PA.deref<T>();
+ T CB = PB.deref<T>();
+ if (CA > CB)
+ return returnResult(1);
+ else if (CA < CB)
+ return returnResult(-1);
+ else if (CA.isZero() || CB.isZero())
+ return returnResult(0);
+ });
+ continue;
+ }
+
uint8_t CA = PA.deref<uint8_t>();
uint8_t CB = PB.deref<uint8_t>();
- if (CA > CB) {
- Result = 1;
- break;
- } else if (CA < CB) {
- Result = -1;
- break;
- }
+ if (CA > CB)
+ return returnResult(1);
+ else if (CA < CB)
+ return returnResult(-1);
if (CA == 0 || CB == 0)
- break;
+ return returnResult(0);
}
- pushInteger(S, Result, Call->getType());
- return true;
+ return returnResult(0);
}
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
@@ -2120,6 +2143,10 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
case Builtin::BIstrcmp:
case Builtin::BI__builtin_strncmp:
case Builtin::BIstrncmp:
+ case Builtin::BI__builtin_wcsncmp:
+ case Builtin::BIwcsncmp:
+ case Builtin::BI__builtin_wcscmp:
+ case Builtin::BIwcscmp:
if (!interp__builtin_strcmp(S, OpPC, Frame, F, Call))
return false;
break;
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp b/clang/test/AST/ByteCode/builtin-functions.cpp
index 828822375e95e..8408286314bb8 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -28,6 +28,8 @@ extern "C" {
extern char *strchr(const char *s, int c);
extern wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n);
extern wchar_t *wcschr(const wchar_t *s, wchar_t c);
+ extern int wcscmp(const wchar_t *s1, const wchar_t *s2);
+ extern int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n);
}
namespace strcmp {
@@ -72,6 +74,50 @@ namespace strcmp {
static_assert(__builtin_strncmp("abab\0banana", "abab\0canada", 100) == 0);
}
+namespace WcsCmp {
+ constexpr wchar_t kFoobar[6] = {L'f',L'o',L'o',L'b',L'a',L'r'};
+ constexpr wchar_t kFoobazfoobar[12] = {L'f',L'o',L'o',L'b',L'a',L'z',L'f',L'o',L'o',L'b',L'a',L'r'};
+
+ static_assert(__builtin_wcscmp(L"abab", L"abab") == 0);
+ static_assert(__builtin_wcscmp(L"abab", L"abba") == -1);
+ static_assert(__builtin_wcscmp(L"abab", L"abaa") == 1);
+ static_assert(__builtin_wcscmp(L"ababa", L"abab") == 1);
+ static_assert(__builtin_wcscmp(L"abab", L"ababa") == -1);
+ static_assert(__builtin_wcscmp(L"abab\0banana", L"abab") == 0);
+ static_assert(__builtin_wcscmp(L"abab", L"abab\0banana") == 0);
+ static_assert(__builtin_wcscmp(L"abab\0banana", L"abab\0canada") == 0);
+#if __WCHAR_WIDTH__ == 32
+ static_assert(__builtin_wcscmp(L"a\x83838383", L"a") == (wchar_t)-1U >> 31);
+#endif
+ static_assert(__builtin_wcscmp(0, L"abab") == 0); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced null}}
+ static_assert(__builtin_wcscmp(L"abab", 0) == 0); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced null}}
+
+ static_assert(__builtin_wcscmp(kFoobar, kFoobazfoobar) == -1);
+ static_assert(__builtin_wcscmp(kFoobar, kFoobazfoobar + 6) == 0); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced one-past-the-end}}
+
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 5) == -1);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 4) == -1);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 3) == -1);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 2) == 0);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 1) == 0);
+ static_assert(__builtin_wcsncmp(L"abaa", L"abba", 0) == 0);
+ static_assert(__builtin_wcsncmp(0, 0, 0) == 0);
+ static_assert(__builtin_wcsncmp(L"abab\0banana", L"abab\0canada", 100) == 0);
+#if __WCHAR_WIDTH__ == 32
+ static_assert(__builtin_wcsncmp(L"a\x83838383", L"aa", 2) ==
+ (wchar_t)-1U >> 31);
+#endif
+
+ static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 6) == -1);
+ static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 7) == -1);
+ static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar + 6, 6) == 0);
+ static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar + 6, 7) == 0); // both-error {{not an integral constant}} \
+ // both-note {{dereferenced one-past-the-end}}
+}
+
/// Copied from constant-expression-cxx11.cpp
namespace strlen {
constexpr const char *a = "foo\0quux";
``````````
</details>
https://github.com/llvm/llvm-project/pull/132963
More information about the cfe-commits
mailing list