diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h
index 54d06e07396ad968eedb6bc1f736f51533b13594..77fd947f96a90c5414c4490d82054c5ff2d27334 100644
--- a/include/clang/Basic/VersionTuple.h
+++ b/include/clang/Basic/VersionTuple.h
@@ -24,30 +24,35 @@ namespace clang {
 
 /// \brief Represents a version number in the form major[.minor[.subminor]].
 class VersionTuple {
-  unsigned Major;
+  unsigned Major : 31;
   unsigned Minor : 31;
   unsigned Subminor : 31;
   unsigned HasMinor : 1;
   unsigned HasSubminor : 1;
+  unsigned UsesUnderscores : 1;
 
 public:
   VersionTuple() 
-    : Major(0), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false) { }
+    : Major(0), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false),
+      UsesUnderscores(false) { }
 
   explicit VersionTuple(unsigned Major)
-    : Major(Major), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false)
+    : Major(Major), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false),
+      UsesUnderscores(false)
   { }
 
-  explicit VersionTuple(unsigned Major, unsigned Minor)
+  explicit VersionTuple(unsigned Major, unsigned Minor,
+                        bool UsesUnderscores = false)
     : Major(Major), Minor(Minor), Subminor(0), HasMinor(true), 
-      HasSubminor(false)
+      HasSubminor(false), UsesUnderscores(UsesUnderscores)
   { }
 
-  explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor)
+  explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor,
+                        bool UsesUnderscores = false)
     : Major(Major), Minor(Minor), Subminor(Subminor), HasMinor(true), 
-      HasSubminor(true)
+      HasSubminor(true), UsesUnderscores(UsesUnderscores)
   { }
-
+  
   /// \brief Determine whether this version information is empty
   /// (e.g., all version components are zero).
   bool empty() const { return Major == 0 && Minor == 0 && Subminor == 0; }
@@ -69,6 +74,14 @@ public:
     return Subminor;
   }
 
+  bool usesUnderscores() const {
+    return UsesUnderscores;
+  }
+
+  void UseDotAsSeparator() {
+    UsesUnderscores = false;
+  }
+  
   /// \brief Determine if two version numbers are equivalent. If not
   /// provided, minor and subminor version numbers are considered to be zero.
   friend bool operator==(const VersionTuple& X, const VersionTuple &Y) {
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 49d05d0d407c29633ea67cab1587f1dc0a79aca2..014e3f9ef55c183fb5205aa7fe3cace76862894b 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -374,8 +374,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
     if (Message) {
       Message->clear();
       llvm::raw_string_ostream Out(*Message);
+      VersionTuple VTI(A->getIntroduced());
+      VTI.UseDotAsSeparator();
       Out << "introduced in " << PrettyPlatformName << ' ' 
-          << A->getIntroduced() << HintMessage;
+          << VTI << HintMessage;
     }
 
     return AR_NotYetIntroduced;
@@ -386,8 +388,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
     if (Message) {
       Message->clear();
       llvm::raw_string_ostream Out(*Message);
+      VersionTuple VTO(A->getObsoleted());
+      VTO.UseDotAsSeparator();
       Out << "obsoleted in " << PrettyPlatformName << ' ' 
-          << A->getObsoleted() << HintMessage;
+          << VTO << HintMessage;
     }
     
     return AR_Unavailable;
@@ -398,8 +402,10 @@ static AvailabilityResult CheckAvailability(ASTContext &Context,
     if (Message) {
       Message->clear();
       llvm::raw_string_ostream Out(*Message);
+      VersionTuple VTD(A->getDeprecated());
+      VTD.UseDotAsSeparator();
       Out << "first deprecated in " << PrettyPlatformName << ' '
-          << A->getDeprecated() << HintMessage;
+          << VTD << HintMessage;
     }
     
     return AR_Deprecated;
diff --git a/lib/Basic/VersionTuple.cpp b/lib/Basic/VersionTuple.cpp
index 8b781ab0a30426ae98cc9a2cb0dc24c15afbb1ef..aa43ae298e232b6248a178ad3ed28f47e537c9ad 100644
--- a/lib/Basic/VersionTuple.cpp
+++ b/lib/Basic/VersionTuple.cpp
@@ -29,9 +29,9 @@ raw_ostream& clang::operator<<(raw_ostream &Out,
                                      const VersionTuple &V) {
   Out << V.getMajor();
   if (Optional<unsigned> Minor = V.getMinor())
-    Out << '.' << *Minor;
+    Out << (V.usesUnderscores() ? '_' : '.') << *Minor;
   if (Optional<unsigned> Subminor = V.getSubminor())
-    Out << '.' << *Subminor;
+    Out << (V.usesUnderscores() ? '_' : '.') << *Subminor;
   return Out;
 }
 
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 6b1289b6f21628b5e653b5177946065e24b21459..b05af8fa760e521109a19689dbf6ef953a3d7a82 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -714,7 +714,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
       return VersionTuple();
     }
 
-    return VersionTuple(Major, Minor);
+    return VersionTuple(Major, Minor, (AfterMajorSeparator == '_'));
   }
 
   const char AfterMinorSeparator = ThisTokBegin[AfterMinor];
