From d95843aa8a12aa7661087d739f655eab37f9b464 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sun, 6 Nov 2011 09:39:46 +0000 Subject: 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: 143871 --- clang/lib/Driver/ToolChains.cpp | 136 ++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 81 deletions(-) (limited to 'clang/lib/Driver/ToolChains.cpp') diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index 0a8aa7a4a7c..07be52b20fc 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -1519,87 +1519,62 @@ 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) { - const GCCVersion BadVersion = { VersionText, -1, -1, -1, "" }; - std::pair First = VersionText.split('.'); - std::pair Second = First.second.split('.'); - - 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) || - GoodVersion.Minor < 0) - return BadVersion; - - // 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); - } +/// 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 First = VersionText.split('.'); + std::pair Second = First.second.split('.'); + + 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) || + GoodVersion.Minor < 0) + return BadVersion; + + // 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 GoodVersion; +} - // 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; +/// \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; - // 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); } - bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); } -}; + // 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; +} /// \brief Construct a GCCInstallationDetector from the driver. /// @@ -1656,7 +1631,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; @@ -1665,7 +1640,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]); } } } @@ -1730,8 +1705,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. @@ -1763,12 +1737,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 -- cgit v1.2.3