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()