[API Notes] Allow removal of explicit attributes via versioned API notes.

Teach API notes to distinguish between unspecified API notes and
false/empty API notes. When a versioned API note explicitly specifies
an empty/false state, *remove* an the corresponding attribute from the
AST even when it was explicitly specified in the source. This allows
headers to move forward while API notes provide backward compatibility.

Another part of rdar://problem/28455809.

(cherry picked from commit 1fbea6c310b39c87e1f78e56430569a9dcd75488)
diff --git a/include/clang/APINotes/Types.h b/include/clang/APINotes/Types.h
index 9761510..4620bfd 100644
--- a/include/clang/APINotes/Types.h
+++ b/include/clang/APINotes/Types.h
@@ -127,26 +127,48 @@
   /// The Swift type to which a given type is bridged.
   ///
   /// Reflects the swift_bridge attribute.
-  std::string SwiftBridge;
+  Optional<std::string> SwiftBridge;
 
   /// The NS error domain for this type.
-  std::string NSErrorDomain;
+  Optional<std::string> NSErrorDomain;
 
 public:
   CommonTypeInfo() : CommonEntityInfo() { }
 
-  const std::string &getSwiftBridge() const { return SwiftBridge; }
-  void setSwiftBridge(const std::string &swiftType) { SwiftBridge = swiftType; }
+  const Optional<std::string> &getSwiftBridge() const { return SwiftBridge; }
 
-  const std::string &getNSErrorDomain() const { return NSErrorDomain; }
-  void setNSErrorDomain(const std::string &domain) { NSErrorDomain = domain; }
+  void setSwiftBridge(const Optional<std::string> &swiftType) {
+    SwiftBridge = swiftType;
+  }
+
+  void setSwiftBridge(const Optional<StringRef> &swiftType) {
+    if (swiftType)
+      SwiftBridge = *swiftType;
+    else
+      SwiftBridge = None;
+  }
+
+  const Optional<std::string> &getNSErrorDomain() const {
+    return NSErrorDomain;
+  }
+
+  void setNSErrorDomain(const Optional<std::string> &domain) {
+    NSErrorDomain = domain;
+  }
+
+  void setNSErrorDomain(const Optional<StringRef> &domain) {
+    if (domain)
+      NSErrorDomain = *domain;
+    else
+      NSErrorDomain = None;
+  }
 
   friend CommonTypeInfo &operator|=(CommonTypeInfo &lhs,
                                     const CommonTypeInfo &rhs) {
     static_cast<CommonEntityInfo &>(lhs) |= rhs;
-    if (lhs.SwiftBridge.empty() && !rhs.SwiftBridge.empty())
+    if (!lhs.SwiftBridge && rhs.SwiftBridge)
       lhs.SwiftBridge = rhs.SwiftBridge;
-    if (lhs.NSErrorDomain.empty() && !rhs.NSErrorDomain.empty())
+    if (!lhs.NSErrorDomain && rhs.NSErrorDomain)
       lhs.NSErrorDomain = rhs.NSErrorDomain;
     return lhs;
   }
