Fix a bug in compare_numeric().
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 30 Sep 2011 17:03:55 +0000 (17:03 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Fri, 30 Sep 2011 17:03:55 +0000 (17:03 +0000)
Thanks to Alexandru Dura and Jonas Paulsson for finding it.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140859 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Support/StringRef.cpp
unittests/ADT/StringRefTest.cpp

index 8c3fc094cd11b4bc3003b50f24b5c3469f1aba7c..b5b4f9476026ee9a4e48eb2d1dd7212ee2d2e2ee 100644 (file)
@@ -46,12 +46,12 @@ int StringRef::compare_lower(StringRef RHS) const {
 /// compare_numeric - Compare strings, handle embedded numbers.
 int StringRef::compare_numeric(StringRef RHS) const {
   for (size_t I = 0, E = min(Length, RHS.Length); I != E; ++I) {
-    if (Data[I] == RHS.Data[I])
-      continue;
+    // Check for sequences of digits.
     if (ascii_isdigit(Data[I]) && ascii_isdigit(RHS.Data[I])) {
-      // The longer sequence of numbers is larger. This doesn't really handle
-      // prefixed zeros well.
-      for (size_t J = I+1; J != E+1; ++J) {
+      // The longer sequence of numbers is considered larger.
+      // This doesn't really handle prefixed zeros well.
+      size_t J;
+      for (J = I + 1; J != E + 1; ++J) {
         bool ld = J < Length && ascii_isdigit(Data[J]);
         bool rd = J < RHS.Length && ascii_isdigit(RHS.Data[J]);
         if (ld != rd)
@@ -59,8 +59,15 @@ int StringRef::compare_numeric(StringRef RHS) const {
         if (!rd)
           break;
       }
+      // The two number sequences have the same length (J-I), just memcmp them.
+      if (int Res = compareMemory(Data + I, RHS.Data + I, J - I))
+        return Res < 0 ? -1 : 1;
+      // Identical number sequences, continue search after the numbers.
+      I = J - 1;
+      continue;
     }
-    return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1;
+    if (Data[I] != RHS.Data[I])
+      return (unsigned char)Data[I] < (unsigned char)RHS.Data[I] ? -1 : 1;
   }
   if (Length == RHS.Length)
     return 0;
index 5731e4abaf1525055a2ddc6ba98b08b141aa097c..8364eac827487b70698370fac253f44904e80e37 100644 (file)
@@ -73,6 +73,12 @@ TEST(StringRefTest, StringOps) {
   EXPECT_EQ( 1, StringRef("2").compare_numeric("1"));
   EXPECT_EQ( 0, StringRef("llvm_v1i64_ty").compare_numeric("llvm_v1i64_ty"));
   EXPECT_EQ( 1, StringRef("\xFF").compare_numeric("\1"));
+  EXPECT_EQ( 1, StringRef("V16").compare_numeric("V1_q0"));
+  EXPECT_EQ(-1, StringRef("V1_q0").compare_numeric("V16"));
+  EXPECT_EQ(-1, StringRef("V8_q0").compare_numeric("V16"));
+  EXPECT_EQ( 1, StringRef("V16").compare_numeric("V8_q0"));
+  EXPECT_EQ(-1, StringRef("V1_q0").compare_numeric("V8_q0"));
+  EXPECT_EQ( 1, StringRef("V8_q0").compare_numeric("V1_q0"));
 }
 
 TEST(StringRefTest, Operators) {