r330656 - [AST] strcmp/memcmp always compares unsigned chars.
Benjamin Kramer via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 23 15:04:34 PDT 2018
Author: d0k
Date: Mon Apr 23 15:04:34 2018
New Revision: 330656
URL: http://llvm.org/viewvc/llvm-project?rev=330656&view=rev
Log:
[AST] strcmp/memcmp always compares unsigned chars.
This makes it return the right result in a couple of edge cases. The
wide versions always do the comparison on the underlying wchar_t type.
Modified:
cfe/trunk/lib/AST/ExprConstant.cpp
cfe/trunk/test/SemaCXX/constexpr-string.cpp
Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=330656&r1=330655&r2=330656&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Mon Apr 23 15:04:34 2018
@@ -8046,14 +8046,24 @@ bool IntExprEvaluator::VisitBuiltinCallE
BuiltinOp != Builtin::BIwmemcmp &&
BuiltinOp != Builtin::BI__builtin_memcmp &&
BuiltinOp != Builtin::BI__builtin_wmemcmp);
+ bool IsWide = BuiltinOp == Builtin::BIwcscmp ||
+ BuiltinOp == Builtin::BIwcsncmp ||
+ BuiltinOp == Builtin::BIwmemcmp ||
+ BuiltinOp == Builtin::BI__builtin_wcscmp ||
+ BuiltinOp == Builtin::BI__builtin_wcsncmp ||
+ BuiltinOp == Builtin::BI__builtin_wmemcmp;
for (; MaxLength; --MaxLength) {
APValue Char1, Char2;
if (!handleLValueToRValueConversion(Info, E, CharTy, String1, Char1) ||
!handleLValueToRValueConversion(Info, E, CharTy, String2, Char2) ||
!Char1.isInt() || !Char2.isInt())
return false;
- if (Char1.getInt() != Char2.getInt())
- return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E);
+ if (Char1.getInt() != Char2.getInt()) {
+ if (IsWide) // wmemcmp compares with wchar_t signedness.
+ return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E);
+ // memcmp always compares unsigned chars.
+ return Success(Char1.getInt().ult(Char2.getInt()) ? -1 : 1, E);
+ }
if (StopAtNull && !Char1.getInt())
return Success(0, E);
assert(!(StopAtNull && !Char2.getInt()));
Modified: cfe/trunk/test/SemaCXX/constexpr-string.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constexpr-string.cpp?rev=330656&r1=330655&r2=330656&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constexpr-string.cpp (original)
+++ cfe/trunk/test/SemaCXX/constexpr-string.cpp Mon Apr 23 15:04:34 2018
@@ -53,6 +53,8 @@ namespace StrcmpEtc {
static_assert(__builtin_strcmp("abab", "abaa") == 1);
static_assert(__builtin_strcmp("ababa", "abab") == 1);
static_assert(__builtin_strcmp("abab", "ababa") == -1);
+ static_assert(__builtin_strcmp("a\203", "a") == 1);
+ static_assert(__builtin_strcmp("a\203", "a\003") == 1);
static_assert(__builtin_strcmp("abab\0banana", "abab") == 0);
static_assert(__builtin_strcmp("abab", "abab\0banana") == 0);
static_assert(__builtin_strcmp("abab\0banana", "abab\0canada") == 0);
@@ -78,6 +80,8 @@ namespace StrcmpEtc {
static_assert(__builtin_memcmp("abaa", "abba", 3) == -1);
static_assert(__builtin_memcmp("abaa", "abba", 2) == 0);
+ static_assert(__builtin_memcmp("a\203", "a", 2) == 1);
+ static_assert(__builtin_memcmp("a\203", "a\003", 2) == 1);
static_assert(__builtin_memcmp(0, 0, 0) == 0);
static_assert(__builtin_memcmp("abab\0banana", "abab\0banana", 100) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 100) == -1); // FIXME: Should we reject this?
@@ -102,6 +106,9 @@ namespace WcscmpEtc {
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") == -1);
+#endif
static_assert(__builtin_wcscmp(0, L"abab") == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
static_assert(__builtin_wcscmp(L"abab", 0) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced null}}
@@ -116,6 +123,9 @@ namespace WcscmpEtc {
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) == -1);
+#endif
static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 6) == -1);
static_assert(__builtin_wcsncmp(kFoobar, kFoobazfoobar, 7) == -1); // FIXME: Should we reject this?
@@ -125,6 +135,9 @@ namespace WcscmpEtc {
static_assert(__builtin_wmemcmp(L"abaa", L"abba", 3) == -1);
static_assert(__builtin_wmemcmp(L"abaa", L"abba", 2) == 0);
static_assert(__builtin_wmemcmp(0, 0, 0) == 0);
+#if __WCHAR_WIDTH__ == 32
+ static_assert(__builtin_wmemcmp(L"a\x83838383", L"aa", 2) == -1);
+#endif
static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0banana", 100) == 0); // expected-error {{not an integral constant}} expected-note {{dereferenced one-past-the-end}}
static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 100) == -1); // FIXME: Should we reject this?
static_assert(__builtin_wmemcmp(L"abab\0banana", L"abab\0canada", 7) == -1);
More information about the cfe-commits
mailing list