forked from OSchip/llvm-project
Fix up lookup rules for properties declared in
objc's continuation class. llvm-svn: 68339
This commit is contained in:
parent
d5ca2d0165
commit
38a5c9650e
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue