From e4fd640147b0cc062da4f31ccfaf32bff4852082 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 1 Apr 2009 23:23:53 +0000 Subject: [PATCH] Fix a bug in declaration of property in continuation class which was exposed by implementation of objc2's nonfragile abi code gen. llvm-svn: 68259 --- clang/lib/AST/DeclObjC.cpp | 10 +++++++ clang/lib/Sema/SemaDeclObjC.cpp | 28 +++++++++---------- .../CodeGenObjC/synthesize_ivar-cont-class.m | 18 ++++++++++++ 3 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 clang/test/CodeGenObjC/synthesize_ivar-cont-class.m diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 57bd8eab1efa..f2e0b791fdd6 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -91,6 +91,16 @@ 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) { diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index c68eede1045f..af9c0f7c8c4b 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1596,28 +1596,26 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, // May modify Attributes. CheckObjCPropertyAttributes(T, AtLoc, Attributes); + ObjCMethodDecl *SetterDecl = 0; if (ObjCCategoryDecl *CDecl = dyn_cast(ClassDecl)) if (!CDecl->getIdentifier()) { - // This is an anonymous category. property requires special + // This is a continuation class. 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! + // with continuation class's readwrite property attribute! unsigned PIkind = PIDecl->getPropertyAttributes(); if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { if ((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); + // Make the continuation class property attribute Read/Write + Attributes &= ~ObjCPropertyDecl::OBJC_PR_readonly; + Attributes |= ObjCPropertyDecl::OBJC_PR_readwrite; // FIXME: use a common routine with addPropertyMethods. - ObjCMethodDecl *SetterDecl = + SetterDecl = ObjCMethodDecl::Create(Context, AtLoc, AtLoc, SetterSel, Context.VoidTy, ICDecl, @@ -1628,12 +1626,13 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, FD.D.getIdentifier(), 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) << ICDecl->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 @@ -1660,6 +1659,7 @@ 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); diff --git a/clang/test/CodeGenObjC/synthesize_ivar-cont-class.m b/clang/test/CodeGenObjC/synthesize_ivar-cont-class.m new file mode 100644 index 000000000000..e25b737e452f --- /dev/null +++ b/clang/test/CodeGenObjC/synthesize_ivar-cont-class.m @@ -0,0 +1,18 @@ +// RUN: clang-cc -triple x86_64-apple-darwin10 -emit-llvm -o %t %s && +// RUN: grep '_OBJC_IVAR_$_XCOrganizerDeviceNodeInfo.viewController' %t + +@interface XCOrganizerNodeInfo +@property (readonly, retain) id viewController; +@end + +@interface XCOrganizerDeviceNodeInfo : XCOrganizerNodeInfo +@end + +@interface XCOrganizerDeviceNodeInfo() +@property (retain) id viewController; +@end + +@implementation XCOrganizerDeviceNodeInfo +@synthesize viewController; +@end +