forked from OSchip/llvm-project
Property declared in continuation class can only be used to
change a readonly property declared in the class (and its inherited protocols) to writable property. (Fixes radar 7350645). llvm-svn: 85836
This commit is contained in:
parent
ac0b098d4d
commit
de8db16a7d
|
@ -347,6 +347,8 @@ public:
|
||||||
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
|
ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const;
|
||||||
|
|
||||||
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
|
ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const;
|
||||||
|
ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(
|
||||||
|
IdentifierInfo *PropertyId) const;
|
||||||
|
|
||||||
// Marks the end of the container.
|
// Marks the end of the container.
|
||||||
SourceLocation getAtEndLoc() const { return AtEndLoc; }
|
SourceLocation getAtEndLoc() const { return AtEndLoc; }
|
||||||
|
|
|
@ -264,7 +264,8 @@ def warn_objc_property_copy_missing_on_block : Warning<
|
||||||
"'copy' attribute must be specified for the block property "
|
"'copy' attribute must be specified for the block property "
|
||||||
"when -fobjc-gc-only is specified">;
|
"when -fobjc-gc-only is specified">;
|
||||||
def err_use_continuation_class : Error<
|
def err_use_continuation_class : Error<
|
||||||
"attribute of property in continuation class of %0 can only be 'readwrite'">;
|
"property declaration in continuation class of %0 is to change a 'readonly' "
|
||||||
|
"property to 'readwrite'">;
|
||||||
def err_continuation_class : Error<"continuation class has no primary class">;
|
def err_continuation_class : Error<"continuation class has no primary class">;
|
||||||
def err_property_type : Error<"property cannot have array or function type %0">;
|
def err_property_type : Error<"property cannot have array or function type %0">;
|
||||||
def error_missing_property_context : Error<
|
def error_missing_property_context : Error<
|
||||||
|
@ -274,7 +275,7 @@ def error_bad_property_decl : Error<
|
||||||
def error_category_property : Error<
|
def error_category_property : Error<
|
||||||
"property declared in category %0 cannot be implemented in "
|
"property declared in category %0 cannot be implemented in "
|
||||||
"class implementation">;
|
"class implementation">;
|
||||||
def note_category_property : Note<
|
def note_property_declare : Note<
|
||||||
"property declared here">;
|
"property declared here">;
|
||||||
def error_synthesize_category_decl : Error<
|
def error_synthesize_category_decl : Error<
|
||||||
"@synthesize not allowed in a category's implementation">;
|
"@synthesize not allowed in a category's implementation">;
|
||||||
|
|
|
@ -118,6 +118,27 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
|
||||||
|
/// with name 'PropertyId' in the primary class; including those in protocols
|
||||||
|
/// (direct or indirect) used by the promary class.
|
||||||
|
/// FIXME: Convert to DeclContext lookup...
|
||||||
|
///
|
||||||
|
ObjCPropertyDecl *
|
||||||
|
ObjCContainerDecl::FindPropertyVisibleInPrimaryClass(
|
||||||
|
IdentifierInfo *PropertyId) const {
|
||||||
|
assert(isa<ObjCInterfaceDecl>(this) && "FindPropertyVisibleInPrimaryClass");
|
||||||
|
for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I)
|
||||||
|
if ((*I)->getIdentifier() == PropertyId)
|
||||||
|
return *I;
|
||||||
|
const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(this);
|
||||||
|
// Look through protocols.
|
||||||
|
for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(),
|
||||||
|
E = OID->protocol_end(); I != E; ++I)
|
||||||
|
if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
|
||||||
|
return P;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
|
void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
|
||||||
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
|
ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
|
||||||
ASTContext &C)
|
ASTContext &C)
|
||||||
|
|
|
@ -1893,17 +1893,9 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
|
||||||
// handling.
|
// handling.
|
||||||
if ((CCPrimary = CDecl->getClassInterface())) {
|
if ((CCPrimary = CDecl->getClassInterface())) {
|
||||||
// Find the property in continuation class's primary class only.
|
// Find the property in continuation class's primary class only.
|
||||||
ObjCPropertyDecl *PIDecl = 0;
|
|
||||||
IdentifierInfo *PropertyId = FD.D.getIdentifier();
|
IdentifierInfo *PropertyId = FD.D.getIdentifier();
|
||||||
for (ObjCInterfaceDecl::prop_iterator
|
if (ObjCPropertyDecl *PIDecl =
|
||||||
I = CCPrimary->prop_begin(), E = CCPrimary->prop_end();
|
CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId)) {
|
||||||
I != E; ++I)
|
|
||||||
if ((*I)->getIdentifier() == PropertyId) {
|
|
||||||
PIDecl = *I;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PIDecl) {
|
|
||||||
// property 'PIDecl's readonly attribute will be over-ridden
|
// property 'PIDecl's readonly attribute will be over-ridden
|
||||||
// with continuation class's readwrite property attribute!
|
// with continuation class's readwrite property attribute!
|
||||||
unsigned PIkind = PIDecl->getPropertyAttributes();
|
unsigned PIkind = PIDecl->getPropertyAttributes();
|
||||||
|
@ -1917,9 +1909,11 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
|
||||||
if (Attributes & ObjCDeclSpec::DQ_PR_copy)
|
if (Attributes & ObjCDeclSpec::DQ_PR_copy)
|
||||||
PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
|
PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
|
||||||
PIDecl->setSetterName(SetterSel);
|
PIDecl->setSetterName(SetterSel);
|
||||||
} else
|
} else {
|
||||||
Diag(AtLoc, diag::err_use_continuation_class)
|
Diag(AtLoc, diag::err_use_continuation_class)
|
||||||
<< CCPrimary->getDeclName();
|
<< CCPrimary->getDeclName();
|
||||||
|
Diag(PIDecl->getLocation(), diag::note_property_declare);
|
||||||
|
}
|
||||||
*isOverridingProperty = true;
|
*isOverridingProperty = true;
|
||||||
// Make sure setter decl is synthesized, and added to primary
|
// Make sure setter decl is synthesized, and added to primary
|
||||||
// class's list.
|
// class's list.
|
||||||
|
@ -2051,7 +2045,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
|
||||||
dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
|
dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
|
||||||
if (CD->getIdentifier()) {
|
if (CD->getIdentifier()) {
|
||||||
Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
|
Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
|
||||||
Diag(property->getLocation(), diag::note_category_property);
|
Diag(property->getLocation(), diag::note_property_declare);
|
||||||
return DeclPtrTy();
|
return DeclPtrTy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,35 @@
|
||||||
id _object1;
|
id _object1;
|
||||||
}
|
}
|
||||||
@property(readonly) id object;
|
@property(readonly) id object;
|
||||||
@property(readwrite, assign) id object1;
|
@property(readwrite, assign) id object1; // expected-note {{property declared here}}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ReadOnly ()
|
@interface ReadOnly ()
|
||||||
@property(readwrite, copy) id object;
|
@property(readwrite, copy) id object;
|
||||||
@property(readonly) id object1; // expected-error {{attribute of property in continuation class of 'ReadOnly' can only be 'readwrite'}}
|
@property(readonly) id object1; // expected-error {{property declaration in continuation class of 'ReadOnly' is to change a 'readonly' property to 'readwrite'}}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
@protocol Proto
|
||||||
|
@property (copy) id fee; // expected-note {{property declared here}}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@protocol Foo<Proto>
|
||||||
|
@property (copy) id foo; // expected-note {{property declared here}}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface Bar <Foo> {
|
||||||
|
id _foo;
|
||||||
|
id _fee;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface Bar ()
|
||||||
|
@property (copy) id foo; // expected-error {{property declaration in continuation class of 'Bar' is to change a 'readonly' property to 'readwrite'}}
|
||||||
|
@property (copy) id fee; // expected-error {{property declaration in continuation class of 'Bar' is to change a 'readonly' property to 'readwrite'}}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation Bar
|
||||||
|
@synthesize foo = _foo;
|
||||||
|
@synthesize fee = _fee;
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue