[flang][runtime] ensure character compares to blank are unsigned
authorJean Perier <jperier@nvidia.com>
Tue, 13 Sep 2022 08:39:33 +0000 (10:39 +0200)
committerJean Perier <jperier@nvidia.com>
Tue, 13 Sep 2022 08:42:53 +0000 (10:42 +0200)
CompareToBlankPadding was doing signed compare on architecture where
`char` is signed. This caused `'abc'//char(128) > 'abc'` to evaluate
to false at runtime instead of true.

Differential Revision: https://reviews.llvm.org/D133693

flang/runtime/character.cpp
flang/unittests/Runtime/CharacterTest.cpp

index 16f3933..dd522f1 100644 (file)
@@ -20,11 +20,14 @@ namespace Fortran::runtime {
 
 template <typename CHAR>
 inline int CompareToBlankPadding(const CHAR *x, std::size_t chars) {
+  using UNSIGNED_CHAR = std::make_unsigned_t<CHAR>;
+  const auto blank{static_cast<UNSIGNED_CHAR>(' ')};
   for (; chars-- > 0; ++x) {
-    if (*x < ' ') {
+    const UNSIGNED_CHAR ux{*reinterpret_cast<const UNSIGNED_CHAR *>(x)};
+    if (ux < blank) {
       return -1;
     }
-    if (*x > ' ') {
+    if (ux > blank) {
       return 1;
     }
   }
index 6e14ebd..e54fd8a 100644 (file)
@@ -171,6 +171,8 @@ static ComparisonTestCasesTy comparisonTestCases{
         std::make_tuple("abc", "def", 3, 3, -1),
         std::make_tuple("ab ", "abc", 3, 2, 0),
         std::make_tuple("abc", "abc", 2, 3, -1),
+        std::make_tuple("ab\xff", "ab ", 3, 2, 1),
+        std::make_tuple("ab ", "ab\xff", 2, 3, -1),
     },
     {
         std::make_tuple(u"abc", u"abc", 3, 3, 0),