Merge pull request #22145 from rintaro/5.0-sourcekit-rdar47426948

[5.0][SourceKit] Fix a crash in SwiftDocumentStructureWalker::getObjCSelectorName()
diff --git a/include/swift/ABI/Metadata.h b/include/swift/ABI/Metadata.h
index dc59061..34c2994 100644
--- a/include/swift/ABI/Metadata.h
+++ b/include/swift/ABI/Metadata.h
@@ -2808,21 +2808,79 @@
 using ExtensionContextDescriptor = TargetExtensionContextDescriptor<InProcess>;
 
 template<typename Runtime>
+struct TargetMangledContextName {
+  /// The mangled name of the context.
+  TargetRelativeDirectPointer<Runtime, const char, /*nullable*/ false> name;
+};
+
+template<typename Runtime>
 struct TargetAnonymousContextDescriptor final
     : TargetContextDescriptor<Runtime>,
-      TrailingGenericContextObjects<TargetAnonymousContextDescriptor<Runtime>>
+      TrailingGenericContextObjects<TargetAnonymousContextDescriptor<Runtime>,
+                                    TargetGenericContextDescriptorHeader,
+                                    TargetMangledContextName<Runtime>>
 {
 private:
   using TrailingGenericContextObjects
-    = TrailingGenericContextObjects<TargetAnonymousContextDescriptor<Runtime>>;
+    = TrailingGenericContextObjects<TargetAnonymousContextDescriptor<Runtime>,
+                                    TargetGenericContextDescriptorHeader,
+                                    TargetMangledContextName<Runtime>>;
+  using TrailingObjects =
+    typename TrailingGenericContextObjects::TrailingObjects;
+  friend TrailingObjects;
 
 public:
-  using TrailingGenericContextObjects::getGenericContext;
+  using MangledContextName = TargetMangledContextName<Runtime>;
 
+  using TrailingGenericContextObjects::getGenericContext;
+  using TrailingGenericContextObjects::getGenericContextHeader;
+  using TrailingGenericContextObjects::getFullGenericContextHeader;
+  using TrailingGenericContextObjects::getGenericParams;
+
+  AnonymousContextDescriptorFlags getAnonymousContextDescriptorFlags() const {
+    return AnonymousContextDescriptorFlags(this->Flags.getKindSpecificFlags());
+  }
+
+  /// Whether this anonymous context descriptor contains a full mangled name,
+  /// which can be used to match the anonymous type to its textual form.
+  bool hasMangledName() const {
+    return getAnonymousContextDescriptorFlags().hasMangledName();
+  }
+
+  /// Retrieve the mangled name of this context, or NULL if it was not
+  /// recorded in the metadata.
+  ConstTargetPointer<Runtime, char> getMangledName() const {
+    if (!hasMangledName())
+      return ConstTargetPointer<Runtime, char>();
+
+    return this->template getTrailingObjects<MangledContextName>()->name;
+  }
+
+  /// Retrieve a pointer to the mangled context name structure.
+  const MangledContextName *getMangledContextName() const {
+    if (!hasMangledName())
+      return nullptr;
+
+    return this->template getTrailingObjects<MangledContextName>();
+  }
+
+private:
+  template<typename T>
+  using OverloadToken =
+    typename TrailingGenericContextObjects::template OverloadToken<T>;
+
+  using TrailingGenericContextObjects::numTrailingObjects;
+
+  size_t numTrailingObjects(OverloadToken<MangledContextName>) const {
+    return this->hasMangledNam() ? 1 : 0;
+  }
+
+public:
   static bool classof(const TargetContextDescriptor<Runtime> *cd) {
     return cd->getKind() == ContextDescriptorKind::Anonymous;
   }
 };
+using AnonymousContextDescriptor = TargetAnonymousContextDescriptor<InProcess>;
 
 /// A protocol descriptor.
 ///
