SemaObjCProperty.cpp revision f921a4868cf1876636f6684e7f68697b18c0cb47
1c3aae25116e66c177579b0b79182b09340b19753Chris Lattner//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===// 2edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman// 3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// The LLVM Compiler Infrastructure 4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 7edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman// 8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===// 978ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner// 10c3aae25116e66c177579b0b79182b09340b19753Chris Lattner// This file implements semantic analysis for Objective C @property and 1178ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner// @synthesize declarations. 1278ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner// 1378ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner//===----------------------------------------------------------------------===// 14c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 150ff39b3feb10477c224138156941234f5fa46f58Evan Cheng#include "Sema.h" 164d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov 17b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venanciousing namespace clang; 1870a248d284af550ae46c8dfc18ea2bbc15d31eb0Chris Lattner 1995c218a83ecf77590b9dc40c636720772d2b5cd7Christopher Lamb//===----------------------------------------------------------------------===// 20c3aae25116e66c177579b0b79182b09340b19753Chris Lattner// Grammar actions. 21707e0184233f27e0e9f9aee0309f2daab8cfe7f8Dan Gohman//===----------------------------------------------------------------------===// 22c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 23d6594ae54cfde4db4d30272192645c0a45fb9902Evan ChengSema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, 2437ce9df0da6cddc3b8bfef9b63d33d058a0f2f15Chris Lattner FieldDeclarator &FD, 25a844bdeab31ef04221e7ef59a8467893584cc14dEvan Cheng ObjCDeclSpec &ODS, 2669de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman Selector GetterSel, 276f0d024a534af18d9e60b3ea757376cd8a3a980eDan Gohman Selector SetterSel, 2895c218a83ecf77590b9dc40c636720772d2b5cd7Christopher Lamb DeclPtrTy ClassCategory, 29b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner bool *isOverridingProperty, 30760f86f3395750ef6d03ecfe6f82d2867fbf568bDan Gohman tok::ObjCKeywordKind MethodImplKind) { 31f3e133a35f5aa6ed32ca29aa3675eff349d61008Chris Lattner unsigned Attributes = ODS.getPropertyAttributes(); 32f3e133a35f5aa6ed32ca29aa3675eff349d61008Chris Lattner bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || 336f287b22d2e57600b4cd5dc209d0d869e7736c0bBill Wendling // default is readwrite! 34b4459088d62670b0f0333eab1b260622955ec3e5Owen Anderson !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); 35944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner // property is defaulted to 'assign' if it is readwrite and is 36944fac71e082cc2664cc71b4d3f6c72bab7143fbChris Lattner // not retain or copy 37b4459088d62670b0f0333eab1b260622955ec3e5Owen Anderson bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || 38012f241987a017ea74d34d4c126997f84902ef61Chris Lattner (isReadWrite && 39d48c5e871a0f3386e536e0987ca06dbc4e274acfChris Lattner !(Attributes & ObjCDeclSpec::DQ_PR_retain) && 40af47b11b959713d70c45bee1922e468adfaeaff0Duncan Sands !(Attributes & ObjCDeclSpec::DQ_PR_copy))); 41190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner 42115c036a4c83cd277ffac0867a21b34f63829db7Evan Cheng QualType T = GetTypeForDeclarator(FD.D, S); 43fd161e964aa02636c00364ae4d46bf4e384df096Jeff Cohen if (T->isReferenceType()) { 4497af751deb9b26fd42fbcee082da9ccc4ded5b45Jeff Cohen Diag(AtLoc, diag::error_reference_property); 45e25738cab63977282f8ebc26012142debfbd1d20Chris Lattner return DeclPtrTy(); 46d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke } 470b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner // Validate the attributes on the @property. 480b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner CheckObjCPropertyAttributes(T, AtLoc, Attributes); 4983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands 500b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner // Proceed with constructing the ObjCPropertDecls. 510b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner ObjCContainerDecl *ClassDecl = 520b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner cast<ObjCContainerDecl>(ClassCategory.getAs<Decl>()); 530b3e525a3a6b55b66dc5676675712b26e4c1ed9fChris Lattner 5483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) 5583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands if (CDecl->IsClassExtension()) 56ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner return HandlePropertyInClassExtension(S, CDecl, AtLoc, 57ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner FD, GetterSel, SetterSel, 58ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner isAssign, isReadWrite, 59ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner Attributes, 60ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner isOverridingProperty, T, 61ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner MethodImplKind); 62ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner 63ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner return DeclPtrTy::make(CreatePropertyDecl(S, ClassDecl, AtLoc, FD, 64ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner GetterSel, SetterSel, 65f8dc0617baceeba8ccd67c8881eb88eb1be2902cChris Lattner isAssign, isReadWrite, 66f8dc0617baceeba8ccd67c8881eb88eb1be2902cChris Lattner Attributes, T, MethodImplKind)); 6758b968be853ef02d0f448e5e2c31676e361c210fJim Laskey} 6858b968be853ef02d0f448e5e2c31676e361c210fJim Laskey 6958b968be853ef02d0f448e5e2c31676e361c210fJim LaskeySema::DeclPtrTy 7058b968be853ef02d0f448e5e2c31676e361c210fJim LaskeySema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, 7158b968be853ef02d0f448e5e2c31676e361c210fJim Laskey SourceLocation AtLoc, FieldDeclarator &FD, 7258b968be853ef02d0f448e5e2c31676e361c210fJim Laskey Selector GetterSel, Selector SetterSel, 7358b968be853ef02d0f448e5e2c31676e361c210fJim Laskey const bool isAssign, 7458b968be853ef02d0f448e5e2c31676e361c210fJim Laskey const bool isReadWrite, 75e6c1742914149d44360fbf05a653041a672282afDale Johannesen const unsigned Attributes, 764fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman bool *isOverridingProperty, 7758b968be853ef02d0f448e5e2c31676e361c210fJim Laskey QualType T, 7858b968be853ef02d0f448e5e2c31676e361c210fJim Laskey tok::ObjCKeywordKind MethodImplKind) { 7983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands 80f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen // Diagnose if this property is already in continuation class. 8183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands DeclContext *DC = cast<DeclContext>(CDecl); 82fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel IdentifierInfo *PropertyId = FD.D.getIdentifier(); 839dd2ce46c58dd05f0835df77f308396715890d66Dale Johannesen 849dd2ce46c58dd05f0835df77f308396715890d66Dale Johannesen if (ObjCPropertyDecl *prevDecl = 859dd2ce46c58dd05f0835df77f308396715890d66Dale Johannesen ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { 86ec4a5672f86a42730d8fcf98243322520eaffb33Chris Lattner Diag(AtLoc, diag::err_duplicate_property); 87fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel Diag(prevDecl->getLocation(), diag::note_property_declare); 88f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen return DeclPtrTy(); 89f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen } 9023a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen 9123a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen // Create a new ObjCPropertyDecl with the DeclContext being 9223a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen // the class extension. 9323a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen ObjCPropertyDecl *PDecl = 94f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), 95f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen PropertyId, AtLoc, T); 9658b968be853ef02d0f448e5e2c31676e361c210fJim Laskey if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 9761d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 9858b968be853ef02d0f448e5e2c31676e361c210fJim Laskey if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) 995cdcc58d51c792d329202bab97c34aefbc043b15Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 100a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng 10161d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner DC->addDecl(PDecl); 102a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng 103547a16f27315a08527c41dc521c7cdf6ad9a0b6cChris Lattner // We need to look in the @interface to see if the @property was 104547a16f27315a08527c41dc521c7cdf6ad9a0b6cChris Lattner // already declared. 105ba36cb5242eb02b12b277f82b9efe497f7da4d7fGabor Greif ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); 106fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel if (!CCPrimary) { 107a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng Diag(CDecl->getLocation(), diag::err_continuation_class); 108fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel *isOverridingProperty = true; 10961d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner return DeclPtrTy(); 110fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel } 11161d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner 11261d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner // Find the property in continuation class's primary class only. 11361d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner ObjCPropertyDecl *PIDecl = 114fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); 11561d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner 11661d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner if (!PIDecl) { 117fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel // No matching property found in the primary class. Just fall thru 11861d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner // and add property to continuation class's primary class. 11961d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner ObjCPropertyDecl *PDecl = 120475871a144eb604ddaf37503397ba0941442e5fbDan Gohman CreatePropertyDecl(S, CCPrimary, AtLoc, 121a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng FD, GetterSel, SetterSel, isAssign, isReadWrite, 122a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng Attributes, T, MethodImplKind); 123a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng 124a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng // A case of continuation class adding a new property in the class. This 1256c231501f80e1ff05e3cada3d051b1c826d1f478Dan Gohman // is not what it was meant for. However, gcc supports it and so should we. 12623a98551ab65eeb8fe5019df8b7db4891582a4bdDale Johannesen // Make sure setter/getters are declared here. 1276c231501f80e1ff05e3cada3d051b1c826d1f478Dan Gohman ProcessPropertyDecl(PDecl, CCPrimary); 128a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng return DeclPtrTy::make(PDecl); 12961d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner 130fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel } 13161d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner 13261d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner // The property 'PIDecl's readonly attribute will be over-ridden 13361d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner // with continuation class's readwrite property attribute! 13461d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner unsigned PIkind = PIDecl->getPropertyAttributes(); 13561d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { 13661d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner unsigned retainCopyNonatomic = 13761d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner (ObjCPropertyDecl::OBJC_PR_retain | 13861d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner ObjCPropertyDecl::OBJC_PR_copy | 13961d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner ObjCPropertyDecl::OBJC_PR_nonatomic); 14061d4399dfc7046595e30ad34a28c72a885cb8100Chris Lattner if ((Attributes & retainCopyNonatomic) != 1414a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng (PIkind & retainCopyNonatomic)) { 1424a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng Diag(AtLoc, diag::warn_property_attr_mismatch); 1434a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng Diag(PIDecl->getLocation(), diag::note_property_declare); 144547a16f27315a08527c41dc521c7cdf6ad9a0b6cChris Lattner } 145547a16f27315a08527c41dc521c7cdf6ad9a0b6cChris Lattner DeclContext *DC = cast<DeclContext>(CCPrimary); 146ba36cb5242eb02b12b277f82b9efe497f7da4d7fGabor Greif if (!ObjCPropertyDecl::findPropertyDecl(DC, 147fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel PIDecl->getDeclName().getAsIdentifierInfo())) { 1484a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng // Protocol is not in the primary class. Must build one for it. 149fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel ObjCDeclSpec ProtocolPropertyODS; 150a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind 151fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel // and ObjCPropertyDecl::PropertyAttributeKind have identical 152a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng // values. Should consolidate both into one enum type. 153a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng ProtocolPropertyODS. 154a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) 155fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel PIkind); 156a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng 157a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng DeclPtrTy ProtocolPtrTy = 158fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, 15968f32cbb1f9e62d5e6047b048c0d7d217b8717e1Dan Gohman PIDecl->getGetterName(), 160a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng PIDecl->getSetterName(), 161475871a144eb604ddaf37503397ba0941442e5fbDan Gohman DeclPtrTy::make(CCPrimary), isOverridingProperty, 162a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng MethodImplKind); 163a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng PIDecl = ProtocolPtrTy.getAs<ObjCPropertyDecl>(); 164a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng } 165a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng PIDecl->makeitReadWriteAttribute(); 166eaf089430e7681fcddc3465c3b33b9645273ab02Dale Johannesen if (Attributes & ObjCDeclSpec::DQ_PR_retain) 167a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 168a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng if (Attributes & ObjCDeclSpec::DQ_PR_copy) 169a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 170fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel PIDecl->setSetterName(SetterSel); 17168f32cbb1f9e62d5e6047b048c0d7d217b8717e1Dan Gohman } else { 172a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng Diag(AtLoc, diag::err_use_continuation_class) 173a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng << CCPrimary->getDeclName(); 174a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng Diag(PIDecl->getLocation(), diag::note_property_declare); 175a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng } 176a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng *isOverridingProperty = true; 177a8df166fbef047c90adba3c673162a1b1f6681c4Evan Cheng // Make sure setter decl is synthesized, and added to primary class's list. 1784a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng ProcessPropertyDecl(PIDecl, CCPrimary); 1794a147842eb24a7611fcd7bfb37c55185b4664927Evan Cheng return DeclPtrTy(); 180efec751a1b786724862ceff52748df94873a807eEvan Cheng} 181efec751a1b786724862ceff52748df94873a807eEvan Cheng 182efec751a1b786724862ceff52748df94873a807eEvan ChengObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, 183efec751a1b786724862ceff52748df94873a807eEvan Cheng ObjCContainerDecl *CDecl, 184efec751a1b786724862ceff52748df94873a807eEvan Cheng SourceLocation AtLoc, 185efec751a1b786724862ceff52748df94873a807eEvan Cheng FieldDeclarator &FD, 186efec751a1b786724862ceff52748df94873a807eEvan Cheng Selector GetterSel, 187efec751a1b786724862ceff52748df94873a807eEvan Cheng Selector SetterSel, 188efec751a1b786724862ceff52748df94873a807eEvan Cheng const bool isAssign, 189efec751a1b786724862ceff52748df94873a807eEvan Cheng const bool isReadWrite, 190efec751a1b786724862ceff52748df94873a807eEvan Cheng const unsigned Attributes, 191efec751a1b786724862ceff52748df94873a807eEvan Cheng QualType T, 192efec751a1b786724862ceff52748df94873a807eEvan Cheng tok::ObjCKeywordKind MethodImplKind){ 193475871a144eb604ddaf37503397ba0941442e5fbDan Gohman 194efec751a1b786724862ceff52748df94873a807eEvan Cheng IdentifierInfo *PropertyId = FD.D.getIdentifier(); 195efec751a1b786724862ceff52748df94873a807eEvan Cheng 196efec751a1b786724862ceff52748df94873a807eEvan Cheng // Issue a warning if property is 'assign' as default and its object, which is 197efec751a1b786724862ceff52748df94873a807eEvan Cheng // gc'able conforms to NSCopying protocol 198efec751a1b786724862ceff52748df94873a807eEvan Cheng if (getLangOptions().getGCMode() != LangOptions::NonGC && 199efec751a1b786724862ceff52748df94873a807eEvan Cheng isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) 200efec751a1b786724862ceff52748df94873a807eEvan Cheng if (T->isObjCObjectPointerType()) { 201bb81d97feb396a8bb21d074db1c57e9f66525f40Evan Cheng QualType InterfaceTy = T->getPointeeType(); 2024406604047423576e36657c7ede266ca42e79642Dan Gohman if (const ObjCInterfaceType *OIT = 203bb81d97feb396a8bb21d074db1c57e9f66525f40Evan Cheng InterfaceTy->getAs<ObjCInterfaceType>()) { 204475871a144eb604ddaf37503397ba0941442e5fbDan Gohman ObjCInterfaceDecl *IDecl = OIT->getDecl(); 2054406604047423576e36657c7ede266ca42e79642Dan Gohman if (IDecl) 2064406604047423576e36657c7ede266ca42e79642Dan Gohman if (ObjCProtocolDecl* PNSCopying = 207e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman LookupProtocol(&Context.Idents.get("NSCopying"))) 208e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman if (IDecl->ClassImplementsProtocol(PNSCopying, true)) 2094406604047423576e36657c7ede266ca42e79642Dan Gohman Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; 2104406604047423576e36657c7ede266ca42e79642Dan Gohman } 211bb81d97feb396a8bb21d074db1c57e9f66525f40Evan Cheng } 212bb81d97feb396a8bb21d074db1c57e9f66525f40Evan Cheng if (T->isObjCInterfaceType()) 213c3aae25116e66c177579b0b79182b09340b19753Chris Lattner Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object); 214c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 215c3aae25116e66c177579b0b79182b09340b19753Chris Lattner DeclContext *DC = cast<DeclContext>(CDecl); 216c3aae25116e66c177579b0b79182b09340b19753Chris Lattner ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, 217c3aae25116e66c177579b0b79182b09340b19753Chris Lattner FD.D.getIdentifierLoc(), 218c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PropertyId, AtLoc, T); 219c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 220c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (ObjCPropertyDecl *prevDecl = 221c3aae25116e66c177579b0b79182b09340b19753Chris Lattner ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { 222a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling Diag(PDecl->getLocation(), diag::err_duplicate_property); 223c3aae25116e66c177579b0b79182b09340b19753Chris Lattner Diag(prevDecl->getLocation(), diag::note_property_declare); 224c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setInvalidDecl(); 225c3aae25116e66c177579b0b79182b09340b19753Chris Lattner } 226c3aae25116e66c177579b0b79182b09340b19753Chris Lattner else 227c3aae25116e66c177579b0b79182b09340b19753Chris Lattner DC->addDecl(PDecl); 228c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 229c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (T->isArrayType() || T->isFunctionType()) { 230c3aae25116e66c177579b0b79182b09340b19753Chris Lattner Diag(AtLoc, diag::err_property_type) << T; 231c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setInvalidDecl(); 232c3aae25116e66c177579b0b79182b09340b19753Chris Lattner } 233a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling 234c3aae25116e66c177579b0b79182b09340b19753Chris Lattner ProcessDeclAttributes(S, PDecl, FD.D); 235a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling 236a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling // Regardless of setter/getter attribute, we save the default getter/setter 237c3aae25116e66c177579b0b79182b09340b19753Chris Lattner // selector names in anticipation of declaration of setter/getter methods. 238c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setGetterName(GetterSel); 239c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setSetterName(SetterSel); 240c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 241c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 242c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 243c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 244c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (Attributes & ObjCDeclSpec::DQ_PR_getter) 245c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter); 246c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 247c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (Attributes & ObjCDeclSpec::DQ_PR_setter) 248c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter); 249c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 250c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (isReadWrite) 251c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 252c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 253c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (Attributes & ObjCDeclSpec::DQ_PR_retain) 254c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 255c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 256c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (Attributes & ObjCDeclSpec::DQ_PR_copy) 257c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 258c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 259c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (isAssign) 260c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); 261c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 262c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 263c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); 264c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 265c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (MethodImplKind == tok::objc_required) 266c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); 267c3aae25116e66c177579b0b79182b09340b19753Chris Lattner else if (MethodImplKind == tok::objc_optional) 268c3aae25116e66c177579b0b79182b09340b19753Chris Lattner PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); 269edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman 270c3aae25116e66c177579b0b79182b09340b19753Chris Lattner return PDecl; 271edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman} 272c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 273c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 274c3aae25116e66c177579b0b79182b09340b19753Chris Lattner/// ActOnPropertyImplDecl - This routine performs semantic checks and 275e41102bb610aeebe73eeec6a4afe62301de10042Chris Lattner/// builds the AST node for a property implementation declaration; declared 276fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel/// as @synthesize or @dynamic. 277e41102bb610aeebe73eeec6a4afe62301de10042Chris Lattner/// 278e41102bb610aeebe73eeec6a4afe62301de10042Chris LattnerSema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, 279e41102bb610aeebe73eeec6a4afe62301de10042Chris Lattner SourceLocation PropertyLoc, 280fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel bool Synthesize, 281c3aae25116e66c177579b0b79182b09340b19753Chris Lattner DeclPtrTy ClassCatImpDecl, 282c3aae25116e66c177579b0b79182b09340b19753Chris Lattner IdentifierInfo *PropertyId, 283c3aae25116e66c177579b0b79182b09340b19753Chris Lattner IdentifierInfo *PropertyIvar) { 284c3aae25116e66c177579b0b79182b09340b19753Chris Lattner Decl *ClassImpDecl = ClassCatImpDecl.getAs<Decl>(); 285c3aae25116e66c177579b0b79182b09340b19753Chris Lattner // Make sure we have a context for the property implementation declaration. 286c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (!ClassImpDecl) { 287c3aae25116e66c177579b0b79182b09340b19753Chris Lattner Diag(AtLoc, diag::error_missing_property_context); 288c3aae25116e66c177579b0b79182b09340b19753Chris Lattner return DeclPtrTy(); 289c3aae25116e66c177579b0b79182b09340b19753Chris Lattner } 290c3aae25116e66c177579b0b79182b09340b19753Chris Lattner ObjCPropertyDecl *property = 0; 291c3aae25116e66c177579b0b79182b09340b19753Chris Lattner ObjCInterfaceDecl* IDecl = 0; 292edf128a7fa90f2b0b7ee24741a04a7ae1ecd6f7eMisha Brukman // Find the class or category class where this property must have 293c3aae25116e66c177579b0b79182b09340b19753Chris Lattner // a declaration. 294c3aae25116e66c177579b0b79182b09340b19753Chris Lattner ObjCImplementationDecl *IC = 0; 295a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner ObjCCategoryImplDecl* CatImplClass = 0; 296fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) { 297a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner IDecl = IC->getClassInterface(); 298a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner // We always synthesize an interface for an implementation 299a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner // without an interface decl. So, IDecl is always non-zero. 300a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner assert(IDecl && 301883a52de66da854de158b602952d8242acddcb48Chris Lattner "ActOnPropertyImplDecl - @implementation without @interface"); 302d64a78c9ed62f2615ca1ea524d1f1942f798c8deDan Gohman 303883a52de66da854de158b602952d8242acddcb48Chris Lattner // Look for this property declaration in the @implementation's @interface 304883a52de66da854de158b602952d8242acddcb48Chris Lattner property = IDecl->FindPropertyDeclaration(PropertyId); 305883a52de66da854de158b602952d8242acddcb48Chris Lattner if (!property) { 306a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); 307a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner return DeclPtrTy(); 308fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel } 309a83385fb7bdb325921d091729d95e2e1f4d49cc1Chris Lattner if (const ObjCCategoryDecl *CD = 310c3aae25116e66c177579b0b79182b09340b19753Chris Lattner dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { 311c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (!CD->IsClassExtension()) { 312b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); 3136448d91ad1e5497fe2f7015d61b57cb5f3040879Dan Gohman Diag(property->getLocation(), diag::note_property_declare); 314b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner return DeclPtrTy(); 315b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner } 31658b968be853ef02d0f448e5e2c31676e361c210fJim Laskey } 317583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { 318583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey if (Synthesize) { 319583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey Diag(AtLoc, diag::error_synthesize_category_decl); 320def69b92e70d156ed6f8c7af33c9a87d3f475e09Jim Laskey return DeclPtrTy(); 321def69b92e70d156ed6f8c7af33c9a87d3f475e09Jim Laskey } 322583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey IDecl = CatImplClass->getClassInterface(); 323583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey if (!IDecl) { 324583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey Diag(AtLoc, diag::error_missing_property_interface); 325583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey return DeclPtrTy(); 326583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey } 327583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey ObjCCategoryDecl *Category = 328844731a7f1909f55935e3514c9e713a62d67662eDan Gohman IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); 329fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel 330583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey // If category for this implementation not found, it is an error which 331583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey // has already been reported eralier. 332def69b92e70d156ed6f8c7af33c9a87d3f475e09Jim Laskey if (!Category) 333def69b92e70d156ed6f8c7af33c9a87d3f475e09Jim Laskey return DeclPtrTy(); 334583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey // Look for this property declaration in @implementation's category 335475871a144eb604ddaf37503397ba0941442e5fbDan Gohman property = Category->FindPropertyDeclaration(PropertyId); 33663e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner if (!property) { 337ba36cb5242eb02b12b277f82b9efe497f7da4d7fGabor Greif Diag(PropertyLoc, diag::error_bad_category_property_decl) 33899a6cb92d173c142073416c81efe6d3daeb80b49Gabor Greif << Category->getDeclName(); 33963e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner return DeclPtrTy(); 340583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey } 341583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey } else { 3426d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman Diag(AtLoc, diag::error_bad_property_context); 3436d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman return DeclPtrTy(); 3446d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman } 3456d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman ObjCIvarDecl *Ivar = 0; 3466d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman // Check that we have a valid, previously declared ivar for @synthesize 347e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman if (Synthesize) { 348e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman // @synthesize 3496d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman if (!PropertyIvar) 3506d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman PropertyIvar = PropertyId; 3516d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman QualType PropType = Context.getCanonicalType(property->getType()); 352583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey // Check that this is a previously declared 'ivar' in 'IDecl' interface 353fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel ObjCInterfaceDecl *ClassDeclared; 354475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); 355583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey if (!Ivar) { 356583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey DeclContext *EnclosingContext = cast_or_null<DeclContext>(ClassImpDecl); 357583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey assert(EnclosingContext && 358583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey "null DeclContext for synthesized ivar - ActOnPropertyImplDecl"); 359583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, PropertyLoc, 3600dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands PropertyIvar, PropType, /*Dinfo=*/0, 3610dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands ObjCIvarDecl::Public, 3620dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands (Expr *)0); 3632041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen EnclosingContext->addDecl(Ivar); 3642a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner IDecl->makeDeclVisibleInContext(Ivar, false); 3652a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner property->setPropertyIvarDecl(Ivar); 3662a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner 3672041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen if (!getLangOptions().ObjCNonFragileABI) 368276dcbdc8db6614cfd5004dc7dc35e437ddf9c58Duncan Sands Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId; 369276dcbdc8db6614cfd5004dc7dc35e437ddf9c58Duncan Sands // Note! I deliberately want it to fall thru so, we have a 370276dcbdc8db6614cfd5004dc7dc35e437ddf9c58Duncan Sands // a property implementation and to avoid future warnings. 3712041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen } else if (getLangOptions().ObjCNonFragileABI && 3722041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen ClassDeclared != IDecl) { 3734fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman Diag(PropertyLoc, diag::error_ivar_in_superclass_use) 3742041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen << property->getDeclName() << Ivar->getDeclName() 3752041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen << ClassDeclared->getDeclName(); 376eaf089430e7681fcddc3465c3b33b9645273ab02Dale Johannesen Diag(Ivar->getLocation(), diag::note_previous_access_declaration) 3774fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman << Ivar << Ivar->getNameAsCString(); 3782041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // Note! I deliberately want it to fall thru so more errors are caught. 379eaf089430e7681fcddc3465c3b33b9645273ab02Dale Johannesen } 3802041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen QualType IvarType = Context.getCanonicalType(Ivar->getType()); 381b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio 382b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio // Check that type of property and its ivar are type compatible. 383b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio if (PropType != IvarType) { 384b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman if (CheckAssignmentConstraints(PropType, IvarType) != Compatible) { 3852041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen Diag(PropertyLoc, diag::error_property_ivar_type) 3862041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen << property->getDeclName() << PropType 3872a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner << Ivar->getDeclName() << IvarType; 3882041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen Diag(Ivar->getLocation(), diag::note_ivar_decl); 3892041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // Note! I deliberately want it to fall thru so, we have a 3902041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // a property implementation and to avoid future warnings. 3912041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen } 3922041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen 3932041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // FIXME! Rules for properties are somewhat different that those 3942041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // for assignments. Use a new routine to consolidate all cases; 3952041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // specifically for property redeclarations as well as for ivars. 3967f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType(); 3977f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); 3987f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman if (lhsType != rhsType && 3997f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman lhsType->isArithmeticType()) { 4007f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman Diag(PropertyLoc, diag::error_property_ivar_type) 4017f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman << property->getDeclName() << PropType 4027f460203b0c5350e9b2c592f438e40f7a7de6e45Dan Gohman << Ivar->getDeclName() << IvarType; 40369de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman Diag(Ivar->getLocation(), diag::note_ivar_decl); 40469de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman // Fall thru - see previous comment 40569de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman } 40669de1932b350d7cdfc0ed1f4198d6f78c7822a02Dan Gohman // __weak is explicit. So it works on Canonical type. 40736b5c1338a03453ba1c110b120269ca972fb65a3Dan Gohman if (PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && 408b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman getLangOptions().getGCMode() != LangOptions::NonGC) { 4092041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen Diag(PropertyLoc, diag::error_weak_property) 4102041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen << property->getDeclName() << Ivar->getDeclName(); 4112041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // Fall thru - see previous comment 4122041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen } 4132041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen if ((property->getType()->isObjCObjectPointerType() || 4142041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && 4152041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen getLangOptions().getGCMode() != LangOptions::NonGC) { 4162041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen Diag(PropertyLoc, diag::error_strong_property) 4172041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen << property->getDeclName() << Ivar->getDeclName(); 4182041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // Fall thru - see previous comment 4192041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen } 4202041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen } 421b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman } else if (PropertyIvar) 4222041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen // @dynamic 4232041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl); 4242041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen assert (property && "ActOnPropertyImplDecl - property declaration missing"); 4252041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen ObjCPropertyImplDecl *PIDecl = 4262041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, 4272041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen property, 4282041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen (Synthesize ? 4292041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen ObjCPropertyImplDecl::Synthesize 4305eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman : ObjCPropertyImplDecl::Dynamic), 4315eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman Ivar); 4325eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman if (IC) { 4335eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman if (Synthesize) 4345eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman if (ObjCPropertyImplDecl *PPIDecl = 4355eb0cecbc5dd370e33d4e0ab1abee7ce8597ca9cDan Gohman IC->FindPropertyImplIvarDecl(PropertyIvar)) { 4362041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen Diag(PropertyLoc, diag::error_duplicate_ivar_use) 437b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 4383b3adbb7456411957681e590b29697b3af307dd1Duncan Sands << PropertyIvar; 439a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman Diag(PPIDecl->getLocation(), diag::note_previous_use); 4402041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen } 4412041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen 4422041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen if (ObjCPropertyImplDecl *PPIDecl 443b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman = IC->FindPropertyImplDecl(PropertyId)) { 4443b3adbb7456411957681e590b29697b3af307dd1Duncan Sands Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 445a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 4462041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen return DeclPtrTy(); 4472041a0ef7544ec5ceece9cabd3963cc887861c1dDale Johannesen } 4480b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman IC->addPropertyImplementation(PIDecl); 4490b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman } else { 4500b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman if (Synthesize) 4510b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman if (ObjCPropertyImplDecl *PPIDecl = 4520b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { 4530b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman Diag(PropertyLoc, diag::error_duplicate_ivar_use) 4540b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 4550b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman << PropertyIvar; 4560b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman Diag(PPIDecl->getLocation(), diag::note_previous_use); 4570b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman } 4580b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman 4590b1d4a798d1dd2f39521b6b381cd1c1911c9ab52Dan Gohman if (ObjCPropertyImplDecl *PPIDecl = 460b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman CatImplClass->FindPropertyImplDecl(PropertyId)) { 461a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 462a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 46328873106309db515d58889a4c4fa3e0a92d1b60eMon P Wang return DeclPtrTy(); 464583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey } 4659008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman CatImplClass->addPropertyImplementation(PIDecl); 4669008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman } 4679008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman 4689008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman return DeclPtrTy::make(PIDecl); 4699008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman} 4709008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman 4719008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman//===----------------------------------------------------------------------===// 47228873106309db515d58889a4c4fa3e0a92d1b60eMon P Wang// Helper methods. 473583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey//===----------------------------------------------------------------------===// 474583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey 4750dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands/// DiagnosePropertyMismatch - Compares two properties for their 4760dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands/// attributes and types and warns on a variety of inconsistencies. 4770dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands/// 4780dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sandsvoid 4790dc4045bd27c177416745d2e72277b0a92c3ab83Duncan SandsSema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 4800dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands ObjCPropertyDecl *SuperProperty, 4810dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands const IdentifierInfo *inheritedName) { 4820dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands ObjCPropertyDecl::PropertyAttributeKind CAttr = 4830dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands Property->getPropertyAttributes(); 4840dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands ObjCPropertyDecl::PropertyAttributeKind SAttr = 4850dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands SuperProperty->getPropertyAttributes(); 4860dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) 4870dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) 488b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman Diag(Property->getLocation(), diag::warn_readonly_property) 489a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman << Property->getDeclName() << inheritedName; 490a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) 491b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) 492a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling Diag(Property->getLocation(), diag::warn_property_attribute) 493a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman << Property->getDeclName() << "copy" << inheritedName; 494a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman else if ((CAttr & ObjCPropertyDecl::OBJC_PR_retain) 495a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman != (SAttr & ObjCPropertyDecl::OBJC_PR_retain)) 496a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman Diag(Property->getLocation(), diag::warn_property_attribute) 497a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman << Property->getDeclName() << "retain" << inheritedName; 498a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman 499a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) 500a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) 501a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman Diag(Property->getLocation(), diag::warn_property_attribute) 502a7ce741ff0ab02510833854bfa6a1c8c265faee3Dan Gohman << Property->getDeclName() << "atomic" << inheritedName; 503b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman if (Property->getSetterName() != SuperProperty->getSetterName()) 504b8d2f550b84523e8a73198f98e5d450ec3b4fee7Dan Gohman Diag(Property->getLocation(), diag::warn_property_attribute) 505583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey << Property->getDeclName() << "setter" << inheritedName; 50658b968be853ef02d0f448e5e2c31676e361c210fJim Laskey if (Property->getGetterName() != SuperProperty->getGetterName()) 50758b968be853ef02d0f448e5e2c31676e361c210fJim Laskey Diag(Property->getLocation(), diag::warn_property_attribute) 508b48da3953642d3d006edebd7fc6c1ca5bcfdb5cdChris Lattner << Property->getDeclName() << "getter" << inheritedName; 5090dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands 5100dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands QualType LHSType = 5110dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands Context.getCanonicalType(SuperProperty->getType()); 5120dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands QualType RHSType = 5130dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands Context.getCanonicalType(Property->getType()); 5140dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands 5150dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands if (!Context.typesAreCompatible(LHSType, RHSType)) { 5160dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands // FIXME: Incorporate this test with typesAreCompatible. 5170dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType()) 5180dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false)) 5190dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands return; 5200dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) 5210dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands << Property->getType() << SuperProperty->getType() << inheritedName; 5220dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands } 5230dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands} 5240dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands 5250dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sandsbool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 5260dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands ObjCMethodDecl *GetterMethod, 5270dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands SourceLocation Loc) { 5280dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands if (GetterMethod && 5290dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands GetterMethod->getResultType() != property->getType()) { 5300dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands AssignConvertType result = Incompatible; 5310dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands if (property->getType()->isObjCObjectPointerType()) 5320e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner result = CheckAssignmentConstraints(GetterMethod->getResultType(), 533190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner property->getType()); 534190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner if (result != Compatible) { 5350e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner Diag(Loc, diag::warn_accessor_property_type_mismatch) 5360e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner << property->getDeclName() 5379503859c545496838165a340b1e1730dc1b83736Chris Lattner << GetterMethod->getSelector(); 5380e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner Diag(GetterMethod->getLocation(), diag::note_declared_at); 539190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner return true; 540fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel } 541190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner } 542de202b3cda00f17ba2c047be7270b51f9585a413Chris Lattner return false; 543190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner} 544190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner 545190a418bf6b49a4ef1c1980229a2f0d516e8a2cdChris Lattner/// ComparePropertiesInBaseAndSuper - This routine compares property 5460fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman/// declarations in base and its super class, if any, and issues 547fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel/// diagnostics in a variety of inconsistant situations. 5480e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner/// 5499503859c545496838165a340b1e1730dc1b83736Chris Lattnervoid Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { 5500e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); 5510e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner if (!SDecl) 5520fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman return; 5530fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman // FIXME: O(N^2) 5540fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(), 5550fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman E = SDecl->prop_end(); S != E; ++S) { 556130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng ObjCPropertyDecl *SuperPDecl = (*S); 557130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng // Does property in super class has declaration in current class? 558130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(), 559130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng E = IDecl->prop_end(); I != E; ++I) { 560e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman ObjCPropertyDecl *PDecl = (*I); 561fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel if (SuperPDecl->getIdentifier() == PDecl->getIdentifier()) 562f8dc0617baceeba8ccd67c8881eb88eb1be2902cChris Lattner DiagnosePropertyMismatch(PDecl, SuperPDecl, 563edfcf598faab9ce294712551ecf67093acd1c66eDuncan Sands SDecl->getIdentifier()); 564fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel } 565130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng } 566130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng} 567130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng 568130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng/// MatchOneProtocolPropertiesInClass - This routine goes thru the list 569130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng/// of properties declared in a protocol and compares their attribute against 570e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman/// the same property declared in the class or category. 571e7852d014432a06c783de3c350eb96e686f10f92Dan Gohmanvoid 572e7852d014432a06c783de3c350eb96e686f10f92Dan GohmanSema::MatchOneProtocolPropertiesInClass(Decl *CDecl, 573e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman ObjCProtocolDecl *PDecl) { 574e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); 575130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng if (!IDecl) { 576130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng // Category 577130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); 578130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng assert (CatDecl && "MatchOneProtocolPropertiesInClass"); 579a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling if (!CatDecl->IsClassExtension()) 580c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 581130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng E = PDecl->prop_end(); P != E; ++P) { 582130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng ObjCPropertyDecl *Pr = (*P); 583130a6471b90f66e99b1f9f42877fdf611c330ac6Evan Cheng ObjCCategoryDecl::prop_iterator CP, CE; 5840fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman // Is this property already in category's list of properties? 585e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP) 5860fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman if ((*CP)->getIdentifier() == Pr->getIdentifier()) 5870fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman break; 5880fe9c6e7babb3c0731d9cb864ec498ec4184760fDan Gohman if (CP != CE) 589c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner // Property protocol already exist in class. Diagnose any mismatch. 590c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); 591c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner } 592c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner return; 593fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel } 5941e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 5951e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner E = PDecl->prop_end(); P != E; ++P) { 5961e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner ObjCPropertyDecl *Pr = (*P); 5971e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner ObjCInterfaceDecl::prop_iterator CP, CE; 5981e111c7bbb50eec1cb1ebc7d12fcfb22c36f8d87Chris Lattner // Is this property already in class's list of properties? 599e77f89de8cb6690ac45b87b03c588e9d287c1eebDan Gohman for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP) 600e77f89de8cb6690ac45b87b03c588e9d287c1eebDan Gohman if ((*CP)->getIdentifier() == Pr->getIdentifier()) 601c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman break; 602f06c835f769aa1cf67801ed1f6bd366a447c18b1Dan Gohman if (CP != CE) 603e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman // Property protocol already exist in class. Diagnose any mismatch. 604a1dc6025422cd0e6f951c69a8427f7f885cf52c3Bill Wendling DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); 605c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman } 606c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman} 607c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman 608c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman/// CompareProperties - This routine compares properties 609c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman/// declared in 'ClassOrProtocol' objects (which can be a class or an 61063e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner/// inherited protocol with the list of properties for class/category 'CDecl' 611fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel/// 612c53361294957b63a9c1e405256c6f0a81db1685cDan Gohmanvoid Sema::CompareProperties(Decl *CDecl, 613c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman DeclPtrTy ClassOrProtocol) { 614c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman Decl *ClassDecl = ClassOrProtocol.getAs<Decl>(); 615c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); 6161146728bfaeb471f675b805ceb27a08d28bbf468Dan Gohman 617c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner if (!IDecl) { 618c26aefa15ae7f02b37923f6fed5a74d60e76ff56Chris Lattner // Category 619149c58ce0b94e64faf3c4ccdbf894061cf7d66e1Chris Lattner ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); 620149c58ce0b94e64faf3c4ccdbf894061cf7d66e1Chris Lattner assert (CatDecl && "CompareProperties"); 621149c58ce0b94e64faf3c4ccdbf894061cf7d66e1Chris Lattner if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 622149c58ce0b94e64faf3c4ccdbf894061cf7d66e1Chris Lattner for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(), 623095cc29f321382e1f7d295e262a28197f92c5491Dan Gohman E = MDecl->protocol_end(); P != E; ++P) 6246621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner // Match properties of category with those of protocol (*P) 6250e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner MatchOneProtocolPropertiesInClass(CatDecl, *P); 626f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman 627f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman // Go thru the list of protocols for this category and recursively match 628095cc29f321382e1f7d295e262a28197f92c5491Dan Gohman // their properties with those in the category. 629095cc29f321382e1f7d295e262a28197f92c5491Dan Gohman for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(), 6307cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner E = CatDecl->protocol_end(); P != E; ++P) 6317cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner CompareProperties(CatDecl, DeclPtrTy::make(*P)); 6327cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner } else { 6336621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); 6347cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), 6357cf7e3f33f25544d08492d47cc8a1cbba25dc8d7Chris Lattner E = MD->protocol_end(); P != E; ++P) 636056292fd738924f3f7703725d8f630983794b5a5Bill Wendling MatchOneProtocolPropertiesInClass(CatDecl, *P); 637056292fd738924f3f7703725d8f630983794b5a5Bill Wendling } 6380e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner return; 6391af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner } 6401af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner 6411af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { 6421af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(), 6431af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner E = MDecl->protocol_end(); P != E; ++P) 6442a2de66db2093a5bc1fd620d1b6ae7992a552b24Andrew Lenharth // Match properties of class IDecl with those of protocol (*P). 6451af2231da64a14d638406d133c7912bfc1c8a9ceChris Lattner MatchOneProtocolPropertiesInClass(IDecl, *P); 646f411b83c8c6853c2a922b692e782566353153f08Duncan Sands 64783ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands // Go thru the list of protocols for this class and recursively match 64883ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands // their properties with those declared in the class. 649f411b83c8c6853c2a922b692e782566353153f08Duncan Sands for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(), 650f411b83c8c6853c2a922b692e782566353153f08Duncan Sands E = IDecl->protocol_end(); P != E; ++P) 65183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands CompareProperties(IDecl, DeclPtrTy::make(*P)); 65283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands } else { 653f411b83c8c6853c2a922b692e782566353153f08Duncan Sands ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); 65415e4b01920d6a0ffbe35d3e5aa88a4b42970b6a7Chris Lattner for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), 655f411b83c8c6853c2a922b692e782566353153f08Duncan Sands E = MD->protocol_end(); P != E; ++P) 6560e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner MatchOneProtocolPropertiesInClass(IDecl, *P); 6574a283e90af7984762eb3e984cee747d32c82e3dbChris Lattner } 6584a283e90af7984762eb3e984cee747d32c82e3dbChris Lattner} 6590e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner 6600e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner/// isPropertyReadonly - Return true if property is readonly, by searching 6616621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner/// for the property in the class and in its categories and implementations 662fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel/// 6636621e3b9636174886c9665b648f2ddc13effbc8aChris Lattnerbool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, 6646621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner ObjCInterfaceDecl *IDecl) { 6656621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner // by far the most common case. 6660dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands if (!PDecl->isReadOnly()) 667b5bec2b6f6f4a4da96170d1c258ad424112ad2c5Dan Gohman return false; 668832171cb9724d2d31c8dfb73172e2be8f6dd13eeBill Wendling // Even if property is ready only, if interface has a user defined setter, 6696621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner // it is not considered read only. 6706621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner if (IDecl->getInstanceMethod(PDecl->getSetterName())) 6716621e3b9636174886c9665b648f2ddc13effbc8aChris Lattner return false; 672095cc29f321382e1f7d295e262a28197f92c5491Dan Gohman 6730e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner // Main class has the property as 'readonly'. Must search 6740e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner // through the category list to see if the property's 675399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman // attribute has been over-ridden to 'readwrite'. 676399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman for (ObjCCategoryDecl *Category = IDecl->getCategoryList(); 677399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman Category; Category = Category->getNextClassCategory()) { 678399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman // Even if property is ready only, if a category has a user defined setter, 6798b8749f367fd30a8a3d57284576a6d59b60b69ebChris Lattner // it is not considered read only. 680399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman if (Category->getInstanceMethod(PDecl->getSetterName())) 681399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman return false; 682399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman ObjCPropertyDecl *P = 683399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman Category->FindPropertyDeclaration(PDecl->getIdentifier()); 684399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman if (P && !P->isReadOnly()) 685399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman return false; 686399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman } 687399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman 688399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman // Also, check for definition of a setter method in the implementation if 689399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman // all else failed. 690399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) { 691399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman if (ObjCImplementationDecl *IMD = 692399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) { 693399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman if (IMD->getInstanceMethod(PDecl->getSetterName())) 694fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel return false; 695399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman } else if (ObjCCategoryImplDecl *CIMD = 696399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 697399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman if (CIMD->getInstanceMethod(PDecl->getSetterName())) 698399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman return false; 699399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman } 70071e8685633e7938ee752004cceedccbd0d850527Evan Cheng } 701399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman // Lastly, look through the implementation (if one is in scope). 702399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation()) 703fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel if (ImpDecl->getInstanceMethod(PDecl->getSetterName())) 704399461095b033438d1f5863cd0d6f82a616f74dcDan Gohman return false; 7058b8749f367fd30a8a3d57284576a6d59b60b69ebChris Lattner // If all fails, look at the super class. 7068b8749f367fd30a8a3d57284576a6d59b60b69ebChris Lattner if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass()) 707df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner return isPropertyReadonly(PDecl, SIDecl); 708fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel return true; 709df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner} 710df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner 711475871a144eb604ddaf37503397ba0941442e5fbDan Gohman/// CollectImmediateProperties - This routine collects all properties in 712a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner/// the class and its conforming protocols; but not those it its super class. 7130dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sandsvoid Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, 7140dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { 71571e8685633e7938ee752004cceedccbd0d850527Evan Cheng if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 716475871a144eb604ddaf37503397ba0941442e5fbDan Gohman for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 717583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey E = IDecl->prop_end(); P != E; ++P) { 71863e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner ObjCPropertyDecl *Prop = (*P); 7190dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands PropMap[Prop->getIdentifier()] = Prop; 720a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner } 721df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner // scan through class's protocols. 722df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), 723df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner E = IDecl->protocol_end(); PI != E; ++PI) 724fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel CollectImmediateProperties((*PI), PropMap); 725df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner } 726df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { 727fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel if (!CATDecl->IsClassExtension()) 728475871a144eb604ddaf37503397ba0941442e5fbDan Gohman for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), 729a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner E = CATDecl->prop_end(); P != E; ++P) { 7300dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands ObjCPropertyDecl *Prop = (*P); 7310dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands PropMap[Prop->getIdentifier()] = Prop; 7320dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands } 733475871a144eb604ddaf37503397ba0941442e5fbDan Gohman // scan through class's protocols. 734583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(), 73563e3f14df6cf76f1a12de1153e1114f4b20b15a9Chris Lattner E = CATDecl->protocol_end(); PI != E; ++PI) 7360dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands CollectImmediateProperties((*PI), PropMap); 737a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner } 738df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 739df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 740df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner E = PDecl->prop_end(); P != E; ++P) { 741df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner ObjCPropertyDecl *Prop = (*P); 742fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; 743df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner if (!PropEntry) 744df6eb30fa9bc8600862cae18fce66da466188323Chris Lattner PropEntry = Prop; 745fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel } 746475871a144eb604ddaf37503397ba0941442e5fbDan Gohman // scan through protocol's protocols. 747a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 7480dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands E = PDecl->protocol_end(); PI != E; ++PI) 7490dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands CollectImmediateProperties((*PI), PropMap); 75071e8685633e7938ee752004cceedccbd0d850527Evan Cheng } 751583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey} 752575e2f4ea874deae3af8a940f30df5348d272190Dan Gohman 7530dc4045bd27c177416745d2e72277b0a92c3ab83Duncan Sands/// LookupPropertyDecl - Looks up a property in the current class and all 754a5682853b9921bbb0dd2ee175c9bd44142d4819eChris Lattner/// its protocols. 755df6eb30fa9bc8600862cae18fce66da466188323Chris LattnerObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, 7568b8749f367fd30a8a3d57284576a6d59b60b69ebChris Lattner IdentifierInfo *II) { 757d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands if (const ObjCInterfaceDecl *IDecl = 758d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands dyn_cast<ObjCInterfaceDecl>(CDecl)) { 759d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 760d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands E = IDecl->prop_end(); P != E; ++P) { 761d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands ObjCPropertyDecl *Prop = (*P); 762d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands if (Prop->getIdentifier() == II) 763d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands return Prop; 764d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands } 765d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands // scan through class's protocols. 766d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), 767d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands E = IDecl->protocol_end(); PI != E; ++PI) { 768d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 769d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands if (Prop) 770d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands return Prop; 771d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands } 772d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands } 773d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands else if (const ObjCProtocolDecl *PDecl = 774d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands dyn_cast<ObjCProtocolDecl>(CDecl)) { 775d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 776d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands E = PDecl->prop_end(); P != E; ++P) { 777d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands ObjCPropertyDecl *Prop = (*P); 778d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands if (Prop->getIdentifier() == II) 779d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands return Prop; 780d22ec5f62813f8cf2ed8091f44a14377209b1a59Duncan Sands } 78115684b29552393553524171bff1913e750f390f8Rafael Espindola // scan through protocol's protocols. 78215684b29552393553524171bff1913e750f390f8Rafael Espindola for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 78315684b29552393553524171bff1913e750f390f8Rafael Espindola E = PDecl->protocol_end(); PI != E; ++PI) { 7849008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 7859008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman if (Prop) 7869008ca6b6b4f638cfafccb593cbc5b1d3f5ab877Nate Begeman return Prop; 787d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands } 788d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands } 789d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands return 0; 790d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands} 791d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands 7929c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman 7939c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohmanvoid Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl, 7949c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman ObjCContainerDecl *CDecl, 7959c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman const llvm::DenseSet<Selector>& InsMap) { 7969c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; 7979c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman CollectImmediateProperties(CDecl, PropMap); 7989c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman if (PropMap.empty()) 7999c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman return; 8009c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman 8019c6e70eca9a49c146b26621cbcbb9464ceeac024Dan Gohman llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; 8020e12e6e0418564d4b2e83138fe2044be29a6f6d5Chris Lattner for (ObjCImplDecl::propimpl_iterator 80392570c4a1a11cbdaf5ffb13547428dbee1103875Dale Johannesen I = IMPDecl->propimpl_begin(), 8047c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman EI = IMPDecl->propimpl_end(); I != EI; ++I) 805b51d40cf40eac676dda3ae9dfeb55822fa403394Devang Patel PropImplMap.insert((*I)->getPropertyDecl()); 80692570c4a1a11cbdaf5ffb13547428dbee1103875Dale Johannesen 80792570c4a1a11cbdaf5ffb13547428dbee1103875Dale Johannesen for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 808f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 8096f17966a804f53518aa06fd0b5f035d5b1a51589Dan Gohman ObjCPropertyDecl *Prop = P->second; 8106f17966a804f53518aa06fd0b5f035d5b1a51589Dan Gohman // Is there a matching propery synthesize/dynamic? 8116e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel if (Prop->isInvalidDecl() || 8126e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 8137c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman PropImplMap.count(Prop)) 8147c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman continue; 8156e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel if (LangOpts.ObjCNonFragileABI2) { 8167c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman ActOnPropertyImplDecl(IMPDecl->getLocation(), 8177c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman SourceLocation(), 81878ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner true, DeclPtrTy::make(IMPDecl), 819f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman Prop->getIdentifier(), 820f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman Prop->getIdentifier()); 821f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman continue; 822f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman } 8231146728bfaeb471f675b805ceb27a08d28bbf468Dan Gohman if (!InsMap.count(Prop->getGetterName())) { 8241146728bfaeb471f675b805ceb27a08d28bbf468Dan Gohman Diag(Prop->getLocation(), 825c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman isa<ObjCCategoryDecl>(CDecl) ? 826c53361294957b63a9c1e405256c6f0a81db1685cDan Gohman diag::warn_setter_getter_impl_required_in_category : 82778ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner diag::warn_setter_getter_impl_required) 82878ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner << Prop->getDeclName() << Prop->getGetterName(); 8297c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman Diag(IMPDecl->getLocation(), 830f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman diag::note_property_impl_required); 831f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman } 832f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman 833f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) { 834f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman Diag(Prop->getLocation(), 835056292fd738924f3f7703725d8f630983794b5a5Bill Wendling isa<ObjCCategoryDecl>(CDecl) ? 836056292fd738924f3f7703725d8f630983794b5a5Bill Wendling diag::warn_setter_getter_impl_required_in_category : 837f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman diag::warn_setter_getter_impl_required) 838f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman << Prop->getDeclName() << Prop->getSetterName(); 839f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman Diag(IMPDecl->getLocation(), 840f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman diag::note_property_impl_required); 841f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman } 842e7852d014432a06c783de3c350eb96e686f10f92Dan Gohman } 843f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman} 844f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman 845f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohmanvoid 846f350b277f32d7d47f86c0e54f4aec4d470500618Dan GohmanSema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, 8476ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling ObjCContainerDecl* IDecl) { 8486ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling // Rules apply in non-GC mode only 8496ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling if (getLangOptions().getGCMode() != LangOptions::NonGC) 8506ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling return; 8516ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), 8526ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling E = IDecl->prop_end(); 8536ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling I != E; ++I) { 8546ce610f04bb232ce8b57e50e885f30f65d19e1a6Bill Wendling ObjCPropertyDecl *Property = (*I); 8554c2454623841f05c6c665659b34c214950d12d7eBob Wilson unsigned Attributes = Property->getPropertyAttributes(); 8564c2454623841f05c6c665659b34c214950d12d7eBob Wilson // We only care about readwrite atomic property. 85741b9d278add97c744930aa2a0048ff1c01e48c4fBill Wendling if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || 858bd209ab9bc0f6ad667c15df4453955c2ed4c2434Dan Gohman !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) 859bd209ab9bc0f6ad667c15df4453955c2ed4c2434Dan Gohman continue; 860bd209ab9bc0f6ad667c15df4453955c2ed4c2434Dan Gohman if (const ObjCPropertyImplDecl *PIDecl 86141b9d278add97c744930aa2a0048ff1c01e48c4fBill Wendling = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { 86241b9d278add97c744930aa2a0048ff1c01e48c4fBill Wendling if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 86341b9d278add97c744930aa2a0048ff1c01e48c4fBill Wendling continue; 864475871a144eb604ddaf37503397ba0941442e5fbDan Gohman ObjCMethodDecl *GetterMethod = 8650ff39b3feb10477c224138156941234f5fa46f58Evan Cheng IMPDecl->getInstanceMethod(Property->getGetterName()); 866ce9bc12c6f3c3544f7518c0c60203f2f9dff342fDan Gohman ObjCMethodDecl *SetterMethod = 867ce9bc12c6f3c3544f7518c0c60203f2f9dff342fDan Gohman IMPDecl->getInstanceMethod(Property->getSetterName()); 868ce9bc12c6f3c3544f7518c0c60203f2f9dff342fDan Gohman if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { 86983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands SourceLocation MethodLoc = 8706394b099e836f56a937cdcc7332c9487b504ca68Dan Gohman (GetterMethod ? GetterMethod->getLocation() 8716394b099e836f56a937cdcc7332c9487b504ca68Dan Gohman : SetterMethod->getLocation()); 872475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Diag(MethodLoc, diag::warn_atomic_property_rule) 8734fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman << Property->getIdentifier(); 8744fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman Diag(Property->getLocation(), diag::note_property_declare); 8754fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman } 8764fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman } 87783ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands } 878890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman} 8790ff39b3feb10477c224138156941234f5fa46f58Evan Cheng 88083ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 8816394b099e836f56a937cdcc7332c9487b504ca68Dan Gohman/// have the property type and issue diagnostics if they don't. 88261b09412fe2c98367730c7064d56eff537b03434Chris Lattner/// Also synthesize a getter/setter method if none exist (and update the 88361b09412fe2c98367730c7064d56eff537b03434Chris Lattner/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized 884583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey/// methods is the "right" thing to do. 8856d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohmanvoid Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, 8864fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman ObjCContainerDecl *CD) { 88761b09412fe2c98367730c7064d56eff537b03434Chris Lattner ObjCMethodDecl *GetterMethod, *SetterMethod; 888890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman 889890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman GetterMethod = CD->getInstanceMethod(property->getGetterName()); 89083ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands SetterMethod = CD->getInstanceMethod(property->getSetterName()); 891475871a144eb604ddaf37503397ba0941442e5fbDan Gohman DiagnosePropertyAccessorMismatch(property, GetterMethod, 892890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman property->getLocation()); 893fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman 8944fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman if (SetterMethod) { 895890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman ObjCPropertyDecl::PropertyAttributeKind CAttr = 896890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman property->getPropertyAttributes(); 897890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && 898890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman Context.getCanonicalType(SetterMethod->getResultType()) != 899475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Context.VoidTy) 90083ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands Diag(SetterMethod->getLocation(), diag::err_setter_type_void); 901475871a144eb604ddaf37503397ba0941442e5fbDan Gohman if (SetterMethod->param_size() != 1 || 90283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands ((*SetterMethod->param_begin())->getType() != property->getType())) { 903a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng Diag(property->getLocation(), 904a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng diag::warn_accessor_property_type_mismatch) 905890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman << property->getDeclName() 906890813243f9b4f5aa9c6d5ab79ffe948458197abDan Gohman << SetterMethod->getSelector(); 90778ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner Diag(SetterMethod->getLocation(), diag::note_declared_at); 90878ec311bd5fcdf44ed64841a0f5df1124b3a9b17Chris Lattner } 909475871a144eb604ddaf37503397ba0941442e5fbDan Gohman } 9100bd4893a0726889b942405262e53d06cf3fe3be8Chris Lattner 9110bd4893a0726889b942405262e53d06cf3fe3be8Chris Lattner // Synthesize getter/setter methods if none exist. 9120bd4893a0726889b942405262e53d06cf3fe3be8Chris Lattner // Find the default getter and if one not found, add one. 9130bd4893a0726889b942405262e53d06cf3fe3be8Chris Lattner // FIXME: The synthesized property we set here is misleading. We almost always 914475871a144eb604ddaf37503397ba0941442e5fbDan Gohman // synthesize these methods unless the user explicitly provided prototypes 9154fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman // (which is odd, but allowed). Sema should be typechecking that the 9164fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman // declarations jive in that situation (which it is not currently). 9174fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman if (!GetterMethod) { 9184fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman // No instance method of same name as property getter name was found. 91983ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands // Declare a getter method and add it to the list of methods 920fdc40a0a696c658d550d894ea03772e5f8af2c94Scott Michel // for this class. 92183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), 92283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands property->getLocation(), property->getGetterName(), 923c3aae25116e66c177579b0b79182b09340b19753Chris Lattner property->getType(), 0, CD, true, false, true, 924d8658616cf8b6ad984974bb764dc9ee4b77499aaChris Lattner (property->getPropertyImplementation() == 925d8658616cf8b6ad984974bb764dc9ee4b77499aaChris Lattner ObjCPropertyDecl::Optional) ? 926d8658616cf8b6ad984974bb764dc9ee4b77499aaChris Lattner ObjCMethodDecl::Optional : 927c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner ObjCMethodDecl::Required); 928583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey CD->addDecl(GetterMethod); 9296d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman } else 9304fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman // A user declared getter will be synthesize when @synthesize of 931c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner // the property with the same name is seen in the @implementation 932c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng GetterMethod->setSynthesized(true); 933c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng property->setGetterMethodDecl(GetterMethod); 93483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands 935475871a144eb604ddaf37503397ba0941442e5fbDan Gohman // Skip setter if property is read-only. 936c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng if (!property->isReadOnly()) { 937fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman // Find the default setter and if one not found, add one. 9384fbd796a1251a27e6590765a0a34876f436a0af9Dan Gohman if (!SetterMethod) { 939c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng // No instance method of same name as property setter name was found. 940c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng // Declare a setter method and add it to the list of methods 941c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng // for this class. 942c908dcde45c6d7ddff0443cbc174a7cbfec21d1bEvan Cheng SetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), 943475871a144eb604ddaf37503397ba0941442e5fbDan Gohman property->getLocation(), 94483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands property->getSetterName(), 945475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Context.VoidTy, 0, CD, true, false, true, 94683ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands (property->getPropertyImplementation() == 947a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng ObjCPropertyDecl::Optional) ? 948a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng ObjCMethodDecl::Optional : 949a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng ObjCMethodDecl::Required); 9507f32156bb9c017b71971c52fac892fa7b9b06dd2Dan Gohman // Invent the arguments for the setter. We don't bother making a 9517f32156bb9c017b71971c52fac892fa7b9b06dd2Dan Gohman // nice name for the argument. 952c3aae25116e66c177579b0b79182b09340b19753Chris Lattner ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, 953c3aae25116e66c177579b0b79182b09340b19753Chris Lattner property->getLocation(), 954475871a144eb604ddaf37503397ba0941442e5fbDan Gohman property->getIdentifier(), 95583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands property->getType(), 95683ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands /*TInfo=*/0, 957f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen VarDecl::None, 958f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen 0); 959f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen SetterMethod->setMethodParams(Context, &Argument, 1); 960f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen CD->addDecl(SetterMethod); 961f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen } else 962f04afdbb48568ef09f11fd10ac03426101f2dbf8Dale Johannesen // A user declared setter will be synthesize when @synthesize of 963475871a144eb604ddaf37503397ba0941442e5fbDan Gohman // the property with the same name is seen in the @implementation 9646520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman SetterMethod->setSynthesized(true); 9652a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner property->setSetterMethodDecl(SetterMethod); 9662a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner } 9672a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner // Add any synthesized methods to the global pool. This allows us to 9682a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner // handle the following, which is supported by GCC (and part of the design). 9692a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner // 9706520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman // @interface Foo 9714401361a2fb92c82317dbfbb1616f54ced2b51f3Dan Gohman // @property double bar; 9726520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman // @end 9736520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman // 9746520e20e4fb31f2e65e25c38b372b19d33a83df4Dan Gohman // void thisIsUnfortunate() { 9754d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov // id foo; 9764d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov // double bar = [foo bar]; 977c73ede0a9beaee2e11d004f816a8207d9bd79072Anton Korobeynikov // } 9784d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov // 97919e861a4ffb896f16a691d5ac869e894df3cd464Anton Korobeynikov if (GetterMethod) 9804d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov AddInstanceMethodToGlobalPool(GetterMethod); 9814d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov if (SetterMethod) 9822a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner AddInstanceMethodToGlobalPool(SetterMethod); 983b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio} 984b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio 985b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venanciovoid Sema::CheckObjCPropertyAttributes(QualType PropertyTy, 986b3a0417cad8b625acc3033bd5e24afb9ffd0b084Lauro Ramos Venancio SourceLocation Loc, 9874d86e2a6b8edc814165a3e63f55bfaea0b8f224dAnton Korobeynikov unsigned &Attributes) { 988583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey // FIXME: Improve the reported location. 9896d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman 99061b09412fe2c98367730c7064d56eff537b03434Chris Lattner // readonly and readwrite/assign/retain/copy conflict. 99161b09412fe2c98367730c7064d56eff537b03434Chris Lattner if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 9922a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | 99361b09412fe2c98367730c7064d56eff537b03434Chris Lattner ObjCDeclSpec::DQ_PR_assign | 99461b09412fe2c98367730c7064d56eff537b03434Chris Lattner ObjCDeclSpec::DQ_PR_copy | 99574692c0d65d92865674ff8e0491a21b98950284aDan Gohman ObjCDeclSpec::DQ_PR_retain))) { 996fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ? 9972a4ed82ce2ba4a02f2a02eb4ed8ce5186f3f93daChris Lattner "readwrite" : 99861b09412fe2c98367730c7064d56eff537b03434Chris Lattner (Attributes & ObjCDeclSpec::DQ_PR_assign) ? 999c3aae25116e66c177579b0b79182b09340b19753Chris Lattner "assign" : 1000475871a144eb604ddaf37503397ba0941442e5fbDan Gohman (Attributes & ObjCDeclSpec::DQ_PR_copy) ? 1001c3aae25116e66c177579b0b79182b09340b19753Chris Lattner "copy" : "retain"; 1002c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 1003475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ? 1004c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner diag::err_objc_property_attr_mutually_exclusive : 1005583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey diag::warn_objc_property_attr_mutually_exclusive) 10066d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman << "readonly" << which; 1007c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner } 1008c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner 1009c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner // Check for copy or retain on non-object types. 1010475871a144eb604ddaf37503397ba0941442e5fbDan Gohman if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) && 1011fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman !PropertyTy->isObjCObjectPointerType() && 10120e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman !PropertyTy->isBlockPointerType() && 1013c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner !Context.isObjCNSObjectType(PropertyTy)) { 101437efe6764568a3829fee26aba532283131d1a104Nate Begeman Diag(Loc, diag::err_objc_property_requires_object) 1015475871a144eb604ddaf37503397ba0941442e5fbDan Gohman << (Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain"); 101637efe6764568a3829fee26aba532283131d1a104Nate Begeman Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain); 101737efe6764568a3829fee26aba532283131d1a104Nate Begeman } 1018475871a144eb604ddaf37503397ba0941442e5fbDan Gohman 1019c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner // Check for more than one of { assign, copy, retain }. 1020583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey if (Attributes & ObjCDeclSpec::DQ_PR_assign) { 10216d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1022c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1023c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner << "assign" << "copy"; 1024c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 1025475871a144eb604ddaf37503397ba0941442e5fbDan Gohman } 1026fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 10270e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1028c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner << "assign" << "retain"; 102937efe6764568a3829fee26aba532283131d1a104Nate Begeman Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1030475871a144eb604ddaf37503397ba0941442e5fbDan Gohman } 103137efe6764568a3829fee26aba532283131d1a104Nate Begeman } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 103237efe6764568a3829fee26aba532283131d1a104Nate Begeman if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1033475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1034475871a144eb604ddaf37503397ba0941442e5fbDan Gohman << "copy" << "retain"; 1035475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 103650284d81f863a6576582e1a171a22eb0f012ddf3Dan Gohman } 10371606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng } 1038c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner 1039583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey // Warn if user supplied no assignment attribute, property is 10406d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman // readwrite, and this is an object type. 1041c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | 1042c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner ObjCDeclSpec::DQ_PR_retain)) && 1043130fc13506b4da64981632c83734721a8b5b2d2dChris Lattner !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1044c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner PropertyTy->isObjCObjectPointerType()) { 1045c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner // Skip this warning in gc-only mode. 1046475871a144eb604ddaf37503397ba0941442e5fbDan Gohman if (getLangOptions().getGCMode() != LangOptions::GCOnly) 1047fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman Diag(Loc, diag::warn_objc_property_no_assignment_attribute); 10480e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman 1049c9f8f416800784ca6453222b307bc44ad24739b0Chris Lattner // If non-gc code warn that this is likely inappropriate. 10504025a9c2cc4ac3b9efa465a2f64be50fdaba9da9Chris Lattner if (getLangOptions().getGCMode() == LangOptions::NonGC) 1051475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Diag(Loc, diag::warn_objc_property_default_assign_on_object); 10524025a9c2cc4ac3b9efa465a2f64be50fdaba9da9Chris Lattner 10534025a9c2cc4ac3b9efa465a2f64be50fdaba9da9Chris Lattner // FIXME: Implement warning dependent on NSCopying being 1054c3aae25116e66c177579b0b79182b09340b19753Chris Lattner // implemented. See also: 1055475871a144eb604ddaf37503397ba0941442e5fbDan Gohman // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496> 1056475871a144eb604ddaf37503397ba0941442e5fbDan Gohman // (please trim this list while you are at it). 1057475871a144eb604ddaf37503397ba0941442e5fbDan Gohman } 105850284d81f863a6576582e1a171a22eb0f012ddf3Dan Gohman 10591606e8e4cd937e6de6681f686c266cf61722d972Evan Cheng if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) 1060d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng && getLangOptions().getGCMode() == LangOptions::GCOnly 1061583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey && PropertyTy->isBlockPointerType()) 10626d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman Diag(Loc, diag::warn_objc_property_copy_missing_on_block); 1063d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng} 1064d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng 1065583bd47f777fe3eb8305872fa0eadab31e833dffJim LaskeyObjCIvarDecl* 1066d6594ae54cfde4db4d30272192645c0a45fb9902Evan ChengSema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl, 1067d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng IdentifierInfo *NameII) { 1068475871a144eb604ddaf37503397ba0941442e5fbDan Gohman ObjCIvarDecl *Ivar = 0; 1069fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII); 10700e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman if (Prop && !Prop->isInvalidDecl()) { 1071d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl); 1072d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng QualType PropType = Context.getCanonicalType(Prop->getType()); 1073475871a144eb604ddaf37503397ba0941442e5fbDan Gohman assert(EnclosingContext && 1074d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng "null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar"); 1075d6594ae54cfde4db4d30272192645c0a45fb9902Evan Cheng Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, 1076475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Prop->getLocation(), 1077583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey NameII, PropType, /*Dinfo=*/0, 10786d9cdd56173fb915a9e3a8f0f6b5a8ed9bed1098Dan Gohman ObjCIvarDecl::Public, 107961b09412fe2c98367730c7064d56eff537b03434Chris Lattner (Expr *)0); 108061b09412fe2c98367730c7064d56eff537b03434Chris Lattner Ivar->setLexicalDeclContext(IDecl); 108161b09412fe2c98367730c7064d56eff537b03434Chris Lattner IDecl->addDecl(Ivar); 1082475871a144eb604ddaf37503397ba0941442e5fbDan Gohman Prop->setPropertyIvarDecl(Ivar); 1083fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman } 10840e5f1306b059b62d7725f324e087efbc8e7a782dDan Gohman return Ivar; 108561b09412fe2c98367730c7064d56eff537b03434Chris Lattner} 1086c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 1087475871a144eb604ddaf37503397ba0941442e5fbDan Gohman