Merge pull request #9673 from DougGregor/lazy-generic-env-deserialization-4.0

[4.0] [Serialization] Stop pre-loading generic environments.
diff --git a/include/swift/IDE/Utils.h b/include/swift/IDE/Utils.h
index 66c42a7..c4bea80 100644
--- a/include/swift/IDE/Utils.h
+++ b/include/swift/IDE/Utils.h
@@ -250,7 +250,7 @@
 struct ResolvedRangeInfo {
   RangeKind Kind;
   ReturnTyAndWhetherExit ExitInfo;
-  StringRef Content;
+  CharSourceRange Content;
   bool HasSingleEntry;
   bool ThrowingUnhandledError;
   OrphanKind Orphan;
@@ -260,8 +260,8 @@
   ArrayRef<DeclaredDecl> DeclaredDecls;
   ArrayRef<ReferencedDecl> ReferencedDecls;
   DeclContext* RangeContext;
-  ResolvedRangeInfo(RangeKind Kind, ReturnTyAndWhetherExit ExitInfo, StringRef Content,
-                    DeclContext* RangeContext,
+  ResolvedRangeInfo(RangeKind Kind, ReturnTyAndWhetherExit ExitInfo,
+                    CharSourceRange Content, DeclContext* RangeContext,
                     bool HasSingleEntry, bool ThrowingUnhandledError,
                     OrphanKind Orphan, ArrayRef<ASTNode> ContainedNodes,
                     ArrayRef<DeclaredDecl> DeclaredDecls,
@@ -273,7 +273,7 @@
                       DeclaredDecls(DeclaredDecls),
                       ReferencedDecls(ReferencedDecls),
                       RangeContext(RangeContext) {}
-  ResolvedRangeInfo(StringRef Content) :
+  ResolvedRangeInfo(CharSourceRange Content) :
   ResolvedRangeInfo(RangeKind::Invalid, {nullptr, false}, Content, nullptr,
                     /*Single entry*/true, /*unhandled error*/false,
                     OrphanKind::None, {}, {}, {}) {}
diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp
index 171e28d..ccaf626 100644
--- a/lib/ClangImporter/ClangImporter.cpp
+++ b/lib/ClangImporter/ClangImporter.cpp
@@ -3041,37 +3041,30 @@
     // If the entry is not visible, skip it.
     if (!isVisibleClangEntry(clangCtx, clangDecl)) continue;
 
-    // Import the declaration.
-    auto decl =
-        cast_or_null<ValueDecl>(importDeclReal(clangDecl, CurrentVersion));
-    if (!decl)
-      continue;
+    forEachDistinctName(clangDecl,
+                        [&](ImportedName importedName,
+                            ImportNameVersion nameVersion) {
+      // Import the declaration.
+      auto decl =
+          cast_or_null<ValueDecl>(importDeclReal(clangDecl, nameVersion));
+      if (!decl)
+        return;
 
-    // If the name we found matches, report the declaration.
-    bool matchedAny = false;
-    if (decl->getFullName().matchesRef(name)) {
-      consumer.foundDecl(decl, DeclVisibilityKind::DynamicLookup);
-      matchedAny = true;
-    }
-
-    // Check for an alternate declaration; if it's name matches,
-    // report it.
-    for (auto alternate : getAlternateDecls(decl)) {
-      if (alternate->getFullName().matchesRef(name)) {
-        consumer.foundDecl(alternate, DeclVisibilityKind::DynamicLookup);
-        matchedAny = true;
+      // If the name we found matches, report the declaration.
+      // FIXME: If we didn't need to check alternate decls here, we could avoid
+      // importing the member at all by checking importedName ahead of time.
+      if (decl->getFullName().matchesRef(name)) {
+        consumer.foundDecl(decl, DeclVisibilityKind::DynamicLookup);
       }
-    }
 
-    // If we didn't find anything, try under the Swift 2 name.
-    if (!matchedAny) {
-      if (auto swift2Decl = cast_or_null<ValueDecl>(
-                              importDeclReal(clangDecl, Version::Swift2))) {
-        if (swift2Decl->getFullName().matchesRef(name)) {
-          consumer.foundDecl(swift2Decl, DeclVisibilityKind::DynamicLookup);
+      // Check for an alternate declaration; if its name matches,
+      // report it.
+      for (auto alternate : getAlternateDecls(decl)) {
+        if (alternate->getFullName().matchesRef(name)) {
+          consumer.foundDecl(alternate, DeclVisibilityKind::DynamicLookup);
         }
       }
-    }
+    });
   }
 }
 
diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp
index 64016d2..d06378e 100644
--- a/lib/ClangImporter/ImportDecl.cpp
+++ b/lib/ClangImporter/ImportDecl.cpp
@@ -345,6 +345,29 @@
   return true;
 }
 
+void ClangImporter::Implementation::forEachDistinctName(
+    const clang::NamedDecl *decl,
+    llvm::function_ref<void(ImportedName, ImportNameVersion)> action) {
+  using ImportNameKey = std::pair<DeclName, EffectiveClangContext>;
+  SmallVector<ImportNameKey, 8> seenNames;
+  forEachImportNameVersionFromCurrent(CurrentVersion,
+                                      [&](ImportNameVersion nameVersion) {
+    // Check to see if the name is different.
+    ImportedName newName = importFullName(decl, nameVersion);
+    ImportNameKey key(newName, newName.getEffectiveContext());
+    bool seen = llvm::any_of(seenNames,
+                             [&key](const ImportNameKey &existing) -> bool {
+      if (key.first != existing.first)
+        return false;
+      return key.second.equalsWithoutResolving(existing.second);
+    });
+    if (seen)
+      return;
+    seenNames.push_back(key);
+    action(newName, nameVersion);
+  });
+}
+
 // Build the init(rawValue:) initializer for an imported NS_ENUM.
 //   enum NSSomeEnum: RawType {
 //     init?(rawValue: RawType) {
@@ -2139,7 +2162,7 @@
       if (Name.empty())
         return nullptr;
 
-      // If we've been asked to produce a Swift 2 stub, handle it via a
+      // If we've been asked to produce a compatibility stub, handle it via a
       // typealias.
       if (correctSwiftName)
         return importCompatibilityTypeAlias(Decl, importedName,
@@ -2350,7 +2373,7 @@
       if (!importedName)
         return nullptr;
 
-      // If we've been asked to produce a Swift 2 stub, handle it via a
+      // If we've been asked to produce a compatibility stub, handle it via a
       // typealias.
       if (correctSwiftName)
         return importCompatibilityTypeAlias(decl, importedName,
@@ -2581,7 +2604,9 @@
         break;
       }
       }
-      Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
+
+      const clang::EnumDecl *canonicalClangDecl = decl->getCanonicalDecl();
+      Impl.ImportedDecls[{canonicalClangDecl, getVersion()}] = result;
 
       // Import each of the enumerators.
       
@@ -2610,23 +2635,56 @@
         }
       }
 
+      auto contextIsEnum = [&](const ImportedName &name) -> bool {
+        EffectiveClangContext importContext = name.getEffectiveContext();
+        switch (importContext.getKind()) {
+        case EffectiveClangContext::DeclContext:
+          return importContext.getAsDeclContext() == canonicalClangDecl;
+        case EffectiveClangContext::TypedefContext: {
+          auto *typedefName = importContext.getTypedefName();
+          clang::QualType underlyingTy = typedefName->getUnderlyingType();
+          return underlyingTy->getAsTagDecl() == canonicalClangDecl;
+        }
+        case EffectiveClangContext::UnresolvedContext:
+          // Assume this is a context other than the enum.
+          return false;
+        }
+      };
+
       for (auto constant : decl->enumerators()) {
-        Decl *enumeratorDecl;
-        Decl *swift2EnumeratorDecl = nullptr;
+        Decl *enumeratorDecl = nullptr;
+        TinyPtrVector<Decl *> variantDecls;
         switch (enumKind) {
         case EnumKind::Constants:
         case EnumKind::Unknown:
-          enumeratorDecl = Impl.importDecl(constant, getActiveSwiftVersion());
-          swift2EnumeratorDecl =
-              Impl.importDecl(constant, ImportNameVersion::Swift2);
+          Impl.forEachDistinctName(constant,
+                                   [&](ImportedName newName,
+                                       ImportNameVersion nameVersion) {
+            Decl *imported = Impl.importDecl(constant, nameVersion);
+            if (!imported)
+              return;
+            if (nameVersion == getActiveSwiftVersion())
+              enumeratorDecl = imported;
+            else
+              variantDecls.push_back(imported);
+          });
           break;
         case EnumKind::Options:
-          enumeratorDecl =
-              SwiftDeclConverter(Impl, getActiveSwiftVersion())
-                  .importOptionConstant(constant, decl, result);
-          swift2EnumeratorDecl =
-              SwiftDeclConverter(Impl, ImportNameVersion::Swift2)
-                  .importOptionConstant(constant, decl, result);
+          Impl.forEachDistinctName(constant,
+                                   [&](ImportedName newName,
+                                       ImportNameVersion nameVersion) {
+            if (!contextIsEnum(newName))
+              return;
+            SwiftDeclConverter converter(Impl, nameVersion);
+            Decl *imported =
+                converter.importOptionConstant(constant, decl, result);
+            if (!imported)
+              return;
+            if (nameVersion == getActiveSwiftVersion())
+              enumeratorDecl = imported;
+            else
+              variantDecls.push_back(imported);
+          });
           break;
         case EnumKind::Enum: {
           auto canonicalCaseIter =
@@ -2671,10 +2729,21 @@
             }
           }
 
-          swift2EnumeratorDecl =
-              SwiftDeclConverter(Impl, ImportNameVersion::Swift2)
-                  .importEnumCase(constant, decl, cast<EnumDecl>(result),
-                                  enumeratorDecl);
+          Impl.forEachDistinctName(constant,
+                                   [&](ImportedName newName,
+                                       ImportNameVersion nameVersion) {
+            if (nameVersion == getActiveSwiftVersion())
+              return;
+            if (!contextIsEnum(newName))
+              return;
+            SwiftDeclConverter converter(Impl, nameVersion);
+            Decl *imported =
+                converter.importEnumCase(constant, decl, cast<EnumDecl>(result),
+                                         enumeratorDecl);
+            if (!imported)
+              return;
+            variantDecls.push_back(imported);
+          });
           break;
         }
         }
