Commit c954a306 authored by Chandler Carruth's avatar Chandler Carruth
Browse files

Merging r143871:

------------------------------------------------------------------------
r143871 | chandlerc | 2011-11-06 01:39:46 -0800 (Sun, 06 Nov 2011) | 3 lines

Lift the GCCVersion type into the header file and start persisting it in
the detected GCC installation. This allows us to expose another aspect
of what we detected: the GCC version. This will be used shortly.
------------------------------------------------------------------------

llvm-svn: 143948
parent 421c8baa
Loading
Loading
Loading
Loading
+55 −81
Original line number Diff line number Diff line
@@ -1521,32 +1521,10 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) {
  return UnknownDistro;
}

/// \brief Struct to store and manipulate GCC versions.
/// \brief Parse a GCCVersion object out of a string of text.
///
/// 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 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 {
  /// \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) {
/// This is the primary means of forming GCCVersion objects.
/*static*/ Linux::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) {
  const GCCVersion BadVersion = { VersionText, -1, -1, -1, "" };
  std::pair<StringRef, StringRef> First = VersionText.split('.');
  std::pair<StringRef, StringRef> Second = First.second.split('.');
@@ -1582,7 +1560,8 @@ struct Linux::GCCVersion {
  return GoodVersion;
}

  bool operator<(const GCCVersion &RHS) const {
/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering.
bool Linux::GCCVersion::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;

@@ -1598,10 +1577,6 @@ struct Linux::GCCVersion {
  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); }
  bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
};

/// \brief Construct a GCCInstallationDetector from the driver.
///
@@ -1658,7 +1633,7 @@ Linux::GCCInstallationDetector::GCCInstallationDetector(const Driver &D)

  // Loop over the various components which exist and select the best GCC
  // installation available. GCC installs are ranked by version number.
  GCCVersion BestVersion = GCCVersion::Parse("0.0.0");
  Version = GCCVersion::Parse("0.0.0");
  for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) {
    if (!llvm::sys::fs::exists(Prefixes[i]))
      continue;
@@ -1667,7 +1642,7 @@ Linux::GCCInstallationDetector::GCCInstallationDetector(const Driver &D)
      if (!llvm::sys::fs::exists(LibDir))
        continue;
      for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k)
        ScanLibDirForGCCTriple(LibDir, CandidateTriples[k], BestVersion);
        ScanLibDirForGCCTriple(LibDir, CandidateTriples[k]);
    }
  }
}
@@ -1732,8 +1707,7 @@ Linux::GCCInstallationDetector::GCCInstallationDetector(const Driver &D)
}

void Linux::GCCInstallationDetector::ScanLibDirForGCCTriple(
    const std::string &LibDir, StringRef CandidateTriple,
    GCCVersion &BestVersion) {
    const std::string &LibDir, StringRef CandidateTriple) {
  // There are various different suffixes involving the triple we
  // check for. We also record what is necessary to walk from each back
  // up to the lib directory.
@@ -1765,12 +1739,12 @@ void Linux::GCCInstallationDetector::ScanLibDirForGCCTriple(
      static const GCCVersion MinVersion = { "4.1.1", 4, 1, 1, "" };
      if (CandidateVersion < MinVersion)
        continue;
      if (CandidateVersion <= BestVersion)
      if (CandidateVersion <= Version)
        continue;
      if (!llvm::sys::fs::exists(LI->path() + "/crtbegin.o"))
        continue;

      BestVersion = CandidateVersion;
      Version = CandidateVersion;
      GccTriple = CandidateTriple.str();
      // FIXME: We hack together the directory name here instead of
      // using LI to ensure stable path separators across Windows and
+38 −3
Original line number Diff line number Diff line
@@ -372,7 +372,38 @@ public:
};

class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
  struct GCCVersion;
  /// \brief Struct to store and manipulate GCC versions.
  ///
  /// 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 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 GCCVersion {
    /// \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);
    bool operator<(const GCCVersion &RHS) const;
    bool operator>(const GCCVersion &RHS) const { return RHS < *this; }
    bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); }
    bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); }
  };


  /// \brief This is a class to find a viable GCC installation for Clang to
  /// use.
@@ -389,6 +420,8 @@ class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
    std::string GccInstallPath;
    std::string GccParentLibPath;

    GCCVersion Version;

  public:
    GCCInstallationDetector(const Driver &D);

@@ -404,14 +437,16 @@ class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF {
    /// \brief Get the detected GCC parent lib path.
    StringRef getParentLibPath() const { return GccParentLibPath; }

    /// \brief Get the detected GCC version string.
    StringRef getVersion() const { return Version.Text; }

  private:
    static void CollectLibDirsAndTriples(llvm::Triple::ArchType HostArch,
                                         SmallVectorImpl<StringRef> &LibDirs,
                                         SmallVectorImpl<StringRef> &Triples);

    void ScanLibDirForGCCTriple(const std::string &LibDir,
                                StringRef CandidateTriple,
                                GCCVersion &BestVersion);
                                StringRef CandidateTriple);
  };

  GCCInstallationDetector GCCInstallation;