@@ -308,24 +330,41 @@
 
 /// Describes a function or method parameter.
 class ParamInfo : public VariableInfo {
+  /// Whether noescape was specified.
+  unsigned NoEscapeSpecified : 1;
+
   /// Whether the this parameter has the 'noescape' attribute.
   unsigned NoEscape : 1;
 
 public:
-  ParamInfo() : VariableInfo(), NoEscape(false) { }
+  ParamInfo() : VariableInfo(), NoEscapeSpecified(false), NoEscape(false) { }
 
-  bool isNoEscape() const { return NoEscape; }
-  void setNoEscape(bool noescape) { NoEscape = noescape; }
+  Optional<bool> isNoEscape() const {
+    if (!NoEscapeSpecified) return None;
+    return NoEscape;
+  }
+  void setNoEscape(Optional<bool> noescape) {
+    if (noescape) {
+      NoEscapeSpecified = true;
+      NoEscape = *noescape;
+    } else {
+      NoEscapeSpecified = false;
+      NoEscape = false;
+    }
+  }
 
   friend ParamInfo &operator|=(ParamInfo &lhs, const ParamInfo &rhs) {
     static_cast<VariableInfo &>(lhs) |= rhs;
-    if (!lhs.NoEscape && rhs.NoEscape)
-      lhs.NoEscape = true;
+    if (!lhs.NoEscapeSpecified && rhs.NoEscapeSpecified) {
+      lhs.NoEscapeSpecified = true;
+      lhs.NoEscape = rhs.NoEscape;
+    }
     return lhs;
   }
 
   friend bool operator==(const ParamInfo &lhs, const ParamInfo &rhs) {
     return static_cast<const VariableInfo &>(lhs) == rhs &&
+           lhs.NoEscapeSpecified == rhs.NoEscapeSpecified &&
            lhs.NoEscape == rhs.NoEscape;
   }
 
diff --git a/lib/APINotes/APINotesFormat.h b/lib/APINotes/APINotesFormat.h
index 9b68cf2..6f7734b 100644
--- a/lib/APINotes/APINotesFormat.h
+++ b/lib/APINotes/APINotesFormat.h
@@ -36,7 +36,7 @@
 /// API notes file minor version number.
 ///
 /// When the format changes IN ANY WAY, this number should be incremented.
-const uint16_t VERSION_MINOR = 16;  // versioned API notes.
+const uint16_t VERSION_MINOR = 17;  // optional NSErrorDomain
 
 using IdentifierID = PointerEmbeddedInt<unsigned, 31>;
 using IdentifierIDField = BCVBR<16>;
diff --git a/lib/APINotes/APINotesReader.cpp b/lib/APINotes/APINotesReader.cpp
index 964cc1b..0e25409 100644
--- a/lib/APINotes/APINotesReader.cpp
+++ b/lib/APINotes/APINotesReader.cpp
@@ -126,15 +126,19 @@
 
     unsigned swiftBridgeLength =
         endian::readNext<uint16_t, little, unaligned>(data);
-    info.setSwiftBridge(
-        StringRef(reinterpret_cast<const char *>(data), swiftBridgeLength));
-    data += swiftBridgeLength;
+    if (swiftBridgeLength > 0) {
+      info.setSwiftBridge(
+        std::string(reinterpret_cast<const char *>(data), swiftBridgeLength-1));
+      data += swiftBridgeLength-1;
+    }
 
     unsigned errorDomainLength =
       endian::readNext<uint16_t, little, unaligned>(data);
-    info.setNSErrorDomain(
-        StringRef(reinterpret_cast<const char *>(data), errorDomainLength));
-    data += errorDomainLength;
+    if (errorDomainLength > 0) {
+      info.setNSErrorDomain(
+        std::string(reinterpret_cast<const char *>(data), errorDomainLength-1));
+      data += errorDomainLength-1;
+    }
   }
 
   /// Used to deserialize the on-disk identifier table.
@@ -303,8 +307,10 @@
       if (payload & 0x01)
         pi.setNullabilityAudited(static_cast<NullabilityKind>(nullabilityValue));
       payload >>= 1;
-      pi.setNoEscape(payload & 0x01);
-      payload >>= 1; assert(payload == 0 && "Bad API notes");
+      if (payload & 0x01) {
+        pi.setNoEscape(payload & 0x02);
+      }
+      payload >>= 2; assert(payload == 0 && "Bad API notes");
 
       info.Params.push_back(pi);
       --numParams;
diff --git a/lib/APINotes/APINotesWriter.cpp b/lib/APINotes/APINotesWriter.cpp
index 6debe99..2cd5776 100644
--- a/lib/APINotes/APINotesWriter.cpp
+++ b/lib/APINotes/APINotesWriter.cpp
@@ -343,8 +343,8 @@
   // Retrieve the serialized size of the given CommonTypeInfo, for use
   // in on-disk hash tables.
   static unsigned getCommonTypeInfoSize(const CommonTypeInfo &info) {
-    return 2 + info.getSwiftBridge().size() +
-           2 + info.getNSErrorDomain().size() +
+    return 2 + (info.getSwiftBridge() ? info.getSwiftBridge()->size() : 0) +
+           2 + (info.getNSErrorDomain() ? info.getNSErrorDomain()->size() : 0) +
            getCommonEntityInfoSize(info);
   }
 
