Reflection: Emit descriptors for referenced imported protocols

When we encounter a protocol typeref, we have to know if its @objc,
class-bound, or opaque, so make sure we provide the necessary
information when imported protocols are referenced.
This commit is contained in:
Slava Pestov
2016-05-26 15:39:51 -07:00
parent 97fd1a7411
commit 7a46b0f23f
5 changed files with 44 additions and 11 deletions

View File

@@ -188,11 +188,13 @@ protected:
// for now, at least until we want to import C++ types or
// something like that.
//
// Classes go down a different path.
// Classes and protocols go down a different path.
if (auto Nominal = t->getAnyNominal())
if (Nominal->hasClangNode()) {
if (auto CD = dyn_cast<ClassDecl>(Nominal))
IGM.ImportedClasses.insert(CD);
else if (auto PD = dyn_cast<ProtocolDecl>(Nominal))
IGM.ImportedProtocols.insert(PD);
else
IGM.BuiltinTypes.insert(CanType(t));
}
@@ -372,7 +374,9 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
auto type = NTD->getDeclaredType()->getCanonicalType();
addTypeRef(NTD->getModuleContext(), type);
if (NTD->hasClangNode() && !isa<ClassDecl>(NTD))
if (NTD->hasClangNode() &&
!isa<ClassDecl>(NTD) &&
!isa<ProtocolDecl>(NTD))
return;
switch (NTD->getKind()) {
@@ -884,6 +888,9 @@ void IRGenModule::emitBuiltinReflectionMetadata() {
for (auto CD : ImportedClasses)
emitFieldMetadataRecord(CD);
for (auto PD : ImportedProtocols)
emitFieldMetadataRecord(PD);
BuiltinTypeMetadataBuilder builder(*this);
auto var = builder.emit();
if (var)

View File

@@ -721,6 +721,9 @@ public:
/// Imported classes referenced by types in this module when emitting
/// reflection metadata.
llvm::SetVector<ClassDecl *> ImportedClasses;
/// Imported protocols referenced by types in this module when emitting
/// reflection metadata.
llvm::SetVector<ProtocolDecl *> ImportedProtocols;
llvm::Constant *getAddrOfStringForTypeRef(StringRef Str);
llvm::Constant *getAddrOfFieldName(StringRef Name);

View File

@@ -29,6 +29,6 @@ public class HasObjCClasses {
let rect = NSRect(x: 0, y: 1, width: 2, height: 3)
}
public func closureHasObjCClasses(b: NSBundle) -> () -> () {
return { _ = b }
public func closureHasObjCClasses(b: NSBundle, c: NSCoding) -> () -> () {
return { _ = b; _ = c }
}

View File

@@ -45,6 +45,8 @@
// CHECK: ---------------
// CHECK: __ObjC.NSURL
// CHECK: ------------
// CHECK: __ObjC.NSCoding
// CHECK: ---------------
// CHECK: ASSOCIATED TYPES:
// CHECK: =================
@@ -72,6 +74,23 @@
// CHECK: (tuple))
// CHECK: - Metadata sources:
// CHECK: - Capture types:
// CHECK: (struct Swift.StaticString)
// CHECK: (struct Swift.StaticString)
// CHECK: (struct Swift.UInt)
// CHECK: (struct Swift.UInt)
// CHECK: - Metadata sources:
// CHECK: - Capture types:
// CHECK: (function
// CHECK: (tuple))
// CHECK: - Metadata sources:
// CHECK: - Capture types:
// CHECK: (class __ObjC.NSBundle)
// CHECK: (protocol __ObjC.NSCoding)
// CHECK: - Metadata sources:
// CHECK: - Capture types:
// CHECK: (struct Swift.StaticString)
// CHECK: (bound_generic_struct Swift.UnsafeBufferPointer

View File

@@ -6,14 +6,14 @@
import SwiftReflectionTest
import Foundation
func capturesImportedClass(x: Int, n: NSURL, r: NSRect) {
reflect(function: {print(x); print(n); print(r)})
func capturesImportedTypes(x: Int, n: NSURL, r: NSRect, c: NSCoding) {
reflect(function: {print(x); print(n); print(r); print(c)})
// CHECK-32: Type reference:
// CHECK-32-NEXT: (builtin Builtin.NativeObject)
// CHECK-32: Type info:
// CHECK-32-NEXT: (closure_context size=56 alignment=8 stride=56 num_extra_inhabitants=0
// CHECK-32-NEXT: (closure_context size=60 alignment=8 stride=60 num_extra_inhabitants=0
// CHECK-32-NEXT: (field offset=12
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0
// CHECK-32-NEXT: (field name=_value offset=0
@@ -21,13 +21,15 @@ func capturesImportedClass(x: Int, n: NSURL, r: NSRect) {
// CHECK-32-NEXT: (field offset=16
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))
// CHECK-32-NEXT: (field offset=24
// CHECK-32-NEXT: (builtin size=32 alignment=8 stride=32 num_extra_inhabitants=0)))
// CHECK-32-NEXT: (builtin size=32 alignment=8 stride=32 num_extra_inhabitants=0))
// CHECK-32-NEXT: (field offset=56
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown)))
// CHECK-64: Type reference:
// CHECK-64-NEXT: (builtin Builtin.NativeObject)
// CHECK-64: Type info:
// CHECK-64-NEXT: (closure_context size=64 alignment=8 stride=64 num_extra_inhabitants=0
// CHECK-64-NEXT: (closure_context size=72 alignment=8 stride=72 num_extra_inhabitants=0
// CHECK-64-NEXT: (field offset=16
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0
// CHECK-64-NEXT: (field name=_value offset=0
@@ -35,9 +37,11 @@ func capturesImportedClass(x: Int, n: NSURL, r: NSRect) {
// CHECK-64-NEXT: (field offset=24
// CHECK-64-NEXT: (reference kind=strong refcounting=unknown))
// CHECK-64-NEXT: (field offset=32
// CHECK-64-NEXT: (builtin size=32 alignment=8 stride=32 num_extra_inhabitants=0)))
// CHECK-64-NEXT: (builtin size=32 alignment=8 stride=32 num_extra_inhabitants=0))
// CHECK-64-NEXT: (field offset=64
// CHECK-64-NEXT: (reference kind=strong refcounting=unknown)))
}
capturesImportedClass(x: 10, n: NSURL(), r: NSRect(x: 1, y: 2, width: 3, height: 4))
capturesImportedTypes(x: 10, n: NSURL(), r: NSRect(x: 1, y: 2, width: 3, height: 4), c: "" as NSString)
doneReflecting()