aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-11-07 10:39:29 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-11-07 10:39:29 +0000
commitc954a30696f312d13c22ff0e7c26b58e0723c558 (patch)
treef08b6053902bc81ab7f6f0b573f509ef5b2ac056
parent421c8baa5fe5aba82e0c465b7c9003bca1de7032 (diff)
downloadllvm-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.cpp136
-rw-r--r--clang/lib/Driver/ToolChains.h41
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;