@@ -745,7 +745,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {
     return VersionTuple();
   }
   ConsumeToken();
-  return VersionTuple(Major, Minor, Subminor);
+  return VersionTuple(Major, Minor, Subminor, (AfterMajorSeparator == '_'));
 }
 
 /// \brief Parse the contents of the "availability" attribute.
diff --git a/test/Misc/ast-print-objectivec.m b/test/Misc/ast-print-objectivec.m
index 5e7acd37b873a198984a2727eb96f4bd20df348d..ef0fcaa9e32f664af8862c93b612d43258ebda41 100644
--- a/test/Misc/ast-print-objectivec.m
+++ b/test/Misc/ast-print-objectivec.m
@@ -11,7 +11,7 @@
 @end
 
 @interface I(CAT)
-- (void)MethCAT __attribute__((availability(macosx,introduced=10.1.0,deprecated=10.2)));
+- (void)MethCAT __attribute__((availability(macosx,introduced=10_1_0,deprecated=10_2)));
 @end
 
 @implementation I
@@ -28,7 +28,7 @@
 // CHECK: @end
 
 // CHECK: @interface I(CAT)
-// CHECK: - (void) MethCAT __attribute__((availability(macosx, introduced=10.1.0, deprecated=10.2)));
+// CHECK: - (void) MethCAT __attribute__((availability(macosx, introduced=10_1_0, deprecated=10_2)));
 // CHECK: @end
 
 // CHECK: @implementation I
diff --git a/test/SemaObjC/attr-availability-1.m b/test/SemaObjC/attr-availability-1.m
index 3a9a7d7ef6fa7679c65e89d13ce7d113dcf8edb2..af0fcfe3537be60961ce9b2b394176e9d5215b6d 100644
--- a/test/SemaObjC/attr-availability-1.m
+++ b/test/SemaObjC/attr-availability-1.m
@@ -21,10 +21,10 @@
 // rdar://11475360
 @interface B : A
 - (void)method; // NOTE: we expect 'method' to *not* inherit availability.
-- (void)overridden __attribute__((availability(macosx,introduced=10_4))); // expected-warning{{overriding method introduced after overridden method on OS X (10.4 vs. 10.3)}}
+- (void)overridden __attribute__((availability(macosx,introduced=10_4))); // expected-warning{{overriding method introduced after overridden method on OS X (10_4 vs. 10_3)}}
 - (void)overridden2 __attribute__((availability(macosx,introduced=10_2)));
 - (void)overridden3 __attribute__((availability(macosx,deprecated=10_4)));
-- (void)overridden4 __attribute__((availability(macosx,deprecated=10_2))); // expected-warning{{overriding method deprecated before overridden method on OS X (10.3 vs. 10.2)}}
+- (void)overridden4 __attribute__((availability(macosx,deprecated=10_2))); // expected-warning{{overriding method deprecated before overridden method on OS X (10_3 vs. 10_2)}}
 - (void)overridden5 __attribute__((availability(macosx,introduced=10_3)));
 - (void)overridden6 __attribute__((availability(macosx,unavailable))); // expected-warning{{overriding method cannot be unavailable on OS X when its overridden method is available}}
 @end