aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-11-06 09:39:46 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-11-06 09:39:46 +0000
commit0e29dbb96121386c2e6d03b59eebf2c329a2a578 (patch)
treeb9556758ed943d7b17f3f1677b4cf2219cc4442b /lib
parent4f80e00dc64ceabd8822db927259b94d486e0f15 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143871 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Driver/ToolChains.cpp136
-rw-r--r--lib/Driver/ToolChains.h41
2 files changed, 93 insertions, 84 deletions
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 0a8aa7a4a7..07be52b20f 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/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<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.
///
@@ -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
diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h
index 57b14cc8dd..7599cd6b45 100644
--- a/lib/Driver/ToolChains.h
+++ b/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;