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:
Fariborz Jahanian 2008-11-26 20:01:34 +00:00
parent 6e41adddab
commit f8ef9f3dc9
8 changed files with 129 additions and 6 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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;
}

View File

@ -60,4 +60,5 @@ NSSize minimumSize;
NSRect dummy, result = {};
NSDivideRect(self.bounds, &result, &dummy, self.tabAreaThickness, self.rectEdgeForTabs);
}
@end