[cfe-commits] r143841 - in /cfe/trunk: lib/Driver/ test/Driver/ test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/ test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/ test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/ test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/ test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/ test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/ test/Driver/Inp...

Chandler Carruth chandlerc at gmail.com
Sat Nov 5 16:24:30 PDT 2011


Author: chandlerc
Date: Sat Nov  5 18:24:30 2011
New Revision: 143841

URL: http://llvm.org/viewvc/llvm-project?rev=143841&view=rev
Log:
Enhance the GCC version parsing and comparison logic to handle some more
edge cases and have better behavior. Specifically, we should actually
prefer the general '4.6' version string over the '4.6.1' string, as
'4.6.2' should be able to replace it without breaking rpaths or any
other place that these paths have been embedded. Debian-based
distributions are already using a path structure with symlinks to
achieve in-place upgrades for patch versions. Now our parsing reflects
this and we select the shorter paths instead of the longer paths.

A separate issue was that we would not parse a leading patch version
number even in the presence of a suffix. The above change makes this
more problematic as it would cause a suffix being added to make us treat
the entire thing as patch-version-agnostic, which it isn't. This changes
the logic to distinguish between '4.4.x' and 4.4.1-x', and retain that
the latter has *some* patch number information. Currently, we always
bias toward the shorter and more canonical version strings. If it
becomes important we can add more Debian like rules to produce sequences
such as '4.4.1b' > '4.4.1' > '4.4.1-rc3' > '4.4.1-rc2' > '4.4.1-pre5',
but I'm very doubtful this will ever matter or be desirable.

I've made the tests for this logic a bit more interesting, and added
some specific tests for logic that is now different.

Added:
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.0/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.1/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing3/lib/gcc/i386-unknown-linux/4.7.98/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing3/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/bin/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/bin/.keep
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.98/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99-rc5/
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99-rc5/crtbegin.o
    cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99/crtbegin.o
Modified:
    cfe/trunk/lib/Driver/ToolChains.cpp
    cfe/trunk/test/Driver/linux-ld.c

Modified: cfe/trunk/lib/Driver/ToolChains.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains.cpp?rev=143841&r1=143840&r2=143841&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains.cpp Sat Nov  5 18:24:30 2011
@@ -1523,34 +1523,78 @@
 ///
 /// We rely on assumptions about the form and structure of GCC version
 /// numbers: they consist of at most three '.'-separated components, and each
-/// component is a non-negative integer.
+/// component is a non-negative integer except for the last component. For the
+/// last component we are very flexible in order to tolerate release candidates
+/// or 'x' wildcards.
+///
+/// Note that the ordering established among GCCVersions is based on the
+/// preferred version string to use. For example we prefer versions without
+/// a hard-coded patch number to those with a hard coded patch number.
+///
+/// Currently this doesn't provide any logic for textual suffixes to patches in
+/// the way that (for example) Debian's version format does. If that ever
+/// becomes necessary, it can be added.
 struct Linux::GCCVersion {
-  unsigned Major, Minor, Patch;
+  /// \brief The unparsed text of the version.
+  StringRef Text;
+
+  /// \brief The parsed major, minor, and patch numbers.
+  int Major, Minor, Patch;
+
+  /// \brief Any textual suffix on the patch number.
+  StringRef PatchSuffix;
 
   static GCCVersion Parse(StringRef VersionText) {
-    const GCCVersion BadVersion = {0, 0, 0};
+    const GCCVersion BadVersion = { VersionText, -1, -1, -1, "" };
     std::pair<StringRef, StringRef> First = VersionText.split('.');
     std::pair<StringRef, StringRef> Second = First.second.split('.');
 
-    GCCVersion GoodVersion = {0, 0, 0};
-    if (First.first.getAsInteger(10, GoodVersion.Major))
+    GCCVersion GoodVersion = { VersionText, -1, -1, -1, "" };
+    if (First.first.getAsInteger(10, GoodVersion.Major) ||
+        GoodVersion.Major < 0)
       return BadVersion;
-    if (Second.first.getAsInteger(10, GoodVersion.Minor))
+    if (Second.first.getAsInteger(10, GoodVersion.Minor) ||
+        GoodVersion.Minor < 0)
       return BadVersion;
-    // We accept a number, or a string for the patch version, in case there
-    // is a strang suffix, or other mangling: '4.1.x', '4.1.2-rc3'. When it
-    // isn't a number, we just use '0' as the number but accept it.
-    if (Second.first.getAsInteger(10, GoodVersion.Patch))
-      GoodVersion.Patch = 0;
+
+    // First look for a number prefix and parse that if present. Otherwise just
+    // stash the entire patch string in the suffix, and leave the number
+    // unspecified. This covers versions strings such as:
+    //   4.4
+    //   4.4.0
+    //   4.4.x
+    //   4.4.2-rc4
+    //   4.4.x-patched
+    // And retains any patch number it finds.
+    StringRef PatchText = GoodVersion.PatchSuffix = Second.second;
+    if (!PatchText.empty()) {
+      if (unsigned EndNumber = PatchText.find_first_not_of("0123456789")) {
+        // Try to parse the number and any suffix.
+        if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) ||
+            GoodVersion.Patch < 0)
+          return BadVersion;
+        GoodVersion.PatchSuffix = PatchText.substr(EndNumber);
+      }
+    }
+
     return GoodVersion;
   }
 
   bool operator<(const GCCVersion &RHS) const {
-    if (Major < RHS.Major) return true;
-    if (Major > RHS.Major) return false;
-    if (Minor < RHS.Minor) return true;
-    if (Minor > RHS.Minor) return false;
-    return Patch < RHS.Patch;
+    if (Major < RHS.Major) return true; if (Major > RHS.Major) return false;
+    if (Minor < RHS.Minor) return true; if (Minor > RHS.Minor) return false;
+
+    // Note that we rank versions with *no* patch specified is better than ones
+    // hard-coding a patch version. Thus if the RHS has no patch, it always
+    // wins, and the LHS only wins if it has no patch and the RHS does have
+    // a patch.
+    if (RHS.Patch == -1) return true;   if (Patch == -1) return false;
+    if (Patch < RHS.Patch) return true; if (Patch > RHS.Patch) return false;
+
+    // Finally, between completely tied version numbers, the version with the
+    // suffix loses as we prefer full releases.
+    if (RHS.PatchSuffix.empty()) return true;
+    return false;
   }
   bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
   bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
