diff options
author | Chandler Carruth <chandlerc@gmail.com> | 2011-11-07 10:39:29 +0000 |
---|---|---|
committer | Chandler Carruth <chandlerc@gmail.com> | 2011-11-07 10:39:29 +0000 |
commit | c954a30696f312d13c22ff0e7c26b58e0723c558 (patch) | |
tree | f08b6053902bc81ab7f6f0b573f509ef5b2ac056 | |
parent | 421c8baa5fe5aba82e0c465b7c9003bca1de7032 (diff) | |
download | llvm-c954a30696f312d13c22ff0e7c26b58e0723c558.zip llvm-c954a30696f312d13c22ff0e7c26b58e0723c558.tar.gz llvm-c954a30696f312d13c22ff0e7c26b58e0723c558.tar.bz2 |
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
-rw-r--r-- | clang/lib/Driver/ToolChains.cpp | 136 | ||||
-rw-r--r-- | clang/lib/Driver/ToolChains.h | 41 |
2 files changed, 93 insertions, 84 deletions
diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index 7ddb98e..6d848ef 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -1521,87 +1521,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<StringRef, StringRef> First = VersionText.split('.'); - std::pair<StringRef, StringRef> 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<StringRef, StringRef> First = VersionText.split('.'); + std::pair<StringRef, StringRef> 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. /// @@ -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 diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h index 57b14cc..7599cd6 100644 --- a/clang/lib/Driver/ToolChains.h +++ b/clang/lib/Driver/ToolChains.h @@ -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; |