Merge pull request #23590 from compnerd/more-tests-more-better

test: loosen restrictions on DebugInfo test
diff --git a/docs/ABI/Mangling.rst b/docs/ABI/Mangling.rst
index 979c323..ec64599 100644
--- a/docs/ABI/Mangling.rst
+++ b/docs/ABI/Mangling.rst
@@ -112,6 +112,8 @@
   global ::= nominal-type 'Mn'           // nominal type descriptor
   global ::= nominal-type 'Mu'           // class method lookup function
   global ::= nominal-type 'MU'           // ObjC metadata update callback function
+  global ::= nominal-type 'Ms'           // ObjC resilient class stub
+  global ::= nominal-type 'Mt'           // Full ObjC resilient class stub (private)
   global ::= module 'MXM'                // module descriptor
   global ::= context 'MXE'               // extension descriptor
   global ::= context 'MXX'               // anonymous context descriptor
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index a3976ea..d06f7c7 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -3683,6 +3683,28 @@
   TargetRelativeDirectPointer<Runtime, const void, /*nullable*/true> Superclass;
 };
 
+/// A structure that stores a reference to an Objective-C class stub.
+///
+/// This is not the class stub itself; it is part of a class context
+/// descriptor.
+template <typename Runtime>
+struct TargetObjCResilientClassStubInfo {
+  /// A relative pointer to an Objective-C resilient class stub.
+  ///
+  /// We do not declare a struct type for class stubs since the Swift runtime
+  /// does not need to interpret them. The class stub struct is part of
+  /// the Objective-C ABI, and is laid out as follows:
+  /// - isa pointer, always 1
+  /// - an update callback, of type 'Class (*)(Class *, objc_class_stub *)'
+  ///
+  /// Class stubs are used for two purposes:
+  ///
+  /// - Objective-C can reference class stubs when calling static methods.
+  /// - Objective-C and Swift can reference class stubs when emitting
+  ///   categories (in Swift, extensions with @objc members).
+  TargetRelativeDirectPointer<Runtime, const void> Stub;
+};
+
 template <typename Runtime>
 class TargetClassDescriptor final
     : public TargetTypeContextDescriptor<Runtime>,
@@ -3695,7 +3717,8 @@
                               TargetVTableDescriptorHeader<Runtime>,
                               TargetMethodDescriptor<Runtime>,
                               TargetOverrideTableHeader<Runtime>,
-                              TargetMethodOverrideDescriptor<Runtime>> {
+                              TargetMethodOverrideDescriptor<Runtime>,
+                              TargetObjCResilientClassStubInfo<Runtime>> {
 private:
   using TrailingGenericContextObjects =
     TrailingGenericContextObjects<TargetClassDescriptor<Runtime>,
@@ -3706,7 +3729,8 @@
                                   TargetVTableDescriptorHeader<Runtime>,
                                   TargetMethodDescriptor<Runtime>,
                                   TargetOverrideTableHeader<Runtime>,
-                                  TargetMethodOverrideDescriptor<Runtime>>;
+                                  TargetMethodOverrideDescriptor<Runtime>,
+                                  TargetObjCResilientClassStubInfo<Runtime>>;
 
   using TrailingObjects =
     typename TrailingGenericContextObjects::TrailingObjects;
@@ -3722,6 +3746,8 @@
     TargetForeignMetadataInitialization<Runtime>;
   using SingletonMetadataInitialization =
     TargetSingletonMetadataInitialization<Runtime>;
+  using ObjCResilientClassStubInfo =
+    TargetObjCResilientClassStubInfo<Runtime>;
 
   using StoredPointer = typename Runtime::StoredPointer;
   using StoredPointerDifference = typename Runtime::StoredPointerDifference;
@@ -3759,7 +3785,9 @@
     /// positive size of metadata objects of this class (in words).
     uint32_t MetadataPositiveSizeInWords;
 
-    // Maybe add something here that's useful only for resilient types?
+    /// Otherwise, these flags are used to do things like indicating
+    /// the presence of an Objective-C resilient class stub.
+    ExtraClassDescriptorFlags ExtraClassFlags;
   };
 
   /// The number of additional members added by this class to the class
@@ -3835,6 +3863,10 @@
     return getOverrideTable()->NumEntries;
   }
 
+  size_t numTrailingObjects(OverloadToken<ObjCResilientClassStubInfo>) const {
+    return hasObjCResilientClassStub() ? 1 : 0;
+  }
+
 public:
   const TargetRelativeDirectPointer<Runtime, const void, /*nullable*/true> &
   getResilientSuperclass() const {
@@ -3954,7 +3986,24 @@
            && i < numTrailingObjects(OverloadToken<MethodDescriptor>{}));
     return getMethodDescriptors()[i].Impl.get();
   }
-  
+
+  /// Whether this context descriptor references an Objective-C resilient
+  /// class stub. See the above description of TargetObjCResilientClassStubInfo
+  /// for details.
+  bool hasObjCResilientClassStub() const {
+    if (!hasResilientSuperclass())
+      return false;
+    return ExtraClassFlags.hasObjCResilientClassStub();
+  }
+
+  const void *getObjCResilientClassStub() const {
+    if (!hasObjCResilientClassStub())
+      return nullptr;
+
+    return this->template getTrailingObjects<ObjCResilientClassStubInfo>()
+      ->Stub.get();
+  }
+
   static bool classof(const TargetContextDescriptor<Runtime> *cd) {
     return cd->getKind() == ContextDescriptorKind::Class;
   }
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index f6c5497..70abb80 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -1309,6 +1309,28 @@
                                  class_setResilientSuperclassReferenceKind)
 };
 
+/// Extra flags for resilient classes, since we need more than 16 bits of
+/// flags there.
+class ExtraClassDescriptorFlags : public FlagSet<uint32_t> {
+  enum {
+    /// Set if the context descriptor includes a pointer to an Objective-C
+    /// resilient class stub structure. See the description of
+    /// TargetObjCResilientClassStubInfo in Metadata.h for details.
+    ///
+    /// Only meaningful for class descriptors when Objective-C interop is
+    /// enabled.
+    HasObjCResilientClassStub = 0,
+  };
+
+public:
+  explicit ExtraClassDescriptorFlags(uint32_t bits) : FlagSet(bits) {}
+  constexpr ExtraClassDescriptorFlags() {}
+
+  FLAGSET_DEFINE_FLAG_ACCESSORS(HasObjCResilientClassStub,
+                                hasObjCResilientClassStub,
+                                setObjCResilientClassStub)
+};
+
 /// Flags for protocol context descriptors. These values are used as the
 /// kindSpecificFlags of the ContextDescriptorFlags for the protocol.
 class ProtocolContextDescriptorFlags : public FlagSet<uint16_t> {
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index 8c06c8b..a4eeb75 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -542,7 +542,7 @@
     NumRequirementsInSignature : 16
   );
 
-  SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+2+1+2+1+3+1+1+1+1,
+  SWIFT_INLINE_BITFIELD(ClassDecl, NominalTypeDecl, 1+2+1+2+1+6+1+1+1,
     /// Whether this class requires all of its instance variables to
     /// have in-class initializers.
     RequiresStoredPropertyInits : 1,
@@ -563,12 +563,11 @@
     /// control inserting the implicit destructor.
     HasDestructorDecl : 1,
 
-    /// Whether the class has @objc ancestry.
-    ObjCKind : 3,
+    /// Information about the class's ancestry.
+    Ancestry : 6,
 
-    /// Whether this class has @objc members.
-    HasObjCMembersComputed : 1,
-    HasObjCMembers : 1,
+    /// Whether we have computed the above field or not.
+    AncestryComputed : 1,
 
     HasMissingDesignatedInitializers : 1,
     HasMissingVTableEntries : 1
@@ -3545,21 +3544,33 @@
   UIApplicationMain,
 };
 
-enum class ObjCClassKind : uint8_t {
-  /// Neither the class nor any of its superclasses are @objc.
-  NonObjC,
-  /// One of the superclasses is @objc but another superclass or the
-  /// class itself has generic parameters, so while it cannot be
-  /// directly represented in Objective-C, it has implicitly @objc
-  /// members.
-  ObjCMembers,
-  /// The top-level ancestor of this class is not @objc, but the
-  /// class itself is.
-  ObjCWithSwiftRoot,
-  /// The class is bona-fide @objc.
-  ObjC,
+/// This is the base type for AncestryOptions. Each flag describes possible
+/// interesting kinds of superclasses that a class may have.
+enum class AncestryFlags : uint8_t {
+  /// The class or one of its superclasses is @objc.
+  ObjC = (1<<0),
+
+  /// The class or one of its superclasses is @objcMembers.
+  ObjCMembers = (1<<1),
+
+  /// The class or one of its superclasses is generic.
+  Generic = (1<<2),
+
+  /// The class or one of its superclasses is resilient.
+  Resilient = (1<<3),
+
+  /// The class or one of its superclasses has resilient metadata and is in a
+  /// different resilience domain.
+  ResilientOther = (1<<4),
+
+  /// The class or one of its superclasses is imported from Clang.
+  ClangImported = (1<<5),
 };
 
+/// Return type of ClassDecl::checkAncestry(). Describes a set of interesting
+/// kinds of superclasses that a class may have.
+using AncestryOptions = OptionSet<AncestryFlags>;
+
 /// ClassDecl - This is the declaration of a class, for example:
 ///
 ///    class Complex { var R : Double, I : Double }
@@ -3589,8 +3600,6 @@
   friend class SuperclassTypeRequest;
   friend class TypeChecker;
 
-  bool hasObjCMembersSlow();
-
 public:
   ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
             MutableArrayRef<TypeLoc> Inherited,
@@ -3622,6 +3631,9 @@
   /// is no superclass.
   ClassDecl *getSuperclassDecl() const;
 
+  /// Check if this class is a superclass or equal to the given class.
+  bool isSuperclassOf(ClassDecl *other) const;
+
   /// Set the superclass of this class.
   void setSuperclass(Type superclass);
 
@@ -3749,18 +3761,13 @@
     Bits.ClassDecl.InheritsSuperclassInits = true;
   }
 
-  /// Returns if this class has any @objc ancestors, or if it is directly
-  /// visible to Objective-C. The latter is a stronger condition which is only
-  /// true if the class does not have any generic ancestry.
-  ObjCClassKind checkObjCAncestry() const;
+  /// Walks the class hierarchy starting from this class, checking various
+  /// conditions.
+  AncestryOptions checkAncestry() const;
 
-  /// Returns if the class has implicitly @objc members. This is true if any
-  /// ancestor class has the @objcMembers attribute.
-  bool hasObjCMembers() const {
-    if (Bits.ClassDecl.HasObjCMembersComputed)
-      return Bits.ClassDecl.HasObjCMembers;
-
-    return const_cast<ClassDecl *>(this)->hasObjCMembersSlow();
+  /// Check if the class has ancestry of the given kind.
+  bool checkAncestry(AncestryFlags flag) const {
+    return checkAncestry().contains(flag);
   }
 
   /// The type of metaclass to use for a class.
diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def
index 408c2ce..83f6653 100644
--- a/include/swift/AST/DiagnosticsSema.def
+++ b/include/swift/AST/DiagnosticsSema.def
@@ -3592,9 +3592,11 @@
 ERROR(objc_in_extension_context,none,
       "members of constrained extensions cannot be declared @objc", ())
 ERROR(objc_in_generic_extension,none,
-      "members of extensions of "
-      "%select{classes from generic context|generic classes}0 "
-      "cannot be declared @objc", (bool))
+      "extensions of %select{classes from generic context|generic classes}0 "
+      "cannot contain '@objc' members", (bool))
+ERROR(objc_in_resilient_extension,none,
+      "extensions of classes built with library evolution support "
+      "cannot contain '@objc' members", ())
 ERROR(objc_operator, none,
       "operator methods cannot be declared @objc", ())
 ERROR(objc_operator_proto, none,
@@ -3615,6 +3617,10 @@
 ERROR(objc_for_generic_class,none,
       "generic subclasses of '@objc' classes cannot have an explicit '@objc' "
       "because they are not directly visible from Objective-C", ())
+ERROR(objc_for_resilient_class,none,
+      "classes built with library evolution support cannot have explicit "
+      "'@objc' subclasses because they are not directly "
+      "visible from Objective-C", ())
 ERROR(objc_getter_for_nonobjc_property,none,
       "'@objc' getter for non-'@objc' property", ())
 ERROR(objc_getter_for_nonobjc_subscript,none,
diff --git a/include/swift/AST/Module.h b/include/swift/AST/Module.h
index da93097..abab16b 100644
--- a/include/swift/AST/Module.h
+++ b/include/swift/AST/Module.h
@@ -324,6 +324,10 @@
     Bits.ModuleDecl.RawResilienceStrategy = unsigned(strategy);
   }
 
+  bool isResilient() const {
+    return getResilienceStrategy() != ResilienceStrategy::Default;
+  }
+
   /// Look up a (possibly overloaded) value set at top-level scope
   /// (but with the specified access path, which may come from an import decl)
   /// within the current module.
diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h
index 88e0b47..eb8d10d 100644
--- a/include/swift/Basic/LangOptions.h
+++ b/include/swift/Basic/LangOptions.h
@@ -296,6 +296,11 @@
     /// set to true.
     bool ExperimentalDependenciesIncludeIntrafileOnes = false;
 
+    /// Enable experimental support for emitting Objective-C resilient class
+    /// stubs. This is a language option since it also determines if we admit
+    /// @objc members in extensions of classes with resilient ancestry.
+    bool EnableObjCResilientClassStubs = false;
+
     /// Sets the target we are building for and updates platform conditions
     /// to match.
     ///
diff --git a/include/swift/Demangling/DemangleNodes.def b/include/swift/Demangling/DemangleNodes.def
index 3c0c6d6..dec6c39 100644
--- a/include/swift/Demangling/DemangleNodes.def
+++ b/include/swift/Demangling/DemangleNodes.def
@@ -134,6 +134,8 @@
 NODE(Metaclass)
 NODE(MethodLookupFunction)
 NODE(ObjCMetadataUpdateFunction)
+NODE(ObjCResilientClassStub)
+NODE(FullObjCResilientClassStub)
 CONTEXT_NODE(ModifyAccessor)
 CONTEXT_NODE(Module)
 CONTEXT_NODE(NativeOwningAddressor)
diff --git a/include/swift/IRGen/Linking.h b/include/swift/IRGen/Linking.h
index 5a98fe4..efad066 100644
--- a/include/swift/IRGen/Linking.h
+++ b/include/swift/IRGen/Linking.h
@@ -96,7 +96,7 @@
     // This field appears in the ValueWitness kind.
     ValueWitnessShift = 8, ValueWitnessMask = 0xFF00,
 
-    // This field appears in the TypeMetadata kind.
+    // This field appears in the TypeMetadata and ObjCResilientClassStub kinds.
     MetadataAddressShift = 8, MetadataAddressMask = 0x0300,
 
     // This field appears in associated type access functions.
@@ -164,6 +164,12 @@
     /// ClassMetadataStrategy::Update or ::FixedOrUpdate.
     ObjCMetadataUpdateFunction,
 
+    /// A stub that we emit to allow Clang-generated code to statically refer
+    /// to Swift classes with resiliently-sized metadata, since the metadata
+    /// is not statically-emitted. Used when getClassMetadataStrategy() is
+    /// equal to ClassMetadataStrategy::Resilient.
+    ObjCResilientClassStub,
+
     /// A class metadata base offset global variable.  This stores the offset
     /// of the immediate members of a class (generic parameters, field offsets,
     /// vtable offsets) in the class's metadata.  The immediate members begin
@@ -613,13 +619,19 @@
     return entity;
   }
 