diff --git a/include/swift/ABI/MetadataValues.h b/include/swift/ABI/MetadataValues.h
index bf2ce18..f6c5497 100644
--- a/include/swift/ABI/MetadataValues.h
+++ b/include/swift/ABI/MetadataValues.h
@@ -1344,6 +1344,23 @@
                                  setSpecialProtocol)
 };
 
+/// Flags for anonymous type context descriptors. These values are used as the
+/// kindSpecificFlags of the ContextDescriptorFlags for the anonymous context.
+class AnonymousContextDescriptorFlags : public FlagSet<uint16_t> {
+  enum {
+    /// Whether this anonymous context descriptor is followed by its
+    /// mangled name, which can be used to match the descriptor at runtime.
+    HasMangledName = 0,
+  };
+
+public:
+  explicit AnonymousContextDescriptorFlags(uint16_t bits) : FlagSet(bits) {}
+  constexpr AnonymousContextDescriptorFlags() {}
+
+  FLAGSET_DEFINE_FLAG_ACCESSORS(HasMangledName, hasMangledName,
+                                setHasMangledName)
+};
+
 enum class GenericParamKind : uint8_t {
   /// A type parameter.
   Type = 0,
diff --git a/include/swift/AST/IRGenOptions.h b/include/swift/AST/IRGenOptions.h
index 3fd4d44..1ca21db 100644
--- a/include/swift/AST/IRGenOptions.h
+++ b/include/swift/AST/IRGenOptions.h
@@ -165,6 +165,9 @@
   /// Emit names of struct stored properties and enum cases.
   unsigned EnableReflectionNames : 1;
 
+  /// Emit mangled names of anonymous context descriptors.
+  unsigned EnableAnonymousContextMangledNames : 1;
+
   /// Enables resilient class layout.
   unsigned EnableClassResilience : 1;
 
@@ -224,7 +227,8 @@
         EmitStackPromotionChecks(false), PrintInlineTree(false),
         EmbedMode(IRGenEmbedMode::None), HasValueNamesSetting(false),
         ValueNames(false), EnableReflectionMetadata(true),
-        EnableReflectionNames(true), EnableClassResilience(false),
+        EnableReflectionNames(true), EnableAnonymousContextMangledNames(false),
+        EnableClassResilience(false),
         EnableResilienceBypass(false), LazyInitializeClassMetadata(false),
         UseIncrementalLLVMCodeGen(true), UseSwiftCall(false),
         GenerateProfile(false), EnableDynamicReplacementChaining(false),
diff --git a/include/swift/Option/FrontendOptions.td b/include/swift/Option/FrontendOptions.td
index b902c40..68d3637 100644
--- a/include/swift/Option/FrontendOptions.td
+++ b/include/swift/Option/FrontendOptions.td
@@ -272,6 +272,10 @@
 def enable_llvm_value_names : Flag<["-"], "enable-llvm-value-names">,
   HelpText<"Add names to local values in LLVM IR">;
 
+def enable_anonymous_context_mangled_names :
+  Flag<["-"], "enable-anonymous-context-mangled-names">,
+  HelpText<"Enable emission of mangled names in anonymous context descriptors">;
+
 def disable_reflection_metadata : Flag<["-"], "disable-reflection-metadata">,
   HelpText<"Disable emission of reflection metadata for nominal types">;
 
diff --git a/include/swift/Remote/MetadataReader.h b/include/swift/Remote/MetadataReader.h
index c8d9eb2..a589fda 100644
--- a/include/swift/Remote/MetadataReader.h
+++ b/include/swift/Remote/MetadataReader.h
@@ -594,8 +594,8 @@
         return BuiltType();
 
       // Build the demangling tree from the context tree.
-      Demangle::NodeFactory nodeFactory;
-      auto node = buildContextMangling(descriptor, nodeFactory);
+      Demangler dem;
+      auto node = buildContextMangling(descriptor, dem);
       if (!node || node->getKind() != Node::Kind::Type)
         return BuiltType();
 
@@ -1203,7 +1203,7 @@
     }
   }
 
-  /// Given the address of a nominal type descriptor, attempt to read it.
+  /// Given the address of a context descriptor, attempt to read it.
   ContextDescriptorRef
   readContextDescriptor(StoredPointer address) {
     if (address == 0)
@@ -1248,6 +1248,10 @@
       break;
     case ContextDescriptorKind::Anonymous:
       baseSize = sizeof(TargetAnonymousContextDescriptor<Runtime>);
+      if (AnonymousContextDescriptorFlags(flags.getKindSpecificFlags())
+            .hasMangledName()) {
+        baseSize += sizeof(TargetMangledContextName<Runtime>);
+      }
       break;
     case ContextDescriptorKind::Class:
       baseSize = sizeof(TargetClassDescriptor<Runtime>);
@@ -1352,12 +1356,162 @@
     return false;
   }
 
+  /// Read the name from a module, type, or protocol context descriptor.
+  Optional<std::string> readContextDescriptorName(
+      ContextDescriptorRef descriptor,
+      Optional<TypeImportInfo<std::string>> &importInfo) {
+    std::string name;
+    auto context = descriptor.getLocalBuffer();
+
+    // Read the name of a protocol.
+    if (auto protoBuffer =
+            dyn_cast<TargetProtocolDescriptor<Runtime>>(context)) {
+      auto nameAddress = resolveRelativeField(descriptor, protoBuffer->Name);
+      if (Reader->readString(RemoteAddress(nameAddress), name))
+        return name;
+
+      return None;
+    }
+
+    // Read the name of a module.
+    if (auto moduleBuffer =
+            dyn_cast<TargetModuleContextDescriptor<Runtime>>(context)) {
+      auto nameAddress = resolveRelativeField(descriptor, moduleBuffer->Name);
+      if (Reader->readString(RemoteAddress(nameAddress), name))
+        return name;
+
+      return None;
+    }
+
+    // Only type contexts remain.
+    auto typeBuffer = dyn_cast<TargetTypeContextDescriptor<Runtime>>(context);
+    if (!typeBuffer)
+      return None;
+
+    auto nameAddress = resolveRelativeField(descriptor, typeBuffer->Name);
+    if (!Reader->readString(RemoteAddress(nameAddress), name))
+      return None;
+
+    // Read the TypeImportInfo if present.
+    if (typeBuffer->getTypeContextDescriptorFlags().hasImportInfo()) {
+      importInfo.emplace();
+      nameAddress += name.size() + 1;
+
+      while (true) {
+        // Read the next string.
+        std::string temp;
+        if (!Reader->readString(RemoteAddress(nameAddress), temp))
+          return None;
+
+        // If we read an empty string, we're done.
+        if (temp.empty())
+          break;
+
+        // Advance past the string.
+        nameAddress += temp.size() + 1;
+
+        // Collect the import information.  Ignore anything we don't
+        // understand.
+        importInfo->collect</*asserting*/false>(std::move(temp));
+      }
+
+      // Ignore the original if we have an ABI name override.
+      if (!importInfo->ABIName.empty())
+        name = std::move(importInfo->ABIName);
+    }
+
+    return name;
+  }
+
+  /// If we have a context whose parent context is an anonymous context
+  /// that provides the local/private name for the current context,
+  /// produce a mangled node describing the name of \c context.
+  Demangle::NodePointer
+  adoptAnonymousContextName(ContextDescriptorRef contextRef,
+                            Optional<ContextDescriptorRef> &parentContextRef,
+                            Demangler &dem) {
+    if (!parentContextRef || !*parentContextRef)
+      return nullptr;
+
+    auto context = contextRef.getLocalBuffer();
+    auto typeContext = dyn_cast<TargetTypeContextDescriptor<Runtime>>(context);
+    auto protoContext = dyn_cast<TargetProtocolDescriptor<Runtime>>(context);
+    if (!typeContext && !protoContext)
+      return nullptr;
+
+    auto anonymousParent = dyn_cast_or_null<TargetAnonymousContextDescriptor<Runtime>>(
+            parentContextRef->getLocalBuffer());
+    if (!anonymousParent)
+      return nullptr;
+
+    // Only perform this transformation when we have a mangled name describing
+    // the context.
+    if (!anonymousParent->hasMangledName())
+      return nullptr;
+
+    // Read the mangled name.
+    auto mangledContextName = anonymousParent->getMangledContextName();
+    auto mangledNameAddress = resolveRelativeField(*parentContextRef,
+                                                   mangledContextName->name);
+
+    std::string mangledName;
+    if (!Reader->readString(RemoteAddress(mangledNameAddress), mangledName))
+      return nullptr;
+
+    auto mangledNode = dem.demangleSymbol(mangledName);
+    if (!mangledNode)
+      return nullptr;
+
+    if (mangledNode->getKind() == Demangle::Node::Kind::Global)
+      mangledNode = mangledNode->getFirstChild();
+
+    if (mangledNode->getNumChildren() < 2)
+      return nullptr;
+
+    // Dig out the name of the entity.
+    // FIXME: LocalDeclName
+    NodePointer nameChild = mangledNode->getChild(1);
+    if (nameChild->getKind() != Node::Kind::PrivateDeclName ||
+        nameChild->getNumChildren() < 2)
+      return nullptr;
+
+    // Make sure we have an identifier where we expect it.
+    auto identifierNode = nameChild->getChild(1);
+    if (identifierNode->getKind() != Node::Kind::Identifier ||
+        !identifierNode->hasText())
+      return nullptr;
+
+    // Read the name of the current context.
+    Optional<TypeImportInfo<std::string>> importInfo;
+    auto contextName = readContextDescriptorName(contextRef, importInfo);
+    if (!contextName)
+      return nullptr;
+
+    // Make sure the name of the current context matches the one in the mangled
+    // name of the parent anonymous context.
+    // FIXME: Use the ABI name here.
+    if (*contextName != identifierNode->getText())
+      return nullptr;
+
+    // We have a match. Update the parent context to skip the anonymous
+    // context entirely.
+    parentContextRef = readParentContextDescriptor(*parentContextRef);
+
+    // Return the name.
+    return nameChild;
+  }
+
   Demangle::NodePointer
   buildContextDescriptorMangling(ContextDescriptorRef descriptor,
-                                 Demangle::NodeFactory &nodeFactory) {
+                                 Demangler &dem) {
     // Read the parent descriptor.
     auto parentDescriptorResult = readParentContextDescriptor(descriptor);
 
+    // If the parent is an anonymous context that provides a complete
+    // name for this node, note that.
+    auto nameNode = adoptAnonymousContextName(
+        descriptor, parentDescriptorResult, dem);
+
     // If there was a problem reading the parent descriptor, we're done.
     if (!parentDescriptorResult) return nullptr;
 
@@ -1365,81 +1519,48 @@
     Demangle::NodePointer parentDemangling = nullptr;
     if (auto parentDescriptor = *parentDescriptorResult) {
       parentDemangling =
-        buildContextDescriptorMangling(parentDescriptor, nodeFactory);
+        buildContextDescriptorMangling(parentDescriptor, dem);
       if (!parentDemangling)
         return nullptr;
     }
 
-    std::string nodeName;
-    std::string relatedTag;
     Demangle::Node::Kind nodeKind;
     Optional<TypeImportInfo<std::string>> importInfo;
 
-    auto getTypeName = [&]() -> bool {
-      auto typeBuffer =
-        reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
-          (descriptor.getLocalBuffer());
-      auto nameAddress = resolveRelativeField(descriptor, typeBuffer->Name);
-      if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
-        return false;
+    auto getContextName = [&]() -> bool {
+      if (nameNode)
+        return true;
 
-      // Read the TypeImportInfo if present.
-      if (typeBuffer->getTypeContextDescriptorFlags().hasImportInfo()) {
-        importInfo.emplace();
-        nameAddress += nodeName.size() + 1;
-
-        while (true) {
-          // Read the next string.
-          std::string temp;
-          if (!Reader->readString(RemoteAddress(nameAddress), temp))
-            return false;
-
-          // If we read an empty string, we're done.
-          if (temp.empty())
-            break;
-
-          // Advance past the string.
-          nameAddress += temp.size() + 1;
-
-          // Collect the import information.  Ignore anything we don't
-          // understand.
-          importInfo->collect</*asserting*/false>(std::move(temp));
-        }
-
-        // Ignore the original if we have an ABI name override.
-        if (!importInfo->ABIName.empty())
-          nodeName = std::move(importInfo->ABIName);
+      if (auto name = readContextDescriptorName(descriptor, importInfo)) {
+        nameNode = dem.createNode(Node::Kind::Identifier, std::move(*name));
+        return true;
       }
-      
-      return true;
+
+      return false;
     };
-    
+
     bool isTypeContext = false;
     switch (auto contextKind = descriptor->getKind()) {
     case ContextDescriptorKind::Class:
-      if (!getTypeName())
+      if (!getContextName())
         return nullptr;
       nodeKind = Demangle::Node::Kind::Class;
       isTypeContext = true;
       break;
     case ContextDescriptorKind::Struct:
-      if (!getTypeName())
+      if (!getContextName())
         return nullptr;
       nodeKind = Demangle::Node::Kind::Structure;
       isTypeContext = true;
       break;
     case ContextDescriptorKind::Enum:
-      if (!getTypeName())
+      if (!getContextName())
         return nullptr;
       nodeKind = Demangle::Node::Kind::Enum;
       isTypeContext = true;
       break;
     case ContextDescriptorKind::Protocol: {
-      auto protocolBuffer =
-        reinterpret_cast<const TargetProtocolDescriptor<Runtime> *>
-          (descriptor.getLocalBuffer());
-      auto nameAddress = resolveRelativeField(descriptor, protocolBuffer->Name);
-      if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
+      if (!getContextName())
         return nullptr;
 
       nodeKind = Demangle::Node::Kind::Protocol;
@@ -1454,13 +1575,13 @@
       char addressBuf[18];
       snprintf(addressBuf, sizeof(addressBuf), "$%" PRIx64,
                (uint64_t)descriptor.getAddress());
-      auto anonNode = nodeFactory.createNode(Node::Kind::AnonymousContext);
+      auto anonNode = dem.createNode(Node::Kind::AnonymousContext);
       CharVector addressStr;
-      addressStr.append(addressBuf, nodeFactory);
-      auto name = nodeFactory.createNode(Node::Kind::Identifier, addressStr);
-      anonNode->addChild(name, nodeFactory);
+      addressStr.append(addressBuf, dem);
+      auto name = dem.createNode(Node::Kind::Identifier, addressStr);
+      anonNode->addChild(name, dem);
       if (parentDemangling)
-        anonNode->addChild(parentDemangling, nodeFactory);
+        anonNode->addChild(parentDemangling, dem);
       
       return anonNode;
     }
@@ -1477,12 +1598,13 @@
           (descriptor.getLocalBuffer());
       auto nameAddress
         = resolveRelativeField(descriptor, moduleBuffer->Name);
-      if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
+      std::string moduleName;
+      if (!Reader->readString(RemoteAddress(nameAddress), moduleName))
         return nullptr;
 
       // The form of module contexts is a little different from other
       // contexts; just create the node directly here and return.
-      return nodeFactory.createNode(nodeKind, std::move(nodeName));
+      return dem.createNode(nodeKind, std::move(moduleName));
     }
     
     default:
@@ -1513,15 +1635,13 @@
         nodeKind = Demangle::Node::Kind::Structure;
     }
 
-    auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
-                                           std::move(nodeName));
-
     // Use private declaration names for anonymous context references.
-    if (parentDemangling->getKind() == Node::Kind::AnonymousContext) {
+    if (parentDemangling->getKind() == Node::Kind::AnonymousContext
+        && nameNode->getKind() == Node::Kind::Identifier) {
       auto privateDeclName =
-        nodeFactory.createNode(Node::Kind::PrivateDeclName);
-      privateDeclName->addChild(parentDemangling->getChild(0), nodeFactory);
-      privateDeclName->addChild(nameNode, nodeFactory);
+        dem.createNode(Node::Kind::PrivateDeclName);
+      privateDeclName->addChild(parentDemangling->getChild(0), dem);
+      privateDeclName->addChild(nameNode, dem);
 
       nameNode = privateDeclName;
       parentDemangling = parentDemangling->getChild(1);
@@ -1529,15 +1649,15 @@
 
     if (importInfo && !importInfo->RelatedEntityName.empty()) {
       auto relatedNode =
-        nodeFactory.createNode(Node::Kind::RelatedEntityDeclName,
+        dem.createNode(Node::Kind::RelatedEntityDeclName,
                                std::move(importInfo->RelatedEntityName));
-      relatedNode->addChild(nameNode, nodeFactory);
+      relatedNode->addChild(nameNode, dem);
       nameNode = relatedNode;
     }
 
-    auto demangling = nodeFactory.createNode(nodeKind);
-    demangling->addChild(parentDemangling, nodeFactory);
-    demangling->addChild(nameNode, nodeFactory);
+    auto demangling = dem.createNode(nodeKind);
+    demangling->addChild(parentDemangling, dem);
+    demangling->addChild(nameNode, dem);
     return demangling;
   }
 
@@ -1545,8 +1665,8 @@
   /// for it.
   Demangle::NodePointer
   buildContextMangling(ContextDescriptorRef descriptor,
-                       Demangle::NodeFactory &nodeFactory) {
-    auto demangling = buildContextDescriptorMangling(descriptor, nodeFactory);
+                       Demangler &dem) {
+    auto demangling = buildContextDescriptorMangling(descriptor, dem);
     if (!demangling)
       return nullptr;
 
@@ -1554,8 +1674,8 @@
     // References to type nodes behave as types in the mangling.
     if (isa<TargetTypeContextDescriptor<Runtime>>(descriptor.getLocalBuffer()) ||
         isa<TargetProtocolDescriptor<Runtime>>(descriptor.getLocalBuffer())) {
-      top = nodeFactory.createNode(Node::Kind::Type);
-      top->addChild(demangling, nodeFactory);
+      top = dem.createNode(Node::Kind::Type);
+      top->addChild(demangling, dem);
     } else {
       top = demangling;
     }
@@ -1568,8 +1688,8 @@
   BuiltNominalTypeDecl
   buildNominalTypeDecl(ContextDescriptorRef descriptor) {
     // Build the demangling tree from the context tree.
-    Demangle::NodeFactory nodeFactory;
-    auto node = buildContextMangling(descriptor, nodeFactory);
+    Demangler dem;
+    auto node = buildContextMangling(descriptor, dem);
     if (!node || node->getKind() != Node::Kind::Type)
       return BuiltNominalTypeDecl();
     BuiltNominalTypeDecl decl = Builder.createNominalTypeDecl(node);
diff --git a/lib/Demangling/NodePrinter.cpp b/lib/Demangling/NodePrinter.cpp
index b2d764e..1ce7b3e 100644
--- a/lib/Demangling/NodePrinter.cpp
+++ b/lib/Demangling/NodePrinter.cpp
@@ -1013,8 +1013,11 @@
   case Node::Kind::AnonymousContext:
     if (Options.QualifyEntities && Options.DisplayExtensionContexts) {
       print(Node->getChild(1));
-      Printer << ".(unknown context at " << Node->getChild(0)->getText() << ")";
-      if (Node->getChild(2)->getNumChildren() > 0) {
+      Printer << ".(unknown context at ";
+      print(Node->getChild(0));
+      Printer << ")";
+      if (Node->getNumChildren() >= 3 &&
+          Node->getChild(2)->getNumChildren() > 0) {
         Printer << '<';
         print(Node->getChild(2));
         Printer << '>';
diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp
index 9250e4d..e4a55c3 100644
--- a/lib/Driver/ToolChains.cpp
+++ b/lib/Driver/ToolChains.cpp
@@ -243,6 +243,12 @@
     arguments.push_back(inputArgs.MakeArgString(workingDirectory));
   }
 
+  // -g implies -enable-anonymous-context-mangled-names, because the extra
+  // metadata aids debugging.
+  if (inputArgs.hasArg(options::OPT_g)) {
+    arguments.push_back("-enable-anonymous-context-mangled-names");
+  }
+
   // Pass through any subsystem flags.
   inputArgs.AddAllArgs(arguments, options::OPT_Xllvm);
   inputArgs.AddAllArgs(arguments, options::OPT_Xcc);
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index a8d0b22..f21a41a 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1041,6 +1041,9 @@
     Opts.EnableReflectionNames = false;
   }
 
+  if (Args.hasArg(OPT_enable_anonymous_context_mangled_names))
+    Opts.EnableAnonymousContextMangledNames = true;
+
   if (Args.hasArg(OPT_disable_reflection_names)) {
     Opts.EnableReflectionNames = false;
   }
diff --git a/lib/IRGen/GenMeta.cpp b/lib/IRGen/GenMeta.cpp
index b24f2d6..a3678de 100644
--- a/lib/IRGen/GenMeta.cpp
+++ b/lib/IRGen/GenMeta.cpp
@@ -511,6 +511,7 @@
     void layout() {
       super::layout();
       asImpl().addGenericSignature();
+      asImpl().addMangledName();
     }
   
     ConstantReference getParent() {
@@ -530,6 +531,26 @@
       return true;
     }
 
+    uint16_t getKindSpecificFlags() {
+      AnonymousContextDescriptorFlags flags{};
+      flags.setHasMangledName(
+        IGM.IRGen.Opts.EnableAnonymousContextMangledNames);
+
+      return flags.getOpaqueValue();
+    }
+
+    void addMangledName() {
+      if (!IGM.IRGen.Opts.EnableAnonymousContextMangledNames)
+        return;
+
+      IRGenMangler mangler;
+      auto mangledName = mangler.mangleContext(DC);
+      auto mangledNameConstant =
+        IGM.getAddrOfGlobalString(mangledName,
+                                  /*willBeRelativelyAddressed*/ true);
+      B.addRelativeAddress(mangledNameConstant);
+    }
+
     void emit() {
       asImpl().layout();
       auto addr = IGM.getAddrOfAnonymousContextDescriptor(DC,
diff --git a/lib/IRGen/IRGenMangler.h b/lib/IRGen/IRGenMangler.h
index 9f3b7aa..4d92b15 100644
--- a/lib/IRGen/IRGenMangler.h
+++ b/lib/IRGen/IRGenMangler.h
@@ -153,7 +153,13 @@
     appendOperator("MXX");
     return finalize();
   }
-  
+
+  std::string mangleContext(const DeclContext *DC) {
+    beginMangling();
+    appendContext(DC);
+    return finalize();
+  }
+
   std::string mangleBareProtocol(const ProtocolDecl *Decl) {
     beginMangling();
     appendProtocolName(Decl, /*allowStandardSubstitution=*/false);
diff --git a/test/Driver/debug_anonymous_context_metadata.swift b/test/Driver/debug_anonymous_context_metadata.swift
new file mode 100644
index 0000000..7138ab2
--- /dev/null
+++ b/test/Driver/debug_anonymous_context_metadata.swift
@@ -0,0 +1,4 @@
+// RUN: %target-swiftc_driver -### -g %s 2>&1 | %FileCheck %s
+
+// CHECK: -enable-anonymous-context-mangled-names
+
diff --git a/test/IRGen/anonymous_context_descriptors.sil b/test/IRGen/anonymous_context_descriptors.sil
index 3097d5a..82d973b 100644
--- a/test/IRGen/anonymous_context_descriptors.sil
+++ b/test/IRGen/anonymous_context_descriptors.sil
@@ -1,4 +1,5 @@
 // RUN: %target-swift-frontend -emit-ir %s | %FileCheck %s
+// RUN: %target-swift-frontend -emit-ir -enable-anonymous-context-mangled-names %s | %FileCheck %s -check-prefix CHECK-MANGLED
 
 import Builtin
 import Swift
@@ -9,15 +10,30 @@
   private struct Inner<U: P> { }
 }
 
+// Mangled name of the anonymous descriptor
+// CHECK-NOT: private constant [84 x i8] c"$s29anonymous_context_descriptors4BlahC5Inner33_4F495173994818481DD703D65EB08308LLV\00"
+// CHECK-MANGLED: [[INNER_MANGLED:@[0-9]+]] = private constant [84 x i8] c"$s29anonymous_context_descriptors4BlahC5Inner33_4F495173994818481DD703D65EB08308LLV\00"
+
 // Anonymous descriptor
 // CHECK: @"$s29anonymous_context_descriptors4BlahC5Inner33{{.*}}MXX" =
+// CHECK-MANGLED: @"$s29anonymous_context_descriptors4BlahC5Inner33{{.*}}MXX" =
 
 // Flags: anonymous (2) + generic (0x80) + unique (0x40)
 // CHECK-SAME: i32 194
 
+// Flags: anonymous (2) + generic (0x80) + unique (0x40) + has mangled name (0x10000)
+// CHECK-MANGLED-SAME: i32 65730
+
 // Parent
 // CHECK-SAME: $s29anonymous_context_descriptors4BlahCMn
+// CHECK-MANGLED-SAME: $s29anonymous_context_descriptors4BlahCMn
 
 // # generic header
 // CHECK-SAME: i16 2, i16 2
 // CHECK-SAME: i16 4, i16 0
+
+// CHECK-MANGLED-SAME: i16 2, i16 2
+// CHECK-MANGLED-SAME: i16 4, i16 0
+
+// # mangled name
+// CHECK-MANGLED-SAME: [[INNER_MANGLED]]
diff --git a/test/RemoteAST/nominal_types.swift b/test/RemoteAST/nominal_types.swift
index b5385bd..4db9ae1 100644
--- a/test/RemoteAST/nominal_types.swift
+++ b/test/RemoteAST/nominal_types.swift
@@ -1,4 +1,4 @@
-// RUN: %target-swift-remoteast-test %s | %FileCheck %s
+// RUN: %target-swift-remoteast-test -enable-anonymous-context-mangled-names %s | %FileCheck %s
 
 // REQUIRES: swift-remoteast-test
 
@@ -92,3 +92,37 @@
 // CHECK: found type: J & K
 printType(KJ.self)
 // CHECK: found type: J & K
+
+struct L {
+  private struct PrivateInner { }
+  private struct PrivateInnerGeneric<T> { }
+
+  static func testPrivate() {
+    // CHECK: L.PrivateInner
+    printType(L.PrivateInner.self)
+
+    // CHECK: L.PrivateInnerGeneric<Int>
+    printType(L.PrivateInnerGeneric<Int>.self)
+
+    // CHECK: L.PrivateInnerGeneric<String>
+    printType(L.PrivateInnerGeneric<String>.self)
+  }
+}
+L.testPrivate()
+
+struct M<T, U> {
+  private struct Inner { }
+  private struct InnerGeneric<V> { }
+
+  static func testPrivate() {
+    // CHECK: M<Int, String>.Inner
+    printType(Inner.self)
+
+    // CHECK: M<Int, String>.InnerGeneric<Double>
+    printType(InnerGeneric<Double>.self)
+
+    // CHECK: M<Int, String>.InnerGeneric<(String, Int)>
+    printType(InnerGeneric<(U, T)>.self)
+  }
+}
+M<Int, String>.testPrivate()