Fix up lookup rules for properties declared in

objc's continuation class.

llvm-svn: 68339
This commit is contained in:
Fariborz Jahanian 2009-04-02 18:44:20 +00:00
parent d5ca2d0165
commit 38a5c9650e
5 changed files with 55 additions and 109 deletions

View File

@ -614,17 +614,6 @@ void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI,
if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl()) if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl())
Fields.push_back(cast<FieldDecl>(IV)); Fields.push_back(cast<FieldDecl>(IV));
} }
// look into continuation class.
for (ObjCCategoryDecl *Categories = OI->getCategoryList();
Categories; Categories = Categories->getNextClassCategory())
if (!Categories->getIdentifier()) {
for (ObjCInterfaceDecl::prop_iterator I = Categories->prop_begin(),
E = Categories->prop_end(); I != E; ++I) {
if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl())
Fields.push_back(cast<FieldDecl>(IV));
}
break;
}
} }
/// addRecordToClass - produces record info. for the class for its /// addRecordToClass - produces record info. for the class for its
@ -722,17 +711,6 @@ ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) {
if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
NewEntry->LayoutField(Ivar, i++, false, StructPacking, *this); NewEntry->LayoutField(Ivar, i++, false, StructPacking, *this);
} }
// Also continuation class.
for (ObjCCategoryDecl *Categories = D->getCategoryList();
Categories; Categories = Categories->getNextClassCategory())
if (!Categories->getIdentifier()) {
for (ObjCInterfaceDecl::prop_iterator I = Categories->prop_begin(),
E = Categories->prop_end(); I != E; ++I) {
if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl())
NewEntry->LayoutField(Ivar, i++, false, StructPacking, *this);
}
break;
}
// Finally, round the size of the total struct up to the alignment of the // Finally, round the size of the total struct up to the alignment of the
// struct itself. // struct itself.

View File

@ -91,16 +91,6 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I) for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I)
if ((*I)->getIdentifier() == PropertyId) if ((*I)->getIdentifier() == PropertyId)
return *I; return *I;
// Also look for property declared in its continuation class.
if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(this))
for (ObjCCategoryDecl *Categories = OID->getCategoryList();
Categories; Categories = Categories->getNextClassCategory())
if (!Categories->getIdentifier()) {
for (ObjCInterfaceDecl::prop_iterator I = Categories->prop_begin(),
E = Categories->prop_end(); I != E; ++I)
if ((*I)->getIdentifier() == PropertyId)
return *I;
}
const ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(this); const ObjCProtocolDecl *PID = dyn_cast<ObjCProtocolDecl>(this);
if (PID) { if (PID) {
@ -157,22 +147,6 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(
return IV; return IV;
} }
} }
// look into continuation class.
for (ObjCCategoryDecl *Categories = ClassDecl->getCategoryList();
Categories; Categories = Categories->getNextClassCategory())
if (!Categories->getIdentifier()) {
for (ObjCInterfaceDecl::prop_iterator I = Categories->prop_begin(),
E = Categories->prop_end(); I != E; ++I) {
ObjCPropertyDecl *PDecl = (*I);
if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl())
if (IV->getIdentifier() == ID) {
clsDeclared = ClassDecl;
return IV;
}
}
break;
}
ClassDecl = ClassDecl->getSuperClass(); ClassDecl = ClassDecl->getSuperClass();
} }
return NULL; return NULL;

View File