+  static LinkEntity forObjCResilientClassStub(ClassDecl *decl,
+                                              TypeMetadataAddress addr) {
+    LinkEntity entity;
+    entity.setForDecl(Kind::ObjCResilientClassStub, decl);
+    entity.Data |= LINKENTITY_SET_FIELD(MetadataAddress, unsigned(addr));
+    return entity;
+  }
+
   static LinkEntity forTypeMetadata(CanType concreteType,
                                     TypeMetadataAddress addr) {
     LinkEntity entity;
-    entity.Pointer = concreteType.getPointer();
-    entity.SecondaryPointer = nullptr;
-    entity.Data = LINKENTITY_SET_FIELD(Kind, unsigned(Kind::TypeMetadata))
-                | LINKENTITY_SET_FIELD(MetadataAddress, unsigned(addr));
+    entity.setForType(Kind::TypeMetadata, concreteType);
+    entity.Data |= LINKENTITY_SET_FIELD(MetadataAddress, unsigned(addr));
     return entity;
   }
 
@@ -1021,7 +1033,8 @@
     return ValueWitness(LINKENTITY_GET_FIELD(Data, ValueWitness));
   }
   TypeMetadataAddress getMetadataAddress() const {
-    assert(getKind() == Kind::TypeMetadata);
+    assert(getKind() == Kind::TypeMetadata ||
+           getKind() == Kind::ObjCResilientClassStub);
     return (TypeMetadataAddress)LINKENTITY_GET_FIELD(Data, MetadataAddress);
   }
   bool isForeignTypeMetadataCandidate() const {
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index 045a723..c60d32a 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -555,4 +555,8 @@
   Flags<[FrontendOption]>,
   HelpText<"One of 'all', 'resilient' or 'fragile'">;
 
+def enable_objc_resilient_class_stubs : Flag<["-"], "enable-resilient-objc-class-stubs">,
+  HelpText<"Emit Objective-C resilient class stubs for classes with "
+           "resiliently-sized metadata">;
+
 } // end let Flags = [FrontendOption, NoDriverOption, HelpHidden]
diff --git a/include/swift/Option/SanitizerOptions.h b/include/swift/Option/SanitizerOptions.h
index b8991cc..f19500c 100644
--- a/include/swift/Option/SanitizerOptions.h
+++ b/include/swift/Option/SanitizerOptions.h
@@ -42,5 +42,8 @@
         const llvm::Triple &Triple,
         DiagnosticEngine &Diag,
         OptionSet<SanitizerKind> sanitizers);
+
+/// Returns the active sanitizers as a comma-separated list.
+std::string getSanitizerList(const OptionSet<SanitizerKind> &Set);
 }
 #endif // SWIFT_OPTIONS_SANITIZER_OPTIONS_H
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 68ae9a4..1489410 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -1927,14 +1927,7 @@
   if (!isFormallyResilient())
     return false;
 
-  switch (getDeclContext()->getParentModule()->getResilienceStrategy()) {
-  case ResilienceStrategy::Resilient:
-    return true;
-  case ResilienceStrategy::Default:
-    return false;
-  }
-
-  llvm_unreachable("Unhandled ResilienceStrategy in switch.");
+  return getModuleContext()->isResilient();
 }
 
 bool AbstractStorageDecl::isResilient(ModuleDecl *M,
@@ -3077,20 +3070,10 @@
 }
 
 bool NominalTypeDecl::isResilient() const {
-  // If we're not formally resilient, don't check the module resilience
-  // strategy.
   if (!isFormallyResilient())
     return false;
 
-  // Otherwise, check the module.
-  switch (getParentModule()->getResilienceStrategy()) {
-  case ResilienceStrategy::Resilient:
-    return true;
-  case ResilienceStrategy::Default:
-    return false;
-  }
-
-  llvm_unreachable("Unhandled ResilienceStrategy in switch.");
+  return getModuleContext()->isResilient();
 }
 
 bool NominalTypeDecl::isResilient(ModuleDecl *M,
@@ -3536,9 +3519,8 @@
   Bits.ClassDecl.InheritsSuperclassInits = 0;
   Bits.ClassDecl.RawForeignKind = 0;
   Bits.ClassDecl.HasDestructorDecl = 0;
-  Bits.ClassDecl.ObjCKind = 0;
-  Bits.ClassDecl.HasObjCMembersComputed = 0;
-  Bits.ClassDecl.HasObjCMembers = 0;
+  Bits.ClassDecl.Ancestry = 0;
+  Bits.ClassDecl.AncestryComputed = 0;
   Bits.ClassDecl.HasMissingDesignatedInitializers = 0;
   Bits.ClassDecl.HasMissingVTableEntries = 0;
 }
@@ -3549,8 +3531,7 @@
     return false;
 
   // If the module is not resilient, neither is the class metadata.
-  if (getParentModule()->getResilienceStrategy()
-          != ResilienceStrategy::Resilient)
+  if (!getModuleContext()->isResilient())
     return false;
 
   // If the class is not public, we can't use it outside the module at all.
@@ -3652,16 +3633,18 @@
   return Bits.ClassDecl.InheritsSuperclassInits;
 }
 
-ObjCClassKind ClassDecl::checkObjCAncestry() const {
+AncestryOptions ClassDecl::checkAncestry() const {
   // See if we've already computed this.
-  if (Bits.ClassDecl.ObjCKind)
-    return ObjCClassKind(Bits.ClassDecl.ObjCKind - 1);
+  if (Bits.ClassDecl.AncestryComputed)
+    return AncestryOptions(Bits.ClassDecl.Ancestry);
 
   llvm::SmallPtrSet<const ClassDecl *, 8> visited;
-  bool genericAncestry = false, isObjC = false;
-  const ClassDecl *CD = this;
 
-  for (;;) {
+  AncestryOptions result;
+  const ClassDecl *CD = this;
+  auto *M = getParentModule();
+
+  do {
     // If we hit circularity, we will diagnose at some point in typeCheckDecl().
     // However we have to explicitly guard against that here because we get
     // called as part of validateDecl().
@@ -3669,55 +3652,54 @@
       break;
 
     if (CD->isGenericContext())
-      genericAncestry = true;
+      result |= AncestryFlags::Generic;
 
-    // Is this class @objc? For the current class, only look at the attribute
-    // to avoid cycles; for superclasses, compute @objc completely.
-    if ((CD == this && CD->getAttrs().hasAttribute<ObjCAttr>()) ||
-        (CD != this && CD->isObjC()))
-      isObjC = true;
+    // Note: it's OK to check for @objc explicitly instead of calling isObjC()
+    // to infer it since we're going to visit every superclass.
+    if (CD->getAttrs().hasAttribute<ObjCAttr>())
+      result |= AncestryFlags::ObjC;
 
-    if (!CD->hasSuperclass())
-      break;
+    if (CD->getAttrs().hasAttribute<ObjCMembersAttr>())
+      result |= AncestryFlags::ObjCMembers;
+
+    if (CD->hasClangNode())
+      result |= AncestryFlags::ClangImported;
+
+    if (CD->hasResilientMetadata())
+      result |= AncestryFlags::Resilient;
+
+    if (CD->hasResilientMetadata(M, ResilienceExpansion::Maximal))
+      result |= AncestryFlags::ResilientOther;
+
     CD = CD->getSuperclassDecl();
-    // If we don't have a valid class here, we should have diagnosed
-    // elsewhere.
-    if (!CD)
-      break;
-  }
-
-  ObjCClassKind kind = ObjCClassKind::ObjC;
-  if (!isObjC)
-    kind = ObjCClassKind::NonObjC;
-  else if (genericAncestry)
-    kind = ObjCClassKind::ObjCMembers;
-  else if (CD == this || !CD->isObjC())
-    kind = ObjCClassKind::ObjCWithSwiftRoot;
+  } while (CD != nullptr);
 
   // Save the result for later.
-  const_cast<ClassDecl *>(this)->Bits.ClassDecl.ObjCKind
-    = unsigned(kind) + 1;
-  return kind;
+  const_cast<ClassDecl *>(this)->Bits.ClassDecl.Ancestry = result.toRaw();
+  const_cast<ClassDecl *>(this)->Bits.ClassDecl.AncestryComputed = 1;
+  return result;
 }
 
-bool ClassDecl::hasObjCMembersSlow() {
-  // Don't attempt to calculate this again.
-  Bits.ClassDecl.HasObjCMembersComputed = true;
+bool ClassDecl::isSuperclassOf(ClassDecl *other) const {
+  llvm::SmallPtrSet<const ClassDecl *, 8> visited;
 
-  bool result = false;
-  if (getAttrs().hasAttribute<ObjCMembersAttr>())
-    result = true;
-  else if (auto *superclassDecl = getSuperclassDecl())
-    result = superclassDecl->hasObjCMembers();
+  do {
+    if (!visited.insert(other).second)
+      break;
 
-  Bits.ClassDecl.HasObjCMembers = result;
-  return result;
+    if (this == other)
+      return true;
+
+    other = other->getSuperclassDecl();
+  } while (other != nullptr);
+
+  return false;
 }
 
 ClassDecl::MetaclassKind ClassDecl::getMetaclassKind() const {
   assert(getASTContext().LangOpts.EnableObjCInterop &&
          "querying metaclass kind without objc interop");
-  auto objc = checkObjCAncestry() != ObjCClassKind::NonObjC;
+  auto objc = checkAncestry(AncestryFlags::ObjC);
   return objc ? MetaclassKind::ObjC : MetaclassKind::SwiftStub;
 }
 
@@ -3807,8 +3789,6 @@
       }
     }
     // Check the superclass
-    if (!C->hasSuperclass())
-      break;
     C = C->getSuperclassDecl();
   }
   return nullptr;
@@ -3891,12 +3871,8 @@
 
   // Non-imported enums in non-resilient modules are exhaustive.
   const ModuleDecl *containingModule = getModuleContext();
-  switch (containingModule->getResilienceStrategy()) {
-  case ResilienceStrategy::Default:
+  if (!containingModule->isResilient())
     return true;
-  case ResilienceStrategy::Resilient:
-    break;
-  }
 
   // Non-public, non-versioned enums are always exhaustive.
   AccessScope accessScope = getFormalAccessScope(/*useDC*/nullptr,
diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp
index 1afedd8..9aecda4 100644
--- a/lib/AST/ProtocolConformance.cpp
+++ b/lib/AST/ProtocolConformance.cpp
@@ -458,12 +458,7 @@
   if (!getType()->getAnyNominal()->isResilient())
     return false;
 
-  switch (getDeclContext()->getParentModule()->getResilienceStrategy()) {
-  case ResilienceStrategy::Resilient:
-    return true;
-  case ResilienceStrategy::Default:
-    return false;
-  }
+  return getDeclContext()->getParentModule()->isResilient();
 }
 
 Optional<ArrayRef<Requirement>>
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 5c4e593..59226e5 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -3110,9 +3110,7 @@
 #ifndef NDEBUG
   auto *currentClass = getConcreteTypeForSuperclassTraversing(this)
       ->getClassOrBoundGenericClass();
-  while (currentClass && currentClass != baseClass)
-    currentClass = currentClass->getSuperclassDecl();
-  assert(currentClass == baseClass &&
+  assert(baseClass->isSuperclassOf(currentClass) &&
          "no inheritance relationship between given classes");
 #endif
 
@@ -3950,13 +3948,9 @@
 }
 
 static ReferenceCounting getClassReferenceCounting(ClassDecl *theClass) {
-  while (auto superclass = theClass->getSuperclassDecl()) {
-    theClass = superclass;
-  }
-
-  return theClass->hasClangNode()
-           ? ReferenceCounting::ObjC
-           : ReferenceCounting::Native;
+  return (theClass->checkAncestry(AncestryFlags::ClangImported)
+          ? ReferenceCounting::ObjC
+          : ReferenceCounting::Native);
 }
 
 ReferenceCounting TypeBase::getReferenceCounting() {
diff --git a/lib/Demangling/Demangler.cpp b/lib/Demangling/Demangler.cpp
index 6c32412..57487d4 100644
--- a/lib/Demangling/Demangler.cpp
+++ b/lib/Demangling/Demangler.cpp
@@ -1809,6 +1809,10 @@
       return createWithPoppedType(Node::Kind::MethodLookupFunction);
     case 'U':
       return createWithPoppedType(Node::Kind::ObjCMetadataUpdateFunction);
+    case 's':
+      return createWithPoppedType(Node::Kind::ObjCResilientClassStub);
+    case 't':
+      return createWithPoppedType(Node::Kind::FullObjCResilientClassStub);
     case 'B':
       return createWithChild(Node::Kind::ReflectionMetadataBuiltinDescriptor,
                              popNode(Node::Kind::Type));
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index 6878925..8a2babc 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -353,6 +353,7 @@
     case Node::Kind::Extension:
     case Node::Kind::EnumCase:
     case Node::Kind::FieldOffset:
+    case Node::Kind::FullObjCResilientClassStub:
     case Node::Kind::FullTypeMetadata:
     case Node::Kind::Function:
     case Node::Kind::FunctionSignatureSpecialization:
@@ -411,6 +412,7 @@
     case Node::Kind::ObjCAttribute:
     case Node::Kind::ObjCBlock:
     case Node::Kind::ObjCMetadataUpdateFunction:
+    case Node::Kind::ObjCResilientClassStub:
     case Node::Kind::Owned:
     case Node::Kind::OwningAddressor:
     case Node::Kind::OwningMutableAddressor:
@@ -981,6 +983,14 @@
     Printer << "ObjC metadata update function for ";
     print(Node->getChild(0));
     return nullptr;
+  case Node::Kind::ObjCResilientClassStub:
+    Printer << "ObjC resilient class stub for ";
+    print(Node->getChild(0));
+    return nullptr;
+  case Node::Kind::FullObjCResilientClassStub:
+    Printer << "full ObjC resilient class stub for ";
+    print(Node->getChild(0));
+    return nullptr;
   case Node::Kind::OutlinedBridgedMethod:
     Printer << "outlined bridged method (" << Node->getText() << ") of ";
     return nullptr;
diff --git a/lib/Demangling/OldRemangler.cpp b/lib/Demangling/OldRemangler.cpp
index aca002f..58f07ae 100644
--- a/lib/Demangling/OldRemangler.cpp
+++ b/lib/Demangling/OldRemangler.cpp
@@ -1807,6 +1807,14 @@
   Buffer << "<objc-metadata-update-function>";
 }
 