@@ -1612,7 +1656,7 @@
 
   // Loop over the various components which exist and select the best GCC
   // installation available. GCC installs are ranked by version number.
-  GCCVersion BestVersion = {0, 0, 0};
+  GCCVersion BestVersion = GCCVersion::Parse("0.0.0");
   for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
     if (!llvm::sys::fs::exists(Prefixes[i]))
       continue;
@@ -1716,7 +1760,7 @@
          !EC && LI != LE; LI = LI.increment(EC)) {
       StringRef VersionText = llvm::sys::path::filename(LI->path());
       GCCVersion CandidateVersion = GCCVersion::Parse(VersionText);
-      static const GCCVersion MinVersion = { 4, 1, 1 };
+      static const GCCVersion MinVersion = { "4.1.1", 4, 1, 1, "" };
       if (CandidateVersion < MinVersion)
         continue;
       if (CandidateVersion <= BestVersion)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.6/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing1/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.99/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.6.x/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.0/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing2/lib/gcc/i386-unknown-linux/4.7.1/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing3/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing3/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/bin/.keep
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/bin/.keep?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.98/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99-rc5/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99-rc5/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Added: cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99/crtbegin.o
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/Inputs/gcc_version_parsing4/lib/gcc/i386-unknown-linux/4.7.99/crtbegin.o?rev=143841&view=auto
==============================================================================
    (empty)

Modified: cfe/trunk/test/Driver/linux-ld.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/linux-ld.c?rev=143841&r1=143840&r2=143841&view=diff
==============================================================================
--- cfe/trunk/test/Driver/linux-ld.c (original)
+++ cfe/trunk/test/Driver/linux-ld.c Sat Nov  5 18:24:30 2011
@@ -137,3 +137,11 @@
 // CHECK-GCC-VERSION3: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
 // CHECK-GCC-VERSION3: "{{.*}}/Inputs/gcc_version_parsing3/bin/../lib/gcc/i386-unknown-linux/4.7.99-rc5/crtbegin.o"
 // CHECK-GCC-VERSION3: "-L{{.*}}/Inputs/gcc_version_parsing3/bin/../lib/gcc/i386-unknown-linux/4.7.99-rc5"
+// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \
+// RUN:     -ccc-host-triple i386-unknown-linux -m32 \
+// RUN:     -ccc-install-dir %S/Inputs/gcc_version_parsing4/bin \
+// RUN:     --sysroot=%S/Inputs/basic_linux_tree \
+// RUN:   | FileCheck --check-prefix=CHECK-GCC-VERSION4 %s
+// CHECK-GCC-VERSION4: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]"
+// CHECK-GCC-VERSION4: "{{.*}}/Inputs/gcc_version_parsing4/bin/../lib/gcc/i386-unknown-linux/4.7.99/crtbegin.o"
+// CHECK-GCC-VERSION4: "-L{{.*}}/Inputs/gcc_version_parsing4/bin/../lib/gcc/i386-unknown-linux/4.7.99"





More information about the cfe-commits mailing list