mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Reflection: Decode imported Objective-C classes and protocols as their own TypeRef
Right now we expect that every class and protocol has a field descriptor that tells us if the entity is @objc or not. For imported types, the descriptor will not exist if we did not directly emit a field whose concrete type contains the imported type. For example, in lldb, we might have a generic type whose runtime substituted type includes an imported type. In this case, TypeLowering would fail to produce a layout because it did not find a field descriptor for the imported type. A better approach is to have the TypeDecoder call a different factory method for imported types, and handle them specially in TypeLowering, bypassing the field type metadata altogether.
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "swift/Demangling/Demangler.h"
|
||||
#include "swift/Basic/LLVM.h"
|
||||
#include "swift/Runtime/Unreachable.h"
|
||||
#include "swift/Strings.h"
|
||||
#include <vector>
|
||||
|
||||
namespace swift {
|
||||
@@ -75,6 +76,34 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
/// For a mangled node that refers to an Objective-C class or protocol,
|
||||
/// return the class or protocol name.
|
||||
static inline Optional<StringRef> getObjCClassOrProtocolName(
|
||||
const Demangle::NodePointer &node) {
|
||||
if (node->getKind() != Demangle::Node::Kind::Class &&
|
||||
node->getKind() != Demangle::Node::Kind::Protocol)
|
||||
return None;
|
||||
|
||||
if (node->getNumChildren() != 2)
|
||||
return None;
|
||||
|
||||
// Check whether we have the __ObjC module.
|
||||
auto moduleNode = node->getChild(0);
|
||||
if (moduleNode->getKind() != Demangle::Node::Kind::Module ||
|
||||
moduleNode->getText() != MANGLING_MODULE_OBJC)
|
||||
return None;
|
||||
|
||||
// Check whether we have an identifier.
|
||||
auto nameNode = node->getChild(1);
|
||||
if (nameNode->getKind() != Demangle::Node::Kind::Identifier)
|
||||
return None;
|
||||
|
||||
return nameNode->getText();
|
||||
}
|
||||
#endif
|
||||
|
||||
/// Decode a mangled type to construct an abstract type, forming such
|
||||
/// types by invoking a custom builder.
|
||||
template <typename BuilderType>
|
||||
@@ -112,6 +141,13 @@ class TypeDecoder {
|
||||
|
||||
return decodeMangledType(Node->getChild(0));
|
||||
case NodeKind::Class:
|
||||
{
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
if (auto mangledName = getObjCClassOrProtocolName(Node))
|
||||
return Builder.createObjCClassType(mangledName->str());
|
||||
#endif
|
||||
LLVM_FALLTHROUGH;
|
||||
}
|
||||
case NodeKind::Enum:
|
||||
case NodeKind::Structure:
|
||||
case NodeKind::TypeAlias: // This can show up for imported Clang decls.
|
||||
@@ -125,6 +161,14 @@ class TypeDecoder {
|
||||
return Builder.createNominalType(typeDecl, parent);
|
||||
}
|
||||
case NodeKind::BoundGenericClass:
|
||||
{
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
if (Node->getNumChildren() == 2)
|
||||
if (auto mangledName = getObjCClassOrProtocolName(Node->getChild(0)))
|
||||
return Builder.createObjCClassType(mangledName->str());
|
||||
#endif
|
||||
LLVM_FALLTHROUGH;
|
||||
}
|
||||
case NodeKind::BoundGenericEnum:
|
||||
case NodeKind::BoundGenericStructure:
|
||||
case NodeKind::BoundGenericOtherNominalType: {
|
||||
@@ -528,6 +572,11 @@ private:
|
||||
&& node->getKind() != NodeKind::ProtocolSymbolicReference)
|
||||
return BuiltProtocolDecl();
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
if (auto objcProtocolName = getObjCClassOrProtocolName(node))
|
||||
return Builder.createObjCProtocolDecl(objcProtocolName->str());
|
||||
#endif
|
||||
|
||||
return Builder.createProtocolDecl(node);
|
||||
}
|
||||
|
||||
|
||||
@@ -386,11 +386,11 @@ public:
|
||||
};
|
||||
|
||||
class ProtocolCompositionTypeRef final : public TypeRef {
|
||||
std::vector<const NominalTypeRef *> Protocols;
|
||||
std::vector<const TypeRef *> Protocols;
|
||||
const TypeRef *Superclass;
|
||||
bool HasExplicitAnyObject;
|
||||
|
||||
static TypeRefID Profile(std::vector<const NominalTypeRef *> Protocols,
|
||||
static TypeRefID Profile(std::vector<const TypeRef *> Protocols,
|
||||
const TypeRef *Superclass,
|
||||
bool HasExplicitAnyObject) {
|
||||
TypeRefID ID;
|
||||
@@ -403,7 +403,7 @@ class ProtocolCompositionTypeRef final : public TypeRef {
|
||||
}
|
||||
|
||||
public:
|
||||
ProtocolCompositionTypeRef(std::vector<const NominalTypeRef *> Protocols,
|
||||
ProtocolCompositionTypeRef(std::vector<const TypeRef *> Protocols,
|
||||
const TypeRef *Superclass,
|
||||
bool HasExplicitAnyObject)
|
||||
: TypeRef(TypeRefKind::ProtocolComposition),
|
||||
@@ -412,13 +412,14 @@ public:
|
||||
|
||||
template <typename Allocator>
|
||||
static const ProtocolCompositionTypeRef *
|
||||
create(Allocator &A, std::vector<const NominalTypeRef *> Protocols,
|
||||
create(Allocator &A, std::vector<const TypeRef *> Protocols,
|
||||
const TypeRef *Superclass, bool HasExplicitAnyObject) {
|
||||
FIND_OR_CREATE_TYPEREF(A, ProtocolCompositionTypeRef, Protocols,
|
||||
Superclass, HasExplicitAnyObject);
|
||||
}
|
||||
|
||||
const std::vector<const NominalTypeRef *> &getProtocols() const {
|
||||
// These are either NominalTypeRef or ObjCProtocolTypeRef.
|
||||
const std::vector<const TypeRef *> &getProtocols() const {
|
||||
return Protocols;
|
||||
}
|
||||
|
||||
@@ -633,6 +634,36 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ObjCProtocolTypeRef final : public TypeRef {
|
||||
std::string Name;
|
||||
static const ObjCProtocolTypeRef *UnnamedSingleton;
|
||||
|
||||
static TypeRefID Profile(const std::string &Name) {
|
||||
TypeRefID ID;
|
||||
ID.addString(Name);
|
||||
return ID;
|
||||
}
|
||||
public:
|
||||
ObjCProtocolTypeRef(const std::string &Name)
|
||||
: TypeRef(TypeRefKind::ObjCProtocol), Name(Name) {}
|
||||
|
||||
static const ObjCProtocolTypeRef *getUnnamed();
|
||||
|
||||
template <typename Allocator>
|
||||
static const ObjCProtocolTypeRef *create(Allocator &A,
|
||||
const std::string &Name) {
|
||||
FIND_OR_CREATE_TYPEREF(A, ObjCProtocolTypeRef, Name);
|
||||
}
|
||||
|
||||
const std::string &getName() const {
|
||||
return Name;
|
||||
}
|
||||
|
||||
static bool classof(const TypeRef *TR) {
|
||||
return TR->getKind() == TypeRefKind::ObjCProtocol;
|
||||
}
|
||||
};
|
||||
|
||||
class OpaqueTypeRef final : public TypeRef {
|
||||
static const OpaqueTypeRef *Singleton;
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ class TypeRefBuilder {
|
||||
public:
|
||||
using BuiltType = const TypeRef *;
|
||||
using BuiltNominalTypeDecl = Optional<std::string>;
|
||||
using BuiltProtocolDecl = Optional<std::string>;
|
||||
using BuiltProtocolDecl = Optional<std::pair<std::string, bool /*isObjC*/>>;
|
||||
|
||||
TypeRefBuilder();
|
||||
|
||||
@@ -214,9 +214,14 @@ public:
|
||||
return Demangle::mangleNode(node);
|
||||
}
|
||||
|
||||
Optional<std::string>
|
||||
BuiltProtocolDecl
|
||||
createProtocolDecl(const Demangle::NodePointer &node) {
|
||||
return Demangle::mangleNode(node);
|
||||
return std::make_pair(Demangle::mangleNode(node), false);
|
||||
}
|
||||
|
||||
BuiltProtocolDecl
|
||||
createObjCProtocolDecl(std::string &&name) {
|
||||
return std::make_pair(name, true);
|
||||
}
|
||||
|
||||
Optional<std::string> createNominalTypeDecl(std::string &&mangledName) {
|
||||
@@ -265,9 +270,15 @@ public:
|
||||
createProtocolCompositionType(ArrayRef<BuiltProtocolDecl> protocols,
|
||||
BuiltType superclass,
|
||||
bool isClassBound) {
|
||||
std::vector<const NominalTypeRef *> protocolRefs;
|
||||
std::vector<const TypeRef *> protocolRefs;
|
||||
for (const auto &protocol : protocols) {
|
||||
protocolRefs.push_back(createNominalType(protocol));
|
||||
if (!protocol)
|
||||
continue;
|
||||
|
||||
if (protocol->second)
|
||||
protocolRefs.push_back(createObjCProtocolType(protocol->first));
|
||||
else
|
||||
protocolRefs.push_back(createNominalType(protocol->first));
|
||||
}
|
||||
|
||||
return ProtocolCompositionTypeRef::create(*this, protocolRefs, superclass,
|
||||
@@ -292,8 +303,12 @@ public:
|
||||
const DependentMemberTypeRef *
|
||||
createDependentMemberType(const std::string &member,
|
||||
const TypeRef *base,
|
||||
Optional<std::string> protocol) {
|
||||
return DependentMemberTypeRef::create(*this, member, base, *protocol);
|
||||
BuiltProtocolDecl protocol) {
|
||||
// Objective-C protocols don't have dependent types.
|
||||
if (protocol->second)
|
||||
return nullptr;
|
||||
return DependentMemberTypeRef::create(*this, member, base,
|
||||
protocol->first);
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, ...) \
|
||||
@@ -306,15 +321,20 @@ public:
|
||||
return SILBoxTypeRef::create(*this, base);
|
||||
}
|
||||
|
||||
const ObjCClassTypeRef *
|
||||
createObjCClassType(const std::string &mangledName) {
|
||||
return ObjCClassTypeRef::create(*this, mangledName);
|
||||
}
|
||||
|
||||
const ObjCClassTypeRef *getUnnamedObjCClassType() {
|
||||
return createObjCClassType("");
|
||||
}
|
||||
|
||||
const ObjCClassTypeRef *
|
||||
createObjCClassType(const std::string &name) {
|
||||
return ObjCClassTypeRef::create(*this, name);
|
||||
}
|
||||
|
||||
const ObjCProtocolTypeRef *
|
||||
createObjCProtocolType(const std::string &name) {
|
||||
return ObjCProtocolTypeRef::create(*this, name);
|
||||
}
|
||||
|
||||
const ForeignClassTypeRef *
|
||||
createForeignClassType(const std::string &mangledName) {
|
||||
return ForeignClassTypeRef::create(*this, mangledName);
|
||||
|
||||
@@ -28,6 +28,7 @@ TYPEREF(GenericTypeParameter, TypeRef)
|
||||
TYPEREF(DependentMember, TypeRef)
|
||||
TYPEREF(ForeignClass, TypeRef)
|
||||
TYPEREF(ObjCClass, TypeRef)
|
||||
TYPEREF(ObjCProtocol, TypeRef)
|
||||
TYPEREF(Opaque, TypeRef)
|
||||
#define REF_STORAGE(Name, ...) \
|
||||
TYPEREF(Name##Storage, TypeRef)
|
||||
|
||||
@@ -509,6 +509,8 @@ public:
|
||||
if (!Demangled)
|
||||
return BuiltType();
|
||||
|
||||
// FIXME: Imported protocols?
|
||||
|
||||
auto Protocol = Builder.createProtocolDecl(Demangled);
|
||||
if (!Protocol)
|
||||
return BuiltType();
|
||||
|
||||
@@ -438,6 +438,16 @@ public:
|
||||
return createNominalType(typeDecl, /*parent*/ Type());
|
||||
}
|
||||
|
||||
ProtocolDecl *createObjCProtocolDecl(StringRef name) {
|
||||
auto typeDecl =
|
||||
findForeignNominalTypeDecl(name, /*relatedEntityKind*/{},
|
||||
ForeignModuleKind::Imported,
|
||||
Demangle::Node::Kind::Protocol);
|
||||
if (auto *protocolDecl = dyn_cast_or_null<ProtocolDecl>(typeDecl))
|
||||
return protocolDecl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Type createForeignClassType(StringRef mangledName) {
|
||||
auto typeDecl = createNominalTypeDecl(mangledName);
|
||||
if (!typeDecl) return Type();
|
||||
|
||||
@@ -197,7 +197,7 @@ BuiltinTypeInfo::BuiltinTypeInfo(const BuiltinTypeDescriptor *descriptor)
|
||||
/// Utility class for building values that contain witness tables.
|
||||
class ExistentialTypeInfoBuilder {
|
||||
TypeConverter &TC;
|
||||
std::vector<const NominalTypeRef *> Protocols;
|
||||
std::vector<const TypeRef *> Protocols;
|
||||
const TypeRef *Superclass = nullptr;
|
||||
ExistentialTypeRepresentation Representation;
|
||||
ReferenceCounting Refcounting;
|
||||
@@ -218,8 +218,9 @@ class ExistentialTypeInfoBuilder {
|
||||
return false;
|
||||
|
||||
for (auto *P : Protocols) {
|
||||
if (P->isErrorProtocol())
|
||||
return true;
|
||||
if (auto *NTD = dyn_cast<NominalTypeRef>(P))
|
||||
if (NTD->isErrorProtocol())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -232,6 +233,20 @@ class ExistentialTypeInfoBuilder {
|
||||
}
|
||||
|
||||
for (auto *P : Protocols) {
|
||||
auto *NTD = dyn_cast<NominalTypeRef>(P);
|
||||
auto *OP = dyn_cast<ObjCProtocolTypeRef>(P);
|
||||
if (!NTD && !OP) {
|
||||
DEBUG_LOG(std::cerr << "Bad protocol: "; P->dump())
|
||||
Invalid = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't look up field info for imported Objective-C protocols.
|
||||
if (OP) {
|
||||
ObjC = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::pair<const FieldDescriptor *, const ReflectionInfo *> FD =
|
||||
TC.getBuilder().getFieldTypeInfo(P);
|
||||
if (FD.first == nullptr) {
|
||||
@@ -270,7 +285,7 @@ public:
|
||||
ObjC(false), WitnessTableCount(0),
|
||||
Invalid(false) {}
|
||||
|
||||
void addProtocol(const NominalTypeRef *P) {
|
||||
void addProtocol(const TypeRef *P) {
|
||||
Protocols.push_back(P);
|
||||
}
|
||||
|
||||
@@ -286,11 +301,19 @@ public:
|
||||
// Anything else should either be a superclass constraint, or
|
||||
// we have an invalid typeref.
|
||||
if (!isa<NominalTypeRef>(T) &&
|
||||
!isa<BoundGenericTypeRef>(T)) {
|
||||
!isa<BoundGenericTypeRef>(T) &&
|
||||
!isa<ObjCClassTypeRef>(T)) {
|
||||
DEBUG_LOG(std::cerr << "Bad existential member: "; T->dump())
|
||||
Invalid = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't look up field info for imported Objective-C classes.
|
||||
if (auto *OC = dyn_cast<ObjCClassTypeRef>(T)) {
|
||||
addAnyObject();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &FD = TC.getBuilder().getFieldTypeInfo(T);
|
||||
if (FD.first == nullptr) {
|
||||
DEBUG_LOG(std::cerr << "No field descriptor: "; T->dump())
|
||||
@@ -721,6 +744,10 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitObjCProtocolTypeRef(const ObjCProtocolTypeRef *OP) {
|
||||
return true;
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, ...) \
|
||||
bool \
|
||||
visit##Name##StorageTypeRef(const Name##StorageTypeRef *US) { \
|
||||
@@ -848,6 +875,10 @@ public:
|
||||
return MetatypeRepresentation::Unknown;
|
||||
}
|
||||
|
||||
MetatypeRepresentation visitObjCProtocolTypeRef(const ObjCProtocolTypeRef *OP) {
|
||||
return MetatypeRepresentation::Unknown;
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, ...) \
|
||||
MetatypeRepresentation \
|
||||
visit##Name##StorageTypeRef(const Name##StorageTypeRef *US) { \
|
||||
@@ -1197,6 +1228,11 @@ public:
|
||||
ReferenceCounting::Unknown);
|
||||
}
|
||||
|
||||
const TypeInfo *visitObjCProtocolTypeRef(const ObjCProtocolTypeRef *OP) {
|
||||
return TC.getReferenceTypeInfo(ReferenceKind::Strong,
|
||||
ReferenceCounting::Unknown);
|
||||
}
|
||||
|
||||
// Apply a storage qualifier, like 'weak', 'unowned' or 'unowned(unsafe)'
|
||||
// to a type with reference semantics, such as a class reference or
|
||||
// class-bound existential.
|
||||
|
||||
@@ -236,6 +236,13 @@ public:
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
void visitObjCProtocolTypeRef(const ObjCProtocolTypeRef *OC) {
|
||||
printHeader("objective_c_protocol");
|
||||
if (!OC->getName().empty())
|
||||
printField("name", OC->getName());
|
||||
OS << ')';
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, name, ...) \
|
||||
void visit##Name##StorageTypeRef(const Name##StorageTypeRef *US) { \
|
||||
printHeader(#name "_storage"); \
|
||||
@@ -334,6 +341,10 @@ struct TypeRefIsConcrete
|
||||
bool visitObjCClassTypeRef(const ObjCClassTypeRef *OC) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitObjCProtocolTypeRef(const ObjCProtocolTypeRef *OC) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool visitOpaqueTypeRef(const OpaqueTypeRef *O) {
|
||||
return true;
|
||||
@@ -514,6 +525,10 @@ public:
|
||||
return OC;
|
||||
}
|
||||
|
||||
const TypeRef *visitObjCProtocolTypeRef(const ObjCProtocolTypeRef *OP) {
|
||||
return OP;
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, name, ...) \
|
||||
const TypeRef *visit##Name##StorageTypeRef(const Name##StorageTypeRef *US) { \
|
||||
return US; \
|
||||
@@ -657,19 +672,21 @@ public:
|
||||
SubstBase = Superclass;
|
||||
}
|
||||
|
||||
auto Protocol = std::make_pair(DM->getProtocol(), false);
|
||||
|
||||
// We didn't find the member type, so return something to let the
|
||||
// caller know we're dealing with incomplete metadata.
|
||||
if (TypeWitness == nullptr)
|
||||
return Builder.createDependentMemberType(DM->getMember(),
|
||||
SubstBase,
|
||||
DM->getProtocol());
|
||||
Protocol);
|
||||
|
||||
// Likewise if we can't get the substitution map.
|
||||
auto SubstMap = SubstBase->getSubstMap();
|
||||
if (!SubstMap)
|
||||
return Builder.createDependentMemberType(DM->getMember(),
|
||||
SubstBase,
|
||||
DM->getProtocol());
|
||||
Protocol);
|
||||
|
||||
// Apply base type substitutions to get the fully-substituted nested type.
|
||||
auto *Subst = TypeWitness->subst(Builder, *SubstMap);
|
||||
@@ -686,6 +703,10 @@ public:
|
||||
return OC;
|
||||
}
|
||||
|
||||
const TypeRef *visitObjCProtocolTypeRef(const ObjCProtocolTypeRef *OP) {
|
||||
return OP;
|
||||
}
|
||||
|
||||
#define REF_STORAGE(Name, name, ...) \
|
||||
const TypeRef *visit##Name##StorageTypeRef(const Name##StorageTypeRef *US) { \
|
||||
return Name##StorageTypeRef::create(Builder, visit(US->getType())); \
|
||||
|
||||
@@ -330,31 +330,6 @@ ParsedTypeIdentity::parse(const TypeContextDescriptor *type) {
|
||||
}
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
/// For a mangled node that refers to an Objective-C class or protocol,
|
||||
/// return the class or protocol name.
|
||||
static Optional<StringRef> getObjCClassOrProtocolName(
|
||||
const Demangle::NodePointer &node) {
|
||||
if (node->getKind() != Demangle::Node::Kind::Class &&
|
||||
node->getKind() != Demangle::Node::Kind::Protocol)
|
||||
return None;
|
||||
|
||||
if (node->getNumChildren() != 2)
|
||||
return None;
|
||||
|
||||
// Check whether we have the __ObjC module.
|
||||
auto moduleNode = node->getChild(0);
|
||||
if (moduleNode->getKind() != Demangle::Node::Kind::Module ||
|
||||
moduleNode->getText() != MANGLING_MODULE_OBJC)
|
||||
return None;
|
||||
|
||||
// Check whether we have an identifier.
|
||||
auto nameNode = node->getChild(1);
|
||||
if (nameNode->getKind() != Demangle::Node::Kind::Identifier)
|
||||
return None;
|
||||
|
||||
return nameNode->getText();
|
||||
}
|
||||
|
||||
/// Determine whether the two demangle trees both refer to the same
|
||||
/// Objective-C class or protocol referenced by name.
|
||||
static bool sameObjCTypeManglings(Demangle::NodePointer node1,
|
||||
@@ -363,10 +338,10 @@ static bool sameObjCTypeManglings(Demangle::NodePointer node1,
|
||||
if (node1->getKind() != node2->getKind())
|
||||
return false;
|
||||
|
||||
auto name1 = getObjCClassOrProtocolName(node1);
|
||||
auto name1 = Demangle::getObjCClassOrProtocolName(node1);
|
||||
if (!name1) return false;
|
||||
|
||||
auto name2 = getObjCClassOrProtocolName(node2);
|
||||
auto name2 = Demangle::getObjCClassOrProtocolName(node2);
|
||||
if (!name2) return false;
|
||||
|
||||
return *name1 == *name2;
|
||||
@@ -950,45 +925,19 @@ public:
|
||||
lookupDependentMember(lookupDependentMember) { }
|
||||
|
||||
using BuiltType = const Metadata *;
|
||||
|
||||
struct BuiltNominalTypeDecl :
|
||||
llvm::PointerUnion<const TypeContextDescriptor *, const Metadata *>
|
||||
{
|
||||
using PointerUnion::PointerUnion;
|
||||
|
||||
explicit operator bool() const { return !isNull(); }
|
||||
};
|
||||
|
||||
using BuiltNominalTypeDecl = const TypeContextDescriptor *;
|
||||
using BuiltProtocolDecl = ProtocolDescriptorRef;
|
||||
|
||||
Demangle::NodeFactory &getNodeFactory() { return demangler; }
|
||||
|
||||
BuiltNominalTypeDecl createNominalTypeDecl(
|
||||
const Demangle::NodePointer &node) const {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// If we have an Objective-C class name, call into the Objective-C
|
||||
// runtime to find them.
|
||||
if (auto objcClassName = getObjCClassOrProtocolName(node)) {
|
||||
auto objcClass = objc_getClass(objcClassName->str().c_str());
|
||||
return swift_getObjCClassMetadata((const ClassMetadata *)objcClass);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Look for a nominal type descriptor based on its mangled name.
|
||||
return _findNominalTypeDescriptor(node, demangler);
|
||||
}
|
||||
|
||||
BuiltProtocolDecl createProtocolDecl(
|
||||
const Demangle::NodePointer &node) const {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// If we have an Objective-C protocol name, call into the Objective-C
|
||||
// runtime to find them.
|
||||
if (auto objcProtocolName = getObjCClassOrProtocolName(node)) {
|
||||
return ProtocolDescriptorRef::forObjC(objc_getProtocol(
|
||||
objcProtocolName->str().c_str()));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Look for a protocol descriptor based on its mangled name.
|
||||
std::string mangledName;
|
||||
if (auto protocol = _findProtocolDescriptor(node, demangler, mangledName))
|
||||
@@ -1006,6 +955,25 @@ public:
|
||||
return ProtocolDescriptorRef();
|
||||
}
|
||||
|
||||
BuiltProtocolDecl createObjCProtocolDecl(
|
||||
const std::string &mangledName) const {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
return ProtocolDescriptorRef::forObjC(
|
||||
objc_getProtocol(mangledName.c_str()));
|
||||
#else
|
||||
return ProtocolDescriptorRef();
|
||||
#endif
|
||||
}
|
||||
|
||||
BuiltType createObjCClassType(const std::string &mangledName) const {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
auto objcClass = objc_getClass(mangledName.c_str());
|
||||
return swift_getObjCClassMetadata((const ClassMetadata *)objcClass);
|
||||
#else
|
||||
return BuiltType();
|
||||
#endif
|
||||
}
|
||||
|
||||
BuiltType createNominalType(BuiltNominalTypeDecl metadataOrTypeDecl,
|
||||
BuiltType parent) const {
|
||||
// Treat nominal type creation the same way as generic type creation,
|
||||
@@ -1013,15 +981,9 @@ public:
|
||||
return createBoundGenericType(metadataOrTypeDecl, { }, parent);
|
||||
}
|
||||
|
||||
BuiltType createBoundGenericType(BuiltNominalTypeDecl metadataOrTypeDecl,
|
||||
BuiltType createBoundGenericType(BuiltNominalTypeDecl typeDecl,
|
||||
const ArrayRef<BuiltType> genericArgs,
|
||||
const BuiltType parent) const {
|
||||
// If we already have metadata, return it.
|
||||
if (auto metadata = metadataOrTypeDecl.dyn_cast<const Metadata *>())
|
||||
return metadata;
|
||||
|
||||
auto typeDecl = metadataOrTypeDecl.get<const TypeContextDescriptor *>();
|
||||
|
||||
// Figure out the various levels of generic parameters we have in
|
||||
// this type.
|
||||
std::vector<unsigned> genericParamCounts;
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
// CHECK: TypesToReflect.OC
|
||||
// CHECK: -----------------
|
||||
// CHECK: nsObject: __C.NSObject
|
||||
// CHECK: (class __C.NSObject)
|
||||
// CHECK: (objective_c_class name=NSObject)
|
||||
|
||||
// CHECK: nsString: __C.NSString
|
||||
// CHECK: (class __C.NSString)
|
||||
// CHECK: (objective_c_class name=NSString)
|
||||
|
||||
// CHECK: cfString: __C.CFStringRef
|
||||
// CHECK: (alias __C.CFStringRef)
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
// CHECK: ocnss: TypesToReflect.GenericOC<__C.NSString>
|
||||
// CHECK: (bound_generic_class TypesToReflect.GenericOC
|
||||
// CHECK: (class __C.NSString))
|
||||
// CHECK: (objective_c_class name=NSString))
|
||||
|
||||
// CHECK: occfs: TypesToReflect.GenericOC<__C.CFStringRef>
|
||||
// CHECK: (bound_generic_class TypesToReflect.GenericOC
|
||||
@@ -37,7 +37,7 @@
|
||||
// CHECK: TypesToReflect.HasObjCClasses
|
||||
// CHECK: -----------------------------
|
||||
// CHECK: url: __C.NSURL
|
||||
// CHECK: (class __C.NSURL)
|
||||
// CHECK: (objective_c_class name=NSURL)
|
||||
|
||||
// CHECK: integer: Swift.Int
|
||||
// CHECK: (struct Swift.Int)
|
||||
@@ -48,13 +48,6 @@
|
||||
// CHECK: TypesToReflect.OP
|
||||
// CHECK: -----------------
|
||||
|
||||
// CHECK: __C.NSBundle
|
||||
// CHECK: ----------
|
||||
// CHECK: __C.NSURL
|
||||
// CHECK: ---------
|
||||
// CHECK: __C.NSCoding
|
||||
// CHECK: ------------
|
||||
|
||||
// CHECK: ASSOCIATED TYPES:
|
||||
// CHECK: =================
|
||||
|
||||
@@ -77,7 +70,7 @@
|
||||
// CHECK-NEXT: ====================
|
||||
|
||||
// CHECK: - Capture types:
|
||||
// CHECK-NEXT: (class __C.NSBundle)
|
||||
// CHECK-NEXT: (objective_c_class name=NSBundle)
|
||||
// CHECK-NEXT: (protocol_composition
|
||||
// CHECK-NEXT: (protocol __C.NSCoding))
|
||||
// CHECK-NEXT: (objective_c_protocol name=NSCoding))
|
||||
// CHECK-NEXT: - Metadata sources:
|
||||
|
||||
@@ -215,10 +215,10 @@ TEST(TypeRefTest, UniqueFunctionTypeRef) {
|
||||
TEST(TypeRefTest, UniqueProtocolTypeRef) {
|
||||
TypeRefBuilder Builder;
|
||||
|
||||
Optional<std::string> P1 = ABC;
|
||||
Optional<std::string> P2 = ABC;
|
||||
Optional<std::string> P3 = ABCD;
|
||||
Optional<std::string> P4 = XYZ;
|
||||
TypeRefBuilder::BuiltProtocolDecl P1 = std::make_pair(ABC, false);
|
||||
TypeRefBuilder::BuiltProtocolDecl P2 = std::make_pair(ABC, false);
|
||||
TypeRefBuilder::BuiltProtocolDecl P3 = std::make_pair(ABCD, false);
|
||||
TypeRefBuilder::BuiltProtocolDecl P4 = std::make_pair(XYZ, false);
|
||||
|
||||
EXPECT_EQ(P1, P2);
|
||||
EXPECT_NE(P2, P3);
|
||||
@@ -280,8 +280,8 @@ TEST(TypeRefTest, UniqueDependentMemberTypeRef) {
|
||||
|
||||
auto N1 = Builder.createNominalType(ABC, nullptr);
|
||||
auto N2 = Builder.createNominalType(XYZ, nullptr);
|
||||
Optional<std::string> P1 = ABC;
|
||||
Optional<std::string> P2 = ABCD;
|
||||
TypeRefBuilder::BuiltProtocolDecl P1 = std::make_pair(ABC, false);
|
||||
TypeRefBuilder::BuiltProtocolDecl P2 = std::make_pair(ABCD, false);
|
||||
|
||||
auto DM1 = Builder.createDependentMemberType("Index", N1, P1);
|
||||
auto DM2 = Builder.createDependentMemberType("Index", N1, P1);
|
||||
|
||||
Reference in New Issue
Block a user