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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits