mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge remote-tracking branch 'origin/master' into master-next
This commit is contained in:
@@ -28,6 +28,7 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
|
#include "swift/Strings.h"
|
||||||
#include "swift/Runtime/Config.h"
|
#include "swift/Runtime/Config.h"
|
||||||
#include "swift/ABI/MetadataValues.h"
|
#include "swift/ABI/MetadataValues.h"
|
||||||
#include "swift/ABI/System.h"
|
#include "swift/ABI/System.h"
|
||||||
@@ -2344,6 +2345,9 @@ using ProtocolConformanceRecord = TargetProtocolConformanceRecord<InProcess>;
|
|||||||
template<typename Runtime>
|
template<typename Runtime>
|
||||||
struct TargetGenericContext;
|
struct TargetGenericContext;
|
||||||
|
|
||||||
|
template<typename Runtime>
|
||||||
|
struct TargetModuleContextDescriptor;
|
||||||
|
|
||||||
/// Base class for all context descriptors.
|
/// Base class for all context descriptors.
|
||||||
template<typename Runtime>
|
template<typename Runtime>
|
||||||
struct TargetContextDescriptor {
|
struct TargetContextDescriptor {
|
||||||
@@ -2361,6 +2365,12 @@ struct TargetContextDescriptor {
|
|||||||
/// context is not generic.
|
/// context is not generic.
|
||||||
const TargetGenericContext<Runtime> *getGenericContext() const;
|
const TargetGenericContext<Runtime> *getGenericContext() const;
|
||||||
|
|
||||||
|
/// Get the module context for this context.
|
||||||
|
const TargetModuleContextDescriptor<Runtime> *getModuleContext() const;
|
||||||
|
|
||||||
|
/// Is this context part of a C-imported module?
|
||||||
|
bool isCImportedContext() const;
|
||||||
|
|
||||||
unsigned getNumGenericParams() const {
|
unsigned getNumGenericParams() const {
|
||||||
auto *genericContext = getGenericContext();
|
auto *genericContext = getGenericContext();
|
||||||
return genericContext
|
return genericContext
|
||||||
@@ -2376,12 +2386,24 @@ private:
|
|||||||
|
|
||||||
using ContextDescriptor = TargetContextDescriptor<InProcess>;
|
using ContextDescriptor = TargetContextDescriptor<InProcess>;
|
||||||
|
|
||||||
|
inline bool isCImportedModuleName(StringRef name) {
|
||||||
|
// This does not include MANGLING_MODULE_CLANG_IMPORTER because that's
|
||||||
|
// used only for synthesized declarations and not actual imported
|
||||||
|
// declarations.
|
||||||
|
return name == MANGLING_MODULE_OBJC;
|
||||||
|
}
|
||||||
|
|
||||||
/// Descriptor for a module context.
|
/// Descriptor for a module context.
|
||||||
template<typename Runtime>
|
template<typename Runtime>
|
||||||
struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
|
struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
|
||||||
/// The module name.
|
/// The module name.
|
||||||
RelativeDirectPointer<const char, /*nullable*/ false> Name;
|
RelativeDirectPointer<const char, /*nullable*/ false> Name;
|
||||||
|
|
||||||
|
/// Is this module a special C-imported module?
|
||||||
|
bool isCImportedContext() const {
|
||||||
|
return isCImportedModuleName(Name.get());
|
||||||
|
}
|
||||||
|
|
||||||
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
|
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
|
||||||
return cd->getKind() == ContextDescriptorKind::Module;
|
return cd->getKind() == ContextDescriptorKind::Module;
|
||||||
}
|
}
|
||||||
@@ -2389,6 +2411,21 @@ struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
|
|||||||
|
|
||||||
using ModuleContextDescriptor = TargetModuleContextDescriptor<InProcess>;
|
using ModuleContextDescriptor = TargetModuleContextDescriptor<InProcess>;
|
||||||
|
|
||||||
|
template<typename Runtime>
|
||||||
|
inline bool TargetContextDescriptor<Runtime>::isCImportedContext() const {
|
||||||
|
return getModuleContext()->isCImportedContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Runtime>
|
||||||
|
inline const TargetModuleContextDescriptor<Runtime> *
|
||||||
|
TargetContextDescriptor<Runtime>::getModuleContext() const {
|
||||||
|
// All context chains should eventually find a module.
|
||||||
|
for (auto cur = this; true; cur = cur->Parent.get()) {
|
||||||
|
if (auto module = dyn_cast<TargetModuleContextDescriptor<Runtime>>(cur))
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Runtime>
|
template<typename Runtime>
|
||||||
struct TargetGenericContextDescriptorHeader {
|
struct TargetGenericContextDescriptorHeader {
|
||||||
uint16_t NumParams, NumRequirements, NumKeyArguments, NumExtraArguments;
|
uint16_t NumParams, NumRequirements, NumKeyArguments, NumExtraArguments;
|
||||||
|
|||||||
@@ -1321,9 +1321,6 @@ public:
|
|||||||
getImportNamespace,
|
getImportNamespace,
|
||||||
setImportNamespace)
|
setImportNamespace)
|
||||||
|
|
||||||
bool isCTag() const {
|
|
||||||
return getImportNamespace() == CTag;
|
|
||||||
}
|
|
||||||
bool isCTypedef() const {
|
bool isCTypedef() const {
|
||||||
return getImportNamespace() == CTypedef;
|
return getImportNamespace() == CTypedef;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1291,15 +1291,171 @@ private:
|
|||||||
return ContextDescriptorRef(address, descriptor);
|
return ContextDescriptorRef(address, descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
ContextDescriptorRef
|
/// Returns Optional(nullptr) if there's no parent descriptor.
|
||||||
|
/// Returns None if there was an error reading the parent descriptor.
|
||||||
|
Optional<ContextDescriptorRef>
|
||||||
readParentContextDescriptor(ContextDescriptorRef base) {
|
readParentContextDescriptor(ContextDescriptorRef base) {
|
||||||
auto parentAddress =
|
auto parentAddress =
|
||||||
resolveNullableRelativeIndirectableField(base, base->Parent);
|
resolveNullableRelativeIndirectableField(base, base->Parent);
|
||||||
|
if (!parentAddress)
|
||||||
|
return None;
|
||||||
|
if (!*parentAddress)
|
||||||
|
return ContextDescriptorRef(nullptr);
|
||||||
|
if (auto parentDescriptor = readContextDescriptor(*parentAddress))
|
||||||
|
return parentDescriptor;
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
if (parentAddress) {
|
static bool isCImportedContext(Demangle::NodePointer node) {
|
||||||
return readContextDescriptor(*parentAddress);
|
do {
|
||||||
|
if (node->getKind() == Demangle::Node::Kind::Module) {
|
||||||
|
return isCImportedModuleName(node->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue to the parent.
|
||||||
|
node = node->getChild(0);
|
||||||
|
} while (node);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Demangle::NodePointer
|
||||||
|
buildContextDescriptorMangling(ContextDescriptorRef descriptor,
|
||||||
|
Demangle::NodeFactory &nodeFactory) {
|
||||||
|
// Read the parent descriptor.
|
||||||
|
auto parentDescriptorResult = readParentContextDescriptor(descriptor);
|
||||||
|
|
||||||
|
// If there was a problem reading the parent descriptor, we're done.
|
||||||
|
if (!parentDescriptorResult) return nullptr;
|
||||||
|
|
||||||
|
// Try to produce a mangle-tree for the parent.
|
||||||
|
Demangle::NodePointer parentDemangling = nullptr;
|
||||||
|
if (auto parentDescriptor = *parentDescriptorResult) {
|
||||||
|
parentDemangling =
|
||||||
|
buildContextDescriptorMangling(parentDescriptor, nodeFactory);
|
||||||
|
if (!parentDemangling)
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
|
std::string nodeName;
|
||||||
|
std::string relatedTag;
|
||||||
|
Demangle::Node::Kind nodeKind;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (typeBuffer->isSynthesizedRelatedEntity()) {
|
||||||
|
nameAddress += nodeName.size() + 1;
|
||||||
|
if (!Reader->readString(RemoteAddress(nameAddress), relatedTag))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool isTypeContext = false;
|
||||||
|
switch (auto contextKind = descriptor->getKind()) {
|
||||||
|
case ContextDescriptorKind::Class:
|
||||||
|
if (!getTypeName())
|
||||||
|
return nullptr;
|
||||||
|
nodeKind = Demangle::Node::Kind::Class;
|
||||||
|
isTypeContext = true;
|
||||||
|
break;
|
||||||
|
case ContextDescriptorKind::Struct:
|
||||||
|
if (!getTypeName())
|
||||||
|
return nullptr;
|
||||||
|
nodeKind = Demangle::Node::Kind::Structure;
|
||||||
|
isTypeContext = true;
|
||||||
|
break;
|
||||||
|
case ContextDescriptorKind::Enum:
|
||||||
|
if (!getTypeName())
|
||||||
|
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))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
nodeKind = Demangle::Node::Kind::Protocol;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ContextDescriptorKind::Extension:
|
||||||
|
// TODO: Remangle something about the extension context here.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
case ContextDescriptorKind::Anonymous:
|
||||||
|
// TODO: Remangle something about the anonymous context here.
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
case ContextDescriptorKind::Module: {
|
||||||
|
// Modules shouldn't have a parent.
|
||||||
|
if (parentDemangling) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nodeKind = Demangle::Node::Kind::Module;
|
||||||
|
auto moduleBuffer =
|
||||||
|
reinterpret_cast<const TargetModuleContextDescriptor<Runtime> *>
|
||||||
|
(descriptor.getLocalBuffer());
|
||||||
|
auto nameAddress
|
||||||
|
= resolveRelativeField(descriptor, moduleBuffer->Name);
|
||||||
|
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Not a kind of context we know about.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The root context should be a module context, which we handled directly
|
||||||
|
// in the switch, so if we got here without a parent, we're ill-formed.
|
||||||
|
if (!parentDemangling) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the node kind if this was a Clang-imported type.
|
||||||
|
if (isTypeContext) {
|
||||||
|
auto typeFlags =
|
||||||
|
TypeContextDescriptorFlags(descriptor->Flags.getKindSpecificFlags());
|
||||||
|
|
||||||
|
if (typeFlags.isCTypedef())
|
||||||
|
nodeKind = Demangle::Node::Kind::TypeAlias;
|
||||||
|
|
||||||
|
// As a special case, always use the struct mangling for C-imported
|
||||||
|
// value types.
|
||||||
|
else if (nodeKind == Demangle::Node::Kind::Enum &&
|
||||||
|
!typeFlags.isSynthesizedRelatedEntity() &&
|
||||||
|
isCImportedContext(parentDemangling))
|
||||||
|
nodeKind = Demangle::Node::Kind::Structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
|
||||||
|
std::move(nodeName));
|
||||||
|
if (!relatedTag.empty()) {
|
||||||
|
auto relatedNode =
|
||||||
|
nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
|
||||||
|
relatedNode->addChild(nameNode, nodeFactory);
|
||||||
|
nameNode = relatedNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto demangling = nodeFactory.createNode(nodeKind);
|
||||||
|
demangling->addChild(parentDemangling, nodeFactory);
|
||||||
|
demangling->addChild(nameNode, nodeFactory);
|
||||||
|
return demangling;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a read nominal type descriptor, attempt to build a demangling tree
|
/// Given a read nominal type descriptor, attempt to build a demangling tree
|
||||||
@@ -1307,129 +1463,10 @@ private:
|
|||||||
Demangle::NodePointer
|
Demangle::NodePointer
|
||||||
buildNominalTypeMangling(ContextDescriptorRef descriptor,
|
buildNominalTypeMangling(ContextDescriptorRef descriptor,
|
||||||
Demangle::NodeFactory &nodeFactory) {
|
Demangle::NodeFactory &nodeFactory) {
|
||||||
std::vector<std::pair<Demangle::Node::Kind, Demangle::NodePointer>>
|
auto demangling = buildContextDescriptorMangling(descriptor, nodeFactory);
|
||||||
nameComponents;
|
if (!demangling)
|
||||||
ContextDescriptorRef parent = descriptor;
|
|
||||||
|
|
||||||
while (parent) {
|
|
||||||
std::string nodeName;
|
|
||||||
std::string relatedTag;
|
|
||||||
Demangle::Node::Kind nodeKind;
|
|
||||||
|
|
||||||
auto getTypeName = [&]() -> bool {
|
|
||||||
auto typeBuffer =
|
|
||||||
reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
|
|
||||||
(parent.getLocalBuffer());
|
|
||||||
auto nameAddress = resolveRelativeField(parent, typeBuffer->Name);
|
|
||||||
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (typeBuffer->isSynthesizedRelatedEntity()) {
|
|
||||||
nameAddress += nodeName.size() + 1;
|
|
||||||
if (!Reader->readString(RemoteAddress(nameAddress), relatedTag))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
bool isTypeContext = false;
|
|
||||||
switch (auto contextKind = parent->getKind()) {
|
|
||||||
case ContextDescriptorKind::Class:
|
|
||||||
if (!getTypeName())
|
|
||||||
return nullptr;
|
|
||||||
nodeKind = Demangle::Node::Kind::Class;
|
|
||||||
isTypeContext = true;
|
|
||||||
break;
|
|
||||||
case ContextDescriptorKind::Struct:
|
|
||||||
if (!getTypeName())
|
|
||||||
return nullptr;
|
|
||||||
nodeKind = Demangle::Node::Kind::Structure;
|
|
||||||
isTypeContext = true;
|
|
||||||
break;
|
|
||||||
case ContextDescriptorKind::Enum:
|
|
||||||
if (!getTypeName())
|
|
||||||
return nullptr;
|
|
||||||
nodeKind = Demangle::Node::Kind::Enum;
|
|
||||||
isTypeContext = true;
|
|
||||||
break;
|
|
||||||
case ContextDescriptorKind::Protocol: {
|
|
||||||
auto protocolBuffer =
|
|
||||||
reinterpret_cast<const TargetProtocolDescriptor<Runtime> *>
|
|
||||||
(parent.getLocalBuffer());
|
|
||||||
auto nameAddress = resolveRelativeField(parent, protocolBuffer->Name);
|
|
||||||
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
nodeKind = Demangle::Node::Kind::Protocol;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ContextDescriptorKind::Extension:
|
|
||||||
// TODO: Remangle something about the extension context here.
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
case ContextDescriptorKind::Anonymous:
|
|
||||||
// TODO: Remangle something about the anonymous context here.
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
case ContextDescriptorKind::Module: {
|
|
||||||
nodeKind = Demangle::Node::Kind::Module;
|
|
||||||
auto moduleBuffer =
|
|
||||||
reinterpret_cast<const TargetModuleContextDescriptor<Runtime> *>(
|
|
||||||
parent.getLocalBuffer());
|
|
||||||
auto nameAddress
|
|
||||||
= resolveRelativeField(parent, moduleBuffer->Name);
|
|
||||||
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
|
|
||||||
return nullptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Not a kind of context we know about.
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Override the node kind if this was a Clang-imported type.
|
|
||||||
if (isTypeContext) {
|
|
||||||
auto typeFlags =
|
|
||||||
TypeContextDescriptorFlags(parent->Flags.getKindSpecificFlags());
|
|
||||||
|
|
||||||
if (typeFlags.isCTag())
|
|
||||||
nodeKind = Demangle::Node::Kind::Structure;
|
|
||||||
else if (typeFlags.isCTypedef())
|
|
||||||
nodeKind = Demangle::Node::Kind::TypeAlias;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto nameNode = nodeFactory.createNode(Node::Kind::Identifier,
|
|
||||||
nodeName);
|
|
||||||
if (!relatedTag.empty()) {
|
|
||||||
auto relatedNode =
|
|
||||||
nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
|
|
||||||
relatedNode->addChild(nameNode, nodeFactory);
|
|
||||||
nameNode = relatedNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
nameComponents.emplace_back(nodeKind, nameNode);
|
|
||||||
|
|
||||||
parent = readParentContextDescriptor(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should have made our way up to a module context.
|
|
||||||
if (nameComponents.empty())
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (nameComponents.back().first != Node::Kind::Module)
|
|
||||||
return nullptr;
|
|
||||||
auto moduleInfo = std::move(nameComponents.back());
|
|
||||||
nameComponents.pop_back();
|
|
||||||
auto demangling =
|
|
||||||
nodeFactory.createNode(Node::Kind::Module, moduleInfo.second->getText());
|
|
||||||
for (auto &component : reversed(nameComponents)) {
|
|
||||||
auto parent = nodeFactory.createNode(component.first);
|
|
||||||
parent->addChild(demangling, nodeFactory);
|
|
||||||
parent->addChild(component.second, nodeFactory);
|
|
||||||
demangling = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto top = nodeFactory.createNode(Node::Kind::Type);
|
auto top = nodeFactory.createNode(Node::Kind::Type);
|
||||||
top->addChild(demangling, nodeFactory);
|
top->addChild(demangling, nodeFactory);
|
||||||
return top;
|
return top;
|
||||||
|
|||||||
@@ -165,10 +165,11 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
|
|||||||
// Override the node kind if this is a Clang-imported type so we give it
|
// Override the node kind if this is a Clang-imported type so we give it
|
||||||
// a stable mangling.
|
// a stable mangling.
|
||||||
auto typeFlags = type->getTypeContextDescriptorFlags();
|
auto typeFlags = type->getTypeContextDescriptorFlags();
|
||||||
if (typeFlags.isCTag()) {
|
if (typeFlags.isCTypedef()) {
|
||||||
nodeKind = Node::Kind::Structure;
|
|
||||||
} else if (typeFlags.isCTypedef()) {
|
|
||||||
nodeKind = Node::Kind::TypeAlias;
|
nodeKind = Node::Kind::TypeAlias;
|
||||||
|
} else if (nodeKind != Node::Kind::Structure &&
|
||||||
|
isCImportedTagType(type)) {
|
||||||
|
nodeKind = Node::Kind::Structure;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto typeNode = Dem.createNode(nodeKind);
|
auto typeNode = Dem.createNode(nodeKind);
|
||||||
|
|||||||
@@ -153,6 +153,24 @@ static const TypeContextDescriptor *
|
|||||||
_findNominalTypeDescriptor(Demangle::NodePointer node,
|
_findNominalTypeDescriptor(Demangle::NodePointer node,
|
||||||
Demangle::Demangler &Dem);
|
Demangle::Demangler &Dem);
|
||||||
|
|
||||||
|
bool swift::isCImportedTagType(const TypeContextDescriptor *type) {
|
||||||
|
// Tag types are always imported as structs or enums.
|
||||||
|
if (type->getKind() != ContextDescriptorKind::Enum &&
|
||||||
|
type->getKind() != ContextDescriptorKind::Struct)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Not a typedef imported as a nominal type.
|
||||||
|
if (type->getTypeContextDescriptorFlags().isCTypedef())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Not a related entity.
|
||||||
|
if (type->isSynthesizedRelatedEntity())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Imported from C.
|
||||||
|
return type->Parent->isCImportedContext();
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
|
swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
|
||||||
Demangle::NodePointer node) {
|
Demangle::NodePointer node) {
|
||||||
@@ -254,8 +272,11 @@ swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
|
|||||||
case Demangle::Node::Kind::OtherNominalType:
|
case Demangle::Node::Kind::OtherNominalType:
|
||||||
break;
|
break;
|
||||||
case Demangle::Node::Kind::Structure:
|
case Demangle::Node::Kind::Structure:
|
||||||
if (type->getKind() != ContextDescriptorKind::Struct
|
// We allow non-structs to match Kind::Structure if they are
|
||||||
&& !type->getTypeContextDescriptorFlags().isCTag())
|
// imported C tag types. This is necessary because we artificially
|
||||||
|
// make imported C tag types Kind::Structure.
|
||||||
|
if (type->getKind() != ContextDescriptorKind::Struct &&
|
||||||
|
!isCImportedTagType(type))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
case Demangle::Node::Kind::Class:
|
case Demangle::Node::Kind::Class:
|
||||||
|
|||||||
@@ -314,6 +314,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Is the given type imported from a C tag type?
|
||||||
|
bool isCImportedTagType(const TypeContextDescriptor *type);
|
||||||
|
|
||||||
/// Check whether a type conforms to a protocol.
|
/// Check whether a type conforms to a protocol.
|
||||||
///
|
///
|
||||||
/// \param value - can be null, in which case the question should
|
/// \param value - can be null, in which case the question should
|
||||||
|
|||||||
Reference in New Issue
Block a user