@@ -2691,7 +2760,8 @@
           };
 
           addDecl(result, enumeratorDecl);
-          addDecl(result, swift2EnumeratorDecl);
+          for (auto *variant : variantDecls)
+            addDecl(result, variant);
           
           // If there is an error wrapper, add an alias within the
           // wrapper to the corresponding value within the enumerator
@@ -2757,7 +2827,7 @@
       if (!importedName)
         return nullptr;
 
-      // If we've been asked to produce a Swift 2 stub, handle it via a
+      // If we've been asked to produce a compatibility stub, handle it via a
       // typealias.
       if (correctSwiftName)
         return importCompatibilityTypeAlias(decl, importedName,
@@ -3000,7 +3070,7 @@
                                           /*static*/ false, decl);
         Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
 
-        // If this is a Swift 2 stub, mark it as such.
+        // If this is a compatibility stub, mark it as such.
         if (correctSwiftName)
           markAsVariant(result, *correctSwiftName);
 
@@ -3039,7 +3109,7 @@
                                           /*static*/ false, decl);
         Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
 
-        // If this is a Swift 2 stub, mark it as such.
+        // If this is a compatibility stub, mark it as such.
         if (correctSwiftName)
           markAsVariant(result, *correctSwiftName);
 
@@ -3096,7 +3166,7 @@
                        name, type, dc);
       result->setInterfaceType(type);
 
-      // If this is a Swift 2 stub, mark is as such.
+      // If this is a compatibility stub, mark is as such.
       if (correctSwiftName)
         markAsVariant(result, *correctSwiftName);
 
@@ -3233,7 +3303,7 @@
       result->setAccessibility(Accessibility::Public);
       finishFuncDecl(decl, result);
 
-      // If this is a Swift 2 stub, mark it as such.
+      // If this is a compatibility stub, mark it as such.
       if (correctSwiftName)
         markAsVariant(result, *correctSwiftName);
 
@@ -3323,7 +3393,7 @@
             new (Impl.SwiftContext) IBOutletAttr(/*IsImplicit=*/false));
       // FIXME: Handle IBOutletCollection.
 
-      // If this is a Swift 2 stub, handle it as such.
+      // If this is a compatibility stub, handle it as such.
       if (correctSwiftName)
         markAsVariant(result, *correctSwiftName);
 
@@ -3401,7 +3471,7 @@
       if (!decl->hasExternalStorage())
         Impl.registerExternalDecl(result);
 
-      // If this is a Swift 2 stub, mark it as such.
+      // If this is a compatibility stub, mark it as such.
       if (correctSwiftName)
         markAsVariant(result, *correctSwiftName);
 
@@ -3579,12 +3649,6 @@
                             {decl->param_begin(), decl->param_size()},
                             decl->isVariadic(), redundant);
 
-      if (auto rawDecl = Impl.importDecl(decl, ImportNameVersion::Raw)) {
-        // We expect the raw decl to always be a method.
-        assert(isa<FuncDecl>(rawDecl));
-        Impl.addAlternateDecl(result, cast<ValueDecl>(rawDecl));
-      }
-
       return result;
     }
 
@@ -3853,13 +3917,6 @@
     importObjCGenericParams(const clang::ObjCInterfaceDecl *decl,
                             DeclContext *dc);
 
-    /// Import members of the given Objective-C container and add them to the
-    /// list of corresponding Swift members.
-    void importObjCMembers(const clang::ObjCContainerDecl *decl,
-                           DeclContext *swiftContext,
-                           llvm::SmallPtrSet<Decl *, 4> &knownMembers,
-                           SmallVectorImpl<Decl *> &members);
-
     /// \brief Import the members of all of the protocols to which the given
     /// Objective-C class, category, or extension explicitly conforms into
     /// the given list of members, so long as the method was not already
@@ -4031,7 +4088,7 @@
       auto importedName = importFullName(decl, correctSwiftName);
       if (!importedName) return nullptr;
 
-      // If we've been asked to produce a Swift 2 stub, handle it via a
+      // If we've been asked to produce a compatibility stub, handle it via a
       // typealias.
       if (correctSwiftName)
         return importCompatibilityTypeAlias(decl, importedName,
@@ -4169,7 +4226,7 @@
       auto importedName = importFullName(decl, correctSwiftName);
       if (!importedName) return nullptr;
 
-      // If we've been asked to produce a Swift 2 stub, handle it via a
+      // If we've been asked to produce a compatibility stub, handle it via a
       // typealias.
       if (correctSwiftName)
         return importCompatibilityTypeAlias(decl, importedName,
@@ -4498,7 +4555,7 @@
             setter->setOverriddenDecl(parentSetter);
       }
 
-      // If this is a Swift 2 stub, mark it as such.
+      // If this is a compatibility stub, mark it as such.
       if (correctSwiftName)
         markAsVariant(result, *correctSwiftName);
 
@@ -4962,7 +5019,7 @@
 Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
                                          const clang::EnumDecl *clangEnum,
                                          EnumDecl *theEnum,
-                                         Decl *swift3Decl) {
+                                         Decl *correctDecl) {
   auto &context = Impl.SwiftContext;
   Optional<ImportedName> correctSwiftName;
   auto name =
@@ -4971,25 +5028,22 @@
     return nullptr;
 
   if (correctSwiftName) {
-    // We're creating a Swift 2 stub. Treat it as an enum case alias.
-    if (!swift3Decl)
+    // We're creating a compatibility stub. Treat it as an enum case alias.
+    auto correctCase = dyn_cast_or_null<EnumElementDecl>(correctDecl);
+    if (!correctCase)
       return nullptr;
 
-    // If the Swift 3 declaration was unavailable, don't map to it.
+    // If the correct declaration was unavailable, don't map to it.
     // FIXME: This eliminates spurious errors, but affects QoI.
-    if (swift3Decl->getAttrs().isUnavailable(Impl.SwiftContext))
+    if (correctCase->getAttrs().isUnavailable(Impl.SwiftContext))
       return nullptr;
 
-    auto swift3Case = dyn_cast<EnumElementDecl>(swift3Decl);
-    if (!swift3Case)
-      return nullptr;
+    auto compatibilityCase =
+        importEnumCaseAlias(name, decl, correctCase, clangEnum, theEnum);
+    if (compatibilityCase)
+      markAsVariant(compatibilityCase, *correctSwiftName);
 
-    auto swift2Case =
-        importEnumCaseAlias(name, decl, swift3Case, clangEnum, theEnum);
-    if (swift2Case)
-      markAsVariant(swift2Case, *correctSwiftName);
-
-    return swift2Case;
+    return compatibilityCase;
   }
 
   // Use the constant's underlying value as its raw value in Swift.
@@ -5053,7 +5107,7 @@
     CD->getAttrs().add(attr);
   }
 