@@ -352,10 +352,18 @@
   static void emitCommonTypeInfo(raw_ostream &out, const CommonTypeInfo &info) {
     emitCommonEntityInfo(out, info);
     endian::Writer<little> writer(out);
-    writer.write<uint16_t>(info.getSwiftBridge().size());
-    out.write(info.getSwiftBridge().c_str(), info.getSwiftBridge().size());
-    writer.write<uint16_t>(info.getNSErrorDomain().size());
-    out.write(info.getNSErrorDomain().c_str(), info.getNSErrorDomain().size());
+    if (auto swiftBridge = info.getSwiftBridge()) {
+      writer.write<uint16_t>(swiftBridge->size() + 1);
+      out.write(swiftBridge->c_str(), swiftBridge->size());
+    } else {
+      writer.write<uint16_t>(0);
+    }
+    if (auto nsErrorDomain = info.getNSErrorDomain()) {
+      writer.write<uint16_t>(nsErrorDomain->size() + 1);
+      out.write(nsErrorDomain->c_str(), info.getNSErrorDomain()->size());
+    } else {
+      writer.write<uint16_t>(0);
+    }
   }
 
   /// Used to serialize the on-disk Objective-C context table.
@@ -687,7 +695,12 @@
     // Parameters.
     writer.write<uint16_t>(info.Params.size());
     for (const auto &pi : info.Params) {
-      uint8_t payload = pi.isNoEscape();
+      uint8_t payload = 0;
+      if (auto noescape = pi.isNoEscape()) {
+        payload |= 0x01;
+        if (*noescape)
+          payload |= 0x02;
+      }
 
       auto nullability = pi.getNullability();
       payload = (payload << 1) | nullability.hasValue();
diff --git a/lib/APINotes/APINotesYAMLCompiler.cpp b/lib/APINotes/APINotesYAMLCompiler.cpp
index 868544f..69ed542 100644
--- a/lib/APINotes/APINotesYAMLCompiler.cpp
+++ b/lib/APINotes/APINotesYAMLCompiler.cpp
@@ -171,7 +171,7 @@
 
   struct Param {
     unsigned Position;
-    bool NoEscape = false;
+    Optional<bool> NoEscape = false;
     llvm::Optional<NullabilityKind> Nullability;
   };
   typedef std::vector<Param> ParamsSeq;
@@ -208,8 +208,8 @@
     AvailabilityItem Availability;
     bool SwiftPrivate = false;
     StringRef SwiftName;
-    StringRef SwiftBridge;
-    StringRef NSErrorDomain;
+    Optional<StringRef> SwiftBridge;
+    Optional<StringRef> NSErrorDomain;
     MethodsSeq Methods;
     PropertiesSeq Properties;
   };
@@ -248,8 +248,8 @@
     AvailabilityItem Availability;
     StringRef SwiftName;
     bool SwiftPrivate = false;
-    StringRef SwiftBridge;
-    StringRef NSErrorDomain;
+    Optional<StringRef> SwiftBridge;
+    Optional<StringRef> NSErrorDomain;
   };
   typedef std::vector<Tag> TagsSeq;
 
@@ -258,8 +258,8 @@
     AvailabilityItem Availability;
     StringRef SwiftName;
     bool SwiftPrivate = false;
-    StringRef SwiftBridge;
-    StringRef NSErrorDomain;
+    Optional<StringRef> SwiftBridge;
+    Optional<StringRef> NSErrorDomain;
   };
   typedef std::vector<Typedef> TypedefsSeq;
 
@@ -1033,6 +1033,20 @@
       return StringRef(reinterpret_cast<const char *>(ptr), string.size());
     }
 
+    /// Copy an optional string into allocated memory so it does disappear on us.
+    Optional<StringRef> maybeCopyString(Optional<StringRef> string) {
+      if (!string) return None;
+
+      return copyString(*string);
+    }
+
+    /// Copy an optional string into allocated memory so it does disappear on us.
+    Optional<StringRef> maybeCopyString(Optional<std::string> string) {
+      if (!string) return None;
+
+      return copyString(*string);
+    }
+
     template<typename T>
     void handleCommon(T &record, const CommonEntityInfo &info) {
       handleAvailability(record.Availability, info);
@@ -1043,8 +1057,8 @@
     template<typename T>
     void handleCommonType(T &record, const CommonTypeInfo &info) {
       handleCommon(record, info);
-      record.SwiftBridge = copyString(info.getSwiftBridge());      
-      record.NSErrorDomain = copyString(info.getNSErrorDomain());
+      record.SwiftBridge = maybeCopyString(info.getSwiftBridge());
+      record.NSErrorDomain = maybeCopyString(info.getNSErrorDomain());
     }
 
     /// Map Objective-C context info.
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 6d47dd7..e599840 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -1137,6 +1137,9 @@
     return;
   }
   bool eolnOut = false;