+void Remangler::mangleObjCResilientClassStub(Node *node) {
+  Buffer << "<objc-resilient-class-stub>";
+}
+
+void Remangler::mangleFullObjCResilientClassStub(Node *node) {
+  Buffer << "<full-objc-resilient-class-stub>";
+}
+
 void Remangler::mangleEmptyList(Node *node) {
   Buffer << "<empty>";
 }
diff --git a/lib/Demangling/Remangler.cpp b/lib/Demangling/Remangler.cpp
index 6f11709..d2cdefc 100644
--- a/lib/Demangling/Remangler.cpp
+++ b/lib/Demangling/Remangler.cpp
@@ -2135,6 +2135,16 @@
   Buffer << "MU";
 }
 
+void Remangler::mangleObjCResilientClassStub(Node *node) {
+  mangleSingleChildNode(node);
+  Buffer << "Ms";
+}
+
+void Remangler::mangleFullObjCResilientClassStub(Node *node) {
+  mangleSingleChildNode(node);
+  Buffer << "Mt";
+}
+
 void Remangler::mangleThrowsAnnotation(Node *node) {
   Buffer << 'K';
 }
diff --git a/lib/Driver/UnixToolChains.cpp b/lib/Driver/UnixToolChains.cpp
index 06ae09c..d4a8286 100644
--- a/lib/Driver/UnixToolChains.cpp
+++ b/lib/Driver/UnixToolChains.cpp
@@ -22,6 +22,7 @@
 #include "swift/Driver/Driver.h"
 #include "swift/Driver/Job.h"
 #include "swift/Option/Options.h"
+#include "swift/Option/SanitizerOptions.h"
 #include "clang/Basic/Version.h"
 #include "clang/Driver/Util.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -37,27 +38,6 @@
 using namespace swift::driver;
 using namespace llvm::opt;
 
-static void addLinkSanitizerLibArgsForLinux(const ArgList &Args,
-                                            ArgStringList &Arguments,
-                                            StringRef Sanitizer,
-                                            const ToolChain &TC) {
-  TC.addLinkRuntimeLib(Args, Arguments, TC.sanitizerRuntimeLibName(Sanitizer));
-
-  // Code taken from
-  // https://github.com/apple/swift-clang/blob/ab3cbe7/lib/Driver/Tools.cpp#L3264-L3276
-  // There's no libpthread or librt on RTEMS.
-  if (TC.getTriple().getOS() != llvm::Triple::RTEMS) {
-    Arguments.push_back("-lpthread");
-    Arguments.push_back("-lrt");
-  }
-  Arguments.push_back("-lm");
-
-  // There's no libdl on FreeBSD or RTEMS.
-  if (TC.getTriple().getOS() != llvm::Triple::FreeBSD &&
-      TC.getTriple().getOS() != llvm::Triple::RTEMS)
-    Arguments.push_back("-ldl");
-}
-
 std::string
 toolchains::GenericUnix::sanitizerRuntimeLibName(StringRef Sanitizer,
                                                  bool shared) const {
@@ -293,23 +273,11 @@
   Arguments.push_back(
       context.Args.MakeArgString("--target=" + getTriple().str()));
 
-  if (getTriple().getOS() == llvm::Triple::Linux) {
-    // Make sure we only add SanitizerLibs for executables
-    if (job.getKind() == LinkKind::Executable) {
-      if (context.OI.SelectedSanitizers & SanitizerKind::Address)
-        addLinkSanitizerLibArgsForLinux(context.Args, Arguments, "asan", *this);
-
-      if (context.OI.SelectedSanitizers & SanitizerKind::Thread)
-        addLinkSanitizerLibArgsForLinux(context.Args, Arguments, "tsan", *this);
-
-      if (context.OI.SelectedSanitizers & SanitizerKind::Undefined)
-        addLinkSanitizerLibArgsForLinux(context.Args, Arguments, "ubsan", *this);
-
-      if (context.OI.SelectedSanitizers & SanitizerKind::Fuzzer)
-        addLinkRuntimeLib(context.Args, Arguments,
-                          sanitizerRuntimeLibName("fuzzer"));
-
-    }
+  // Delegate to Clang for sanitizers. It will figure out the correct linker
+  // options.
+  if (job.getKind() == LinkKind::Executable && context.OI.SelectedSanitizers) {
+    Arguments.push_back(context.Args.MakeArgString(
+        "-fsanitize=" + getSanitizerList(context.OI.SelectedSanitizers)));
   }
 
   if (context.Args.hasArg(options::OPT_profile_generate)) {
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 6d00f96..0193fd6 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -450,6 +450,9 @@
   Opts.DisableConstraintSolverPerformanceHacks |=
       Args.hasArg(OPT_disable_constraint_solver_performance_hacks);
 
+  Opts.EnableObjCResilientClassStubs =
+      Args.hasArg(OPT_enable_objc_resilient_class_stubs);
+
   // Must be processed after any other language options that could affect
   // platform conditions.
   bool UnsupportedOS, UnsupportedArch;
diff --git a/lib/IRGen/GenCast.cpp b/lib/IRGen/GenCast.cpp
index 7a4185c..917a2d8 100644
--- a/lib/IRGen/GenCast.cpp
+++ b/lib/IRGen/GenCast.cpp
@@ -107,7 +107,8 @@
   llvm::Value *targetMetadata;
   if ((targetMetadata =
            tryEmitConstantHeapMetadataRef(IGF.IGM, toType.getASTType(),
-                                          /*allowUninitialized*/ false))) {
+                                          /*allowUninitialized*/ false,
+                                          /*allowStub*/ false))) {
     // ok
   } else {
     targetMetadata
diff --git a/lib/IRGen/GenClass.cpp b/lib/IRGen/GenClass.cpp
index b18eafd..8c83508 100644
--- a/lib/IRGen/GenClass.cpp
+++ b/lib/IRGen/GenClass.cpp
@@ -1207,7 +1207,9 @@
       else {
         auto type = getSelfType(getClass()).getASTType();
         llvm::Constant *metadata =
-          tryEmitConstantHeapMetadataRef(IGM, type, /*allowUninit*/ true);
+          tryEmitConstantHeapMetadataRef(IGM, type,
+                                         /*allowUninit*/ true,
+                                         /*allowStub*/ true);
         assert(metadata &&
                "extended objc class doesn't have constant metadata?");
         fields.add(metadata);
@@ -2021,9 +2023,9 @@
 } // end anonymous namespace
 
 static llvm::Function *emitObjCMetadataUpdateFunction(IRGenModule &IGM,
-                                                      ClassDecl *cls) {
+                                                      ClassDecl *D) {
   llvm::Function *f =
-    IGM.getAddrOfObjCMetadataUpdateFunction(cls, ForDefinition);
+    IGM.getAddrOfObjCMetadataUpdateFunction(D, ForDefinition);
   f->setAttributes(IGM.constructInitialAttributes());
 
   IRGenFunction IGF(IGM, f);
@@ -2037,7 +2039,7 @@
 
   // Just directly call our metadata accessor. This should actually
   // return the same metadata; the Objective-C runtime enforces this.
-  auto type = cls->getDeclaredType()->getCanonicalType();
+  auto type = D->getDeclaredType()->getCanonicalType();
   auto *metadata = IGF.emitTypeMetadataRef(type,
                                            MetadataState::Complete)
     .getMetadata();
@@ -2048,6 +2050,48 @@
   return f;
 }
 
+/// We emit Objective-C class stubs for non-generic classes with resilient
+/// ancestry. This lets us attach categories to the class even though it
+/// does not have statically-emitted metadata.
+bool irgen::hasObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D) {
+  assert(IGM.getClassMetadataStrategy(D) == ClassMetadataStrategy::Resilient);
+  return (!D->isGenericContext() &&
+          IGM.ObjCInterop &&
+          IGM.Context.LangOpts.EnableObjCResilientClassStubs);
+}
+
+void irgen::emitObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D) {
+  assert(hasObjCResilientClassStub(IGM, D));
+
+  llvm::Constant *fields[] = {
+    llvm::ConstantInt::get(IGM.SizeTy, 0), // reserved
+    llvm::ConstantInt::get(IGM.SizeTy, 1), // isa
+    IGM.getAddrOfObjCMetadataUpdateFunction(D, NotForDefinition)
+  };
+  auto init = llvm::ConstantStruct::get(IGM.ObjCFullResilientClassStubTy,
+                                        makeArrayRef(fields));
+
+  // Define the full stub. This is a private symbol.
+  auto fullObjCStub = cast<llvm::GlobalVariable>(
+      IGM.getAddrOfObjCResilientClassStub(D, ForDefinition,
+                                          TypeMetadataAddress::FullMetadata));
+  fullObjCStub->setInitializer(init);
+
+  // Emit the metadata update function referenced above.
+  emitObjCMetadataUpdateFunction(IGM, D);
+
+  // Apply the offset.
+  auto *objcStub = llvm::ConstantExpr::getBitCast(fullObjCStub, IGM.Int8PtrTy);
+  objcStub = llvm::ConstantExpr::getInBoundsGetElementPtr(
+      IGM.Int8Ty, objcStub, IGM.getSize(IGM.getPointerSize()));
+  objcStub = llvm::ConstantExpr::getPointerCast(objcStub,
+      IGM.ObjCResilientClassStubTy->getPointerTo());
+
+  auto entity = LinkEntity::forObjCResilientClassStub(
+      D, TypeMetadataAddress::AddressPoint);
+  IGM.defineAlias(entity, objcStub);
+}
+
 /// Emit the private data (RO-data) associated with a class.
 llvm::Constant *irgen::emitClassPrivateData(IRGenModule &IGM,
                                             ClassDecl *cls) {
diff --git a/lib/IRGen/GenClass.h b/lib/IRGen/GenClass.h
index 5c357a9..b7fdf7f 100644
--- a/lib/IRGen/GenClass.h
+++ b/lib/IRGen/GenClass.h
@@ -170,6 +170,14 @@
                                     llvm::Value *selfValue,
                                     llvm::Value *metadataValue);
 
+  /// We emit Objective-C class stubs for non-generic classes with resilient
+  /// ancestry. This lets us attach categories to the class even though it
+  /// does not have statically-emitted metadata.
+  bool hasObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D);
+
+  /// Emit a resilient class stub.
+  void emitObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D);
+
   /// Emit the constant fragile offset of the given property inside an instance
   /// of the class.
   llvm::Constant *
diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp
index 08f1428..3297fde 100644
--- a/lib/IRGen/GenDecl.cpp
+++ b/lib/IRGen/GenDecl.cpp
@@ -2960,7 +2960,7 @@
 llvm::Function *
 IRGenModule::getAddrOfObjCMetadataUpdateFunction(ClassDecl *classDecl,
                                                  ForDefinition_t forDefinition) {
-  IRGen.noteUseOfTypeMetadata(classDecl);
+  assert(ObjCInterop);
 
   LinkEntity entity = LinkEntity::forObjCMetadataUpdateFunction(classDecl);
   llvm::Function *&entry = GlobalFuncs[entity];
@@ -2970,14 +2970,25 @@
   }
 
   // Class _Nullable callback(Class _Nonnull cls, void * _Nullable arg);
-  llvm::Type *params[] = { ObjCClassPtrTy, Int8PtrTy };
-  auto fnType = llvm::FunctionType::get(ObjCClassPtrTy, params, false);
-  Signature signature(fnType, llvm::AttributeList(), DefaultCC);
+  Signature signature(ObjCUpdateCallbackTy, llvm::AttributeList(), DefaultCC);
   LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
   entry = createFunction(*this, link, signature);
   return entry;
 }
 
+/// Fetch the declaration of an Objective-C resilient class stub.
+llvm::Constant *
+IRGenModule::getAddrOfObjCResilientClassStub(ClassDecl *classDecl,
+                                             ForDefinition_t forDefinition,
+                                             TypeMetadataAddress addr) {
+  assert(ObjCInterop);
+  assert(getClassMetadataStrategy(classDecl) ==
+         ClassMetadataStrategy::Resilient);
+
+  LinkEntity entity = LinkEntity::forObjCResilientClassStub(classDecl, addr);
+  return getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
+}
+
 /// Fetch the type metadata access function for a non-generic type.
 llvm::Function *
 IRGenModule::getAddrOfTypeMetadataAccessFunction(CanType type,
diff --git a/lib/IRGen/GenHeap.cpp b/lib/IRGen/GenHeap.cpp
index 031fea3..9d6f62d 100644
--- a/lib/IRGen/GenHeap.cpp
+++ b/lib/IRGen/GenHeap.cpp
@@ -1883,14 +1883,6 @@
   llvm_unreachable("unhandled ISA encoding");
 }
 
