forked from OSchip/llvm-project
Set default property attributes on each property.
Implemented anonymous category (also know as continuation class) used to override main class's property attribute. This is work in propgress. llvm-svn: 60114
This commit is contained in:
parent
6e41adddab
commit
f8ef9f3dc9
|
@ -1228,6 +1228,11 @@ public:
|
|||
PropertyAttributes |= PRVal;
|
||||
}
|
||||
|
||||
void makeitReadWriteAttribute(void) {
|
||||
PropertyAttributes &= ~OBJC_PR_readonly;
|
||||
PropertyAttributes |= OBJC_PR_readwrite;
|
||||
}
|
||||
|
||||
// Helper methods for accessing attributes.
|
||||
|
||||
/// isReadOnly - Return true iff the property has a setter.
|
||||
|
|
|
@ -563,6 +563,12 @@ DIAG(warn_property_attribute, WARNING,
|
|||
"property %0 '%1' attribute does not match the property inherited from %2")
|
||||
DIAG(warn_property_type, WARNING,
|
||||
"property type %0 does not match property type inherited from %1")
|
||||
DIAG(err_continuation_class, ERROR,
|
||||
"continuation class has no primary class")
|
||||
DIAG(err_use_continuation_class, ERROR,
|
||||
"use contination class to override 'readonly' property with 'readwrite'")
|
||||
DIAG(warn_property_attr_mismatch, WARNING,
|
||||
"property attribute in continuation class does not match the primary class")
|
||||
|
||||
/// C++ parser diagnostics
|
||||
DIAG(err_expected_unqualified_id, ERROR,
|
||||
|
|
|
@ -963,6 +963,8 @@ public:
|
|||
virtual DeclTy *ActOnProperty (Scope *S, SourceLocation AtLoc,
|
||||
FieldDeclarator &FD, ObjCDeclSpec &ODS,
|
||||
Selector GetterSel, Selector SetterSel,
|
||||
DeclTy *ClassCategory,
|
||||
bool *OverridingProperty,
|
||||
tok::ObjCKeywordKind MethodImplKind) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -332,10 +332,14 @@ void Parser::ParseObjCInterfaceDeclList(DeclTy *interfaceDecl,
|
|||
FD.D.getIdentifier());
|
||||
Selector SetterSel =
|
||||
PP.getSelectorTable().getUnarySelector(SetterName);
|
||||
bool isOverridingProperty = false;
|
||||
DeclTy *Property = Actions.ActOnProperty(CurScope, AtLoc, FD, OCDS,
|
||||
GetterSel, SetterSel,
|
||||
interfaceDecl,
|
||||
&isOverridingProperty,
|
||||
MethodImplKind);
|
||||
allProperties.push_back(Property);
|
||||
if (!isOverridingProperty)
|
||||
allProperties.push_back(Property);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1051,6 +1051,7 @@ public:
|
|||
virtual DeclTy *ActOnProperty(Scope *S, SourceLocation AtLoc,
|
||||
FieldDeclarator &FD, ObjCDeclSpec &ODS,
|
||||
Selector GetterSel, Selector SetterSel,
|
||||
DeclTy *ClassCategory, bool *OverridingProperty,
|
||||
tok::ObjCKeywordKind MethodImplKind);
|
||||
|
||||
virtual DeclTy *ActOnPropertyImplDecl(SourceLocation AtLoc,
|
||||
|
|
|
@ -1186,12 +1186,81 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
|
|||
ObjCDeclSpec &ODS,
|
||||
Selector GetterSel,
|
||||
Selector SetterSel,
|
||||
DeclTy *ClassCategory,
|
||||
bool *isOverridingProperty,
|
||||
tok::ObjCKeywordKind MethodImplKind) {
|
||||
QualType T = GetTypeForDeclarator(FD.D, S);
|
||||
unsigned Attributes = ODS.getPropertyAttributes();
|
||||
bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
|
||||
// default is readwrite!
|
||||
!(Attributes & ObjCDeclSpec::DQ_PR_readonly));
|
||||
// property is defaulted to 'assign' if it is readwrite and is
|
||||
// not retain or copy
|
||||
bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
|
||||
(isReadWrite &&
|
||||
!(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
|
||||
!(Attributes & ObjCDeclSpec::DQ_PR_copy)));
|
||||
QualType T = GetTypeForDeclarator(FD.D, S);
|
||||
Decl *ClassDecl = static_cast<Decl *>(ClassCategory);
|
||||
|
||||
// May modify Attributes.
|
||||
CheckObjCPropertyAttributes(T, AtLoc, Attributes);
|
||||
|
||||
if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
|
||||
if (!CDecl->getIdentifier()) {
|
||||
// This is an anonymous category. property requires special
|
||||
// handling.
|
||||
if (ObjCInterfaceDecl *ICDecl = CDecl->getClassInterface()) {
|
||||
if (ObjCPropertyDecl *PIDecl =
|
||||
ICDecl->FindPropertyDeclaration(FD.D.getIdentifier())) {
|
||||
// property 'PIDecl's readonly attribute will be over-ridden
|
||||
// with anonymous category's readwrite property attribute!
|
||||
unsigned PIkind = PIDecl->getPropertyAttributes();
|
||||
if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
|
||||
if ((Attributes & ObjCPropertyDecl::OBJC_PR_retain) !=
|
||||
(PIkind & ObjCPropertyDecl::OBJC_PR_retain) ||
|
||||
(Attributes & ObjCPropertyDecl::OBJC_PR_copy) !=
|
||||
(PIkind & ObjCPropertyDecl::OBJC_PR_copy) ||
|
||||
(Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) !=
|
||||
(PIkind & ObjCPropertyDecl::OBJC_PR_nonatomic))
|
||||
Diag(AtLoc, diag::warn_property_attr_mismatch);
|
||||
PIDecl->makeitReadWriteAttribute();
|
||||
if (Attributes & ObjCDeclSpec::DQ_PR_retain)
|
||||
PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
|
||||
if (Attributes & ObjCDeclSpec::DQ_PR_copy)
|
||||
PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
|
||||
PIDecl->setSetterName(SetterSel);
|
||||
// FIXME: use a common routine with addPropertyMethods.
|
||||
ObjCMethodDecl *SetterDecl =
|
||||
ObjCMethodDecl::Create(Context, AtLoc, AtLoc, SetterSel,
|
||||
Context.VoidTy,
|
||||
ICDecl,
|
||||
true, false, true,
|
||||
ObjCMethodDecl::Required);
|
||||
ParmVarDecl *Argument = ParmVarDecl::Create(Context,
|
||||
SetterDecl,
|
||||
SourceLocation(),
|
||||
FD.D.getIdentifier(),
|
||||
T,
|
||||
VarDecl::None,
|
||||
0, 0);
|
||||
SetterDecl->setMethodParams(&Argument, 1);
|
||||
PIDecl->setSetterMethodDecl(SetterDecl);
|
||||
}
|
||||
else
|
||||
Diag(AtLoc, diag::err_use_continuation_class);
|
||||
*isOverridingProperty = true;
|
||||
return 0;
|
||||
}
|
||||
// else
|
||||
// FIXME:
|
||||
// no matching property found in the main class. Must simply
|
||||
// add this property to the main class's property list.
|
||||
} else {
|
||||
Diag(CDecl->getLocation(), diag::err_continuation_class);
|
||||
*isOverridingProperty = true;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, AtLoc,
|
||||
FD.D.getIdentifier(), T);
|
||||
|
@ -1209,10 +1278,7 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
|
|||
if (Attributes & ObjCDeclSpec::DQ_PR_setter)
|
||||
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
|
||||
|
||||
if (Attributes & ObjCDeclSpec::DQ_PR_assign)
|
||||
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
|
||||
|
||||
if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
|
||||
if (isReadWrite)
|
||||
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
|
||||
|
||||
if (Attributes & ObjCDeclSpec::DQ_PR_retain)
|
||||
|
@ -1221,6 +1287,9 @@ Sema::DeclTy *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
|
|||
if (Attributes & ObjCDeclSpec::DQ_PR_copy)
|
||||
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
|
||||
|
||||
if (isAssign)
|
||||
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
|
||||
|
||||
if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
|
||||
PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
// RUN: clang -fnext-runtime --emit-llvm -o %t %s
|
||||
|
||||
@interface Object
|
||||
- (id)new;
|
||||
@end
|
||||
|
||||
@interface ReadOnly : Object
|
||||
{
|
||||
int _object;
|
||||
int _Anotherobject;
|
||||
}
|
||||
@property(readonly) int object;
|
||||
@property(readonly) int Anotherobject;
|
||||
@end
|
||||
|
||||
@interface ReadOnly ()
|
||||
@property(readwrite) int object;
|
||||
@property(readwrite, setter = myAnotherobjectSetter:) int Anotherobject;
|
||||
@end
|
||||
|
||||
@implementation ReadOnly
|
||||
@synthesize object = _object;
|
||||
@synthesize Anotherobject = _Anotherobject;
|
||||
- (void) myAnotherobjectSetter : (int)val {
|
||||
_Anotherobject = val;
|
||||
}
|
||||
@end
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
ReadOnly *test = [ReadOnly new];
|
||||
test.object = 12345;
|
||||
test.Anotherobject = 200;
|
||||
return test.object - 12345 + test.Anotherobject - 200;
|
||||
}
|
||||
|
|
@ -60,4 +60,5 @@ NSSize minimumSize;
|
|||
NSRect dummy, result = {};
|
||||
NSDivideRect(self.bounds, &result, &dummy, self.tabAreaThickness, self.rectEdgeForTabs);
|
||||
}
|
||||
@end
|
||||
|
||||
|
|
Loading…
Reference in New Issue