+  prettyPrintAttributes(OID);
+  if (OID->hasAttrs()) Out << "\n";
+
   Out << "@interface " << I;
 
   if (auto TypeParams = OID->getTypeParamListAsWritten()) {
diff --git a/lib/Sema/SemaAPINotes.cpp b/lib/Sema/SemaAPINotes.cpp
index 4d4ea6e..89cf5b6 100644
--- a/lib/Sema/SemaAPINotes.cpp
+++ b/lib/Sema/SemaAPINotes.cpp
@@ -241,20 +241,22 @@
                             const api_notes::CommonTypeInfo &info,
                             VersionedInfoRole role) {
   // swift_bridge
-  if (!info.getSwiftBridge().empty()) {
-    handleAPINotedAttribute<SwiftBridgeAttr>(S, D, true, role, [&] {
+  if (auto swiftBridge = info.getSwiftBridge()) {
+    handleAPINotedAttribute<SwiftBridgeAttr>(S, D, !swiftBridge->empty(), role,
+                                             [&] {
       return SwiftBridgeAttr::CreateImplicit(S.Context,
                                              CopyString(S.Context,
-                                                        info.getSwiftBridge()));
+                                                        *swiftBridge));
     });
   }
 
   // ns_error_domain
-  if (!info.getNSErrorDomain().empty()) {
-    handleAPINotedAttribute<NSErrorDomainAttr>(S, D, true, role, [&] {
+  if (auto nsErrorDomain = info.getNSErrorDomain()) {
+    handleAPINotedAttribute<NSErrorDomainAttr>(S, D, !nsErrorDomain->empty(),
+                                               role, [&] {
       return NSErrorDomainAttr::CreateImplicit(
                S.Context,
-               &S.Context.Idents.get(info.getNSErrorDomain()));
+               &S.Context.Idents.get(*nsErrorDomain));
     });
   }
 
@@ -281,8 +283,8 @@
                             const api_notes::ParamInfo &info,
                             VersionedInfoRole role) {
   // noescape
-  if (info.isNoEscape()) {
-    handleAPINotedAttribute<NoEscapeAttr>(S, D, true, role, [&] {
+  if (auto noescape = info.isNoEscape()) {
+    handleAPINotedAttribute<NoEscapeAttr>(S, D, *noescape, role, [&] {
       return NoEscapeAttr::CreateImplicit(S.Context);
     });
   }
diff --git a/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes b/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes
index c4e2bc0..1fc6aa4 100644
--- a/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes
+++ b/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.apinotes
@@ -1,6 +1,18 @@
 Name: SomeKit
 SwiftVersions:
   - Version: 3.0
+    Classes:
+      - Name: MyReferenceType
+        SwiftBridge: ''
     Functions:
       - Name: moveToPoint
         SwiftName: 'moveTo(a:b:)'
+      - Name: acceptClosure
+        Parameters:      
+          - Position:        0
+            NoEscape:        false
+    Tags:
+      - Name: MyErrorCode
+        NSErrorDomain: ''
+
+  
\ No newline at end of file
diff --git a/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h b/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h
index 8b0c290..741bdaa 100644
--- a/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h
+++ b/test/APINotes/Inputs/Frameworks/VersionedKit.framework/Headers/VersionedKit.h
@@ -1 +1,15 @@
 void moveToPoint(double x, double y) __attribute__((swift_name("moveTo(x:y:)")));
+
+void acceptClosure(void (^ __attribute__((noescape)) block)(void));
+
+@class NSString;
+
+extern NSString *MyErrorDomain;
+
+enum __attribute__((ns_error_domain(MyErrorDomain))) MyErrorCode {
+  MyErrorCodeFailed = 1
+};
+
+__attribute__((swift_bridge("MyValueType")))
+@interface MyReferenceType
+@end
diff --git a/test/APINotes/Inputs/roundtrip.apinotes b/test/APINotes/Inputs/roundtrip.apinotes
index 13e08a1..7e2e68a 100644
--- a/test/APINotes/Inputs/roundtrip.apinotes
+++ b/test/APINotes/Inputs/roundtrip.apinotes
@@ -9,8 +9,6 @@
     AvailabilityMsg: ''
     SwiftPrivate:    false
     SwiftName:       ''
-    SwiftBridge:     ''
-    NSErrorDomain:   ''
     Methods:         
       - Selector:        'cellWithImage:'
         MethodKind:      Class
@@ -62,7 +60,6 @@
     SwiftPrivate:    false
     SwiftName:       ''
     SwiftBridge:     View
-    NSErrorDomain:   ''
     Methods:         
       - Selector:        'addSubview:'
         MethodKind:      Instance
@@ -78,7 +75,6 @@
           - Position:        0
             NoEscape:        false
           - Position:        1
-            NoEscape:        false
           - Position:        2
             NoEscape:        true
         Nullability:     [ N, N, O ]
@@ -136,14 +132,12 @@
     AvailabilityMsg: ''
     SwiftPrivate:    false
     SwiftName:       SomeEnum
-    SwiftBridge:     ''
     NSErrorDomain:   some_error_domain
   - Name:            NSSomeStruct
     Availability:    available
     AvailabilityMsg: ''
     SwiftPrivate:    false
     SwiftName:       SomeStruct
-    SwiftBridge:     ''
     NSErrorDomain:   ''
 Typedefs:        
   - Name:            NSTypedef
@@ -152,7 +146,6 @@
     SwiftPrivate:    false
     SwiftName:       Typedef
     SwiftBridge:     ''
-    NSErrorDomain:   ''
 SwiftVersions:   
   - Version:         3.0
     Classes:         
@@ -162,7 +155,6 @@
         SwiftPrivate:    false
         SwiftName:       NSBox
         SwiftBridge:     ''
-        NSErrorDomain:   ''
         Methods:         
           - Selector:        init
             MethodKind:      Instance
diff --git a/test/APINotes/versioned.m b/test/APINotes/versioned.m
index c92ccd1..53af333 100644
--- a/test/APINotes/versioned.m
+++ b/test/APINotes/versioned.m
@@ -1,11 +1,11 @@
 // RUN: rm -rf %t && mkdir -p %t
 
 // Build and check the unversioned module file.
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fapinotes-cache-path=%t/APINotesCache -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Unversioned -fdisable-module-hash -fapinotes-modules -fapinotes-cache-path=%t/APINotesCache -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s
 // RUN: %clang_cc1 -ast-print %t/ModulesCache/Unversioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-UNVERSIONED %s
 
 // Build and check the versioned module file.
-// RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash -fapinotes-modules -fapinotes-cache-path=%t/APINotesCache -fapinotes-swift-version=3.0 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s
+// RUN: %clang_cc1 -fmodules -fblocks -fimplicit-module-maps -fmodules-cache-path=%t/ModulesCache/Versioned -fdisable-module-hash -fapinotes-modules -fapinotes-cache-path=%t/APINotesCache -fapinotes-swift-version=3.0 -fsyntax-only -I %S/Inputs/Headers -F %S/Inputs/Frameworks %s
 // RUN: %clang_cc1 -ast-print %t/ModulesCache/Versioned/VersionedKit.pcm | FileCheck -check-prefix=CHECK-VERSIONED %s
 
 #import <VersionedKit/VersionedKit.h>
@@ -13,3 +13,19 @@
 // CHECK-UNVERSIONED: void moveToPoint(double x, double y) __attribute__((swift_name("moveTo(x:y:)")));
 // CHECK-VERSIONED: void moveToPoint(double x, double y) __attribute__((swift_name("moveTo(a:b:)")));
 
+// CHECK-UNVERSIONED: void acceptClosure(void (^block)(void) __attribute__((noescape)));
+// CHECK-VERSIONED: void acceptClosure(void (^block)(void));
+
+// CHECK-UNVERSIONED:      enum MyErrorCode {
+// CHECK-UNVERSIONED-NEXT:     MyErrorCodeFailed = 1
+// CHECK-UNVERSIONED-NEXT: } __attribute__((ns_error_domain(MyErrorDomain)));
+
+// CHECK-UNVERSIONED: __attribute__((swift_bridge("MyValueType")))
+// CHECK-UNVERSIONED: @interface MyReferenceType
+
+// CHECK-VERSIONED:      enum MyErrorCode {
+// CHECK-VERSIONED-NEXT:     MyErrorCodeFailed = 1
+// CHECK-VERSIONED-NEXT: };
+
+// CHECK-VERSIONED-NOT: __attribute__((swift_bridge("MyValueType")))
+// CHECK-VERSIONED: @interface MyReferenceType