Use llvm::VersionTuple instead of manual version marshalling

Summary:
This has multiple advantages:
- we need only one function argument/instance variable instead of three
- no need to default initialize variables
- no custom parsing code
- VersionTuple has comparison operators, which makes version comparisons much
  simpler

Reviewers: zturner, friss, clayborg, jingham

Subscribers: emaste, lldb-commits

Differential Revision: https://reviews.llvm.org/D47889

llvm-svn: 334950
diff --git a/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp b/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
index 4f79f62..8013114 100644
--- a/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
+++ b/lldb/source/Host/freebsd/HostInfoFreeBSD.cpp
@@ -18,16 +18,17 @@
 
 using namespace lldb_private;
 
-bool HostInfoFreeBSD::GetOSVersion(uint32_t &major, uint32_t &minor,
-                                   uint32_t &update) {
+llvm::VersionTuple HostInfoFreeBSD::GetOSVersion() {
   struct utsname un;
 
   ::memset(&un, 0, sizeof(utsname));
   if (uname(&un) < 0)
     return false;
 
-  int status = sscanf(un.release, "%u.%u", &major, &minor);
-  return status == 2;
+  unsigned major, minor;
+  if (2 == sscanf(un.release, "%u.%u", &major, &minor))
+    return llvm::VersionTuple(major, minor);
+  return llvm::VersionTuple();
 }
 
 bool HostInfoFreeBSD::GetOSBuildString(std::string &s) {
@@ -73,4 +74,4 @@
     }
   }
   return g_program_filespec;
-}
\ No newline at end of file
+}
diff --git a/lldb/source/Host/linux/HostInfoLinux.cpp b/lldb/source/Host/linux/HostInfoLinux.cpp
index 4983947..1d95010 100644
--- a/lldb/source/Host/linux/HostInfoLinux.cpp
+++ b/lldb/source/Host/linux/HostInfoLinux.cpp
@@ -26,12 +26,8 @@
 
 namespace {
 struct HostInfoLinuxFields {
-  HostInfoLinuxFields() : m_os_major(0), m_os_minor(0), m_os_update(0) {}
-
   std::string m_distribution_id;
-  uint32_t m_os_major;
-  uint32_t m_os_minor;
-  uint32_t m_os_update;
+  llvm::VersionTuple m_os_version;
 };
 
 HostInfoLinuxFields *g_fields = nullptr;
@@ -43,34 +39,21 @@
   g_fields = new HostInfoLinuxFields();
 }
 
-bool HostInfoLinux::GetOSVersion(uint32_t &major, uint32_t &minor,
-                                 uint32_t &update) {
-  static bool success = false;
+llvm::VersionTuple HostInfoLinux::GetOSVersion() {
   static llvm::once_flag g_once_flag;
   llvm::call_once(g_once_flag, []() {
-
     struct utsname un;
-    if (uname(&un) == 0) {
-      int status = sscanf(un.release, "%u.%u.%u", &g_fields->m_os_major,
-                          &g_fields->m_os_minor, &g_fields->m_os_update);
-      if (status == 3)
-        success = true;
-      else {
-        // Some kernels omit the update version, so try looking for just "X.Y"
-        // and set update to 0.
-        g_fields->m_os_update = 0;
-        status = sscanf(un.release, "%u.%u", &g_fields->m_os_major,
-                        &g_fields->m_os_minor);
-        if (status == 2)
-          success = true;
-      }
-    }
+    if (uname(&un) != 0)
+      return;
+
+    llvm::StringRef release = un.release;
+    // The kernel release string can include a lot of stuff (e.g.
+    // 4.9.0-6-amd64). We're only interested in the numbered prefix.
+    release = release.substr(0, release.find_first_not_of("0123456789."));
+    g_fields->m_os_version.tryParse(release);
   });
 
-  major = g_fields->m_os_major;
-  minor = g_fields->m_os_minor;
-  update = g_fields->m_os_update;
-  return success;
+  return g_fields->m_os_version;
 }
 
 bool HostInfoLinux::GetOSBuildString(std::string &s) {
diff --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
index dbb7482..5ec57c9 100644
--- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -76,32 +76,21 @@
   return false;
 }
 
-bool HostInfoMacOSX::GetOSVersion(uint32_t &major, uint32_t &minor,
-                                  uint32_t &update) {
-  static uint32_t g_major = 0;
-  static uint32_t g_minor = 0;
-  static uint32_t g_update = 0;
+llvm::VersionTuple HostInfoMacOSX::GetOSVersion() {
+  static llvm::VersionTuple g_version;
 
-  if (g_major == 0) {
+  if (g_version.empty()) {
     @autoreleasepool {
       NSDictionary *version_info = [NSDictionary
           dictionaryWithContentsOfFile:
               @"/System/Library/CoreServices/SystemVersion.plist"];
       NSString *version_value = [version_info objectForKey:@"ProductVersion"];
       const char *version_str = [version_value UTF8String];
-      if (version_str)
-        Args::StringToVersion(llvm::StringRef(version_str), g_major, g_minor,
-                              g_update);
+      g_version.tryParse(version_str);
     }
   }
 
-  if (g_major != 0) {
-    major = g_major;
-    minor = g_minor;
-    update = g_update;
-    return true;
-  }
-  return false;
+  return g_version;
 }
 
 FileSpec HostInfoMacOSX::GetProgramFileSpec() {
diff --git a/lldb/source/Host/netbsd/HostInfoNetBSD.cpp b/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
index 11ac115..19afae3 100644
--- a/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
+++ b/lldb/source/Host/netbsd/HostInfoNetBSD.cpp
@@ -21,8 +21,7 @@
 
 using namespace lldb_private;
 
-bool HostInfoNetBSD::GetOSVersion(uint32_t &major, uint32_t &minor,
-                                  uint32_t &update) {
+llvm::VersionTuple HostInfoNetBSD::GetOSVersion() {
   struct utsname un;
 
   ::memset(&un, 0, sizeof(un));
@@ -33,18 +32,14 @@
   int status = ::sscanf(un.release, "%" PRIu32 ".%" PRIu32 ".%" PRIu32, &major,
                         &minor, &update);
   switch (status) {
-  case 0:
-    return false;
   case 1:
-    minor = 0;
-  /* FALLTHROUGH */
+    return llvm::VersionTuple(major);
   case 2:
-    update = 0;
-  /* FALLTHROUGH */
+    return llvm::VersionTuple(major, minor);
   case 3:
-  default:
-    return true;
+    return llvm::VersionTuple(major, minor, update);
   }
+  return llvm::VersionTuple();
 }
 
 bool HostInfoNetBSD::GetOSBuildString(std::string &s) {
diff --git a/lldb/source/Host/windows/HostInfoWindows.cpp b/lldb/source/Host/windows/HostInfoWindows.cpp
index 5f074c8..a6e16d1 100644
--- a/lldb/source/Host/windows/HostInfoWindows.cpp
+++ b/lldb/source/Host/windows/HostInfoWindows.cpp
@@ -42,8 +42,7 @@
   return systemInfo.dwPageSize;
 }
 
-bool HostInfoWindows::GetOSVersion(uint32_t &major, uint32_t &minor,
-                                   uint32_t &update) {
+llvm::VersionTuple HostInfoWindows::GetOSVersion() {
   OSVERSIONINFOEX info;
 
   ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
@@ -54,16 +53,12 @@
   // in favor of the new Windows Version Helper APIs.  Since we don't specify a
   // minimum SDK version, it's easier to simply disable the warning rather than
   // try to support both APIs.
-  if (GetVersionEx((LPOSVERSIONINFO)&info) == 0) {
-    return false;
-  }
+  if (GetVersionEx((LPOSVERSIONINFO)&info) == 0)
+    return llvm::VersionTuple();
 #pragma warning(pop)
 
-  major = info.dwMajorVersion;
-  minor = info.dwMinorVersion;
-  update = info.wServicePackMajor;
-
-  return true;
+  return llvm::VersionTuple(info.dwMajorVersion, info.dwMinorVersion,
+                            info.wServicePackMajor);
 }
 
 bool HostInfoWindows::GetOSBuildString(std::string &s) {