-  // If this is a Swift 2 stub, mark it as such.
+  // If this is a compatibility stub, mark it as such.
   if (correctSwiftName)
     markAsVariant(CD, *correctSwiftName);
 
@@ -5496,7 +5550,7 @@
       importConstructor(objcMethod, dc, implicit, kind, required, selector,
                         importedName, params, variadic, redundant);
 
-  // If this is a Swift 2 stub, mark it as such.
+  // If this is a compatibility stub, mark it as such.
   if (result && correctSwiftName)
     markAsVariant(result, *correctSwiftName);
 
@@ -6342,37 +6396,6 @@
       genericParams, Impl.importSourceLoc(typeParamList->getRAngleLoc()));
 }
 
-void SwiftDeclConverter::importObjCMembers(
-    const clang::ObjCContainerDecl *decl, DeclContext *swiftContext,
-    llvm::SmallPtrSet<Decl *, 4> &knownMembers,
-    SmallVectorImpl<Decl *> &members) {
-  for (auto m = decl->decls_begin(), mEnd = decl->decls_end(); m != mEnd; ++m) {
-    auto nd = dyn_cast<clang::NamedDecl>(*m);
-    if (!nd || nd != nd->getCanonicalDecl())
-      continue;
-
-    auto member = Impl.importDecl(nd, getVersion());
-    if (!member)
-      continue;
-
-    if (auto objcMethod = dyn_cast<clang::ObjCMethodDecl>(nd)) {
-      // If there is are alternate declarations for this member, add it.
-      for (auto alternate : Impl.getAlternateDecls(member)) {
-        if (alternate->getDeclContext() == member->getDeclContext() &&
-            knownMembers.insert(alternate).second)
-          members.push_back(alternate);
-      }
-
-      // If this declaration shouldn't be visible, don't add it to
-      // the list.
-      if (shouldSuppressDeclImport(objcMethod))
-        continue;
-    }
-
-    members.push_back(member);
-  }
-}
-
 void SwiftDeclConverter::importMirroredProtocolMembers(
     const clang::ObjCContainerDecl *decl, DeclContext *dc,
     ArrayRef<ProtocolDecl *> protocols, SmallVectorImpl<Decl *> &members,
@@ -6412,7 +6435,7 @@
     const auto &languageVersion =
         Impl.SwiftContext.LangOpts.EffectiveLanguageVersion;
     for (auto member : proto->getMembers()) {
-      // Skip Swift 2 stubs; there's no reason to mirror them.
+      // Skip compatibility stubs; there's no reason to mirror them.
       if (member->getAttrs().isUnavailableInSwiftVersion(languageVersion))
         continue;
 
@@ -6512,7 +6535,7 @@
       if (!ctor)
         continue;
 
-      // Don't inherit Swift 2 stubs.
+      // Don't inherit compatibility stubs.
       if (ctor->getAttrs().isUnavailableInSwiftVersion(languageVersion))
         continue;
 
@@ -6557,7 +6580,7 @@
                                   /*required=*/false, ctor->getObjCSelector(),
                                   importedName, objcMethod->parameters(),
                                   objcMethod->isVariadic(), redundant)) {
-          // If this is a Swift 2 stub, mark it as such.
+          // If this is a compatibility stub, mark it as such.
           if (correctSwiftName)
             markAsVariant(newCtor, *correctSwiftName);
 
@@ -7700,14 +7723,8 @@
       // Only continue members in the same submodule as this extension.
       if (decl->getImportedOwningModule() != submodule) continue;
 
-      SmallPtrSet<DeclName, 8> seenNames;
-      forEachImportNameVersionFromCurrent(CurrentVersion,
-                                          [&](ImportNameVersion nameVersion) {
-        // Check to see if the name is different.
-        ImportedName newName = importFullName(decl, nameVersion);
-        if (!seenNames.insert(newName).second)
-          return;
-
+      forEachDistinctName(decl, [&](ImportedName newName,
+                                    ImportNameVersion nameVersion) {
         // Quickly check the context and bail out if it obviously doesn't
         // belong here.
         if (auto *importDC = newName.getEffectiveContext().getAsDeclContext())
@@ -7735,10 +7752,6 @@
                                     Instance->getSourceManager(),
                                     "loading members for");
 
-  // TODO: accommodate deprecated versions as well
-  SwiftDeclConverter converter(*this, CurrentVersion);
-  SwiftDeclConverter swift2Converter(*this, ImportNameVersion::Swift2);
-
   DeclContext *DC;
   IterableDeclContext *IDC;
   SmallVector<ProtocolDecl *, 4> protos;
@@ -7773,9 +7786,36 @@
   ImportingEntityRAII Importing(*this);
 
   SmallVector<Decl *, 16> members;
-  llvm::SmallPtrSet<Decl *, 4> knownMembers;
-  converter.importObjCMembers(objcContainer, DC, knownMembers, members);
-  swift2Converter.importObjCMembers(objcContainer, DC, knownMembers, members);
+  llvm::SmallPtrSet<Decl *, 4> knownAlternateMembers;
+  for (const clang::Decl *m : objcContainer->decls()) {
+    auto nd = dyn_cast<clang::NamedDecl>(m);
+    if (!nd || nd != nd->getCanonicalDecl())
+      continue;
+
+    forEachDistinctName(nd,
+                        [&](ImportedName name, ImportNameVersion nameVersion) {
+      auto member = importDecl(nd, nameVersion);
+      if (!member)
+        return;
+
+      // If there are alternate declarations for this member, add them.
+      for (auto alternate : getAlternateDecls(member)) {
+        if (alternate->getDeclContext() == member->getDeclContext() &&
+            knownAlternateMembers.insert(alternate).second) {
+          members.push_back(alternate);
+        }
+      }
+
+      // If this declaration shouldn't be visible, don't add it to
+      // the list.
+      if (shouldSuppressDeclImport(nd))
+        return;
+
+      members.push_back(member);
+    });
+  }
+
+  SwiftDeclConverter converter(*this, CurrentVersion);
 
   protos = takeImportedProtocols(D);
   if (auto clangClass = dyn_cast<clang::ObjCInterfaceDecl>(objcContainer)) {
@@ -7804,7 +7844,6 @@
   for (auto member : members) {
     IDC->addMember(member);
   }
-
 }
 
 void ClangImporter::Implementation::loadAllConformances(
diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp
index a7a92e9..5f9e227 100644
--- a/lib/ClangImporter/ImportName.cpp
+++ b/lib/ClangImporter/ImportName.cpp
@@ -834,9 +834,11 @@
     case EnumKind::Enum:
     case EnumKind::Options:
       // Enums are mapped to Swift enums, Options to Swift option sets.
-      res = cast<clang::DeclContext>(enumDecl);
-      break;
-
+      if (version != ImportNameVersion::Raw) {
+        res = cast<clang::DeclContext>(enumDecl);
+        break;
+      }
+      LLVM_FALLTHROUGH;
     case EnumKind::Constants:
     case EnumKind::Unknown:
       // The enum constant goes into the redeclaration context of the
@@ -935,9 +937,9 @@
   return false;
 }
 
-bool NameImporter::shouldBeSwiftPrivate(const clang::NamedDecl *decl,
-                                        clang::Sema &clangSema) {
-
+static bool shouldBeSwiftPrivate(NameImporter &nameImporter,
+                                 const clang::NamedDecl *decl,
+                                 ImportNameVersion version) {
   // Decl with the attribute are obviously private
   if (decl->hasAttr<clang::SwiftPrivateAttr>())
     return true;
@@ -946,7 +948,12 @@
   // private if the parent enum is marked private.
   if (auto *ECD = dyn_cast<clang::EnumConstantDecl>(decl)) {
     auto *ED = cast<clang::EnumDecl>(ECD->getDeclContext());
-    switch (getEnumKind(ED)) {
+    switch (nameImporter.getEnumKind(ED)) {
+    case EnumKind::Enum:
+    case EnumKind::Options:
+      if (version != ImportNameVersion::Raw)
+        break;
+      LLVM_FALLTHROUGH;
     case EnumKind::Constants:
     case EnumKind::Unknown:
       if (ED->hasAttr<clang::SwiftPrivateAttr>())
@@ -955,10 +962,6 @@
         if (enumTypedef->hasAttr<clang::SwiftPrivateAttr>())
           return true;
       break;
-
-    case EnumKind::Enum:
-    case EnumKind::Options:
-      break;
     }
   }
 
@@ -1503,7 +1506,7 @@
 
   // Enumeration constants may have common prefixes stripped.
   bool strippedPrefix = false;
-  if (isa<clang::EnumConstantDecl>(D)) {
+  if (version != ImportNameVersion::Raw && isa<clang::EnumConstantDecl>(D)) {
     auto enumDecl = cast<clang::EnumDecl>(D->getDeclContext());
     auto enumInfo = getEnumInfo(enumDecl);
 
@@ -1625,7 +1628,7 @@
   // If this declaration has the swift_private attribute, prepend "__" to the
   // appropriate place.
   SmallString<16> swiftPrivateScratch;
-  if (shouldBeSwiftPrivate(D, clangSema)) {
+  if (shouldBeSwiftPrivate(*this, D, version)) {
     // Special case: empty arg factory, "for historical reasons", is not private
     if (isInitializer && argumentNames.empty() &&
         (result.getInitKind() == CtorInitializerKind::Factory ||
diff --git a/lib/ClangImporter/ImportName.h b/lib/ClangImporter/ImportName.h
index cab8794..b8f33cc 100644
--- a/lib/ClangImporter/ImportName.h
+++ b/lib/ClangImporter/ImportName.h
@@ -363,9 +363,6 @@
                       ArrayRef<const clang::ParmVarDecl *> params,
                       bool isInitializer, bool hasCustomName);
 
-  /// Whether we should import this as Swift Private
-  bool shouldBeSwiftPrivate(const clang::NamedDecl *, clang::Sema &clangSema);
-
   EffectiveClangContext determineEffectiveContext(const clang::NamedDecl *,
                                                   const clang::DeclContext *,
                                                   ImportNameVersion version);
diff --git a/lib/ClangImporter/ImporterImpl.h b/lib/ClangImporter/ImporterImpl.h
index b70a7b1..32f7c33 100644
--- a/lib/ClangImporter/ImporterImpl.h
+++ b/lib/ClangImporter/ImporterImpl.h
@@ -1169,6 +1169,23 @@
   /// Determine the effective Clang context for the given Swift nominal type.
   EffectiveClangContext getEffectiveClangContext(NominalTypeDecl *nominal);
 
+  /// Attempts to import the name of \p decl with each possible
+  /// ImportNameVersion. \p action will be called with each unique name.
+  ///
+  /// In this case, "unique" means either the full name is distinct or the
+  /// effective context is distinct. This method does not attempt to handle
+  /// "unresolved" contexts in any special way---if one name references a
+  /// particular Clang declaration and the other has an unresolved context that
+  /// will eventually reference that declaration, the contexts will still be
+  /// considered distinct.
+  ///
+  /// The names are generated in the same order as
+  /// forEachImportNameVersionFromCurrent. The current name is always first.
+  void forEachDistinctName(
+      const clang::NamedDecl *decl,
+      llvm::function_ref<void(importer::ImportedName,
+                              importer::ImportNameVersion)> action);
+
   /// Dump the Swift-specific name lookup tables we generate.
   void dumpSwiftLookupTables();
 
diff --git a/lib/ClangImporter/SwiftLookupTable.h b/lib/ClangImporter/SwiftLookupTable.h
index a7f5e05..ef315b7 100644
--- a/lib/ClangImporter/SwiftLookupTable.h
+++ b/lib/ClangImporter/SwiftLookupTable.h
@@ -56,10 +56,10 @@
 /// Swift name, this will be recorded as
 class EffectiveClangContext {
 public:
-  enum Kind {
+  enum Kind : uint8_t {
     DeclContext,
     TypedefContext,
-    UnresolvedContext,
+    UnresolvedContext, // must be last
   };
 
 private:
@@ -70,15 +70,19 @@
       const char *Data;
     } Unresolved;
   };
-  Kind TheKind;
-  unsigned UnresolvedLength;
-  
+
+  /// If KindOrBiasedLength < Kind::UnresolvedContext, this represents a Kind.
+  /// Otherwise it's (uintptr_t)Kind::UnresolvedContext plus the length of
+  /// Unresolved.Data.
+  uintptr_t KindOrBiasedLength;
+
 public:
-  EffectiveClangContext() : TheKind(DeclContext) {
+  EffectiveClangContext() : KindOrBiasedLength(DeclContext) {
     DC = nullptr;
   }
 
-  EffectiveClangContext(const clang::DeclContext *dc) : TheKind(DeclContext) {
+  EffectiveClangContext(const clang::DeclContext *dc)
+      : KindOrBiasedLength(DeclContext) {
     assert(dc != nullptr && "use null constructor instead");
     if (auto tagDecl = dyn_cast<clang::TagDecl>(dc)) {
       DC = tagDecl->getCanonicalDecl();
@@ -99,14 +103,13 @@
   }
 
   EffectiveClangContext(const clang::TypedefNameDecl *typedefName)
-    : TheKind(TypedefContext)
-  {
+    : KindOrBiasedLength(TypedefContext) {
     Typedef = typedefName->getCanonicalDecl();
   }
 
-  EffectiveClangContext(StringRef unresolved) : TheKind(UnresolvedContext) {
+  EffectiveClangContext(StringRef unresolved)
+      : KindOrBiasedLength(UnresolvedContext + unresolved.size()) {
     Unresolved.Data = unresolved.data();
-    UnresolvedLength = unresolved.size();
   }
 
   /// Determine whether this effective Clang context was set.
@@ -115,7 +118,12 @@
   }
 
   /// Determine the kind of effective Clang context.
-  Kind getKind() const { return TheKind; }
+  Kind getKind() const {
+    if (KindOrBiasedLength >= UnresolvedContext)
+      return UnresolvedContext;
+    return static_cast<Kind>(KindOrBiasedLength);
+
+  }
 
   /// Retrieve the declaration context.
   const clang::DeclContext *getAsDeclContext() const {
@@ -131,17 +139,26 @@
   /// Retrieve the unresolved context name.
   StringRef getUnresolvedName() const {
     assert(getKind() == UnresolvedContext);
-    return StringRef(Unresolved.Data, UnresolvedLength);
+    return StringRef(Unresolved.Data, KindOrBiasedLength - UnresolvedContext);
+  }
+
+  /// Compares two EffectiveClangContexts without resolving unresolved names.
+  bool equalsWithoutResolving(const EffectiveClangContext &other) const {
+    if (getKind() != other.getKind())
+      return false;
+    switch (getKind()) {
+    case DeclContext:
+      return DC == other.DC;
+    case TypedefContext:
+      return Typedef == other.Typedef;
+    case UnresolvedContext:
+      return getUnresolvedName() == other.getUnresolvedName();
+    }
   }
 };
 
-#if LLVM_PTR_SIZE == 4
-static_assert(sizeof(EffectiveClangContext) <= 4 * sizeof(void *),
-              "should fit in four pointers");
-#else
 static_assert(sizeof(EffectiveClangContext) <= 2 * sizeof(void *),
-              "should fit in a couple pointers");
-#endif
+              "should be small");
 
 class SwiftLookupTableReader;
 class SwiftLookupTableWriter;
diff --git a/lib/IDE/SwiftSourceDocInfo.cpp b/lib/IDE/SwiftSourceDocInfo.cpp
index 88778ef..8bf94ff 100644
--- a/lib/IDE/SwiftSourceDocInfo.cpp
+++ b/lib/IDE/SwiftSourceDocInfo.cpp
@@ -226,7 +226,7 @@
   }
   OS << "</Kind>\n";
 
-  OS << "<Content>" << Content << "</Content>\n";
+  OS << "<Content>" << Content.str() << "</Content>\n";
 
   if (auto Ty = ExitInfo.getPointer()) {
     OS << "<Type>";
@@ -372,7 +372,7 @@
   Token &EndTok;
   SourceLoc Start;
   SourceLoc End;
-  StringRef Content;
+  CharSourceRange Content;
   Optional<ResolvedRangeInfo> Result;
   std::vector<ContextInfo> ContextStack;
   ContextInfo &getCurrentDC() {
@@ -498,7 +498,7 @@
     File(File), Ctx(File.getASTContext()), SM(Ctx.SourceMgr),
     AllTokens(AllTokens), StartTok(AllTokens[StartIdx]), EndTok(AllTokens[EndIdx]),
     Start(StartTok.getLoc()), End(EndTok.getLoc()),
-    Content(getContent()) {
+    Content(getContentRange()) {
       assert(Start.isValid() && End.isValid());
   }
 
@@ -815,11 +815,11 @@
       return RangeMatchKind::NoneMatch;
   }
 
-  StringRef getContent() {
+  CharSourceRange getContentRange() {
     SourceManager &SM = File.getASTContext().SourceMgr;
     return CharSourceRange(SM, StartTok.hasComment() ?
                             StartTok.getCommentStart() : StartTok.getLoc(),
-                           Lexer::getLocForEndOfToken(SM, End)).str();
+                           Lexer::getLocForEndOfToken(SM, End));
   }
 };
 
@@ -882,7 +882,7 @@
 
 ResolvedRangeInfo RangeResolver::resolve() {
   if (!Impl)
-    return ResolvedRangeInfo(StringRef());
+    return ResolvedRangeInfo(CharSourceRange());
   Impl->enter(ASTNode());
   walk(Impl->File);
   return Impl->getResult();
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
index 16e7a8f..79ce060 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.apinotes
@@ -88,12 +88,42 @@
         SwiftImportAsNonGeneric: true
       - Name: RenamedGeneric
         SwiftName: OldRenamedGeneric
+      - Name: ClassWithManyRenames
+        Methods:
+          - Selector: "classWithManyRenamesForInt:"
+            MethodKind: Class
+            SwiftName: "init(swift3Factory:)"
+          - Selector: "initWithBoolean:"
+            MethodKind: Instance
+            SwiftName: "init(swift3Boolean:)"
+          - Selector: "doImportantThings"
+            MethodKind: Instance
+            SwiftName: "swift3DoImportantThings()"
+        Properties:
+          - Name: "importantClassProperty"
+            PropertyKind: Class
+            SwiftName: "swift3ClassProperty"
+          - Name: "importantInstanceProperty"
+            PropertyKind: Instance
+            SwiftName: "swift3InstanceProperty"
     Protocols:
       - Name: ProtoWithVersionedUnavailableMember
         Methods:
           - Selector: requirement
             MethodKind: Instance
             ResultType: 'ForwardClass * _Nullable'
+      - Name: ProtoWithManyRenames
+        Methods:
+          - Selector: "initWithBoolean:"
+            MethodKind: Instance
+            SwiftName: "init(swift3Boolean:)"
+          - Selector: "doImportantThings"
+            MethodKind: Instance
+            SwiftName: "swift3DoImportantThings()"
+        Properties:
+          - Name: "importantClassProperty"
+            PropertyKind: Class
+            SwiftName: "swift3ClassProperty"
     Functions:
       - Name: acceptDoublePointer
         SwiftName: 'acceptPointer(_:)'
@@ -116,3 +146,14 @@
         SwiftName: ImportantCAlias
       - Name: EnclosingStructIdentifier
         SwiftName: EnclosingStructIdentifier
+    Enumerators:
+      - Name: AnonymousEnumRenamed
+        SwiftName: AnonymousEnumRenamedSwift3
+      - Name: UnknownEnumRenamed
+        SwiftName: UnknownEnumRenamedSwift3
+      - Name: TrueEnumRenamed
+        SwiftName: renamedSwift3
+      - Name: TrueEnumAliasRenamed
+        SwiftName: aliasRenamedSwift3
+      - Name: OptionyEnumRenamed
+        SwiftName: renamedSwift3
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
index 97b1d2e..c0f387e 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/APINotesFrameworkTest.h
@@ -25,6 +25,7 @@
 #endif // __OBJC__
 
 #import <APINotesFrameworkTest/Classes.h>
+#import <APINotesFrameworkTest/Enums.h>
 #import <APINotesFrameworkTest/ImportAsMember.h>
 #import <APINotesFrameworkTest/Properties.h>
 #import <APINotesFrameworkTest/Protocols.h>
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Classes.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Classes.h
index c74a642..73e44fa 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Classes.h
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Classes.h
@@ -8,5 +8,14 @@
 @interface RenamedGeneric<Element: Base *> : Base
 @end
 
+@interface ClassWithManyRenames : Base
++ (instancetype)classWithManyRenamesForInt:(int)value;
+- (instancetype)initWithBoolean:(_Bool)value __attribute__((swift_name("init(finalBoolean:)")));
+
+- (void)doImportantThings __attribute__((swift_name("finalDoImportantThings()")));
+@property (class, nullable) id importantClassProperty __attribute__((swift_name("finalClassProperty")));
+@property (nullable) id importantInstanceProperty __attribute__((swift_name("finalInstanceProperty")));
+@end
+
 #pragma clang assume_nonnull end
 #endif // __OBJC__
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Enums.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Enums.h
new file mode 100644
index 0000000..bfe32fc
--- /dev/null
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Enums.h
@@ -0,0 +1,24 @@
+#pragma clang assume_nonnull begin
+
+enum {
+  AnonymousEnumValue,
+  AnonymousEnumRenamed __attribute__((swift_name("AnonymousEnumRenamedSwiftUnversioned")))
+};
+
+enum UnknownEnum {
+  UnknownEnumValue,
+  UnknownEnumRenamed __attribute__((swift_name("UnknownEnumRenamedSwiftUnversioned")))
+};
+
+enum __attribute__((enum_extensibility(open))) TrueEnum {
+  TrueEnumValue,
+  TrueEnumRenamed __attribute__((swift_name("renamedSwiftUnversioned"))),
+  TrueEnumAliasRenamed __attribute__((swift_name("aliasRenamedSwiftUnversioned")))
+};
+
+enum __attribute__((flag_enum)) OptionyEnum {
+  OptionyEnumValue = 1,
+  OptionyEnumRenamed __attribute__((swift_name("renamedSwiftUnversioned"))) = 2
+};
+
+#pragma clang assume_nonnull end
diff --git a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Protocols.h b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Protocols.h
index 6a8840c..1e66303 100644
--- a/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Protocols.h
+++ b/test/APINotes/Inputs/custom-frameworks/APINotesFrameworkTest.framework/Headers/Protocols.h
@@ -7,5 +7,11 @@
 - (nullable id)requirement;
 @end
 
+@protocol ProtoWithManyRenames
+- (instancetype)initWithBoolean:(_Bool)value __attribute__((swift_name("init(finalBoolean:)")));
+- (void)doImportantThings __attribute__((swift_name("finalDoImportantThings()")));
+@property (class, nullable) id importantClassProperty __attribute__((swift_name("finalClassProperty")));
+@end
+
 #pragma clang assume_nonnull end
 #endif // __OBJC__
diff --git a/test/APINotes/versioned-objc-dynamic-lookup.swift b/test/APINotes/versioned-objc-dynamic-lookup.swift
new file mode 100644
index 0000000..d3bf2b6
--- /dev/null
+++ b/test/APINotes/versioned-objc-dynamic-lookup.swift
@@ -0,0 +1,35 @@
+// RUN: rm -rf %t && mkdir -p %t
+
+// RUN: not %target-swift-frontend -typecheck -F %S/Inputs/custom-frameworks -swift-version 4 %s 2>&1 | %FileCheck -check-prefix=CHECK-DIAGS -check-prefix=CHECK-DIAGS-4 %s
+// RUN: not %target-swift-frontend -typecheck -F %S/Inputs/custom-frameworks -swift-version 3 %s 2>&1 | %FileCheck -check-prefix=CHECK-DIAGS -check-prefix=CHECK-DIAGS-3 %s
+
+// REQUIRES: objc_interop
+
+import APINotesFrameworkTest
+
+func testRenamedClassMembers(obj: AnyObject) {
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'doImportantThings()' has been renamed to 'swift3DoImportantThings()'
+  obj.doImportantThings()
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'doImportantThings()' has been renamed to 'finalDoImportantThings()'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  obj.swift3DoImportantThings()
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'swift3DoImportantThings()' has been renamed to 'finalDoImportantThings()'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'finalDoImportantThings()' has been renamed to 'swift3DoImportantThings()'
+  obj.finalDoImportantThings()
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'importantInstanceProperty' has been renamed to 'swift3InstanceProperty'
+  _ = obj.importantInstanceProperty
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'importantInstanceProperty' has been renamed to 'finalInstanceProperty'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  _ = obj.swift3InstanceProperty
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'swift3InstanceProperty' has been renamed to 'finalInstanceProperty'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'finalInstanceProperty' has been renamed to 'swift3InstanceProperty'
+  _ = obj.finalInstanceProperty
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+}
\ No newline at end of file
diff --git a/test/APINotes/versioned-objc.swift b/test/APINotes/versioned-objc.swift
index 9cf44f4..bb6258a 100644
--- a/test/APINotes/versioned-objc.swift
+++ b/test/APINotes/versioned-objc.swift
@@ -43,4 +43,101 @@
   // CHECK-DIAGS-4:[[@LINE-1]]:{{[0-9]+}}: error: 'RenamedGeneric' requires that 'SwiftClass' inherit from 'Base'
 }
 
+func testRenamedClassMembers(obj: ClassWithManyRenames) {
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'classWithManyRenamesForInt' has been replaced by 'init(swift3Factory:)'
+  _ = ClassWithManyRenames.classWithManyRenamesForInt(0)
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'classWithManyRenamesForInt' has been replaced by 'init(for:)'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'init(forInt:)' has been replaced by 'init(swift3Factory:)'
+  _ = ClassWithManyRenames(forInt: 0)
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'init(forInt:)' has been replaced by 'init(for:)'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  _ = ClassWithManyRenames(swift3Factory: 0)
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'init(swift3Factory:)' has been replaced by 'init(for:)'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'init(for:)' has been replaced by 'init(swift3Factory:)'
+  _ = ClassWithManyRenames(for: 0)
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'init(boolean:)' has been renamed to 'init(swift3Boolean:)'
+  _ = ClassWithManyRenames(boolean: false)
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'init(boolean:)' has been renamed to 'init(finalBoolean:)'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  _ = ClassWithManyRenames(swift3Boolean: false)
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'init(swift3Boolean:)' has been renamed to 'init(finalBoolean:)'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'init(finalBoolean:)' has been renamed to 'init(swift3Boolean:)'
+  _ = ClassWithManyRenames(finalBoolean: false)
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'doImportantThings()' has been renamed to 'swift3DoImportantThings()'
+  obj.doImportantThings()
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'doImportantThings()' has been renamed to 'finalDoImportantThings()'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  obj.swift3DoImportantThings()
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'swift3DoImportantThings()' has been renamed to 'finalDoImportantThings()'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'finalDoImportantThings()' has been renamed to 'swift3DoImportantThings()'
+  obj.finalDoImportantThings()
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'importantClassProperty' has been renamed to 'swift3ClassProperty'
+  _ = ClassWithManyRenames.importantClassProperty
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'importantClassProperty' has been renamed to 'finalClassProperty'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  _ = ClassWithManyRenames.swift3ClassProperty
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'swift3ClassProperty' has been renamed to 'finalClassProperty'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'finalClassProperty' has been renamed to 'swift3ClassProperty'
+  _ = ClassWithManyRenames.finalClassProperty
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+}
+
+func testRenamedProtocolMembers(obj: ProtoWithManyRenames) {
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'init(boolean:)' has been renamed to 'init(swift3Boolean:)'
+  _ = type(of: obj).init(boolean: false)
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'init(boolean:)' has been renamed to 'init(finalBoolean:)'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  _ = type(of: obj).init(swift3Boolean: false)
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'init(swift3Boolean:)' has been renamed to 'init(finalBoolean:)'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'init(finalBoolean:)' has been renamed to 'init(swift3Boolean:)'
+  _ = type(of: obj).init(finalBoolean: false)
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'doImportantThings()' has been renamed to 'swift3DoImportantThings()'
+  obj.doImportantThings()
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'doImportantThings()' has been renamed to 'finalDoImportantThings()'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  obj.swift3DoImportantThings()
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'swift3DoImportantThings()' has been renamed to 'finalDoImportantThings()'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'finalDoImportantThings()' has been renamed to 'swift3DoImportantThings()'
+  obj.finalDoImportantThings()
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'importantClassProperty' has been renamed to 'swift3ClassProperty'
+  _ = type(of: obj).importantClassProperty
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'importantClassProperty' has been renamed to 'finalClassProperty'
+
+  // CHECK-DIAGS-3-NOT: :[[@LINE+1]]:{{[0-9]+}}:
+  _ = type(of: obj).swift3ClassProperty
+  // CHECK-DIAGS-4: [[@LINE-1]]:{{[0-9]+}}: error: 'swift3ClassProperty' has been renamed to 'finalClassProperty'
+
+  // CHECK-DIAGS-3: [[@LINE+1]]:{{[0-9]+}}: error: 'finalClassProperty' has been renamed to 'swift3ClassProperty'
+  _ = type(of: obj).finalClassProperty
+  // CHECK-DIAGS-4-NOT: :[[@LINE-1]]:{{[0-9]+}}:
+}
+
 let unrelatedDiagnostic: Int = nil
diff --git a/test/APINotes/versioned.swift b/test/APINotes/versioned.swift
index 34f6e49..17c16ba 100644
--- a/test/APINotes/versioned.swift
+++ b/test/APINotes/versioned.swift
@@ -125,6 +125,127 @@
   // CHECK-DIAGS-3: versioned.swift:[[@LINE-1]]:16: error: cannot convert value of type 'Optional<ImportantCAlias>' (aka 'Optional<Int32>') to specified type 'Int'
 }
 
+func testRenamedEnumConstants() {
+  _ = AnonymousEnumValue // okay
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:7: error: 'AnonymousEnumRenamed' has been renamed to 'AnonymousEnumRenamedSwiftUnversioned'
+  _ = AnonymousEnumRenamed
+  // CHECK-DIAGS-3: [[@LINE-1]]:7: error: 'AnonymousEnumRenamed' has been renamed to 'AnonymousEnumRenamedSwift3'
+
+  // CHECK-DIAGS-4-NOT: :[[@LINE+1]]:7:
+  _ = AnonymousEnumRenamedSwiftUnversioned
+  // CHECK-DIAGS-3: [[@LINE-1]]:7: error: 'AnonymousEnumRenamedSwiftUnversioned' has been renamed to 'AnonymousEnumRenamedSwift3'
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:7: error: 'AnonymousEnumRenamedSwift3' has been renamed to 'AnonymousEnumRenamedSwiftUnversioned'
+  _ = AnonymousEnumRenamedSwift3
+  // CHECK-DIAGS-3-NOT: :[[@LINE-1]]:7:
+}
+
+func testRenamedUnknownEnum() {
+  _ = UnknownEnumValue // okay
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:7: error: 'UnknownEnumRenamed' has been renamed to 'UnknownEnumRenamedSwiftUnversioned'
+  _ = UnknownEnumRenamed
+  // CHECK-DIAGS-3: [[@LINE-1]]:7: error: 'UnknownEnumRenamed' has been renamed to 'UnknownEnumRenamedSwift3'
+
+  // CHECK-DIAGS-4-NOT: :[[@LINE+1]]:7:
+  _ = UnknownEnumRenamedSwiftUnversioned
+  // CHECK-DIAGS-3: [[@LINE-1]]:7: error: 'UnknownEnumRenamedSwiftUnversioned' has been renamed to 'UnknownEnumRenamedSwift3'
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:7: error: 'UnknownEnumRenamedSwift3' has been renamed to 'UnknownEnumRenamedSwiftUnversioned'
+  _ = UnknownEnumRenamedSwift3
+  // CHECK-DIAGS-3-NOT: :[[@LINE-1]]:7:
+}
+
+func testRenamedTrueEnum() {
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: use of unresolved identifier 'TrueEnumValue'
+  _ = TrueEnumValue
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: type 'TrueEnum' has no member 'TrueEnumValue'
+  _ = TrueEnum.TrueEnumValue
+
+  // CHECK-DIAGS: [[@LINE+1]]:16: error: 'Value' has been renamed to 'value'
+  _ = TrueEnum.Value
+
+  _ = TrueEnum.value // okay
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: use of unresolved identifier 'TrueEnumRenamed'
+  _ = TrueEnumRenamed
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: type 'TrueEnum' has no member 'TrueEnumRenamed'
+  _ = TrueEnum.TrueEnumRenamed
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:16: error: 'Renamed' has been renamed to 'renamedSwiftUnversioned'
+  _ = TrueEnum.Renamed
+  // CHECK-DIAGS-3: [[@LINE-1]]:16: error: 'Renamed' has been renamed to 'renamedSwift3'
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: type 'TrueEnum' has no member 'renamed'
+  _ = TrueEnum.renamed
+
+  // CHECK-DIAGS-4-NOT: :[[@LINE+1]]:16:
+  _ = TrueEnum.renamedSwiftUnversioned
+  // CHECK-DIAGS-3: [[@LINE-1]]:16: error: 'renamedSwiftUnversioned' has been renamed to 'renamedSwift3'
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:16: error: 'renamedSwift3' has been renamed to 'renamedSwiftUnversioned'
+  _ = TrueEnum.renamedSwift3
+  // CHECK-DIAGS-3-NOT: :[[@LINE-1]]:16:
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: use of unresolved identifier 'TrueEnumAliasRenamed'
+  _ = TrueEnumAliasRenamed
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: type 'TrueEnum' has no member 'TrueEnumAliasRenamed'
+  _ = TrueEnum.TrueEnumAliasRenamed
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:16: error: 'AliasRenamed' has been renamed to 'aliasRenamedSwiftUnversioned'
+  _ = TrueEnum.AliasRenamed
+  // CHECK-DIAGS-3: [[@LINE-1]]:16: error: 'AliasRenamed' has been renamed to 'aliasRenamedSwift3'
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: type 'TrueEnum' has no member 'aliasRenamed'
+  _ = TrueEnum.aliasRenamed
+
+  // CHECK-DIAGS-4-NOT: :[[@LINE+1]]:16:
+  _ = TrueEnum.aliasRenamedSwiftUnversioned
+  // CHECK-DIAGS-3: [[@LINE-1]]:16: error: 'aliasRenamedSwiftUnversioned' has been renamed to 'aliasRenamedSwift3'
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:16: error: 'aliasRenamedSwift3' has been renamed to 'aliasRenamedSwiftUnversioned'
+  _ = TrueEnum.aliasRenamedSwift3
+  // CHECK-DIAGS-3-NOT: :[[@LINE-1]]:16:
+}
+
+func testRenamedOptionyEnum() {
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: use of unresolved identifier 'OptionyEnumValue'
+  _ = OptionyEnumValue
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: type 'OptionyEnum' has no member 'OptionyEnumValue'
+  _ = OptionyEnum.OptionyEnumValue
+
+  // CHECK-DIAGS: [[@LINE+1]]:19: error: 'Value' has been renamed to 'value'
+  _ = OptionyEnum.Value
+
+  _ = OptionyEnum.value // okay
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: use of unresolved identifier 'OptionyEnumRenamed'
+  _ = OptionyEnumRenamed
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: type 'OptionyEnum' has no member 'OptionyEnumRenamed'
+  _ = OptionyEnum.OptionyEnumRenamed
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:19: error: 'Renamed' has been renamed to 'renamedSwiftUnversioned'
+  _ = OptionyEnum.Renamed
+  // CHECK-DIAGS-3: [[@LINE-1]]:19: error: 'Renamed' has been renamed to 'renamedSwift3'
+
+  // CHECK-DIAGS: [[@LINE+1]]:7: error: type 'OptionyEnum' has no member 'renamed'
+  _ = OptionyEnum.renamed
+
+  // CHECK-DIAGS-4-NOT: :[[@LINE+1]]:19:
+  _ = OptionyEnum.renamedSwiftUnversioned
+  // CHECK-DIAGS-3: [[@LINE-1]]:19: error: 'renamedSwiftUnversioned' has been renamed to 'renamedSwift3'
+
+  // CHECK-DIAGS-4: [[@LINE+1]]:19: error: 'renamedSwift3' has been renamed to 'renamedSwiftUnversioned'
+  _ = OptionyEnum.renamedSwift3
+  // CHECK-DIAGS-3-NOT: :[[@LINE-1]]:19:
+}
+
 #endif
 
 #if !swift(>=4)
diff --git a/test/ClangImporter/Inputs/SwiftPrivateAttr.txt b/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
index 5572fbd..6ea47fa 100644
--- a/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
+++ b/test/ClangImporter/Inputs/SwiftPrivateAttr.txt
@@ -9,21 +9,21 @@
   func __oneArg(_ arg: Int32)
   func __twoArgs(_ arg: Int32, other arg2: Int32)
   class func __withNoArgs() -> Self!
+  @available(swift, obsoleted: 3, renamed: "__withNoArgs()")
+  class func __fooWithNoArgs() -> Self!
+  convenience init!(__oneArg arg: Int32)
   @available(*, unavailable, renamed: "init(__oneArg:)", message: "Not available in Swift")
   class func __fooWithOneArg(_ arg: Int32) -> Self!
-  convenience init!(__oneArg arg: Int32)
+  convenience init!(__twoArgs arg: Int32, other arg2: Int32)
   @available(*, unavailable, renamed: "init(__twoArgs:other:)", message: "Not available in Swift")
   class func __fooWithTwoArgs(_ arg: Int32, other arg2: Int32) -> Self!
-  convenience init!(__twoArgs arg: Int32, other arg2: Int32)
+  convenience init!(__ arg: Int32)
   @available(*, unavailable, renamed: "init(__:)", message: "Not available in Swift")
   class func __foo(_ arg: Int32) -> Self!
-  convenience init!(__ arg: Int32)
   func objectForKeyedSubscript(_ index: Any!) -> Any!
   func __setObject(_ object: Any!, forKeyedSubscript index: Any!)
   func __objectAtIndexedSubscript(_ index: Int32) -> Any!
   func setObject(_ object: Any!, atIndexedSubscript index: Int32)
-  @available(swift, obsoleted: 3, renamed: "__withNoArgs()")
-  class func __fooWithNoArgs() -> Self!
   init()
 }
 class Bar : NSObject {
diff --git a/test/IDE/print_clang_decls_AppKit.swift b/test/IDE/print_clang_decls_AppKit.swift
index 1167e5d..0cbb1a4 100644
--- a/test/IDE/print_clang_decls_AppKit.swift
+++ b/test/IDE/print_clang_decls_AppKit.swift
@@ -20,7 +20,11 @@
 // APPKIT-LABEL: {{^}}class NSView : NSObject, NSCoding, NSAccessibility {{{$}}
 // APPKIT-NEXT: init?(coder aDecoder: NSCoder)
 // APPKIT-NEXT: func isDescendant(of aView: NSView) -> Bool
+// APPKIT-NEXT: @available(swift, obsoleted: 3, renamed: "isDescendant(of:)")
+// APPKIT-NEXT: func isDescendantOf(_ aView: NSView) -> Bool
 // APPKIT-NEXT: func ancestorShared(with aView: NSView) -> NSView?
+// APPKIT-NEXT: @available(swift, obsoleted: 3, renamed: "ancestorShared(with:)")
+// APPKIT-NEXT: func ancestorSharedWithView(_ aView: NSView) -> NSView?
 // APPKIT-NEXT: func addSubview(_ aView: NSView)
 // APPKIT-NEXT: func addSubview(_ aView: NSView, positioned place: UInt32, relativeTo otherView: NSView?)
 // APPKIT-NEXT: unowned(unsafe) var superview: @sil_unmanaged NSView? { get }
diff --git a/test/IDE/print_clang_swift_name.swift b/test/IDE/print_clang_swift_name.swift
index 03af90e..8a79ab0 100644
--- a/test/IDE/print_clang_swift_name.swift
+++ b/test/IDE/print_clang_swift_name.swift
@@ -12,75 +12,79 @@
 class Test : NSObject {
   
   // "Factory methods" that we'd rather have as initializers.
-  @available(*, unavailable, renamed: "init()", message: "Not available in Swift")
-  class func a() -> Self
   @available(*, unavailable, message: "superseded by import of -[NSObject init]")
   convenience init()
+  @available(*, unavailable, renamed: "init()", message: "Not available in Swift")
+  class func a() -> Self
+  convenience init(dummyParam: ())
   @available(*, unavailable, renamed: "init(dummyParam:)", message: "Not available in Swift")
   class func b() -> Self
-  convenience init(dummyParam: ())
   
+  convenience init(cc x: Any)
   @available(*, unavailable, renamed: "init(cc:)", message: "Not available in Swift")
   class func c(_ x: Any) -> Self
-  convenience init(cc x: Any)
+  convenience init(_ x: Any)
   @available(*, unavailable, renamed: "init(_:)", message: "Not available in Swift")
   class func d(_ x: Any) -> Self
-  convenience init(_ x: Any)
   
+  convenience init(aa a: Any, _ b: Any, cc c: Any)
   @available(*, unavailable, renamed: "init(aa:_:cc:)", message: "Not available in Swift")
   class func e(_ a: Any, e b: Any, e c: Any) -> Self
-  convenience init(aa a: Any, _ b: Any, cc c: Any)
   
+  /*not inherited*/ init(fixedType: ())
   @available(*, unavailable, renamed: "init(fixedType:)", message: "Not available in Swift")
   class func f() -> Test
-  /*not inherited*/ init(fixedType: ())
   
   // Would-be initializers.
   class func zz() -> Self
-  class func yy(aa x: Any) -> Self
-  class func xx(_ x: Any, bb xx: Any) -> Self
   @available(swift, obsoleted: 3, renamed: "zz()")
   class func testZ() -> Self
+  class func yy(aa x: Any) -> Self
+  @available(*, unavailable, renamed: "yy(aa:)", message: "Not available in Swift")
+  class func testY(_ x: Any) -> Self
+  class func xx(_ x: Any, bb xx: Any) -> Self
+  @available(*, unavailable, renamed: "xx(_:bb:)", message: "Not available in Swift")
+  class func testX(_ x: Any, xx: Any) -> Self
   
   init()
 }
 
 class TestError : NSObject {
   // Factory methods with NSError.
+  convenience init(error: ()) throws
   @available(*, unavailable, renamed: "init(error:)", message: "Not available in Swift")
   class func err1() throws -> Self
-  convenience init(error: ()) throws
+  convenience init(aa x: Any?, error: ()) throws
   @available(*, unavailable, renamed: "init(aa:error:)", message: "Not available in Swift")
   class func err2(_ x: Any?) throws -> Self
-  convenience init(aa x: Any?, error: ()) throws
+  convenience init(aa x: Any?, error: (), block: @escaping () -> Void) throws
   @available(*, unavailable, renamed: "init(aa:error:block:)", message: "Not available in Swift")
   class func err3(_ x: Any?, callback block: @escaping () -> Void) throws -> Self
-  convenience init(aa x: Any?, error: (), block: @escaping () -> Void) throws
+  convenience init(error: (), block: @escaping () -> Void) throws
   @available(*, unavailable, renamed: "init(error:block:)", message: "Not available in Swift")
   class func err4(callback block: @escaping () -> Void) throws -> Self
-  convenience init(error: (), block: @escaping () -> Void) throws
   
+  convenience init(aa x: Any?) throws
   @available(*, unavailable, renamed: "init(aa:)", message: "Not available in Swift")
   class func err5(_ x: Any?) throws -> Self
-  convenience init(aa x: Any?) throws
+  convenience init(aa x: Any?, block: @escaping () -> Void) throws
   @available(*, unavailable, renamed: "init(aa:block:)", message: "Not available in Swift")
   class func err6(_ x: Any?, callback block: @escaping () -> Void) throws -> Self
-  convenience init(aa x: Any?, block: @escaping () -> Void) throws
+  convenience init(block: @escaping () -> Void) throws
   @available(*, unavailable, renamed: "init(block:)", message: "Not available in Swift")
   class func err7(callback block: @escaping () -> Void) throws -> Self
-  convenience init(block: @escaping () -> Void) throws
   
   // Would-be initializers.
   class func ww(_ x: Any?) throws -> Self
-  class func w2(_ x: Any?, error: ()) throws -> Self
-  class func vv() throws -> Self
-  class func v2(error: ()) throws -> Self
   @available(swift, obsoleted: 3, renamed: "ww(_:)")
   class func testW(_ x: Any?) throws -> Self
+  class func w2(_ x: Any?, error: ()) throws -> Self
   @available(swift, obsoleted: 3, renamed: "w2(_:error:)")
   class func testW2(_ x: Any?) throws -> Self
+  class func vv() throws -> Self
   @available(swift, obsoleted: 3, renamed: "vv()")
   class func testV() throws -> Self
+  class func v2(error: ()) throws -> Self
   @available(swift, obsoleted: 3, renamed: "v2(error:)")
   class func testV2() throws -> Self
   init()
diff --git a/test/IDE/print_omit_needless_words.swift b/test/IDE/print_omit_needless_words.swift
index da2c7b6..0bb9e08 100644
--- a/test/IDE/print_omit_needless_words.swift
+++ b/test/IDE/print_omit_needless_words.swift
@@ -261,25 +261,37 @@
 // CHECK-OMIT-NEEDLESS-WORDS: func addDoodle(_: ABCDoodle)
 
 // Protocols as contexts
-// CHECK-OMIT-NEEDLESS-WORDS: protocol OMWLanding {
+// CHECK-OMIT-NEEDLESS-WORDS-LABEL: protocol OMWLanding {
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: func flip()
 
 // Verify that we get the Swift name from the original declaration.
-// CHECK-OMIT-NEEDLESS-WORDS: protocol OMWWiggle
+// CHECK-OMIT-NEEDLESS-WORDS-LABEL: protocol OMWWiggle
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: func joinSub()
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: func wiggle1()
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: @available(swift, obsoleted: 3, renamed: "wiggle1()")
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: func conflicting1()
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: var wiggleProp1: Int { get }
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: @available(swift, obsoleted: 3, renamed: "wiggleProp1")
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: var conflictingProp1: Int { get }
 
-// CHECK-OMIT-NEEDLESS-WORDS: protocol OMWWaggle
+// CHECK-OMIT-NEEDLESS-WORDS-LABEL: protocol OMWWaggle
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: func waggle1()
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: @available(swift, obsoleted: 3, renamed: "waggle1()")
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: func conflicting1()
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: var waggleProp1: Int { get }
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: @available(swift, obsoleted: 3, renamed: "waggleProp1")
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: var conflictingProp1: Int { get }
 
-// CHECK-OMIT-NEEDLESS-WORDS: class OMWSuper
+// CHECK-OMIT-NEEDLESS-WORDS-LABEL: class OMWSuper
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: func jump()
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: @available(swift, obsoleted: 3, renamed: "jump()")
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: func jumpSuper()
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: var wiggleProp1: Int { get }
 
-// CHECK-OMIT-NEEDLESS-WORDS: class OMWSub
+// CHECK-OMIT-NEEDLESS-WORDS-LABEL: class OMWSub
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: func jump()
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: @available(swift, obsoleted: 3, renamed: "jump()")
+// CHECK-OMIT-NEEDLESS-WORDS-NEXT: func jumpSuper()
 // CHECK-OMIT-NEEDLESS-WORDS-NEXT: func joinSub()
 
 // CHECK-OMIT-NEEDLESS-WORDS-DIAGS: inconsistent Swift name for Objective-C method 'conflicting1' in 'OMWSub' ('waggle1()' in 'OMWWaggle' vs. 'wiggle1()' in 'OMWWiggle')
diff --git a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
index 33aa335..f463328 100644
--- a/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
+++ b/tools/SourceKit/lib/SwiftLang/SwiftSourceDocInfo.cpp
@@ -1341,7 +1341,7 @@
       ASTInvok->applyTo(CompInvok);
       RangeInfo Result;
       Result.RangeKind = Lang.getUIDForRangeKind(Info.Kind);
-      Result.RangeContent = Info.Content;
+      Result.RangeContent = Info.Content.str();
       switch (Info.Kind) {
       case RangeKind::SingleExpression: {
         SmallString<64> SS;