From: Fariborz Jahanian Date: Thu, 2 Apr 2009 18:44:20 +0000 (+0000) Subject: Fix up lookup rules for properties declared in X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d09a456e466597fe1667ea5e757bfe53be2cba7d;p=clang Fix up lookup rules for properties declared in objc's continuation class. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68339 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 8da7b3aa1d..99de7cbf59 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -614,17 +614,6 @@ void ASTContext::CollectObjCIvars(const ObjCInterfaceDecl *OI, if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl()) Fields.push_back(cast(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(IV)); - } - break; - } } /// addRecordToClass - produces record info. for the class for its @@ -722,17 +711,6 @@ ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) { if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) 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 // struct itself. diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index f2e0b791fd..cd1b979dcb 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -91,16 +91,6 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I) if ((*I)->getIdentifier() == PropertyId) return *I; - // Also look for property declared in its continuation class. - if (const ObjCInterfaceDecl *OID = dyn_cast(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(this); if (PID) { @@ -157,22 +147,6 @@ ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable( 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(); } return NULL; diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 580641643f..fa567a0a73 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -1674,18 +1674,6 @@ static int countInheritedIvars(const ObjCInterfaceDecl *OI) { if ((*I)->getPropertyIvarDecl()) ++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; } @@ -1714,20 +1702,6 @@ static const ObjCInterfaceDecl *getInterfaceDeclForIvar( if (IV->getIdentifier() == IVD->getIdentifier()) 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); } @@ -4592,17 +4566,6 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( E = OID->prop_end(); I != E; ++I) if (ObjCIvarDecl *IV = (*I)->getPropertyIvarDecl()) 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; for (RecordDecl::field_iterator e = RD->field_end(); i != e; ++i) { diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index af9c0f7c8c..fb042651f6 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1592,18 +1592,25 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, !(Attributes & ObjCDeclSpec::DQ_PR_copy))); QualType T = GetTypeForDeclarator(FD.D, S); Decl *ClassDecl = ClassCategory.getAs(); - + ObjCInterfaceDecl *CCPrimary = 0; // continuation class's primary class // May modify Attributes. CheckObjCPropertyAttributes(T, AtLoc, Attributes); - - ObjCMethodDecl *SetterDecl = 0; if (ObjCCategoryDecl *CDecl = dyn_cast(ClassDecl)) if (!CDecl->getIdentifier()) { // This is a continuation class. property requires special // handling. - if (ObjCInterfaceDecl *ICDecl = CDecl->getClassInterface()) { - if (ObjCPropertyDecl *PIDecl = - ICDecl->FindPropertyDeclaration(FD.D.getIdentifier())) { + if ((CCPrimary = CDecl->getClassInterface())) { + // Find the property in continuation class's primary class only. + 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 // with continuation class's readwrite property attribute! unsigned PIkind = PIDecl->getPropertyAttributes(); @@ -1611,38 +1618,40 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) != (PIkind & ObjCPropertyDecl::OBJC_PR_nonatomic)) Diag(AtLoc, diag::warn_property_attr_mismatch); - // Make the continuation class property attribute Read/Write - Attributes &= ~ObjCPropertyDecl::OBJC_PR_readonly; - Attributes |= ObjCPropertyDecl::OBJC_PR_readwrite; + 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. - SetterDecl = + ObjCMethodDecl *SetterDecl = ObjCMethodDecl::Create(Context, AtLoc, AtLoc, SetterSel, Context.VoidTy, - ICDecl, + CCPrimary, true, false, true, ObjCMethodDecl::Required); ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterDecl, SourceLocation(), - FD.D.getIdentifier(), + PropertyId, T, VarDecl::None, 0); SetterDecl->setMethodParams(&Argument, 1, Context); + PIDecl->setSetterMethodDecl(SetterDecl); } - else { - Diag(AtLoc, - diag::err_use_continuation_class) << ICDecl->getDeclName(); - *isOverridingProperty = true; - return DeclPtrTy(); - } + else + Diag(AtLoc, diag::err_use_continuation_class) + << CCPrimary->getDeclName(); + *isOverridingProperty = true; + return DeclPtrTy(); } - // No matching property found in the main class. Just fall thru - // and add property to the anonymous category. It looks like - // it works as is. This category becomes just like a category - // for its primary class. + // No matching property found in the primary class. Just fall thru + // and add property to continuation class's primary class. + ClassDecl = CCPrimary; } else { Diag(CDecl->getLocation(), diag::err_continuation_class); *isOverridingProperty = true; return DeclPtrTy(); - } + } } Type *t = T.getTypePtr(); @@ -1659,7 +1668,6 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, // Regardless of setter/getter attribute, we save the default getter/setter // selector names in anticipation of declaration of setter/getter methods. - PDecl->setSetterMethodDecl(SetterDecl); PDecl->setGetterName(GetterSel); PDecl->setSetterName(SetterSel); @@ -1691,6 +1699,11 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); else if (MethodImplKind == tok::objc_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); } diff --git a/test/SemaObjC/ContClassPropertyLookup.m b/test/SemaObjC/ContClassPropertyLookup.m new file mode 100644 index 0000000000..aa5afa7854 --- /dev/null +++ b/test/SemaObjC/ContClassPropertyLookup.m @@ -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