mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Allow @NSManaged to be applied to methods.
Core Data synthesizes Key-Value-Coding-compliant accessors for @NSManaged properties, but Swift won't allow them to be called without predeclaring them. In practice, '@NSManaged' on a method is the same as 'dynamic', except you /can't/ provide a body and overriding it won't work. This is not the long-term model we want (see rdar://problem/20829214), but it fixes a short-term issue with an unfortunate workaround (go through mutableOrderedSetValueForKey(_:) and similar methods). rdar://problem/17583057 Swift SVN r30523
This commit is contained in:
@@ -122,7 +122,7 @@ SIMPLE_DECL_ATTR(IBInspectable, IBInspectable,
|
|||||||
SIMPLE_DECL_ATTR(IBOutlet, IBOutlet,
|
SIMPLE_DECL_ATTR(IBOutlet, IBOutlet,
|
||||||
OnVar, 14)
|
OnVar, 14)
|
||||||
|
|
||||||
SIMPLE_DECL_ATTR(NSManaged, NSManaged, OnVar, 15)
|
SIMPLE_DECL_ATTR(NSManaged, NSManaged, OnVar | OnFunc, 15)
|
||||||
|
|
||||||
SIMPLE_DECL_ATTR(lazy, Lazy, OnVar|DeclModifier, 16)
|
SIMPLE_DECL_ATTR(lazy, Lazy, OnVar|DeclModifier, 16)
|
||||||
|
|
||||||
|
|||||||
@@ -1302,8 +1302,8 @@ ERROR(noescape_conflicts_escaping_autoclosure,attribute_parsing,none,
|
|||||||
|
|
||||||
|
|
||||||
// NSManaged attribute
|
// NSManaged attribute
|
||||||
ERROR(attr_NSManaged_not_property,sema_tcd,none,
|
ERROR(attr_NSManaged_not_instance_member,sema_tcd,none,
|
||||||
"@NSManaged only allowed on a property in a class", ())
|
"@NSManaged only allowed on an instance property or method", ())
|
||||||
ERROR(attr_NSManaged_not_stored,sema_tcd,none,
|
ERROR(attr_NSManaged_not_stored,sema_tcd,none,
|
||||||
"@NSManaged not allowed on %select{computed|observing|adressed}0 "
|
"@NSManaged not allowed on %select{computed|observing|adressed}0 "
|
||||||
"properties", (unsigned))
|
"properties", (unsigned))
|
||||||
@@ -1313,6 +1313,8 @@ ERROR(attr_NSManaged_initial_value,sema_tcd,none,
|
|||||||
"@NSManaged property cannot have an initial value", ())
|
"@NSManaged property cannot have an initial value", ())
|
||||||
ERROR(attr_NSManaged_NSCopying,sema_tcd,none,
|
ERROR(attr_NSManaged_NSCopying,sema_tcd,none,
|
||||||
"@NSManaged property cannot also be marked @NSCopying", ())
|
"@NSManaged property cannot also be marked @NSCopying", ())
|
||||||
|
ERROR(attr_NSManaged_method_body,sema_tcd,none,
|
||||||
|
"@NSManaged method cannot have a body; it must be provided at runtime",())
|
||||||
|
|
||||||
|
|
||||||
// NSCopying attribute
|
// NSCopying attribute
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ const uint16_t VERSION_MAJOR = 0;
|
|||||||
/// To ensure that two separate changes don't silently get merged into one
|
/// To ensure that two separate changes don't silently get merged into one
|
||||||
/// in source control, you should also update the comment to briefly
|
/// in source control, you should also update the comment to briefly
|
||||||
/// describe what change you made.
|
/// describe what change you made.
|
||||||
const uint16_t VERSION_MINOR = 206; // Last change: add reabstraction_thunk type
|
const uint16_t VERSION_MINOR = 207; // Last change: @NSManaged on methods
|
||||||
|
|
||||||
using DeclID = Fixnum<31>;
|
using DeclID = Fixnum<31>;
|
||||||
using DeclIDField = BCFixed<31>;
|
using DeclIDField = BCFixed<31>;
|
||||||
|
|||||||
@@ -109,13 +109,18 @@ private:
|
|||||||
if (auto *VD = dyn_cast<ValueDecl>(member))
|
if (auto *VD = dyn_cast<ValueDecl>(member))
|
||||||
if (VD->isFinal() && VD->getOverriddenDecl() == nullptr)
|
if (VD->isFinal() && VD->getOverriddenDecl() == nullptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// @NSManaged properties and methods don't have vtable entries.
|
||||||
|
if (member->getAttrs().hasAttribute<NSManagedAttr>())
|
||||||
|
continue;
|
||||||
|
|
||||||
// Add entries for methods.
|
// Add entries for methods.
|
||||||
if (auto fn = dyn_cast<FuncDecl>(member)) {
|
if (auto fn = dyn_cast<FuncDecl>(member)) {
|
||||||
// Ignore accessors. These get added when their AbstractStorageDecl is
|
// Ignore accessors. These get added when their AbstractStorageDecl is
|
||||||
// visited.
|
// visited.
|
||||||
if (fn->isAccessor())
|
if (fn->isAccessor())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
addMethodEntries(fn);
|
addMethodEntries(fn);
|
||||||
} else if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
|
} else if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
|
||||||
// Stub constructors don't get an entry.
|
// Stub constructors don't get an entry.
|
||||||
@@ -128,9 +133,6 @@ private:
|
|||||||
// FIXME: Stored properties should either be final or have accessors.
|
// FIXME: Stored properties should either be final or have accessors.
|
||||||
if (!asd->hasAccessorFunctions()) continue;
|
if (!asd->hasAccessorFunctions()) continue;
|
||||||
|
|
||||||
// @NSManaged properties don't have vtable entries.
|
|
||||||
if (asd->getAttrs().hasAttribute<NSManagedAttr>()) continue;
|
|
||||||
|
|
||||||
addMethodEntries(asd->getGetter());
|
addMethodEntries(asd->getGetter());
|
||||||
if (auto *setter = asd->getSetter())
|
if (auto *setter = asd->getSetter())
|
||||||
addMethodEntries(setter);
|
addMethodEntries(setter);
|
||||||
|
|||||||
@@ -1152,7 +1152,11 @@ namespace {
|
|||||||
// getters and setters funcdecls will be handled by their parent
|
// getters and setters funcdecls will be handled by their parent
|
||||||
// var/subscript.
|
// var/subscript.
|
||||||
if (method->isAccessor()) return;
|
if (method->isAccessor()) return;
|
||||||
|
|
||||||
|
// Don't emit getters/setters for @NSManaged methods.
|
||||||
|
if (method->getAttrs().hasAttribute<NSManagedAttr>())
|
||||||
|
return;
|
||||||
|
|
||||||
llvm::Constant *entry = emitObjCMethodDescriptor(IGM, method);
|
llvm::Constant *entry = emitObjCMethodDescriptor(IGM, method);
|
||||||
// This pointer will be set if we need to store the extended method type
|
// This pointer will be set if we need to store the extended method type
|
||||||
// encoding.
|
// encoding.
|
||||||
@@ -1480,7 +1484,7 @@ namespace {
|
|||||||
if (llvm::Constant *prop = buildProperty(var))
|
if (llvm::Constant *prop = buildProperty(var))
|
||||||
Properties.push_back(prop);
|
Properties.push_back(prop);
|
||||||
|
|
||||||
// Don't emit getter/setter descriptors for @NSManagedAttr properties.
|
// Don't emit getter/setter descriptors for @NSManaged properties.
|
||||||
if (var->getAttrs().hasAttribute<NSManagedAttr>() ||
|
if (var->getAttrs().hasAttribute<NSManagedAttr>() ||
|
||||||
// Don't emit descriptors for properties without accessors.
|
// Don't emit descriptors for properties without accessors.
|
||||||
var->getGetter() == nullptr)
|
var->getGetter() == nullptr)
|
||||||
|
|||||||
@@ -146,6 +146,11 @@ public:
|
|||||||
|
|
||||||
void visitFuncDecl(FuncDecl *method) {
|
void visitFuncDecl(FuncDecl *method) {
|
||||||
if (!requiresObjCMethodDescriptor(method)) return;
|
if (!requiresObjCMethodDescriptor(method)) return;
|
||||||
|
|
||||||
|
// Don't emit getters/setters for @NSManaged methods.
|
||||||
|
if (method->getAttrs().hasAttribute<NSManagedAttr>())
|
||||||
|
return;
|
||||||
|
|
||||||
llvm::Constant *name, *imp, *types;
|
llvm::Constant *name, *imp, *types;
|
||||||
emitObjCMethodDescriptorParts(IGM, method,
|
emitObjCMethodDescriptorParts(IGM, method,
|
||||||
/*extended*/false,
|
/*extended*/false,
|
||||||
@@ -203,7 +208,7 @@ public:
|
|||||||
// ObjC doesn't have a notion of class properties, so we'd only do this
|
// ObjC doesn't have a notion of class properties, so we'd only do this
|
||||||
// for instance properties.
|
// for instance properties.
|
||||||
|
|
||||||
// Don't emit getters/setters for @NSManagedAttr properties.
|
// Don't emit getters/setters for @NSManaged properties.
|
||||||
if (prop->getAttrs().hasAttribute<NSManagedAttr>())
|
if (prop->getAttrs().hasAttribute<NSManagedAttr>())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -173,12 +173,15 @@ SILValue SILGenFunction::emitDynamicMethodRef(SILLocation loc,
|
|||||||
|
|
||||||
bool SILGenModule::requiresObjCMethodEntryPoint(FuncDecl *method) {
|
bool SILGenModule::requiresObjCMethodEntryPoint(FuncDecl *method) {
|
||||||
// Property accessors should be generated alongside the property unless
|
// Property accessors should be generated alongside the property unless
|
||||||
// the @NSManagedAttr attribute is present.
|
// the @NSManaged attribute is present.
|
||||||
if (method->isGetterOrSetter()) {
|
if (method->isGetterOrSetter()) {
|
||||||
auto asd = method->getAccessorStorageDecl();
|
auto asd = method->getAccessorStorageDecl();
|
||||||
return asd->isObjC() && !asd->getAttrs().hasAttribute<NSManagedAttr>();
|
return asd->isObjC() && !asd->getAttrs().hasAttribute<NSManagedAttr>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (method->getAttrs().hasAttribute<NSManagedAttr>())
|
||||||
|
return false;
|
||||||
|
|
||||||
return method->isObjC() || method->getAttrs().hasAttribute<IBActionAttr>();
|
return method->isObjC() || method->getAttrs().hasAttribute<IBActionAttr>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -333,12 +333,23 @@ void AttributeEarlyChecker::visitIBOutletAttr(IBOutletAttr *attr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AttributeEarlyChecker::visitNSManagedAttr(NSManagedAttr *attr) {
|
void AttributeEarlyChecker::visitNSManagedAttr(NSManagedAttr *attr) {
|
||||||
// @NSManaged may only be used on properties.
|
// @NSManaged only applies to instance methods and properties within a class.
|
||||||
auto *VD = cast<VarDecl>(D);
|
if (cast<ValueDecl>(D)->isStatic() ||
|
||||||
|
!D->getDeclContext()->isClassOrClassExtensionContext()) {
|
||||||
|
return diagnoseAndRemoveAttr(attr,
|
||||||
|
diag::attr_NSManaged_not_instance_member);
|
||||||
|
}
|
||||||
|
|
||||||
// NSManaged only applies to non-class properties within a class.
|
if (auto *method = dyn_cast<FuncDecl>(D)) {
|
||||||
if (VD->isStatic() || !VD->getDeclContext()->isClassOrClassExtensionContext())
|
// Separate out the checks for methods.
|
||||||
return diagnoseAndRemoveAttr(attr, diag::attr_NSManaged_not_property);
|
if (method->hasBody())
|
||||||
|
return diagnoseAndRemoveAttr(attr, diag::attr_NSManaged_method_body);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Everything below deals with restrictions on @NSManaged properties.
|
||||||
|
auto *VD = cast<VarDecl>(D);
|
||||||
|
|
||||||
if (VD->isLet())
|
if (VD->isLet())
|
||||||
return diagnoseAndRemoveAttr(attr, diag::attr_NSManaged_let_property);
|
return diagnoseAndRemoveAttr(attr, diag::attr_NSManaged_let_property);
|
||||||
|
|||||||
@@ -3903,10 +3903,11 @@ public:
|
|||||||
if (decl->isInvalid() || decl->isImplicit() || decl->hasClangNode())
|
if (decl->isInvalid() || decl->isImplicit() || decl->hasClangNode())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Functions can have asmname and semantics attributes.
|
// Functions can have asmname, semantics, and NSManaged attributes.
|
||||||
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
|
if (auto func = dyn_cast<AbstractFunctionDecl>(decl)) {
|
||||||
if (func->getAttrs().hasAttribute<AsmnameAttr>() ||
|
if (func->getAttrs().hasAttribute<AsmnameAttr>() ||
|
||||||
func->getAttrs().hasAttribute<SemanticsAttr>())
|
func->getAttrs().hasAttribute<SemanticsAttr>() ||
|
||||||
|
func->getAttrs().hasAttribute<NSManagedAttr>())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4158,28 +4159,7 @@ public:
|
|||||||
validateAttributes(TC, FD);
|
validateAttributes(TC, FD);
|
||||||
|
|
||||||
// Member functions need some special validation logic.
|
// Member functions need some special validation logic.
|
||||||
if (auto contextType = FD->getDeclContext()->getDeclaredTypeInContext()) {
|
if (FD->getDeclContext()->isTypeContext()) {
|
||||||
// If this is a class member, mark it final if the class is final.
|
|
||||||
if (auto cls = contextType->getClassOrBoundGenericClass()) {
|
|
||||||
if (cls->isFinal() && !FD->isAccessor() &&
|
|
||||||
!FD->isFinal() && !FD->isDynamic()) {
|
|
||||||
makeFinal(TC.Context, FD);
|
|
||||||
}
|
|
||||||
// static func declarations in classes are synonyms
|
|
||||||
// for `class final func` declarations.
|
|
||||||
if (FD->getStaticSpelling() == StaticSpellingKind::KeywordStatic) {
|
|
||||||
auto finalAttr = FD->getAttrs().getAttribute<FinalAttr>();
|
|
||||||
if (finalAttr) {
|
|
||||||
auto finalRange = finalAttr->getRange();
|
|
||||||
if (finalRange.isValid())
|
|
||||||
TC.diagnose(finalRange.Start, diag::decl_already_final)
|
|
||||||
.highlight(finalRange)
|
|
||||||
.fixItRemove(finalRange);
|
|
||||||
}
|
|
||||||
makeFinal(TC.Context, FD);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!checkOverrides(TC, FD)) {
|
if (!checkOverrides(TC, FD)) {
|
||||||
// If a method has an 'override' keyword but does not
|
// If a method has an 'override' keyword but does not
|
||||||
// override anything, complain.
|
// override anything, complain.
|
||||||
@@ -4239,6 +4219,29 @@ public:
|
|||||||
|
|
||||||
TC.checkDeclAttributes(FD);
|
TC.checkDeclAttributes(FD);
|
||||||
|
|
||||||
|
// If this is a class member, mark it final if the class is final.
|
||||||
|
if (auto contextType = FD->getDeclContext()->getDeclaredTypeInContext()) {
|
||||||
|
if (auto cls = contextType->getClassOrBoundGenericClass()) {
|
||||||
|
if (cls->isFinal() && !FD->isAccessor() &&
|
||||||
|
!FD->isFinal() && !FD->isDynamic()) {
|
||||||
|
makeFinal(TC.Context, FD);
|
||||||
|
}
|
||||||
|
// static func declarations in classes are synonyms
|
||||||
|
// for `class final func` declarations.
|
||||||
|
if (FD->getStaticSpelling() == StaticSpellingKind::KeywordStatic) {
|
||||||
|
auto finalAttr = FD->getAttrs().getAttribute<FinalAttr>();
|
||||||
|
if (finalAttr) {
|
||||||
|
auto finalRange = finalAttr->getRange();
|
||||||
|
if (finalRange.isValid())
|
||||||
|
TC.diagnose(finalRange.Start, diag::decl_already_final)
|
||||||
|
.highlight(finalRange)
|
||||||
|
.fixItRemove(finalRange);
|
||||||
|
}
|
||||||
|
makeFinal(TC.Context, FD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether we have parameters with default arguments that follow a
|
// Check whether we have parameters with default arguments that follow a
|
||||||
// closure parameter; warn about such things, because the closure will not
|
// closure parameter; warn about such things, because the closure will not
|
||||||
// be treated as a trailing closure.
|
// be treated as a trailing closure.
|
||||||
|
|||||||
@@ -11,4 +11,6 @@ func getMyManagedObject() -> MyManagedObject {
|
|||||||
|
|
||||||
extension MyManagedObject {
|
extension MyManagedObject {
|
||||||
@NSManaged var anotherManaged: String
|
@NSManaged var anotherManaged: String
|
||||||
|
|
||||||
|
@NSManaged func managedMethod()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,3 +53,7 @@ func accessOther(om: OtherManagedObject) -> String {
|
|||||||
func accessMine(obj: MyManagedObject) -> String {
|
func accessMine(obj: MyManagedObject) -> String {
|
||||||
return obj.anotherManaged
|
return obj.anotherManaged
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func accessMyMethod(obj: MyManagedObject) {
|
||||||
|
obj.managedMethod()
|
||||||
|
}
|
||||||
|
|||||||
@@ -45,11 +45,12 @@ func method(@#^KEYWORD1^#) {}
|
|||||||
@#^KEYWORD2^#
|
@#^KEYWORD2^#
|
||||||
func method(){}
|
func method(){}
|
||||||
|
|
||||||
// KEYWORD2: Begin completions, 8 items
|
// KEYWORD2: Begin completions, 9 items
|
||||||
// KEYWORD2-NEXT: Keyword/None: available[#Func Attribute#]; name=available{{$}}
|
// KEYWORD2-NEXT: Keyword/None: available[#Func Attribute#]; name=available{{$}}
|
||||||
// KEYWORD2-NEXT: Keyword/None: objc[#Func Attribute#]; name=objc{{$}}
|
// KEYWORD2-NEXT: Keyword/None: objc[#Func Attribute#]; name=objc{{$}}
|
||||||
// KEYWORD2-NEXT: Keyword/None: noreturn[#Func Attribute#]; name=noreturn{{$}}
|
// KEYWORD2-NEXT: Keyword/None: noreturn[#Func Attribute#]; name=noreturn{{$}}
|
||||||
// KEYWORD2-NEXT: Keyword/None: IBAction[#Func Attribute#]; name=IBAction{{$}}
|
// KEYWORD2-NEXT: Keyword/None: IBAction[#Func Attribute#]; name=IBAction{{$}}
|
||||||
|
// KEYWORD2-NEXT: Keyword/None: NSManaged[#Func Attribute#]; name=NSManaged{{$}}
|
||||||
// KEYWORD2-NEXT: Keyword/None: inline[#Func Attribute#]; name=inline{{$}}
|
// KEYWORD2-NEXT: Keyword/None: inline[#Func Attribute#]; name=inline{{$}}
|
||||||
// KEYWORD2-NEXT: Keyword/None: nonobjc[#Func Attribute#]; name=nonobjc{{$}}
|
// KEYWORD2-NEXT: Keyword/None: nonobjc[#Func Attribute#]; name=nonobjc{{$}}
|
||||||
// KEYWORD2-NEXT: Keyword/None: warn_unused_result[#Func Attribute#]; name=warn_unused_result{{$}}
|
// KEYWORD2-NEXT: Keyword/None: warn_unused_result[#Func Attribute#]; name=warn_unused_result{{$}}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ sil_vtable X {}
|
|||||||
|
|
||||||
@objc class SwiftGizmo : Gizmo {
|
@objc class SwiftGizmo : Gizmo {
|
||||||
@objc @NSManaged var x: X
|
@objc @NSManaged var x: X
|
||||||
|
@objc @NSManaged func kvc()
|
||||||
}
|
}
|
||||||
sil @_TToFC19objc_attr_NSManaged1XcfMS0_FT_S0_ : $@convention(objc_method) (@owned X) -> @owned X {
|
sil @_TToFC19objc_attr_NSManaged1XcfMS0_FT_S0_ : $@convention(objc_method) (@owned X) -> @owned X {
|
||||||
bb0(%0 : $X):
|
bb0(%0 : $X):
|
||||||
|
|||||||
@@ -14,8 +14,11 @@ import gizmo
|
|||||||
class SwiftGizmo : Gizmo {
|
class SwiftGizmo : Gizmo {
|
||||||
@NSManaged var x: X
|
@NSManaged var x: X
|
||||||
|
|
||||||
// CHECK-NOT: sil hidden @_TToFC19objc_attr_NSManaged10SwiftGizmog1xCS_1X : $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
|
@NSManaged func kvc()
|
||||||
// CHECK-NOT: sil hidden @_TToFC19objc_attr_NSManaged10SwiftGizmos1xCS_1X
|
|
||||||
|
// CHECK-NOT: sil hidden @_TToFC19objc_attr_NSManaged10SwiftGizmog1x
|
||||||
|
// CHECK-NOT: sil hidden @_TToFC19objc_attr_NSManaged10SwiftGizmos1x
|
||||||
|
// CHECK-NOT: sil hidden @_TToFC19objc_attr_NSManaged10SwiftGizmo3kvc
|
||||||
|
|
||||||
// Make sure that we're calling through the @objc entry points.
|
// Make sure that we're calling through the @objc entry points.
|
||||||
// CHECK-LABEL: sil hidden @_TFC19objc_attr_NSManaged10SwiftGizmo7modifyX{{.*}} : $@convention(method) (@guaranteed SwiftGizmo) -> () {
|
// CHECK-LABEL: sil hidden @_TFC19objc_attr_NSManaged10SwiftGizmo7modifyX{{.*}} : $@convention(method) (@guaranteed SwiftGizmo) -> () {
|
||||||
@@ -28,16 +31,50 @@ class SwiftGizmo : Gizmo {
|
|||||||
x = x.foo()
|
x = x.foo()
|
||||||
// CHECK: return
|
// CHECK: return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: sil hidden @_TFC19objc_attr_NSManaged10SwiftGizmo8testFuncfS0_FT_T_
|
||||||
|
func testFunc() {
|
||||||
|
// CHECK: = class_method [volatile] %0 : $SwiftGizmo, #SwiftGizmo.kvc!1.foreign : SwiftGizmo -> () -> () , $@convention(objc_method) (SwiftGizmo) -> ()
|
||||||
|
// CHECK: return
|
||||||
|
kvc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SwiftGizmo {
|
||||||
|
@NSManaged func extKVC()
|
||||||
|
|
||||||
|
// CHECK-LABEL: _TFC19objc_attr_NSManaged10SwiftGizmo7testExtfS0_FT_T_
|
||||||
|
func testExt() {
|
||||||
|
// CHECK: = class_method [volatile] %0 : $SwiftGizmo, #SwiftGizmo.extKVC!1.foreign : SwiftGizmo -> () -> () , $@convention(objc_method) (SwiftGizmo) -> ()
|
||||||
|
// CHECK: return
|
||||||
|
extKVC()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class FinalGizmo : SwiftGizmo {
|
final class FinalGizmo : SwiftGizmo {
|
||||||
@NSManaged var y: String
|
@NSManaged var y: String
|
||||||
|
|
||||||
|
@NSManaged func kvc2()
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FinalGizmo {
|
||||||
|
@NSManaged func extKVC2()
|
||||||
|
|
||||||
|
// CHECK-LABEL: _TFC19objc_attr_NSManaged10FinalGizmo8testExt2fS0_FT_T_
|
||||||
|
func testExt2() {
|
||||||
|
// CHECK: = class_method [volatile] %0 : $FinalGizmo, #FinalGizmo.extKVC2!1.foreign : FinalGizmo -> () -> () , $@convention(objc_method) (FinalGizmo) -> ()
|
||||||
|
// CHECK: return
|
||||||
|
extKVC2()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: sil hidden @_TF19objc_attr_NSManaged9testFinalFCS_10FinalGizmoSS : $@convention(thin) (@owned FinalGizmo) -> @owned String {
|
// CHECK-LABEL: sil hidden @_TF19objc_attr_NSManaged9testFinalFCS_10FinalGizmoSS : $@convention(thin) (@owned FinalGizmo) -> @owned String {
|
||||||
func testFinal(obj: FinalGizmo) -> String {
|
func testFinal(obj: FinalGizmo) -> String {
|
||||||
|
// CHECK: class_method [volatile] %0 : $FinalGizmo, #FinalGizmo.kvc2!1.foreign : FinalGizmo -> () -> () , $@convention(objc_method) (FinalGizmo) -> ()
|
||||||
|
// CHECK-NOT: return
|
||||||
// CHECK: class_method [volatile] %0 : $FinalGizmo, #FinalGizmo.y!getter.1.foreign : FinalGizmo -> () -> String , $@convention(objc_method) (FinalGizmo) -> @autoreleased NSString
|
// CHECK: class_method [volatile] %0 : $FinalGizmo, #FinalGizmo.y!getter.1.foreign : FinalGizmo -> () -> String , $@convention(objc_method) (FinalGizmo) -> @autoreleased NSString
|
||||||
// CHECK: return
|
// CHECK: return
|
||||||
|
obj.kvc2()
|
||||||
return obj.y
|
return obj.y
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,13 +87,15 @@ func testFinal(obj: FinalGizmo) -> String {
|
|||||||
// The vtable should not contain any entry points for getters and setters.
|
// The vtable should not contain any entry points for getters and setters.
|
||||||
// CHECK-LABEL: sil_vtable SwiftGizmo {
|
// CHECK-LABEL: sil_vtable SwiftGizmo {
|
||||||
// CHECK-NEXT: #SwiftGizmo.modifyX!1: _TFC19objc_attr_NSManaged10SwiftGizmo7modifyXfS0_FT_T_ // objc_attr_NSManaged.SwiftGizmo.modifyX (objc_attr_NSManaged.SwiftGizmo)() -> ()
|
// CHECK-NEXT: #SwiftGizmo.modifyX!1: _TFC19objc_attr_NSManaged10SwiftGizmo7modifyXfS0_FT_T_ // objc_attr_NSManaged.SwiftGizmo.modifyX (objc_attr_NSManaged.SwiftGizmo)() -> ()
|
||||||
// CHECK-NEXT: #SwiftGizmo.deinit!deallocator:
|
// CHECK-NEXT: #SwiftGizmo.testFunc!1: _TFC19objc_attr_NSManaged10SwiftGizmo8testFuncfS0_FT_T_ // objc_attr_NSManaged.SwiftGizmo.testFunc (objc_attr_NSManaged.SwiftGizmo)() -> ()
|
||||||
// CHECK-NEXT: #SwiftGizmo.init!initializer.1: _TFC19objc_attr_NSManaged10SwiftGizmocfMS0_FT_GSQS0__
|
// CHECK-NEXT: #SwiftGizmo.init!initializer.1: _TFC19objc_attr_NSManaged10SwiftGizmocfMS0_FT_GSQS0__
|
||||||
// CHECK-NEXT: #SwiftGizmo.init!initializer.1: _TFC19objc_attr_NSManaged10SwiftGizmocfMS0_FT7bellsOnSi_GSQS0__
|
// CHECK-NEXT: #SwiftGizmo.init!initializer.1: _TFC19objc_attr_NSManaged10SwiftGizmocfMS0_FT7bellsOnSi_GSQS0__
|
||||||
|
// CHECK-NEXT: #SwiftGizmo.deinit!deallocator:
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
|
|
||||||
// CHECK-LABEL: sil_vtable FinalGizmo {
|
// CHECK-LABEL: sil_vtable FinalGizmo {
|
||||||
// CHECK-NEXT: #SwiftGizmo.modifyX!1: _TFC19objc_attr_NSManaged10SwiftGizmo7modifyXfS0_FT_T_
|
// CHECK-NEXT: #SwiftGizmo.modifyX!1: _TFC19objc_attr_NSManaged10SwiftGizmo7modifyXfS0_FT_T_
|
||||||
|
// CHECK-NEXT: #SwiftGizmo.testFunc!1: _TFC19objc_attr_NSManaged10SwiftGizmo8testFuncfS0_FT_T_ // objc_attr_NSManaged.SwiftGizmo.testFunc (objc_attr_NSManaged.SwiftGizmo)() -> ()
|
||||||
// CHECK-NEXT: #SwiftGizmo.init!initializer.1: _TFC19objc_attr_NSManaged10FinalGizmocfMS0_FT_GSQS0__
|
// CHECK-NEXT: #SwiftGizmo.init!initializer.1: _TFC19objc_attr_NSManaged10FinalGizmocfMS0_FT_GSQS0__
|
||||||
// CHECK-NEXT: #SwiftGizmo.init!initializer.1: _TFC19objc_attr_NSManaged10FinalGizmocfMS0_FT7bellsOnSi_GSQS0__
|
// CHECK-NEXT: #SwiftGizmo.init!initializer.1: _TFC19objc_attr_NSManaged10FinalGizmocfMS0_FT7bellsOnSi_GSQS0__
|
||||||
// CHECK-NEXT: #FinalGizmo.deinit!deallocator: _TFC19objc_attr_NSManaged10FinalGizmoD
|
// CHECK-NEXT: #FinalGizmo.deinit!deallocator: _TFC19objc_attr_NSManaged10FinalGizmoD
|
||||||
|
|||||||
@@ -6,14 +6,26 @@ import Foundation
|
|||||||
|
|
||||||
// CHECK-LABEL: sil hidden @_TF25objc_attr_NSManaged_multi9testMultiFCS_10SwiftGizmoPSs9AnyObject_ : $@convention(thin) (@owned SwiftGizmo) -> @owned AnyObject {
|
// CHECK-LABEL: sil hidden @_TF25objc_attr_NSManaged_multi9testMultiFCS_10SwiftGizmoPSs9AnyObject_ : $@convention(thin) (@owned SwiftGizmo) -> @owned AnyObject {
|
||||||
func testMulti(obj: SwiftGizmo) -> AnyObject {
|
func testMulti(obj: SwiftGizmo) -> AnyObject {
|
||||||
|
// CHECK: = class_method [volatile] %0 : $SwiftGizmo, #SwiftGizmo.kvc!1.foreign : SwiftGizmo -> () -> () , $@convention(objc_method) (SwiftGizmo) -> ()
|
||||||
|
// CHECK-NOT: return
|
||||||
|
// CHECK: = class_method [volatile] %0 : $SwiftGizmo, #SwiftGizmo.extKVC!1.foreign : SwiftGizmo -> () -> () , $@convention(objc_method) (SwiftGizmo) -> ()
|
||||||
|
// CHECK-NOT: return
|
||||||
// CHECK: class_method [volatile] %0 : $SwiftGizmo, #SwiftGizmo.x!getter.1.foreign : SwiftGizmo -> () -> X , $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
|
// CHECK: class_method [volatile] %0 : $SwiftGizmo, #SwiftGizmo.x!getter.1.foreign : SwiftGizmo -> () -> X , $@convention(objc_method) (SwiftGizmo) -> @autoreleased X
|
||||||
// CHECK: return
|
// CHECK: return
|
||||||
|
obj.kvc()
|
||||||
|
obj.extKVC()
|
||||||
return obj.x
|
return obj.x
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: sil hidden @_TF25objc_attr_NSManaged_multi14testFinalMultiFCS_10FinalGizmoSS : $@convention(thin) (@owned FinalGizmo) -> @owned String {
|
// CHECK-LABEL: sil hidden @_TF25objc_attr_NSManaged_multi14testFinalMultiFCS_10FinalGizmoSS : $@convention(thin) (@owned FinalGizmo) -> @owned String {
|
||||||
func testFinalMulti(obj: FinalGizmo) -> String {
|
func testFinalMulti(obj: FinalGizmo) -> String {
|
||||||
|
// CHECK: class_method [volatile] %0 : $FinalGizmo, #FinalGizmo.kvc2!1.foreign : FinalGizmo -> () -> () , $@convention(objc_method) (FinalGizmo) -> ()
|
||||||
|
// CHECK-NOT: return
|
||||||
|
// CHECK: class_method [volatile] %0 : $FinalGizmo, #FinalGizmo.extKVC2!1.foreign : FinalGizmo -> () -> () , $@convention(objc_method) (FinalGizmo) -> ()
|
||||||
|
// CHECK-NOT: return
|
||||||
// CHECK: class_method [volatile] %0 : $FinalGizmo, #FinalGizmo.y!getter.1.foreign : FinalGizmo -> () -> String , $@convention(objc_method) (FinalGizmo) -> @autoreleased NSString
|
// CHECK: class_method [volatile] %0 : $FinalGizmo, #FinalGizmo.y!getter.1.foreign : FinalGizmo -> () -> String , $@convention(objc_method) (FinalGizmo) -> @autoreleased NSString
|
||||||
// CHECK: return
|
// CHECK: return
|
||||||
|
obj.kvc2()
|
||||||
|
obj.extKVC2()
|
||||||
return obj.y
|
return obj.y
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
// RUN: %target-parse-verify-swift
|
|
||||||
|
|
||||||
protocol SwiftProto { }
|
|
||||||
|
|
||||||
@objc class C {
|
|
||||||
// okay
|
|
||||||
@NSManaged var x: Int
|
|
||||||
|
|
||||||
// expected-error@+1{{@NSManaged property cannot have an initial value}}
|
|
||||||
@NSManaged var c: C = C()
|
|
||||||
|
|
||||||
// expected-error@+1{{property cannot be marked @NSManaged because its type cannot be represented in Objective-C}}
|
|
||||||
@NSManaged var nonobjc_var: SwiftProto?
|
|
||||||
|
|
||||||
// expected-error@+1{{@NSManaged not allowed on a 'let' property}}
|
|
||||||
@NSManaged let let_property: Int = 10
|
|
||||||
|
|
||||||
// expected-error@+1{{@NSManaged not allowed on computed properties}}
|
|
||||||
@NSManaged var computed_var: Int {
|
|
||||||
return 5
|
|
||||||
}
|
|
||||||
|
|
||||||
// expected-error@+1{{@NSManaged not allowed on observing properties}}
|
|
||||||
@NSManaged var observing_var: Int {
|
|
||||||
willSet { }
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
|
||||||
observing_var = 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -8,17 +8,37 @@ class X : NSObject {
|
|||||||
func foo() -> X { return self }
|
func foo() -> X { return self }
|
||||||
}
|
}
|
||||||
|
|
||||||
@NSManaged var global: Int // expected-error {{@NSManaged only allowed on a property in a class}}
|
@NSManaged struct SomeStruct {} // expected-error {{@NSManaged cannot be applied to this declaration}}
|
||||||
|
|
||||||
@NSManaged // expected-error {{@NSManaged may only be used on 'var' declarations}}
|
@NSManaged var global: Int // expected-error {{@NSManaged only allowed on an instance property or method}}
|
||||||
|
|
||||||
|
@NSManaged // expected-error {{@NSManaged only allowed on an instance property or method}}
|
||||||
func managedFunction() {}
|
func managedFunction() {}
|
||||||
|
|
||||||
|
protocol SwiftProto { }
|
||||||
|
|
||||||
class SwiftGizmo : A {
|
class SwiftGizmo : A {
|
||||||
@NSManaged var a: X
|
@NSManaged var a: X
|
||||||
@NSManaged var b: Int
|
@NSManaged var b: Int
|
||||||
@NSManaged let c: Int // expected-error {{@NSManaged not allowed on a 'let' property}}
|
@NSManaged let c: Int // expected-error {{@NSManaged not allowed on a 'let' property}}
|
||||||
|
|
||||||
|
// expected-error@+1{{@NSManaged property cannot have an initial value}}
|
||||||
|
@NSManaged var gizmo: SwiftGizmo = SwiftGizmo()
|
||||||
|
|
||||||
|
// expected-error@+1{{@NSManaged not allowed on computed properties}}
|
||||||
|
@NSManaged var computed_var: Int {
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
|
||||||
@NSManaged class var d: Int = 4 // expected-error {{@NSManaged only allowed on a property in a class}} \
|
// expected-error@+1{{@NSManaged not allowed on observing properties}}
|
||||||
|
@NSManaged var observing_var: Int {
|
||||||
|
willSet { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// expected-error@+1{{property cannot be marked @NSManaged because its type cannot be represented in Objective-C}}
|
||||||
|
@NSManaged var nonobjc_var: SwiftProto?
|
||||||
|
|
||||||
|
@NSManaged class var d: Int = 4 // expected-error {{@NSManaged only allowed on an instance property or method}} \
|
||||||
// expected-error {{class stored properties not yet supported}}
|
// expected-error {{class stored properties not yet supported}}
|
||||||
|
|
||||||
|
|
||||||
@@ -26,6 +46,10 @@ class SwiftGizmo : A {
|
|||||||
|
|
||||||
@NSCopying @NSManaged var optionalProperty : NSString? // expected-error {{@NSManaged property cannot also be marked @NSCopying}}
|
@NSCopying @NSManaged var optionalProperty : NSString? // expected-error {{@NSManaged property cannot also be marked @NSCopying}}
|
||||||
|
|
||||||
|
@NSManaged func mutableArrayValueForA() // no-warning
|
||||||
|
@NSManaged func mutableArrayValueForB() {} // expected-error {{NSManaged method cannot have a body; it must be provided at runtime}}
|
||||||
|
@NSManaged class func mutableArrayValueForA() {} // expected-error {{@NSManaged only allowed on an instance property or method}}
|
||||||
|
|
||||||
override init() {}
|
override init() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user