@ -1674,18 +1674,6 @@ static int countInheritedIvars(const ObjCInterfaceDecl *OI) {
if ((*I)->getPropertyIvarDecl()) if ((*I)->getPropertyIvarDecl())
++count; ++count;
} }
// look into continuation class.
for (ObjCCategoryDecl *Categories = OI->getCategoryList();
Categories; Categories = Categories->getNextClassCategory()) {
if (!Categories->getIdentifier()) {
for (ObjCInterfaceDecl::prop_iterator I = Categories->prop_begin(),
E = Categories->prop_end(); I != E; ++I) {
if ((*I)->getPropertyIvarDecl())
++count;
}
break;
}
}
return count; return count;
} }
@ -1714,20 +1702,6 @@ static const ObjCInterfaceDecl *getInterfaceDeclForIvar(
if (IV->getIdentifier() == IVD->getIdentifier()) if (IV->getIdentifier() == IVD->getIdentifier())
return OI; return OI;
} }
// look into continuation class.
for (ObjCCategoryDecl *Categories = OI->getCategoryList();
Categories; Categories = Categories->getNextClassCategory()) {
if (!Categories->getIdentifier()) {
for (ObjCInterfaceDecl::prop_iterator I = Categories->prop_begin(),
E = Categories->prop_end(); I != E; ++I) {
ObjCPropertyDecl *PDecl = (*I);
if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl())
if (IV->getIdentifier() == IVD->getIdentifier())
return OI;
}
break;
}
}
return getInterfaceDeclForIvar(OI->getSuperClass(), IVD); return getInterfaceDeclForIvar(OI->getSuperClass(), IVD);
} }
@ -4592,17 +4566,6 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
E = OID->prop_end(); I != E; ++I) E = OID->prop_end(); I != E; ++I)
if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl()) if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl())
OIvars.push_back(IV); OIvars.push_back(IV);
// look into continuation class.
for (ObjCCategoryDecl *Categories = OID->getCategoryList();
Categories; Categories = Categories->getNextClassCategory())
if (!Categories->getIdentifier()) {
for (ObjCInterfaceDecl::prop_iterator I = Categories->prop_begin(),
E = Categories->prop_end(); I != E; ++I) {
if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl())
OIvars.push_back(IV);
}
break;
}
unsigned iv = 0; unsigned iv = 0;
for (RecordDecl::field_iterator e = RD->field_end(); i != e; ++i) { for (RecordDecl::field_iterator e = RD->field_end(); i != e; ++i) {

View File

@ -1592,18 +1592,25 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
!(Attributes & ObjCDeclSpec::DQ_PR_copy))); !(Attributes & ObjCDeclSpec::DQ_PR_copy)));
QualType T = GetTypeForDeclarator(FD.D, S); QualType T = GetTypeForDeclarator(FD.D, S);
Decl *ClassDecl = ClassCategory.getAs<Decl>(); Decl *ClassDecl = ClassCategory.getAs<Decl>();
ObjCInterfaceDecl *CCPrimary = 0; // continuation class's primary class
// May modify Attributes. // May modify Attributes.
CheckObjCPropertyAttributes(T, AtLoc, Attributes); CheckObjCPropertyAttributes(T, AtLoc, Attributes);
ObjCMethodDecl *SetterDecl = 0;
if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
if (!CDecl->getIdentifier()) { if (!CDecl->getIdentifier()) {
// This is a continuation class. property requires special // This is a continuation class. property requires special
// handling. // handling.
if (ObjCInterfaceDecl *ICDecl = CDecl->getClassInterface()) { if ((CCPrimary = CDecl->getClassInterface())) {
if (ObjCPropertyDecl *PIDecl = // Find the property in continuation class's primary class only.
ICDecl->FindPropertyDeclaration(FD.D.getIdentifier())) { ObjCPropertyDecl *PIDecl = 0;
IdentifierInfo *PropertyId = FD.D.getIdentifier();
for (ObjCInterfaceDecl::prop_iterator I = CCPrimary->prop_begin(),
E = CCPrimary->prop_end(); 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();
@ -1611,33 +1618,35 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) != if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) !=
(PIkind & ObjCPropertyDecl::OBJC_PR_nonatomic)) (PIkind & ObjCPropertyDecl::OBJC_PR_nonatomic))
Diag(AtLoc, diag::warn_property_attr_mismatch); Diag(AtLoc, diag::warn_property_attr_mismatch);
// Make the continuation class property attribute Read/Write PIDecl->makeitReadWriteAttribute();
Attributes &= ~ObjCPropertyDecl::OBJC_PR_readonly; if (Attributes & ObjCDeclSpec::DQ_PR_retain)
Attributes |= ObjCPropertyDecl::OBJC_PR_readwrite; 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. // FIXME: use a common routine with addPropertyMethods.
SetterDecl = ObjCMethodDecl *SetterDecl =
ObjCMethodDecl::Create(Context, AtLoc, AtLoc, SetterSel, ObjCMethodDecl::Create(Context, AtLoc, AtLoc, SetterSel,
Context.VoidTy, Context.VoidTy,
ICDecl, CCPrimary,
true, false, true, true, false, true,
ObjCMethodDecl::Required); ObjCMethodDecl::Required);
ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterDecl, ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterDecl,
SourceLocation(), SourceLocation(),
FD.D.getIdentifier(), PropertyId,
T, VarDecl::None, 0); T, VarDecl::None, 0);
SetterDecl->setMethodParams(&Argument, 1, Context); SetterDecl->setMethodParams(&Argument, 1, Context);
PIDecl->setSetterMethodDecl(SetterDecl);
} }
else { else
Diag(AtLoc, Diag(AtLoc, diag::err_use_continuation_class)
diag::err_use_continuation_class) << ICDecl->getDeclName(); << CCPrimary->getDeclName();
*isOverridingProperty = true; *isOverridingProperty = true;
return DeclPtrTy(); return DeclPtrTy();
}
} }
// No matching property found in the main class. Just fall thru // No matching property found in the primary class. Just fall thru
// and add property to the anonymous category. It looks like // and add property to continuation class's primary class.
// it works as is. This category becomes just like a category ClassDecl = CCPrimary;
// for its primary class.
} else { } else {
Diag(CDecl->getLocation(), diag::err_continuation_class); Diag(CDecl->getLocation(), diag::err_continuation_class);
*isOverridingProperty = true; *isOverridingProperty = true;
@ -1659,7 +1668,6 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
// Regardless of setter/getter attribute, we save the default getter/setter // Regardless of setter/getter attribute, we save the default getter/setter
// selector names in anticipation of declaration of setter/getter methods. // selector names in anticipation of declaration of setter/getter methods.
PDecl->setSetterMethodDecl(SetterDecl);
PDecl->setGetterName(GetterSel); PDecl->setGetterName(GetterSel);
PDecl->setSetterName(SetterSel); PDecl->setSetterName(SetterSel);
@ -1691,6 +1699,11 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
else if (MethodImplKind == tok::objc_optional) else if (MethodImplKind == tok::objc_optional)
PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
// A case of continuation class adding a new property in the class. This
// is not what it was meant for. However, gcc supports it and so should we.
// Make sure setter/getters are declared here.
if (CCPrimary)
ProcessPropertyDecl(PDecl, CCPrimary);
return DeclPtrTy::make(PDecl); return DeclPtrTy::make(PDecl);
} }

View File

@ -0,0 +1,18 @@
// RUN: clang-cc -fsyntax-only -verify %s
@interface MyObject {
int _foo;
}
@end
@interface MyObject(whatever)
@property (assign) int foo;
@end
@interface MyObject()
@property (assign) int foo;
@end
@implementation MyObject
@synthesize foo = _foo;
@end