-static ClassDecl *getRootClass(ClassDecl *theClass) {
-  while (theClass->hasSuperclass()) {
-    theClass = theClass->getSuperclassDecl();
-    assert(theClass && "base type of class not a class?");
-  }
-  return theClass;
-}
-
 /// What isa encoding mechanism does a type have?
 IsaEncoding irgen::getIsaEncodingForType(IRGenModule &IGM,
                                          CanType type) {
@@ -1900,7 +1892,7 @@
 
   if (auto theClass = type->getClassOrBoundGenericClass()) {
     // We can access the isas of pure Swift classes directly.
-    if (getRootClass(theClass)->hasKnownSwiftImplementation())
+    if (!theClass->checkAncestry(AncestryFlags::ClangImported))
       return IsaEncoding::Pointer;
     // For ObjC or mixed classes, we need to use object_getClass.
     return IsaEncoding::ObjC;
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index c63f2a5..56d573e 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -1631,6 +1631,7 @@
 
       // union {
       //   uint32_t MetadataPositiveSizeInWords;
+      //   ExtraClassContextFlags ExtraClassFlags;
       // };
       if (!MetadataLayout) {
         // FIXME: do something meaningful for foreign classes?
@@ -1639,7 +1640,10 @@
         B.addInt32(MetadataLayout->getSize().getOffsetToEnd()
                      / IGM.getPointerSize());
       } else {
-        B.addInt32(0); // currently unused
+        ExtraClassDescriptorFlags flags;
+        if (hasObjCResilientClassStub(IGM, getType()))
+          flags.setObjCResilientClassStub(true);
+        B.addInt32(flags.getOpaqueValue());
       }
 
       // uint32_t NumImmediateMembers;
@@ -2481,7 +2485,8 @@
       case ClassMetadataStrategy::Update:
       case ClassMetadataStrategy::FixedOrUpdate:
       case ClassMetadataStrategy::Fixed: {
-        auto type = (Target->checkObjCAncestry() != ObjCClassKind::NonObjC
+        // FIXME: Should this check HasImported instead?
+        auto type = (Target->checkAncestry(AncestryFlags::ObjC)
                     ? IGM.Context.TheUnknownObjectType
                     : IGM.Context.TheNativeObjectType);
         auto wtable = IGM.getAddrOfValueWitnessTable(type);
@@ -2551,7 +2556,8 @@
       Type type = Target->mapTypeIntoContext(Target->getSuperclass());
       auto *metadata = tryEmitConstantHeapMetadataRef(
           IGM, type->getCanonicalType(),
-          /*allowUninit*/ false);
+          /*allowUninit*/ false,
+          /*allowStub*/ false);
       assert(metadata != nullptr);
       B.add(metadata);
     }
@@ -3043,23 +3049,17 @@
 /// references, we emit the symbol as a global asm block.
 static void emitObjCClassSymbol(IRGenModule &IGM,
                                 ClassDecl *classDecl,
-                                llvm::GlobalValue *metadata) {
-  llvm::SmallString<32> classSymbol;
-  LinkEntity::forObjCClass(classDecl).mangle(classSymbol);
-  
-  // Create the alias.
-  auto *metadataTy = cast<llvm::PointerType>(metadata->getType());
+                                llvm::Constant *metadata) {
+  auto entity = LinkEntity::forObjCClass(classDecl);
+  LinkInfo link = LinkInfo::get(IGM, entity, ForDefinition);
 
   // Create the alias.
-  auto *alias = llvm::GlobalAlias::create(metadataTy->getElementType(),
-                                          metadataTy->getAddressSpace(),
-                                          metadata->getLinkage(),
-                                          classSymbol.str(), metadata,
-                                          IGM.getModule());
-  alias->setVisibility(metadata->getVisibility());
-
-  if (IGM.useDllStorage())
-    alias->setDLLStorageClass(metadata->getDLLStorageClass());
+  auto *ptrTy = cast<llvm::PointerType>(metadata->getType());
+  auto *alias = llvm::GlobalAlias::create(
+      ptrTy->getElementType(), ptrTy->getAddressSpace(), link.getLinkage(),
+      link.getName(), metadata, &IGM.Module);
+  ApplyIRLinkage({link.getLinkage(), link.getVisibility(), link.getDLLStorage()})
+      .to(alias);
 }
 
 /// Emit the type metadata or metadata template for a class.
@@ -3142,6 +3142,26 @@
   if (IGM.ObjCInterop) {
     switch (strategy) {
     case ClassMetadataStrategy::Resilient:
+      // Even non-@objc classes can have Objective-C categories attached, so
+      // we always emit a resilient class stub as long as -enable-objc-interop
+      // is set.
+      if (hasObjCResilientClassStub(IGM, classDecl)) {
+        emitObjCResilientClassStub(IGM, classDecl);
+
+        if (classDecl->isObjC()) {
+          auto *stub = IGM.getAddrOfObjCResilientClassStub(
+              classDecl, NotForDefinition,
+              TypeMetadataAddress::AddressPoint);
+          emitObjCClassSymbol(IGM, classDecl, stub);
+
+          // @_objc_non_lazy_realization is only for use by the standard
+          // library, and we cannot support it with Objective-C class
+          // stubs (which there are none of in the standard library).
+          assert(!classDecl->getAttrs().hasAttribute<ObjCNonLazyRealizationAttr>());
+          IGM.addObjCClass(stub, /*eagerInitialization=*/false);
+        }
+      }
+      break;
     case ClassMetadataStrategy::Singleton:
       break;
     
diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h
index 4aa697b..f764c39 100644
--- a/lib/IRGen/IRGenMangler.h
+++ b/lib/IRGen/IRGenMangler.h
@@ -107,6 +107,14 @@
     return mangleNominalTypeSymbol(Decl, "MU");
   }
 
+  std::string mangleObjCResilientClassStub(const ClassDecl *Decl) {
+    return mangleNominalTypeSymbol(Decl, "Ms");
+  }
+
+  std::string mangleFullObjCResilientClassStub(const ClassDecl *Decl) {
+    return mangleNominalTypeSymbol(Decl, "Mt");
+  }
+
   std::string mangleClassMetadataBaseOffset(const ClassDecl *Decl) {
     return mangleNominalTypeSymbol(Decl, "Mo");
   }
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 0d6f7f7..89b4c63 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -430,7 +430,24 @@
                     // point too.
   };
   ObjCBlockStructTy->setBody(objcBlockElts);
-  
+
+  // Class _Nullable callback(Class _Nonnull cls, void * _Nullable arg);
+  llvm::Type *params[] = { ObjCClassPtrTy, Int8PtrTy };
+  ObjCUpdateCallbackTy = llvm::FunctionType::get(ObjCClassPtrTy, params, false);
+
+  // The full class stub structure, including a word before the address point.
+  ObjCFullResilientClassStubTy = createStructType(*this, "objc_full_class_stub", {
+    SizeTy, // zero padding to appease the linker
+    SizeTy, // isa pointer -- always 1
+    ObjCUpdateCallbackTy->getPointerTo() // the update callback
+  });
+
+  // What we actually export.
+  ObjCResilientClassStubTy = createStructType(*this, "objc_class_stub", {
+    SizeTy, // isa pointer -- always 1
+    ObjCUpdateCallbackTy->getPointerTo() // the update callback
+  });
+
   auto ErrorStructTy = llvm::StructType::create(LLVMContext, "swift.error");
   // ErrorStruct is currently opaque to the compiler.
   ErrorPtrTy = ErrorStructTy->getPointerTo(DefaultAS);
diff --git a/lib/IRGen/IRGenModule.h b/lib/IRGen/IRGenModule.h
index 9a65012..97c84fa 100644
--- a/lib/IRGen/IRGenModule.h
+++ b/lib/IRGen/IRGenModule.h
@@ -142,6 +142,7 @@
   struct SymbolicMangling;
   class TypeConverter;
   class TypeInfo;
+  enum class TypeMetadataAddress;
   enum class ValueWitness : unsigned;
   enum class ClassMetadataStrategy;
 
@@ -577,6 +578,9 @@
   llvm::PointerType *ObjCSuperPtrTy;   /// %objc_super*
   llvm::StructType *ObjCBlockStructTy; /// %objc_block
   llvm::PointerType *ObjCBlockPtrTy;   /// %objc_block*
+  llvm::FunctionType *ObjCUpdateCallbackTy;
+  llvm::StructType *ObjCFullResilientClassStubTy;   /// %objc_full_class_stub
+  llvm::StructType *ObjCResilientClassStubTy;   /// %objc_class_stub
   llvm::StructType *ProtocolRecordTy;
   llvm::PointerType *ProtocolRecordPtrTy;
   llvm::StructType *ProtocolConformanceDescriptorTy;
@@ -1331,6 +1335,10 @@
   llvm::Function *getAddrOfObjCMetadataUpdateFunction(ClassDecl *D,
                                                       ForDefinition_t forDefinition);
 
+  llvm::Constant *getAddrOfObjCResilientClassStub(ClassDecl *D,
+                                                  ForDefinition_t forDefinition,
+                                                  TypeMetadataAddress addr);
+
   llvm::Function *
   getAddrOfSILFunction(SILFunction *f, ForDefinition_t forDefinition,
                        bool isDynamicallyReplaceableImplementation = false,
diff --git a/lib/IRGen/Linking.cpp b/lib/IRGen/Linking.cpp
index 5c337dc..4f5cb23 100644
--- a/lib/IRGen/Linking.cpp
+++ b/lib/IRGen/Linking.cpp
@@ -182,6 +182,15 @@
   case Kind::ObjCMetadataUpdateFunction:
     return mangler.mangleObjCMetadataUpdateFunction(cast<ClassDecl>(getDecl()));
 
+  case Kind::ObjCResilientClassStub:
+    switch (getMetadataAddress()) {
+    case TypeMetadataAddress::FullMetadata:
+      return mangler.mangleFullObjCResilientClassStub(cast<ClassDecl>(getDecl()));
+    case TypeMetadataAddress::AddressPoint:
+      return mangler.mangleObjCResilientClassStub(cast<ClassDecl>(getDecl()));
+    }
+    llvm_unreachable("invalid metadata address");
+
   case Kind::ClassMetadataBaseOffset:               // class metadata base offset
     return mangler.mangleClassMetadataBaseOffset(cast<ClassDecl>(getDecl()));
 
@@ -507,6 +516,20 @@
     return SILLinkage::PublicExternal;
 
 
+  case Kind::ObjCResilientClassStub: {
+    switch (getMetadataAddress()) {
+    case TypeMetadataAddress::FullMetadata:
+      // The full class stub object is private to the containing module.
+      return SILLinkage::Private;
+    case TypeMetadataAddress::AddressPoint: {
+      auto *classDecl = cast<ClassDecl>(getDecl());
+      return getSILLinkage(getDeclLinkage(classDecl),
+                           forDefinition);
+    }
+    }
+    llvm_unreachable("invalid metadata address");
+  }
+
   case Kind::EnumCase: {
     auto *elementDecl = cast<EnumElementDecl>(getDecl());
     return getSILLinkage(getDeclLinkage(elementDecl), forDefinition);
@@ -740,6 +763,7 @@
   }
   
   case Kind::ObjCMetadataUpdateFunction:
+  case Kind::ObjCResilientClassStub:
   case Kind::ValueWitness:
   case Kind::TypeMetadataAccessFunction:
   case Kind::TypeMetadataLazyCacheVariable:
@@ -799,6 +823,7 @@
     case TypeMetadataAddress::AddressPoint:
       return IGM.TypeMetadataStructTy;
     }
+    llvm_unreachable("invalid metadata address");
     
   case Kind::TypeMetadataPattern:
     // TODO: Use a real type?
@@ -840,6 +865,16 @@
     return IGM.DynamicReplacementKeyTy;
   case Kind::DynamicallyReplaceableFunctionVariable:
     return IGM.DynamicReplacementLinkEntryTy;
+  case Kind::ObjCMetadataUpdateFunction:
+    return IGM.ObjCUpdateCallbackTy;
+  case Kind::ObjCResilientClassStub:
+    switch (getMetadataAddress()) {
+    case TypeMetadataAddress::FullMetadata:
+      return IGM.ObjCFullResilientClassStubTy;
+    case TypeMetadataAddress::AddressPoint:
+      return IGM.ObjCResilientClassStubTy;
+    }
+    llvm_unreachable("invalid metadata address");
   default:
     llvm_unreachable("declaration LLVM type not specified");
   }
@@ -883,6 +918,7 @@
   case Kind::SwiftMetaclassStub:
   case Kind::DynamicallyReplaceableFunctionVariable:
   case Kind::DynamicallyReplaceableFunctionKey:
+  case Kind::ObjCResilientClassStub:
     return IGM.getPointerAlignment();
   case Kind::SILFunction:
     return Alignment(1);
@@ -947,7 +983,6 @@
   case Kind::ObjCClassRef:
   case Kind::ObjCMetaclass:
   case Kind::SwiftMetaclassStub:
-  case Kind::ObjCMetadataUpdateFunction:
   case Kind::ClassMetadataBaseOffset:
   case Kind::PropertyDescriptor:
   case Kind::NominalTypeDescriptor:
@@ -966,6 +1001,8 @@
                                    ->isWeakImported(module, context);
 
   // TODO: Revisit some of the below, for weak conformances.
+  case Kind::ObjCMetadataUpdateFunction:
+  case Kind::ObjCResilientClassStub:
   case Kind::TypeMetadataPattern:
   case Kind::TypeMetadataInstantiationCache:
   case Kind::TypeMetadataInstantiationFunction:
@@ -1020,6 +1057,7 @@
   case Kind::ObjCMetaclass:
   case Kind::SwiftMetaclassStub:
   case Kind::ObjCMetadataUpdateFunction:
+  case Kind::ObjCResilientClassStub:
   case Kind::ClassMetadataBaseOffset:
   case Kind::PropertyDescriptor:
   case Kind::NominalTypeDescriptor:
diff --git a/lib/IRGen/MetadataRequest.cpp b/lib/IRGen/MetadataRequest.cpp
index 8cd59c5..badab24 100644
--- a/lib/IRGen/MetadataRequest.cpp
+++ b/lib/IRGen/MetadataRequest.cpp
@@ -508,14 +508,20 @@
 /// Attempts to return a constant heap metadata reference for a
 /// class type.  This is generally only valid for specific kinds of
 /// ObjC reference, like superclasses or category references.
-llvm::Constant *irgen::tryEmitConstantHeapMetadataRef(IRGenModule &IGM,
-                                                      CanType type,
-                                              bool allowDynamicUninitialized) {
+llvm::Constant *
+irgen::tryEmitConstantHeapMetadataRef(IRGenModule &IGM,
+                                      CanType type,
+                                      bool allowDynamicUninitialized,
+                                      bool allowStub) {
   auto theDecl = type->getClassOrBoundGenericClass();
   assert(theDecl && "emitting constant heap metadata ref for non-class type?");
 
   switch (IGM.getClassMetadataStrategy(theDecl)) {
   case ClassMetadataStrategy::Resilient:
+    if (allowStub && IGM.Context.LangOpts.EnableObjCResilientClassStubs) {
+      return IGM.getAddrOfObjCResilientClassStub(theDecl, NotForDefinition,
+                                            TypeMetadataAddress::AddressPoint);
+    }
     return nullptr;
 
   case ClassMetadataStrategy::Singleton:
diff --git a/lib/IRGen/MetadataRequest.h b/lib/IRGen/MetadataRequest.h
index b31a47a..cfec1da 100644
--- a/lib/IRGen/MetadataRequest.h
+++ b/lib/IRGen/MetadataRequest.h
@@ -592,7 +592,8 @@
 /// by a constant.
 llvm::Constant *tryEmitConstantHeapMetadataRef(IRGenModule &IGM,
                                                CanType type,
-                                               bool allowUninitialized);
+                                               bool allowUninitialized,
+                                               bool allowStub);
 
 enum class MetadataValueType { ObjCClass, TypeMetadata };
 
diff --git a/lib/Option/SanitizerOptions.cpp b/lib/Option/SanitizerOptions.cpp
index 5cd32bf..7e59996 100644
--- a/lib/Option/SanitizerOptions.cpp
+++ b/lib/Option/SanitizerOptions.cpp
@@ -188,3 +188,13 @@
 
   return sanitizerSet;
 }
+
+std::string swift::getSanitizerList(const OptionSet<SanitizerKind> &Set) {
+  std::string list;
+  if (Set & SanitizerKind::Address) list += "address,";
+  if (Set & SanitizerKind::Thread) list += "thread,";
+  if (Set & SanitizerKind::Fuzzer) list += "fuzzer,";
+  if (Set & SanitizerKind::Undefined) list += "undefined,";
+  if (!list.empty()) list.pop_back(); // Remove last comma
+  return list;
+}
diff --git a/lib/PrintAsObjC/PrintAsObjC.cpp b/lib/PrintAsObjC/PrintAsObjC.cpp
index 4408a50..c13d383 100644
--- a/lib/PrintAsObjC/PrintAsObjC.cpp
+++ b/lib/PrintAsObjC/PrintAsObjC.cpp
@@ -322,14 +322,22 @@
   void visitClassDecl(ClassDecl *CD) {
     printDocumentationComment(CD);
 
+    bool hasResilientAncestry =
+      CD->checkAncestry().contains(AncestryFlags::ResilientOther);
+    if (hasResilientAncestry) {
+      os << "SWIFT_RESILIENT_CLASS";
+    } else {
+      os << "SWIFT_CLASS";
+    }
+
     StringRef customName = getNameForObjC(CD, CustomNamesOnly);
     if (customName.empty()) {
       llvm::SmallString<32> scratch;
-      os << "SWIFT_CLASS(\"" << CD->getObjCRuntimeName(scratch) << "\")";
+      os << "(\"" << CD->getObjCRuntimeName(scratch) << "\")";
       printAvailability(CD);
       os << "\n@interface " << CD->getName();
     } else {
-      os << "SWIFT_CLASS_NAMED(\"" << CD->getName() << "\")";
+      os << "_NAMED(\"" << CD->getName() << "\")";
       printAvailability(CD);
       os << "\n@interface " << customName;
     }
@@ -2640,6 +2648,20 @@
              "SWIFT_CLASS_EXTRA\n"
            "# endif\n"
            "#endif\n"
+           "#if !defined(SWIFT_RESILIENT_CLASS)\n"
+           "# if __has_attribute(objc_class_stub)\n"
+           "#  define SWIFT_RESILIENT_CLASS(SWIFT_NAME) SWIFT_CLASS(SWIFT_NAME) "
+             "__attribute__((objc_class_stub))\n"
+           "#  define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) "
+             "__attribute__((objc_class_stub)) "
+             "SWIFT_CLASS_NAMED(SWIFT_NAME)\n"
+           "# else\n"
+           "#  define SWIFT_RESILIENT_CLASS(SWIFT_NAME) "
+             "SWIFT_CLASS(SWIFT_NAME)\n"
+           "#  define SWIFT_RESILIENT_CLASS_NAMED(SWIFT_NAME) "
+             "SWIFT_CLASS_NAMED(SWIFT_NAME)\n"
+           "# endif\n"
+           "#endif\n"
            "\n"
            "#if !defined(SWIFT_PROTOCOL)\n"
            "# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) "
diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp
index ef5cad9..25ecc64 100644
--- a/lib/SIL/DynamicCasts.cpp
+++ b/lib/SIL/DynamicCasts.cpp
@@ -56,14 +56,14 @@
   return !M->getASTContext().getBridgedToObjC(M, T);
 }
 
-static bool canClassOrSuperclassesHaveExtensions(ClassDecl *CD,
-                                                 bool isWholeModuleOpts) {
+static bool canClassOrSuperclassesHaveUnknownSubclasses(ClassDecl *CD,
+                                                      bool isWholeModuleOpts) {
   while (CD) {
-    // Open classes can always be extended
+    // Open classes can always have unknown subclasses.
     if (CD->getEffectiveAccess() == AccessLevel::Open)
       return true;
 
-    // Internal and public classes can be extended, if we are not in
+    // Internal and public classes may have unknown subclasses if we are not in
     // whole-module-optimization mode.
     if (CD->getEffectiveAccess() >= AccessLevel::Internal &&
         !isWholeModuleOpts)
@@ -110,11 +110,9 @@
   }
 
   // If it is a class and it can be proven that this class and its
-  // superclasses cannot be extended, then it is safe to proceed.
-  // No need to check this for structs, as they do not have any
-  // superclasses.
+  // superclasses cannot have unknown subclasses, then it is safe to proceed.
   if (auto *CD = source.getClassOrBoundGenericClass()) {
-    if (canClassOrSuperclassesHaveExtensions(CD, isWholeModuleOpts))
+    if (canClassOrSuperclassesHaveUnknownSubclasses(CD, isWholeModuleOpts))
       return DynamicCastFeasibility::MaySucceed;
     // Derived types may conform to the protocol.
     if (!CD->isFinal()) {
@@ -555,22 +553,13 @@
         if (targetClass->usesObjCGenericsModel()) {
           // If both classes are ObjC generics, the cast may succeed if the
           // classes are related, irrespective of their generic parameters.
-          auto isDeclSuperclass = [&](ClassDecl *proposedSuper,
-                                      ClassDecl *proposedSub) -> bool {
-            do {
-              if (proposedSuper == proposedSub)
-                return true;
-            } while ((proposedSub = proposedSub->getSuperclassDecl()));
-            
-            return false;
-          };
-          
-          if (isDeclSuperclass(sourceClass, targetClass))
+
+          if (sourceClass->isSuperclassOf(targetClass))
             return DynamicCastFeasibility::MaySucceed;
           
-          if (isDeclSuperclass(targetClass, sourceClass)) {
+          if (targetClass->isSuperclassOf(sourceClass))
             return DynamicCastFeasibility::WillSucceed;
-          }          
+
           return DynamicCastFeasibility::WillFail;
         }
       }
diff --git a/lib/SIL/SILDeclRef.cpp b/lib/SIL/SILDeclRef.cpp
index 4d396bd..13850e2 100644
--- a/lib/SIL/SILDeclRef.cpp
+++ b/lib/SIL/SILDeclRef.cpp
@@ -330,8 +330,7 @@
     d = cast<NominalTypeDecl>(d->getDeclContext());
 
     // FIXME: This should always be true.
-    if (d->getDeclContext()->getParentModule()->getResilienceStrategy() ==
-        ResilienceStrategy::Resilient)
+    if (d->getModuleContext()->isResilient())
       limit = Limit::NeverPublic;
   }
 
diff --git a/lib/SIL/SILVerifier.cpp b/lib/SIL/SILVerifier.cpp
index cd18ab4..064e45c 100644
--- a/lib/SIL/SILVerifier.cpp
+++ b/lib/SIL/SILVerifier.cpp
@@ -2291,10 +2291,8 @@
         ->getInstanceType()->getClassOrBoundGenericClass();
     require(class2,
             "Second operand of dealloc_partial_ref must be a class metatype");
-    while (class1 != class2) {
-      class1 = class1->getSuperclassDecl();
-      require(class1, "First operand not superclass of second instance type");
-    }
+    require(class2->isSuperclassOf(class1),
+            "First operand not superclass of second instance type");
   }
 
   void checkAllocBoxInst(AllocBoxInst *AI) {
@@ -4981,13 +4979,8 @@
     assert(theClass && "vtable entry must refer to a class member");
 
     // The class context must be the vtable's class, or a superclass thereof.
-    auto c = getClass();
-    do {
-      if (c == theClass)
-        break;
-      c = c->getSuperclassDecl();
-    } while (c);
-    assert(c && "vtable entry must refer to a member of the vtable's class");
+    assert(theClass->isSuperclassOf(getClass()) &&
+           "vtable entry must refer to a member of the vtable's class");
 
     // All function vtable entries must be at their natural uncurry level.
     assert(!entry.Method.isCurried && "vtable entry must not be curried");
diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp
index 579c879..11edbc4 100644
--- a/lib/SILGen/SILGen.cpp
+++ b/lib/SILGen/SILGen.cpp
@@ -1368,8 +1368,7 @@
   // stored) and doesn't have a setter with less-than-public visibility.
   auto expansion = ResilienceExpansion::Maximal;
 
-  switch (SGM.M.getSwiftModule()->getResilienceStrategy()) {
-  case ResilienceStrategy::Default: {
+  if (!SGM.M.getSwiftModule()->isResilient()) {
     if (SGM.canStorageUseStoredKeyPathComponent(decl, expansion)) {
       // External modules can't directly access storage, unless this is a
       // property in a fixed-layout type.
@@ -1387,18 +1386,15 @@
 
     return false;
   }
-  case ResilienceStrategy::Resilient: {
-    // A resilient module needs to handle binaries compiled against its older
-    // versions. This means we have to be a bit more conservative, since in
-    // earlier versions, a settable property may have withheld the setter,
-    // or a fixed-layout type may not have been.
-    // Without availability information, only get-only computed properties
-    // can resiliently use trivial descriptors.
-    return !SGM.canStorageUseStoredKeyPathComponent(decl, expansion)
-      && decl->getSetter() == nullptr;
-  }
-  }
-  llvm_unreachable("unhandled strategy");
+
+  // A resilient module needs to handle binaries compiled against its older
+  // versions. This means we have to be a bit more conservative, since in
+  // earlier versions, a settable property may have withheld the setter,
+  // or a fixed-layout type may not have been.
+  // Without availability information, only get-only computed properties
+  // can resiliently use trivial descriptors.
+  return !SGM.canStorageUseStoredKeyPathComponent(decl, expansion)
+    && decl->getSetter() == nullptr;
 }
 
 void SILGenModule::tryEmitPropertyDescriptor(AbstractStorageDecl *decl) {
diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp
index 1a3d203..a0e01f5 100644
--- a/lib/SILGen/SILGenConstructor.cpp
+++ b/lib/SILGen/SILGenConstructor.cpp
@@ -451,14 +451,9 @@
 }
 
 bool Lowering::usesObjCAllocator(ClassDecl *theClass) {
-  while (true) {
-    // If the root class was implemented in Objective-C, use Objective-C's
-    // allocation methods because they may have been overridden.
-    if (!theClass->hasSuperclass())
-      return theClass->hasClangNode();
-
-    theClass = theClass->getSuperclassDecl();
-  }
+  // If the root class was implemented in Objective-C, use Objective-C's
+  // allocation methods because they may have been overridden.
+  return theClass->checkAncestry(AncestryFlags::ClangImported);
 }
 
 void SILGenFunction::emitClassConstructorAllocator(ConstructorDecl *ctor) {
diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
index 3634c64..7ff918e 100644
--- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
+++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp
@@ -255,18 +255,6 @@
     makeAlive(WT);
   }
 
-  /// Returns true if \a Derived is the same as \p Base or derived from it.
-  static bool isDerivedOrEqual(ClassDecl *Derived, ClassDecl *Base) {
-    for (;;) {
-      if (Derived == Base)
-        return true;
-      if (!Derived->hasSuperclass())
-        break;
-      Derived = Derived->getSuperclassDecl();
-    }
-    return false;
-  }
-
   /// Returns true if the implementation of method \p FD in class \p ImplCl
   /// may be called when the type of the class_method's operand is \p MethodCl.
   /// Both, \p MethodCl and \p ImplCl, may by null if not known or if it's a
@@ -277,7 +265,7 @@
       return true;
 
     // All implementations of derived classes may be called.
-    if (isDerivedOrEqual(ImplCl, MethodCl))
+    if (MethodCl->isSuperclassOf(ImplCl))
       return true;
 
     // Check if the method implementation is the same in a super class, i.e.
diff --git a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
index 4076785..f794dd0 100644
--- a/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
+++ b/lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
@@ -283,8 +283,7 @@
 
   // If the class has an @objc ancestry it can be dynamically subclassed and we
   // can't therefore statically know the default case.
-  auto Ancestry = CD->checkObjCAncestry();
-  if (Ancestry != ObjCClassKind::NonObjC)
+  if (CD->checkAncestry(AncestryFlags::ObjC))
     return false;
 
   // Without an associated context we cannot perform any
diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp
index 03bd71cee..55e7576 100644
--- a/lib/Sema/CodeSynthesis.cpp
+++ b/lib/Sema/CodeSynthesis.cpp
@@ -322,7 +322,7 @@
   // Accessors for classes with @objc ancestry are not @_transparent,
   // since they use a field offset variable which is not exported.
   if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
-    if (classDecl->checkObjCAncestry() != ObjCClassKind::NonObjC)
+    if (classDecl->checkAncestry(AncestryFlags::ObjC))
       return;
 
   // Accessors synthesized on-demand are never transaprent.
diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp
index 0e4ee57..befb30b 100644
--- a/lib/Sema/DerivedConformanceEquatableHashable.cpp
+++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp
@@ -631,8 +631,7 @@
   auto boolTy = C.getBoolDecl()->getDeclaredType();
 
   Identifier generatedIdentifier;
-  if (parentDC->getParentModule()->getResilienceStrategy() ==
-      ResilienceStrategy::Resilient) {
+  if (parentDC->getParentModule()->isResilient()) {
     generatedIdentifier = C.Id_EqualsOperator;
   } else if (selfIfaceTy->getEnumOrBoundGenericEnum()) {
     generatedIdentifier = C.Id_derived_enum_equals;
diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp
index 5e26678..a97d959 100644
--- a/lib/Sema/DerivedConformanceRawRepresentable.cpp
+++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp
@@ -147,8 +147,7 @@
                                  AbstractFunctionDecl *afd) {
   ASTContext &C = derived.TC.Context;
   auto parentDC = derived.getConformanceContext();
-  if (parentDC->getParentModule()->getResilienceStrategy() !=
-      ResilienceStrategy::Resilient) {
+  if (!parentDC->getParentModule()->isResilient()) {
     AccessScope access =
         afd->getFormalAccessScope(nullptr,
                                   /*treatUsableFromInlineAsPublic*/true);
diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp
index eab93bd..4685e59 100644
--- a/lib/Sema/MiscDiagnostics.cpp
+++ b/lib/Sema/MiscDiagnostics.cpp
@@ -3335,13 +3335,8 @@
 
       // If the best method was from a subclass of the place where
       // this method was declared, we have a new best.
-      while (auto superclassDecl = bestClassDecl->getSuperclassDecl()) {
-        if (classDecl == superclassDecl) {
-          bestMethod = method;
-          break;
-        }
-
-        bestClassDecl = superclassDecl;
+      if (classDecl->isSuperclassOf(bestClassDecl)) {
+        bestMethod = method;
       }
     }
 
diff --git a/lib/Sema/ResilienceDiagnostics.cpp b/lib/Sema/ResilienceDiagnostics.cpp
index 2f354f8..d87a8fa 100644
--- a/lib/Sema/ResilienceDiagnostics.cpp
+++ b/lib/Sema/ResilienceDiagnostics.cpp
@@ -119,8 +119,7 @@
   // Do enforce the restriction even in pre-Swift-5 modes if the module we're
   // building is resilient, though.
   if (D->isObjCDynamic() && !Context.isSwiftVersionAtLeast(5) &&
-      DC->getParentModule()->getResilienceStrategy() !=
-        ResilienceStrategy::Resilient) {
+      !DC->getParentModule()->isResilient()) {
     return false;
   }
 
diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp
index 59f13d7..9506f8b 100644
--- a/lib/Sema/TypeCheckAccess.cpp
+++ b/lib/Sema/TypeCheckAccess.cpp
@@ -205,12 +205,11 @@
 
   } else {
     // The type violates the rules of access control (with or without taking the
-    // TypeRepr into account).
+    // TypeRepr into account).
 
     if (typeRepr && mayBeInferred &&
         !TC.getLangOpts().isSwiftVersionAtLeast(5) &&
-        useDC->getParentModule()->getResilienceStrategy() !=
-          ResilienceStrategy::Resilient) {
+        !useDC->getParentModule()->isResilient()) {
       // Swift 4.2 and earlier didn't check the Type when a TypeRepr was
       // present. However, this is a major hole when generic parameters are
       // inferred:
diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp
index a092507..457d14a 100644
--- a/lib/Sema/TypeCheckAttr.cpp
+++ b/lib/Sema/TypeCheckAttr.cpp
@@ -2380,12 +2380,9 @@
 void AttributeChecker::visitFrozenAttr(FrozenAttr *attr) {
   auto *ED = cast<EnumDecl>(D);
 
-  switch (ED->getModuleContext()->getResilienceStrategy()) {
-  case ResilienceStrategy::Default:
+  if (!ED->getModuleContext()->isResilient()) {
     diagnoseAndRemoveAttr(attr, diag::enum_frozen_nonresilient, attr);
     return;
-  case ResilienceStrategy::Resilient:
-    break;
   }
 
   if (ED->getFormalAccess() < AccessLevel::Public &&
diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp
index daee66f..6506e49 100644
--- a/lib/Sema/TypeCheckConstraints.cpp
+++ b/lib/Sema/TypeCheckConstraints.cpp
@@ -4040,6 +4040,33 @@
     if (toType->isAnyObject() || fromType->isAnyObject())
       return CheckedCastKind::ValueCast;
 
+    // A cast from an existential type to a concrete type does not succeed. For
+    // example:
+    //
+    // struct S {}
+    // enum FooError: Error { case bar }
+    //
+    // func foo() {
+    //   do {
+    //     throw FooError.bar
+    //   } catch is X { /* Will always fail */
+    //     print("Caught bar error")
+    //   }
+    // }
+    if (fromExistential) {
+      if (auto NTD = toType->getAnyNominal()) {
+        if (!isa<ProtocolDecl>(NTD)) {
+          auto protocolDecl =
+              dyn_cast_or_null<ProtocolDecl>(fromType->getAnyNominal());
+          if (protocolDecl &&
+              !conformsToProtocol(toType, protocolDecl, dc,
+                                  ConformanceCheckFlags::InExpression)) {
+            return failed();
+          }
+        }
+      }
+    }
+
     bool toRequiresClass;
     if (toType->isExistentialType())
       toRequiresClass = toType->getExistentialLayout().requiresClass();
diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp
index 24fc3de..a9fa99c 100644
--- a/lib/Sema/TypeCheckDecl.cpp
+++ b/lib/Sema/TypeCheckDecl.cpp
@@ -2593,17 +2593,8 @@
                                        ArrayRef<VarDecl *> vars) {
     // Check whether we have an Objective-C-defined class in our
     // inheritance chain.
-    while (classDecl) {
-      // If we found an Objective-C-defined class, continue checking.
-      if (classDecl->hasClangNode())
-        break;
-
-      // If we ran out of superclasses, we're done.
-      if (!classDecl->hasSuperclass())
-        return false;
-
-      classDecl = classDecl->getSuperclassDecl();
-    }
+    if (!classDecl->checkAncestry(AncestryFlags::ClangImported))
+      return false;
 
     // If all of the variables are @objc, we can use @NSManaged.
     for (auto var : vars) {
diff --git a/lib/Sema/TypeCheckDeclObjC.cpp b/lib/Sema/TypeCheckDeclObjC.cpp
index 6bc43f0..307ff5d 100644
--- a/lib/Sema/TypeCheckDeclObjC.cpp
+++ b/lib/Sema/TypeCheckDeclObjC.cpp
@@ -383,6 +383,21 @@
     }
 
     if (auto classDecl = ED->getSelfClassDecl()) {
+      auto *mod = value->getModuleContext();
+      auto &ctx = mod->getASTContext();
+
+      if (!ctx.LangOpts.EnableObjCResilientClassStubs) {
+        if (classDecl->checkAncestry().contains(
+              AncestryFlags::ResilientOther) ||
+            classDecl->hasResilientMetadata(mod,
+                                            ResilienceExpansion::Maximal)) {
+          if (diagnose) {
+            value->diagnose(diag::objc_in_resilient_extension);
+          }
+          return true;
+        }
+      }
+
       if (classDecl->isGenericContext()) {
         if (!classDecl->usesObjCGenericsModel()) {
           if (diagnose) {
@@ -993,17 +1008,17 @@
   auto classDecl = VD->getDeclContext()->getSelfClassDecl();
   if (!classDecl) return false;
 
-  return classDecl->hasObjCMembers();
+  return classDecl->checkAncestry(AncestryFlags::ObjCMembers);
 }
 
 // A class is @objc if it does not have generic ancestry, and it either has
 // an explicit @objc attribute, or its superclass is @objc.
 static Optional<ObjCReason> shouldMarkClassAsObjC(const ClassDecl *CD) {
   ASTContext &ctx = CD->getASTContext();
-  ObjCClassKind kind = CD->checkObjCAncestry();
+  auto ancestry = CD->checkAncestry();
 
   if (auto attr = CD->getAttrs().getAttribute<ObjCAttr>()) {
-    if (kind == ObjCClassKind::ObjCMembers) {
+    if (ancestry.contains(AncestryFlags::Generic)) {
       if (attr->hasName() && !CD->isGenericContext()) {
         // @objc with a name on a non-generic subclass of a generic class is
         // just controlling the runtime name. Don't diagnose this case.
@@ -1016,9 +1031,24 @@
         .fixItRemove(attr->getRangeWithAt());
     }
 
+    // If the class has resilient ancestry, @objc just controls the runtime
+    // name unless -enable-resilient-objc-class-stubs is enabled.
+    if (ancestry.contains(AncestryFlags::ResilientOther) &&
+        !ctx.LangOpts.EnableObjCResilientClassStubs) {
+      if (attr->hasName()) {
+        const_cast<ClassDecl *>(CD)->getAttrs().add(
+          new (ctx) ObjCRuntimeNameAttr(*attr));
+        return None;
+      }
+
+      ctx.Diags.diagnose(attr->getLocation(), diag::objc_for_resilient_class)
+        .fixItRemove(attr->getRangeWithAt());
+    }
+
     // Only allow ObjC-rooted classes to be @objc.
     // (Leave a hole for test cases.)
-    if (kind == ObjCClassKind::ObjCWithSwiftRoot) {
+    if (ancestry.contains(AncestryFlags::ObjC) &&
+        !ancestry.contains(AncestryFlags::ClangImported)) {
       if (ctx.LangOpts.EnableObjCAttrRequiresFoundation)
         ctx.Diags.diagnose(attr->getLocation(),
                            diag::invalid_objc_swift_rooted_class)
@@ -1031,9 +1061,18 @@
     return ObjCReason(ObjCReason::ExplicitlyObjC);
   }
 
-  if (kind == ObjCClassKind::ObjCWithSwiftRoot ||
-      kind == ObjCClassKind::ObjC)
+  if (ancestry.contains(AncestryFlags::ObjC)) {
+    if (ancestry.contains(AncestryFlags::Generic)) {
+      return None;
+    }
+
+    if (ancestry.contains(AncestryFlags::ResilientOther) &&
+        !ctx.LangOpts.EnableObjCResilientClassStubs) {
+      return None;
+    }
+
     return ObjCReason(ObjCReason::ImplicitlyObjC);
+  }
 
   return None;
 }
@@ -1214,9 +1253,8 @@
     if (classDecl->isForeign())
       return None;
 
-    if (classDecl->checkObjCAncestry() != ObjCClassKind::NonObjC) {
+    if (classDecl->checkAncestry(AncestryFlags::ObjC))
       return ObjCReason(ObjCReason::MemberOfObjCSubclass);
-    }
   }
 
   return None;
diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp
index 0ca8e73..fb7a4ff 100644
--- a/lib/Sema/TypeCheckProtocol.cpp
+++ b/lib/Sema/TypeCheckProtocol.cpp
@@ -2518,8 +2518,7 @@
       AccessScope requiredAccessScope = getRequiredAccessScope();
 
       if (!TC.Context.isSwiftVersionAtLeast(5) &&
-          DC->getParentModule()->getResilienceStrategy() !=
-              ResilienceStrategy::Resilient) {
+          !DC->getParentModule()->isResilient()) {
         // HACK: In pre-Swift-5, these typealiases were synthesized with the
         // same access level as the conforming type, which might be more
         // visible than the associated type witness. Preserve that behavior
@@ -4859,19 +4858,6 @@
   }
 }
 
-/// Determine whether a particular class has generic ancestry.
-static bool hasGenericAncestry(ClassDecl *classDecl) {
-  SmallPtrSet<ClassDecl *, 4> visited;
-  while (classDecl && visited.insert(classDecl).second) {
-    if (classDecl->isGenericContext())
-      return true;
-
-    classDecl = classDecl->getSuperclassDecl();
-  }
-
-  return false;
-}
-
 /// Infer the attribute tostatic-initialize the Objective-C metadata for the
 /// given class, if needed.
 static void inferStaticInitializeObjCMetadata(TypeChecker &tc,
@@ -4882,7 +4868,7 @@
 
   // If we know that the Objective-C metadata will be statically registered,
   // there's nothing to do.
-  if (!hasGenericAncestry(classDecl)) {
+  if (!classDecl->checkAncestry(AncestryFlags::Generic)) {
     return;
   }
 
diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp
index fbc41ad..431d637 100644
--- a/lib/Serialization/ModuleFile.cpp
+++ b/lib/Serialization/ModuleFile.cpp
@@ -1455,7 +1455,7 @@
     return error(Status::TargetIncompatible);
   }
   if (ctx.LangOpts.EnableTargetOSChecking &&
-      M->getResilienceStrategy() != ResilienceStrategy::Resilient &&
+      !M->isResilient() &&
       isTargetTooNew(moduleTarget, ctx.LangOpts.Target)) {
     return error(Status::TargetTooNew);
   }
diff --git a/lib/TBDGen/TBDGen.cpp b/lib/TBDGen/TBDGen.cpp
index c649d0a..99caf81 100644
--- a/lib/TBDGen/TBDGen.cpp
+++ b/lib/TBDGen/TBDGen.cpp
@@ -343,19 +343,18 @@
 
   visitNominalTypeDecl(CD);
 
-  auto hasResilientAncestor =
-      CD->hasResilientMetadata(SwiftModule, ResilienceExpansion::Minimal);
-  auto ancestor = CD->getSuperclassDecl();
-  while (ancestor && !hasResilientAncestor) {
-    hasResilientAncestor |=
-        ancestor->hasResilientMetadata(SwiftModule, ResilienceExpansion::Maximal);
-    ancestor = ancestor->getSuperclassDecl();
-  }
-
   // Types with resilient superclasses have some extra symbols.
-  if (hasResilientAncestor)
+  if (CD->checkAncestry(AncestryFlags::ResilientOther) ||
+      CD->hasResilientMetadata()) {
     addSymbol(LinkEntity::forClassMetadataBaseOffset(CD));
 
+    auto &Ctx = CD->getASTContext();
+    if (Ctx.LangOpts.EnableObjCResilientClassStubs) {
+      addSymbol(LinkEntity::forObjCResilientClassStub(
+          CD, TypeMetadataAddress::AddressPoint));
+    }
+  }
+
   // Emit dispatch thunks for every new vtable entry.
   struct VTableVisitor : public SILVTableVisitor<VTableVisitor> {
     TBDGenVisitor &TBD;
diff --git a/stdlib/public/runtime/Metadata.cpp b/stdlib/public/runtime/Metadata.cpp
index 3c596df..4eb257d 100644
--- a/stdlib/public/runtime/Metadata.cpp
+++ b/stdlib/public/runtime/Metadata.cpp
@@ -2641,6 +2641,11 @@
   return {MetadataDependency(), super};
 }
 
+// Suppress diagnostic about the availability of _objc_realizeClassFromSwift.
+// We test availability with a nullptr check, but the compiler doesn't see that.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunguarded-availability-new"
+
 static SWIFT_CC(swift) MetadataDependency
 _swift_initClassMetadataImpl(ClassMetadata *self,
                              ClassLayoutFlags layoutFlags,
@@ -2667,6 +2672,11 @@
     (void)unused;
     setUpObjCRuntimeGetImageNameFromClass();
   }, nullptr);
+
+  // Temporary workaround until _objc_realizeClassFromSwift is in the SDK.
+  static auto _objc_realizeClassFromSwift =
+    (Class (*)(Class _Nullable, const void *_Nullable))
+    dlsym(RTLD_NEXT, "_objc_realizeClassFromSwift");
 #endif
 
   // Copy field offsets, generic arguments and (if necessary) vtable entries
@@ -2680,10 +2690,12 @@
 
   initClassFieldOffsetVector(self, numFields, fieldTypes, fieldOffsets);
 
+  auto *description = self->getDescription();
 #if SWIFT_OBJC_INTEROP
-  if (self->getDescription()->isGeneric())
+  if (description->isGeneric()) {
+    assert(!description->hasObjCResilientClassStub());
     initGenericObjCClass(self, numFields, fieldTypes, fieldOffsets);
-  else {
+  } else {
     initObjCClass(self, numFields, fieldTypes, fieldOffsets);
 
     // Register this class with the runtime. This will also cause the
@@ -2691,13 +2703,25 @@
     // globals. Note that the field offset vector is *not* updated;
     // however we should not be using it for anything in a non-generic
     // class.
-    swift_instantiateObjCClass(self);
+    if (auto *stub = description->getObjCResilientClassStub()) {
+      if (_objc_realizeClassFromSwift == nullptr) {
+        fatalError(0, "class %s requires missing Objective-C runtime feature; "
+                  "the deployment target was newer than this OS\n",
+                  self->getDescription()->Name.get());
+      }
+      _objc_realizeClassFromSwift((Class) self, stub);
+    } else
+      swift_instantiateObjCClass(self);
   }
+#else
+  assert(!description->hasObjCResilientClassStub());
 #endif
 
   return MetadataDependency();
 }
 
+#pragma clang diagnostic pop
+
 void swift::swift_initClassMetadata(ClassMetadata *self,
                                     ClassLayoutFlags layoutFlags,
                                     size_t numFields,
@@ -2737,7 +2761,7 @@
 #ifndef OBJC_REALIZECLASSFROMSWIFT_DEFINED
   // Temporary workaround until _objc_realizeClassFromSwift is in the SDK.
   static auto _objc_realizeClassFromSwift =
-    (Class (*)(Class _Nullable, void* _Nullable))
+    (Class (*)(Class _Nullable, const void *_Nullable))
     dlsym(RTLD_NEXT, "_objc_realizeClassFromSwift");
 #endif
 
diff --git a/test/Constraints/casts.swift b/test/Constraints/casts.swift
index 2483a5e..8297d03 100644
--- a/test/Constraints/casts.swift
+++ b/test/Constraints/casts.swift
@@ -111,7 +111,7 @@
 
   _ = p1 as! P1 & P2
 
-  _ = p2 as! S1
+  _ = p2 as! S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}
 
   _ = p12 as! S1
   _ = p12 as! S2
@@ -126,7 +126,7 @@
 
   var _:Bool = p1 is P1 & P2
 
-  var _:Bool = p2 is S1
+  var _:Bool = p2 is S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}
 
   var _:Bool = p12 is S1
   var _:Bool = p12 is S2
diff --git a/test/Constraints/patterns.swift b/test/Constraints/patterns.swift
index 68fc797..7b986d2 100644
--- a/test/Constraints/patterns.swift
+++ b/test/Constraints/patterns.swift
@@ -55,7 +55,7 @@
      is D,
      is S:
   ()
-case is E:
+case is E: // expected-warning {{cast from 'P' to unrelated type 'E' always fails}}
   ()
 default:
   ()
@@ -69,7 +69,7 @@
   d.d()
 case let s as S:
   s.s()
-case let e as E:
+case let e as E: // expected-warning {{cast from 'P' to unrelated type 'E' always fails}}
   e.e()
 default:
   ()
@@ -120,7 +120,7 @@
   ()
 case iPadHair.HairForceOne: // expected-error{{generic enum type 'iPadHair' is ambiguous without explicit generic parameters when matching value of type 'HairType'}}
   ()
-case Watch.Edition: // TODO: should warn that cast can't succeed with currently known conformances
+case Watch.Edition: // expected-warning {{cast from 'HairType' to unrelated type 'Watch' always fails}}
   ()
 case .HairForceOne: // expected-error{{type 'HairType' has no member 'HairForceOne'}}
   ()
diff --git a/test/Driver/fuzzer.swift b/test/Driver/fuzzer.swift
index f6aa60b..9f36c69 100644
--- a/test/Driver/fuzzer.swift
+++ b/test/Driver/fuzzer.swift
@@ -1,8 +1,11 @@
 // UNSUPPORTED: windows
 // UNSUPPORTED: CPU=powerpc64le
-// RUN: %swiftc_driver -driver-print-jobs -sanitize=fuzzer,address -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ %s | %FileCheck -check-prefix=LIBFUZZER %s
+// RUN: %swiftc_driver -driver-print-jobs -sanitize=fuzzer,address -target x86_64-apple-macosx10.9 -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ %s | %FileCheck -check-prefix=LIBFUZZER_OSX %s
+// RUN: %swiftc_driver -driver-print-jobs -sanitize=fuzzer,address -target x86_64-unknown-linux-gnu -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ %s | %FileCheck -check-prefix=LIBFUZZER_LINUX %s
 
-// LIBFUZZER: libclang_rt.fuzzer
+// LIBFUZZER_OSX: libclang_rt.fuzzer
+// LIBFUZZER_LINUX: -fsanitize=address,fuzzer
+
 @_cdecl("LLVMFuzzerTestOneInput") public func fuzzOneInput(Data: UnsafePointer<CChar>, Size: CLong) -> CInt {
   return 0;
 }
diff --git a/test/Driver/sanitizers.swift b/test/Driver/sanitizers.swift
index bde9aea..1f3e91c 100644
--- a/test/Driver/sanitizers.swift
+++ b/test/Driver/sanitizers.swift
@@ -39,6 +39,10 @@
 // RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=UBSAN_LINUX %s
 // RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=undefined -target x86_64-unknown-windows-msvc %s 2>&1 | %FileCheck -check-prefix=UBSAN_WINDOWS %s
 
+/*
+ * Multiple Sanitizers At Once
+ */
+// RUN: %swiftc_driver -resource-dir %S/Inputs/fake-resource-dir/lib/swift/ -driver-print-jobs -sanitize=address,undefined,fuzzer -target x86_64-unknown-linux-gnu %s 2>&1 | %FileCheck -check-prefix=MULTIPLE_SAN_LINUX %s
 
 /*
  * Bad Argument Tests
@@ -65,7 +69,7 @@
 // ASAN_tvOS: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}darwin{{/|\\\\}}libclang_rt.asan_tvos_dynamic.dylib
 // ASAN_watchOS_SIM: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}darwin{{/|\\\\}}libclang_rt.asan_watchossim_dynamic.dylib
 // ASAN_watchOS: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}darwin{{/|\\\\}}libclang_rt.asan_watchos_dynamic.dylib
-// ASAN_LINUX: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}linux{{/|\\\\}}libclang_rt.asan-x86_64.a
+// ASAN_LINUX: -fsanitize=address
 // ASAN_WINDOWS: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}windows{{/|\\\\}}clang_rt.asan-x86_64.lib
 
 // ASAN: -rpath @executable_path
@@ -82,7 +86,7 @@
 // TSAN_watchOS_SIM: unsupported option '-sanitize=thread' for target 'i386-apple-watchos2.0'
 // TSAN_watchOS: unsupported option '-sanitize=thread' for target 'armv7k-apple-watchos2.0'
 // FUZZER_NONEXISTENT: unsupported option '-sanitize=fuzzer' for target 'x86_64-apple-macosx10.9'
-// TSAN_LINUX: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}linux{{/|\\\\}}libclang_rt.tsan-x86_64.a
+// TSAN_LINUX: -fsanitize=thread
 // TSAN_WINDOWS: unsupported option '-sanitize=thread' for target 'x86_64-unknown-windows-msvc'
 
 // TSAN: -rpath @executable_path
@@ -97,10 +101,12 @@
 // UBSAN_tvOS: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}darwin{{/|\\\\}}libclang_rt.ubsan_tvos_dynamic.dylib
 // UBSAN_watchOS_SIM: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}darwin{{/|\\\\}}libclang_rt.ubsan_watchossim_dynamic.dylib
 // UBSAN_watchOS: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}darwin{{/|\\\\}}libclang_rt.ubsan_watchos_dynamic.dylib
-// UBSAN_LINUX: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}linux{{/|\\\\}}libclang_rt.ubsan-x86_64.a
+// UBSAN_LINUX: -fsanitize=undefined
 // UBSAN_WINDOWS: lib{{/|\\\\}}swift{{/|\\\\}}clang{{/|\\\\}}lib{{/|\\\\}}windows{{/|\\\\}}clang_rt.ubsan-x86_64.lib
 
 // UBSAN: -rpath @executable_path
 
+// MULTIPLE_SAN_LINUX: -fsanitize=address,fuzzer,undefined
+
 // BADARG: unsupported argument 'unknown' to option '-sanitize='
 // INCOMPATIBLESANITIZERS: argument '-sanitize=address' is not allowed with '-sanitize=thread'
diff --git a/test/IRGen/class_update_callback_with_stub.swift b/test/IRGen/class_update_callback_with_stub.swift
new file mode 100644
index 0000000..29d81ef
--- /dev/null
+++ b/test/IRGen/class_update_callback_with_stub.swift
@@ -0,0 +1,155 @@
+// RUN: %empty-directory(%t)
+// RUN: %build-irgen-test-overlays
+// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -I %t %S/../Inputs/resilient_struct.swift
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module-path %t/resilient_class.swiftmodule -enable-library-evolution %S/../Inputs/resilient_class.swift
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module-path %t/resilient_objc_class.swiftmodule -enable-library-evolution %S/../Inputs/resilient_objc_class.swift
+// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -I %t -emit-ir -enable-library-evolution -enable-resilient-objc-class-stubs %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime -DINT=i%target-ptrsize
+
+import Foundation
+import resilient_class
+import resilient_objc_class
+
+// REQUIRES: objc_interop
+
+// -- Nominal type descriptor for ResilientSubclass
+// the interesting part is the 'extra class flags' field has a value of 1.
+
+// CHECK-LABEL: @"$s31class_update_callback_with_stub17ResilientSubclassCMn" = constant <{
+// -- flags
+// CHECK-SAME: i32 1644232784, 
+// -- parent
+// CHECK-SAME: @"$s31class_update_callback_with_stubMXM"
+// -- name
+// CHECK-SAME: @1
+// -- access function
+// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCMa"
+// -- field descriptor
+// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCMF"
+// -- superclass
+// CHECK-SAME: @"symbolic 15resilient_class22ResilientOutsideParentC"
+// -- metadata bounds
+// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCMo"
+// -- extra class flags -- has Objective-C resilient class stub
+// CHECK-SAME: i32 1,
+// -- number of immediate members
+// CHECK-SAME: i32 0,
+// -- number of fields
+// CHECK-SAME: i32 0,
+// -- field offset vector offset
+// CHECK-SAME: i32 0,
+// -- resilient superclass
+// CHECK-SAME: @"got.$s15resilient_class22ResilientOutsideParentCMn"
+// -- singleton metadata initialization
+// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCMl"
+// -- resilient class metadata pattern
+// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCMP"
+// -- metadata completion callback
+// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCMr"
+// -- method override
+// CHECK-SAME: @"got.$s15resilient_class22ResilientOutsideParentCMn"
+// CHECK-SAME: @"got.$s15resilient_class22ResilientOutsideParentCACycfCTq"
+// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCACycfC"
+// CHECK-SAME: }>, section "__TEXT,__const", align 4
+
+
+// -- Symbols for full stubs; the address point is one word in, and defined below
+
+// CHECK-LABEL: @"$s31class_update_callback_with_stub17ResilientSubclassCMt" =
+// CHECK-SAME:    internal global %objc_full_class_stub {
+// CHECK-SAME:    [[INT]] 0,
+// CHECK-SAME:    [[INT]] 1,
+// CHECK-SAME:    %objc_class* (%objc_class*, i8*)* @"$s31class_update_callback_with_stub17ResilientSubclassCMU"
+// CHECK-SAME:  }
+
+// CHECK-LABEL: @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMt" =
+// CHECK-SAME:    internal global %objc_full_class_stub {
+// CHECK-SAME:    [[INT]] 0,
+// CHECK-SAME:    [[INT]] 1,
+// CHECK-SAME:    %objc_class* (%objc_class*, i8*)* @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMU"
+// CHECK-SAME:  }
+
+// CHECK-LABEL: @"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMt" =
+// CHECK-SAME:    internal global %objc_full_class_stub {
+// CHECK-SAME:    [[INT]] 0,
+// CHECK-SAME:    [[INT]] 1,
+// CHECK-SAME:    %objc_class* (%objc_class*, i8*)* @"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMU"
+// CHECK-SAME:  }
+
+
+// -- Categories reference the stubs
+
+// CHECK-LABEL: @"_CATEGORY__TtC31class_update_callback_with_stub17ResilientSubclass_$_class_update_callback_with_stub" = private constant
+// CHECK-SAME:  @"$s31class_update_callback_with_stub17ResilientSubclassCMs"
+
+// CHECK-LABEL: @"_CATEGORY__TtC31class_update_callback_with_stub25ResilientNSObjectSubclass_$_class_update_callback_with_stub" = private constant
+// CHECK-SAME:  @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMs"
+
+// CHECK-LABEL: @"_CATEGORY__TtC31class_update_callback_with_stub27FixedLayoutNSObjectSubclass_$_class_update_callback_with_stub" = private constant
+// CHECK-SAME:  @"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMs"
+
+
+// -- The NSObject-derived class appears on the class list
+
+// CHECK-LABEL: @objc_classes = internal global
+// CHECK-SAME: @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMs"
+// CHECK-SAME: @"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMs"
+// CHECK-SAME: , section "__DATA,__objc_classlist,regular,no_dead_strip"
+
+
+// -- The category list
+
+// CHECK-LABEL: @objc_categories = internal global
+// CHECK-SAME: @"_CATEGORY__TtC31class_update_callback_with_stub17ResilientSubclass_$_class_update_callback_with_stub"
+// CHECK-SAME: @"_CATEGORY__TtC31class_update_callback_with_stub25ResilientNSObjectSubclass_$_class_update_callback_with_stub"
+// CHECK-SAME: @"_CATEGORY__TtC31class_update_callback_with_stub27FixedLayoutNSObjectSubclass_$_class_update_callback_with_stub"
+// CHECK-SAME: , section "__DATA,__objc_catlist,regular,no_dead_strip"
+
+
+// -- Address point for class stubs
+
+// CHECK: @"$s31class_update_callback_with_stub17ResilientSubclassCMs" = alias %objc_class_stub, bitcast (i8* getelementptr inbounds (i8, i8* bitcast (%objc_full_class_stub* @"$s31class_update_callback_with_stub17ResilientSubclassCMt" to i8*), [[INT]] {{4|8}}) to %objc_class_stub*)
+// CHECK: @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMs" = alias %objc_class_stub, bitcast (i8* getelementptr inbounds (i8, i8* bitcast (%objc_full_class_stub* @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMt" to i8*), [[INT]] {{4|8}}) to %objc_class_stub*)
+
+
+// -- Class symbol for NSObject-derived class points at the class stub
+// CHECK: @"OBJC_CLASS_$__TtC31class_update_callback_with_stub25ResilientNSObjectSubclass" = alias %objc_class_stub, %objc_class_stub* @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMs"
+
+
+// -- Metadata update callbacks referenced from class stubs
+
+// CHECK-LABEL: define internal %objc_class* @"$s31class_update_callback_with_stub17ResilientSubclassCMU"(%objc_class*, i8*)
+// CHECK:       entry:
+// CHECK-NEXT:    [[RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$s31class_update_callback_with_stub17ResilientSubclassCMa"([[INT]] 0)
+// CHECK-NEXT:    [[METADATA:%.*]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
+// CHECK-NEXT:    [[CLASS:%.*]] = bitcast %swift.type* [[METADATA]] to %objc_class*
+// CHECK-NEXT:    ret %objc_class* [[CLASS]]
+// CHECK-NEXT:  }
+
+// CHECK-LABEL: define internal %objc_class* @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMU"(%objc_class*, i8*)
+// CHECK:       entry:
+// CHECK-NEXT:    [[RESPONSE:%.*]] = call swiftcc %swift.metadata_response @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMa"([[INT]] 0)
+// CHECK-NEXT:    [[METADATA:%.*]] = extractvalue %swift.metadata_response [[RESPONSE]], 0
+// CHECK-NEXT:    [[CLASS:%.*]] = bitcast %swift.type* [[METADATA]] to %objc_class*
+// CHECK-NEXT:    ret %objc_class* [[CLASS]]
+// CHECK-NEXT:  }
+
+open class ResilientSubclass : ResilientOutsideParent {}
+open class ResilientNSObjectSubclass : ResilientNSObjectOutsideParent {}
+
+// Note: @_fixed_layout on a class only applies to the storage layout and
+// not metadata, which remains resilient.
+
+@_fixed_layout
+open class FixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent {}
+
+extension ResilientSubclass {
+  @objc public func objcMethod() {}
+}
+
+extension ResilientNSObjectSubclass {
+  @objc public func objcMethod() {}
+}
+
+extension FixedLayoutNSObjectSubclass {
+  @objc public func objcMethod() {}
+}
\ No newline at end of file
diff --git a/test/Inputs/resilient_objc_class.swift b/test/Inputs/resilient_objc_class.swift
index df95def..db1767b 100644
--- a/test/Inputs/resilient_objc_class.swift
+++ b/test/Inputs/resilient_objc_class.swift
@@ -66,3 +66,8 @@
     super.classMethod()
   }
 }
+
+// Fixed-layout base class
+
+@_fixed_layout
+open class FixedLayoutNSObjectOutsideParent: NSObject {}
\ No newline at end of file
diff --git a/test/PrintAsObjC/Inputs/custom-modules/module.map b/test/PrintAsObjC/Inputs/custom-modules/module.map
index c1770cd..62f8359 100644
--- a/test/PrintAsObjC/Inputs/custom-modules/module.map
+++ b/test/PrintAsObjC/Inputs/custom-modules/module.map
@@ -42,3 +42,8 @@
   header "VersionedFMWK.h"
   export *
 }
+
+module resilient_objc_class {
+  header "resilient_objc_class.h"
+  export *
+}
diff --git a/test/PrintAsObjC/resilient-ancestry.swift b/test/PrintAsObjC/resilient-ancestry.swift
new file mode 100644
index 0000000..6d95e36
--- /dev/null
+++ b/test/PrintAsObjC/resilient-ancestry.swift
@@ -0,0 +1,52 @@
+// Please keep this file in alphabetical order!
+
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module-path %t/resilient_struct.swiftmodule %S/../Inputs/resilient_struct.swift -enable-library-evolution
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module-path %t/resilient_objc_class.swiftmodule %S/../Inputs/resilient_objc_class.swift -I %t -enable-library-evolution -emit-objc-header-path %t/resilient_objc_class.h
+
+// RUN: cp %S/Inputs/custom-modules/module.map %t/module.map
+
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -module-name resilient -emit-objc-header-path %t/resilient.h -I %t -enable-library-evolution
+// RUN: %FileCheck %s --check-prefix=NO-STUBS < %t/resilient.h
+// RUN: %check-in-clang %t/resilient.h -I %t
+
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck %s -module-name resilient -emit-objc-header-path %t/resilient.h -I %t -enable-library-evolution -enable-resilient-objc-class-stubs
+// RUN: %FileCheck %s < %t/resilient.h
+// RUN: %check-in-clang %t/resilient.h -I %t
+
+// REQUIRES: objc_interop
+
+import Foundation
+import resilient_objc_class
+
+// Note: @_fixed_layout on a class only applies to the storage layout and
+// not metadata, which remains resilient.
+
+// NO-STUBS-NOT: FixedLayoutNSObjectSubclass
+
+// CHECK-LABEL: SWIFT_RESILIENT_CLASS("_TtC9resilient27FixedLayoutNSObjectSubclass")
+// CHECK-NEXT: @interface FixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent
+// CHECK-NEXT:   - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
+// CHECK-NEXT: @end
+
+@_fixed_layout
+public class FixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent {}
+
+// NO-STUBS-NOT: ResilientNSObjectSubclass
+
+// CHECK-LABEL: SWIFT_RESILIENT_CLASS("_TtC9resilient25ResilientNSObjectSubclass")
+// CHECK-NEXT: @interface ResilientNSObjectSubclass : ResilientNSObjectOutsideParent
+// CHECK-NEXT:   - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
+// CHECK-NEXT: @end
+
+public class ResilientNSObjectSubclass : ResilientNSObjectOutsideParent {}
+
+// NO-STUBS-NOT: RenamedNSObjectSubclass
+
+// CHECK-LABEL: SWIFT_RESILIENT_CLASS_NAMED("UnrenamedNSObjectSubclass")
+// CHECK-NEXT: @interface RenamedNSObjectSubclass : ResilientNSObjectOutsideParent
+// CHECK-NEXT:   - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
+// CHECK-NEXT: @end
+
+@objc(RenamedNSObjectSubclass)
+public class UnrenamedNSObjectSubclass : ResilientNSObjectOutsideParent {}
diff --git a/test/attr/attr_objc.swift b/test/attr/attr_objc.swift
index e3160fe..4516b2a 100644
--- a/test/attr/attr_objc.swift
+++ b/test/attr/attr_objc.swift
@@ -193,9 +193,9 @@
 }
 
 extension subject_genericClass {
-  @objc var extProp: Int { return 0 } // expected-error{{members of extensions of generic classes cannot be declared @objc}}
+  @objc var extProp: Int { return 0 } // expected-error{{extensions of generic classes cannot contain '@objc' members}}
   
-  @objc func extFoo() {} // expected-error{{members of extensions of generic classes cannot be declared @objc}}
+  @objc func extFoo() {} // expected-error{{extensions of generic classes cannot contain '@objc' members}}
 }
 
 @objc
diff --git a/test/attr/attr_objc_resilience.swift b/test/attr/attr_objc_resilience.swift
new file mode 100644
index 0000000..22829b6
--- /dev/null
+++ b/test/attr/attr_objc_resilience.swift
@@ -0,0 +1,44 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module-path %t/resilient_struct.swiftmodule %S/../Inputs/resilient_struct.swift -enable-library-evolution
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module-path %t/resilient_objc_class.swiftmodule %S/../Inputs/resilient_objc_class.swift -I %t -enable-library-evolution
+// RUN: %target-swift-frontend -typecheck -verify %s -I %t
+
+// REQUIRES: objc_interop
+
+import Foundation
+import resilient_objc_class
+
+@objc public class ResilientNSObjectSubclass : ResilientNSObjectOutsideParent {}
+// expected-error@-1 {{classes built with library evolution support cannot have explicit '@objc' subclasses because they are not directly visible from Objective-C}}
+
+public class AnotherResilientNSObjectSubclass : ResilientNSObjectOutsideParent {}
+
+extension ResilientNSObjectOutsideParent {
+  @objc public func categoryOneMethod() {}
+  // expected-error@-1 {{extensions of classes built with library evolution support cannot contain '@objc' members}}
+}
+
+extension AnotherResilientNSObjectSubclass {
+  @objc public func categoryTwoMethod() {}
+  // expected-error@-1 {{extensions of classes built with library evolution support cannot contain '@objc' members}}
+}
+
+// Note: @_fixed_layout on a class only applies to the storage layout and
+// not metadata, which remains resilient.
+
+@_fixed_layout
+@objc public class FixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent {}
+// expected-error@-1 {{classes built with library evolution support cannot have explicit '@objc' subclasses because they are not directly visible from Objective-C}}
+
+@_fixed_layout
+public class AnotherFixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent {}
+
+extension FixedLayoutNSObjectOutsideParent {
+  @objc public func categoryOneMethod() {}
+  // expected-error@-1 {{extensions of classes built with library evolution support cannot contain '@objc' members}}
+}
+
+extension AnotherFixedLayoutNSObjectSubclass {
+  @objc public func categoryTwoMethod() {}
+  // expected-error@-1 {{extensions of classes built with library evolution support cannot contain '@objc' members}}
+}
diff --git a/test/attr/attr_objc_resilient_stubs.swift b/test/attr/attr_objc_resilient_stubs.swift
new file mode 100644
index 0000000..7831a8e
--- /dev/null
+++ b/test/attr/attr_objc_resilient_stubs.swift
@@ -0,0 +1,41 @@
+// RUN: %empty-directory(%t)
+// RUN: %target-swift-frontend -emit-module-path %t/resilient_struct.swiftmodule %S/../Inputs/resilient_struct.swift -enable-library-evolution
+// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module-path %t/resilient_objc_class.swiftmodule %S/../Inputs/resilient_objc_class.swift -I %t -enable-library-evolution -enable-resilient-objc-class-stubs
+// RUN: %target-swift-frontend -typecheck -verify %s -I %t -enable-resilient-objc-class-stubs
+
+// REQUIRES: objc_interop
+
+import Foundation
+import resilient_objc_class
+
+// When built with -enable-resilient-objc-class-stubs, all of these cases are
+// allowed.
+
+@objc public class ResilientNSObjectSubclass : ResilientNSObjectOutsideParent {}
+
+public class AnotherResilientNSObjectSubclass : ResilientNSObjectOutsideParent {}
+
+extension ResilientNSObjectOutsideParent {
+  @objc public func categoryOneMethod() {}
+}
+
+extension AnotherResilientNSObjectSubclass {
+  @objc public func categoryTwoMethod() {}
+}
+
+// Note: @_fixed_layout on a class only applies to the storage layout and
+// not metadata, which remains resilient.
+
+@_fixed_layout
+@objc public class FixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent {}
+
+@_fixed_layout
+public class AnotherFixedLayoutNSObjectSubclass : FixedLayoutNSObjectOutsideParent {}
+
+extension FixedLayoutNSObjectOutsideParent {
+  @objc public func categoryOneMethod() {}
+}
+
+extension AnotherFixedLayoutNSObjectSubclass {
+  @objc public func categoryTwoMethod() {}
+}
diff --git a/test/decl/ext/extension-generic-objc.swift b/test/decl/ext/extension-generic-objc.swift
index c1bbe42..68e924f 100644
--- a/test/decl/ext/extension-generic-objc.swift
+++ b/test/decl/ext/extension-generic-objc.swift
@@ -15,7 +15,7 @@
 }
 extension A {
     // This should throw an error
-    @objc func a1() {} // expected-error{{members of extensions of generic classes cannot be declared @objc}}
+    @objc func a1() {} // expected-error{{extensions of generic classes cannot contain '@objc' members}}
     // This should *not* throw an error
     func a2() {}
 }
@@ -51,6 +51,6 @@
 
 extension Outer.Inner {
     @objc func outerInner1() {}
-    // expected-error@-1{{members of extensions of classes from generic context cannot be declared @objc}}
+    // expected-error@-1{{extensions of classes from generic context cannot contain '@objc' members}}
     func outerInner2() {}
 }
diff --git a/test/lit.cfg b/test/lit.cfg
index 2001a57..af9e9ee 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -1057,8 +1057,7 @@
         tools_directory,
         '-L%s' % make_path(test_resource_dir, config.target_sdk_name)])
     # The Swift interpreter is not available when targeting Android.
-    if 'swift_interpreter' in config.available_features:
-        config.available_features.remove('swift_interpreter')
+    config.available_features.discard('swift_interpreter')
 
 else:
     lit_config.fatal("Don't know how to define target_run and "
@@ -1500,7 +1499,7 @@
         config.available_features.add('libdispatch')
     else:
         # TSan runtime requires libdispatch on non-Apple platforms
-        config.available_features.remove('tsan_runtime')
+        config.available_features.discard('tsan_runtime')
 
     if has_lib('Foundation'):
         config.available_features.add('foundation')
diff --git a/test/stmt/errors.swift b/test/stmt/errors.swift
index b632132..6799b8f 100644
--- a/test/stmt/errors.swift
+++ b/test/stmt/errors.swift
@@ -165,3 +165,61 @@
     }
   }
 }
+
+// SR 6400
+
+enum SR_6400_E: Error {
+  case castError
+}
+
+struct SR_6400_S_1 {}
+struct SR_6400_S_2: Error {}
+
+protocol SR_6400_FakeApplicationDelegate: AnyObject {}
+class SR_6400_FakeViewController {}
+
+func sr_6400() throws {
+  do {
+    throw SR_6400_E.castError
+  } catch is SR_6400_S_1 { // expected-warning {{cast from 'Error' to unrelated type 'SR_6400_S_1' always fails}}
+    print("Caught error")
+  }
+  
+  do {
+    throw SR_6400_E.castError
+  } catch is SR_6400_S_2 {
+    print("Caught error") // Ok
+  }
+}
+
+func sr_6400_1<T>(error: Error, as type: T.Type) -> Bool {
+  return (error as? T) != nil // Ok
+}
+
+func sr_6400_2(error: Error) {
+  _ = error as? (SR_6400_FakeViewController & Error) // Ok
+}
+func sr_6400_3(error: Error) {
+  _ = error as? (Error & SR_6400_FakeApplicationDelegate) // Ok
+}
+
+class SR_6400_A {}
+class SR_6400_B: SR_6400_FakeApplicationDelegate & Error {}
+
+func sr_6400_4() {
+  do {
+    throw SR_6400_E.castError
+  } catch let error as SR_6400_A { // expected-warning {{cast from 'Error' to unrelated type 'SR_6400_A' always fails}} // expected-warning {{immutable value 'error' was never used; consider replacing with '_' or removing it}}
+    print("Foo")
+  } catch {
+    print("Bar")
+  }
+  
+  do {
+    throw SR_6400_E.castError
+  } catch let error as SR_6400_B { // expected-warning {{immutable value 'error' was never used; consider replacing with '_' or removing it}}
+    print("Foo")
+  } catch {
+    print("Bar")
+  }
+}
diff --git a/tools/SourceKit/CMakeLists.txt b/tools/SourceKit/CMakeLists.txt
index 31e808f..b7455d3 100644
--- a/tools/SourceKit/CMakeLists.txt
+++ b/tools/SourceKit/CMakeLists.txt
@@ -13,15 +13,16 @@
     get_target_property(CLANG_LOCATION clang LOCATION)
     get_filename_component(CLANG_LOCATION ${CLANG_LOCATION} DIRECTORY)
 
-    if(CMAKE_C_COMPILER_ID STREQUAL MSVC OR CMAKE_C_SIMULATE_ID STREQUAL MSVC)
-      set(CMAKE_C_COMPILER_ID
+    if("${CMAKE_C_COMPILER_ID}" STREQUAL "MSVC" OR
+        "${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")
+      set(CMAKE_C_COMPILER
         ${CLANG_LOCATION}/clang-cl${CMAKE_EXECUTABLE_SUFFIX})
-      set(CMAKE_CXX_COMPILER_ID
+      set(CMAKE_CXX_COMPILER
         ${CLANG_LOCATION}/clang-cl${CMAKE_EXECUTABLE_SUFFIX})
     else()
-      set(CMAKE_C_COMPILER_ID
+      set(CMAKE_C_COMPILER
         ${CLANG_LOCATION}/clang${CMAKE_EXECUTABLE_SUFFIX})
-      set(CMAKE_CXX_COMPILER_ID
+      set(CMAKE_CXX_COMPILER
         ${CLANG_LOCATION}/clang++${CMAKE_EXECUTABLE_SUFFIX})
     endif()
   else()