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 <string.h>
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "swift/Strings.h"
|
||||
#include "swift/Runtime/Config.h"
|
||||
#include "swift/ABI/MetadataValues.h"
|
||||
#include "swift/ABI/System.h"
|
||||
@@ -2344,6 +2345,9 @@ using ProtocolConformanceRecord = TargetProtocolConformanceRecord<InProcess>;
|
||||
template<typename Runtime>
|
||||
struct TargetGenericContext;
|
||||
|
||||
template<typename Runtime>
|
||||
struct TargetModuleContextDescriptor;
|
||||
|
||||
/// Base class for all context descriptors.
|
||||
template<typename Runtime>
|
||||
struct TargetContextDescriptor {
|
||||
@@ -2361,6 +2365,12 @@ struct TargetContextDescriptor {
|
||||
/// context is not generic.
|
||||
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 {
|
||||
auto *genericContext = getGenericContext();
|
||||
return genericContext
|
||||
@@ -2376,12 +2386,24 @@ private:
|
||||
|
||||
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.
|
||||
template<typename Runtime>
|
||||
struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
|
||||
/// The module 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) {
|
||||
return cd->getKind() == ContextDescriptorKind::Module;
|
||||
}
|
||||
@@ -2389,6 +2411,21 @@ struct TargetModuleContextDescriptor final : TargetContextDescriptor<Runtime> {
|
||||
|
||||
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>
|
||||
struct TargetGenericContextDescriptorHeader {
|
||||
uint16_t NumParams, NumRequirements, NumKeyArguments, NumExtraArguments;
|
||||
|
||||
@@ -1321,9 +1321,6 @@ public:
|
||||
getImportNamespace,
|
||||
setImportNamespace)
|
||||
|
||||
bool isCTag() const {
|
||||
return getImportNamespace() == CTag;
|
||||
}
|
||||
bool isCTypedef() const {
|
||||
return getImportNamespace() == CTypedef;
|
||||
}
|
||||
|
||||
@@ -1291,27 +1291,51 @@ private:
|
||||
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) {
|
||||
auto parentAddress =
|
||||
resolveNullableRelativeIndirectableField(base, base->Parent);
|
||||
|
||||
if (parentAddress) {
|
||||
return readContextDescriptor(*parentAddress);
|
||||
if (!parentAddress)
|
||||
return None;
|
||||
if (!*parentAddress)
|
||||
return ContextDescriptorRef(nullptr);
|
||||
if (auto parentDescriptor = readContextDescriptor(*parentAddress))
|
||||
return parentDescriptor;
|
||||
return None;
|
||||
}
|
||||
|
||||
static bool isCImportedContext(Demangle::NodePointer node) {
|
||||
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;
|
||||
}
|
||||
|
||||
/// Given a read nominal type descriptor, attempt to build a demangling tree
|
||||
/// for it.
|
||||
Demangle::NodePointer
|
||||
buildNominalTypeMangling(ContextDescriptorRef descriptor,
|
||||
Demangle::NodeFactory &nodeFactory) {
|
||||
std::vector<std::pair<Demangle::Node::Kind, Demangle::NodePointer>>
|
||||
nameComponents;
|
||||
ContextDescriptorRef parent = descriptor;
|
||||
|
||||
while (parent) {
|
||||
std::string nodeName;
|
||||
std::string relatedTag;
|
||||
Demangle::Node::Kind nodeKind;
|
||||
@@ -1319,8 +1343,8 @@ private:
|
||||
auto getTypeName = [&]() -> bool {
|
||||
auto typeBuffer =
|
||||
reinterpret_cast<const TargetTypeContextDescriptor<Runtime> *>
|
||||
(parent.getLocalBuffer());
|
||||
auto nameAddress = resolveRelativeField(parent, typeBuffer->Name);
|
||||
(descriptor.getLocalBuffer());
|
||||
auto nameAddress = resolveRelativeField(descriptor, typeBuffer->Name);
|
||||
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
|
||||
return false;
|
||||
|
||||
@@ -1334,7 +1358,7 @@ private:
|
||||
};
|
||||
|
||||
bool isTypeContext = false;
|
||||
switch (auto contextKind = parent->getKind()) {
|
||||
switch (auto contextKind = descriptor->getKind()) {
|
||||
case ContextDescriptorKind::Class:
|
||||
if (!getTypeName())
|
||||
return nullptr;
|
||||
@@ -1356,8 +1380,8 @@ private:
|
||||
case ContextDescriptorKind::Protocol: {
|
||||
auto protocolBuffer =
|
||||
reinterpret_cast<const TargetProtocolDescriptor<Runtime> *>
|
||||
(parent.getLocalBuffer());
|
||||
auto nameAddress = resolveRelativeField(parent, protocolBuffer->Name);
|
||||
(descriptor.getLocalBuffer());
|
||||
auto nameAddress = resolveRelativeField(descriptor, protocolBuffer->Name);
|
||||
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
|
||||
return nullptr;
|
||||
|
||||
@@ -1373,15 +1397,23 @@ private:
|
||||
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> *>(
|
||||
parent.getLocalBuffer());
|
||||
reinterpret_cast<const TargetModuleContextDescriptor<Runtime> *>
|
||||
(descriptor.getLocalBuffer());
|
||||
auto nameAddress
|
||||
= resolveRelativeField(parent, moduleBuffer->Name);
|
||||
= resolveRelativeField(descriptor, moduleBuffer->Name);
|
||||
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
|
||||
return nullptr;
|
||||
break;
|
||||
|
||||
// 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:
|
||||
@@ -1389,19 +1421,30 @@ private:
|
||||
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(parent->Flags.getKindSpecificFlags());
|
||||
TypeContextDescriptorFlags(descriptor->Flags.getKindSpecificFlags());
|
||||
|
||||
if (typeFlags.isCTag())
|
||||
nodeKind = Demangle::Node::Kind::Structure;
|
||||
else if (typeFlags.isCTypedef())
|
||||
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,
|
||||
nodeName);
|
||||
std::move(nodeName));
|
||||
if (!relatedTag.empty()) {
|
||||
auto relatedNode =
|
||||
nodeFactory.createNode(Node::Kind::RelatedEntityDeclName, relatedTag);
|
||||
@@ -1409,26 +1452,20 @@ private:
|
||||
nameNode = relatedNode;
|
||||
}
|
||||
|
||||
nameComponents.emplace_back(nodeKind, nameNode);
|
||||
|
||||
parent = readParentContextDescriptor(parent);
|
||||
auto demangling = nodeFactory.createNode(nodeKind);
|
||||
demangling->addChild(parentDemangling, nodeFactory);
|
||||
demangling->addChild(nameNode, nodeFactory);
|
||||
return demangling;
|
||||
}
|
||||
|
||||
// We should have made our way up to a module context.
|
||||
if (nameComponents.empty())
|
||||
/// Given a read nominal type descriptor, attempt to build a demangling tree
|
||||
/// for it.
|
||||
Demangle::NodePointer
|
||||
buildNominalTypeMangling(ContextDescriptorRef descriptor,
|
||||
Demangle::NodeFactory &nodeFactory) {
|
||||
auto demangling = buildContextDescriptorMangling(descriptor, nodeFactory);
|
||||
if (!demangling)
|
||||
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);
|
||||
top->addChild(demangling, nodeFactory);
|
||||
|
||||
@@ -165,10 +165,11 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
|
||||
// Override the node kind if this is a Clang-imported type so we give it
|
||||
// a stable mangling.
|
||||
auto typeFlags = type->getTypeContextDescriptorFlags();
|
||||
if (typeFlags.isCTag()) {
|
||||
nodeKind = Node::Kind::Structure;
|
||||
} else if (typeFlags.isCTypedef()) {
|
||||
if (typeFlags.isCTypedef()) {
|
||||
nodeKind = Node::Kind::TypeAlias;
|
||||
} else if (nodeKind != Node::Kind::Structure &&
|
||||
isCImportedTagType(type)) {
|
||||
nodeKind = Node::Kind::Structure;
|
||||
}
|
||||
|
||||
auto typeNode = Dem.createNode(nodeKind);
|
||||
|
||||
@@ -153,6 +153,24 @@ static const TypeContextDescriptor *
|
||||
_findNominalTypeDescriptor(Demangle::NodePointer node,
|
||||
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
|
||||
swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
|
||||
Demangle::NodePointer node) {
|
||||
@@ -254,8 +272,11 @@ swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
|
||||
case Demangle::Node::Kind::OtherNominalType:
|
||||
break;
|
||||
case Demangle::Node::Kind::Structure:
|
||||
if (type->getKind() != ContextDescriptorKind::Struct
|
||||
&& !type->getTypeContextDescriptorFlags().isCTag())
|
||||
// We allow non-structs to match Kind::Structure if they are
|
||||
// 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;
|
||||
break;
|
||||
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.
|
||||
///
|
||||
/// \param value - can be null, in which case the question should
|
||||
|
||||
Reference in New Issue
Block a user