SemaObjCProperty.cpp revision 7939418cbdf1b610a69e6adf29cd7dc8d0e9eaf8
13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file implements semantic analysis for Objective C @property and 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// @synthesize declarations. 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//===----------------------------------------------------------------------===// 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Sema/SemaInternal.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Sema/Initialization.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/DeclObjC.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/ExprObjC.h" 198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "llvm/ADT/DenseSet.h" 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Grammar actions. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)/// Check the internal consistency of a property declaration. 28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) { 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (property->isInvalidDecl()) return; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ObjCPropertyDecl::PropertyAttributeKind propertyKind 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci = property->getPropertyAttributes(); 338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Qualifiers::ObjCLifetime propertyLifetime 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = property->getType().getObjCLifetime(); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Nothing to do if we don't have a lifetime. 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (propertyLifetime == Qualifiers::OCL_None) return; 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Qualifiers::ObjCLifetime expectedLifetime; 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) unsigned selector; 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Strong properties should have either strong or no lifetime. 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (propertyKind & (ObjCPropertyDecl::OBJC_PR_retain | 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ObjCPropertyDecl::OBJC_PR_strong | 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjCPropertyDecl::OBJC_PR_copy)) { 4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) expectedLifetime = Qualifiers::OCL_Strong; 4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) selector = 0; 4858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else if (propertyKind & ObjCPropertyDecl::OBJC_PR_weak) { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expectedLifetime = Qualifiers::OCL_Weak; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) selector = 1; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (propertyKind & (ObjCPropertyDecl::OBJC_PR_assign | 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjCPropertyDecl::OBJC_PR_unsafe_unretained) && 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) property->getType()->isObjCRetainableType()) { 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expectedLifetime = Qualifiers::OCL_ExplicitNone; 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) selector = 2; 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have a lifetime qualifier but no dominating property 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // attribute. That's okay. 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (propertyLifetime == expectedLifetime) return; 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) property->setInvalidDecl(); 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) S.Diag(property->getLocation(), 661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci diag::err_arc_inconsistent_property_ownership) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << property->getDeclName() 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << selector 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << propertyLifetime; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FieldDeclarator &FD, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjCDeclSpec &ODS, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Selector GetterSel, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Selector SetterSel, 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool *isOverridingProperty, 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tok::ObjCKeywordKind MethodImplKind, 795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DeclContext *lexicalDC) { 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) unsigned Attributes = ODS.getPropertyAttributes(); 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QualType T = TSI->getType(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((getLangOptions().getGCMode() != LangOptions::NonGC && 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T.isObjCGCWeak()) || 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (getLangOptions().ObjCAutoRefCount && 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) T.getObjCLifetime() == Qualifiers::OCL_Weak)) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Attributes |= ObjCDeclSpec::DQ_PR_weak; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default is readwrite! 915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // property is defaulted to 'assign' if it is readwrite and is 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not retain or copy 941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (isReadWrite && 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !(Attributes & ObjCDeclSpec::DQ_PR_retain) && 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(Attributes & ObjCDeclSpec::DQ_PR_strong) && 981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !(Attributes & ObjCDeclSpec::DQ_PR_copy) && 99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) && 100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch !(Attributes & ObjCDeclSpec::DQ_PR_weak))); 1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Proceed with constructing the ObjCPropertDecls. 103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext); 104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) 106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch if (CDecl->IsClassExtension()) { 107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Decl *Res = HandlePropertyInClassExtension(S, AtLoc, 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FD, GetterSel, SetterSel, 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) isAssign, isReadWrite, 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Attributes, 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) isOverridingProperty, TSI, 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) MethodImplKind); 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (Res) { 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CheckObjCPropertyAttributes(Res, AtLoc, Attributes); 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (getLangOptions().ObjCAutoRefCount) 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res)); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Res; 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetterSel, SetterSel, 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) isAssign, isReadWrite, 124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch Attributes, TSI, MethodImplKind); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lexicalDC) 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Res->setLexicalDeclContext(lexicalDC); 127 128 // Validate the attributes on the @property. 129 CheckObjCPropertyAttributes(Res, AtLoc, Attributes); 130 131 if (getLangOptions().ObjCAutoRefCount) 132 checkARCPropertyDecl(*this, Res); 133 134 return Res; 135} 136 137Decl * 138Sema::HandlePropertyInClassExtension(Scope *S, 139 SourceLocation AtLoc, FieldDeclarator &FD, 140 Selector GetterSel, Selector SetterSel, 141 const bool isAssign, 142 const bool isReadWrite, 143 const unsigned Attributes, 144 bool *isOverridingProperty, 145 TypeSourceInfo *T, 146 tok::ObjCKeywordKind MethodImplKind) { 147 ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext); 148 // Diagnose if this property is already in continuation class. 149 DeclContext *DC = CurContext; 150 IdentifierInfo *PropertyId = FD.D.getIdentifier(); 151 ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); 152 153 if (CCPrimary) 154 // Check for duplicate declaration of this property in current and 155 // other class extensions. 156 for (const ObjCCategoryDecl *ClsExtDecl = 157 CCPrimary->getFirstClassExtension(); 158 ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { 159 if (ObjCPropertyDecl *prevDecl = 160 ObjCPropertyDecl::findPropertyDecl(ClsExtDecl, PropertyId)) { 161 Diag(AtLoc, diag::err_duplicate_property); 162 Diag(prevDecl->getLocation(), diag::note_property_declare); 163 return 0; 164 } 165 } 166 167 // Create a new ObjCPropertyDecl with the DeclContext being 168 // the class extension. 169 // FIXME. We should really be using CreatePropertyDecl for this. 170 ObjCPropertyDecl *PDecl = 171 ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), 172 PropertyId, AtLoc, T); 173 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 174 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 175 if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) 176 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 177 // Set setter/getter selector name. Needed later. 178 PDecl->setGetterName(GetterSel); 179 PDecl->setSetterName(SetterSel); 180 ProcessDeclAttributes(S, PDecl, FD.D); 181 DC->addDecl(PDecl); 182 183 // We need to look in the @interface to see if the @property was 184 // already declared. 185 if (!CCPrimary) { 186 Diag(CDecl->getLocation(), diag::err_continuation_class); 187 *isOverridingProperty = true; 188 return 0; 189 } 190 191 // Find the property in continuation class's primary class only. 192 ObjCPropertyDecl *PIDecl = 193 CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); 194 195 if (!PIDecl) { 196 // No matching property found in the primary class. Just fall thru 197 // and add property to continuation class's primary class. 198 ObjCPropertyDecl *PDecl = 199 CreatePropertyDecl(S, CCPrimary, AtLoc, 200 FD, GetterSel, SetterSel, isAssign, isReadWrite, 201 Attributes, T, MethodImplKind, DC); 202 203 // A case of continuation class adding a new property in the class. This 204 // is not what it was meant for. However, gcc supports it and so should we. 205 // Make sure setter/getters are declared here. 206 ProcessPropertyDecl(PDecl, CCPrimary, /* redeclaredProperty = */ 0, 207 /* lexicalDC = */ CDecl); 208 return PDecl; 209 } 210 211 // The property 'PIDecl's readonly attribute will be over-ridden 212 // with continuation class's readwrite property attribute! 213 unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); 214 if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { 215 unsigned retainCopyNonatomic = 216 (ObjCPropertyDecl::OBJC_PR_retain | 217 ObjCPropertyDecl::OBJC_PR_strong | 218 ObjCPropertyDecl::OBJC_PR_copy | 219 ObjCPropertyDecl::OBJC_PR_nonatomic); 220 if ((Attributes & retainCopyNonatomic) != 221 (PIkind & retainCopyNonatomic)) { 222 Diag(AtLoc, diag::warn_property_attr_mismatch); 223 Diag(PIDecl->getLocation(), diag::note_property_declare); 224 } 225 DeclContext *DC = cast<DeclContext>(CCPrimary); 226 if (!ObjCPropertyDecl::findPropertyDecl(DC, 227 PIDecl->getDeclName().getAsIdentifierInfo())) { 228 // Protocol is not in the primary class. Must build one for it. 229 ObjCDeclSpec ProtocolPropertyODS; 230 // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind 231 // and ObjCPropertyDecl::PropertyAttributeKind have identical 232 // values. Should consolidate both into one enum type. 233 ProtocolPropertyODS. 234 setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) 235 PIkind); 236 // Must re-establish the context from class extension to primary 237 // class context. 238 ContextRAII SavedContext(*this, CCPrimary); 239 240 Decl *ProtocolPtrTy = 241 ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, 242 PIDecl->getGetterName(), 243 PIDecl->getSetterName(), 244 isOverridingProperty, 245 MethodImplKind, 246 /* lexicalDC = */ CDecl); 247 PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy); 248 } 249 PIDecl->makeitReadWriteAttribute(); 250 if (Attributes & ObjCDeclSpec::DQ_PR_retain) 251 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 252 if (Attributes & ObjCDeclSpec::DQ_PR_strong) 253 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 254 if (Attributes & ObjCDeclSpec::DQ_PR_copy) 255 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 256 PIDecl->setSetterName(SetterSel); 257 } else { 258 // Tailor the diagnostics for the common case where a readwrite 259 // property is declared both in the @interface and the continuation. 260 // This is a common error where the user often intended the original 261 // declaration to be readonly. 262 unsigned diag = 263 (Attributes & ObjCDeclSpec::DQ_PR_readwrite) && 264 (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) 265 ? diag::err_use_continuation_class_redeclaration_readwrite 266 : diag::err_use_continuation_class; 267 Diag(AtLoc, diag) 268 << CCPrimary->getDeclName(); 269 Diag(PIDecl->getLocation(), diag::note_property_declare); 270 } 271 *isOverridingProperty = true; 272 // Make sure setter decl is synthesized, and added to primary class's list. 273 ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl); 274 return 0; 275} 276 277ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, 278 ObjCContainerDecl *CDecl, 279 SourceLocation AtLoc, 280 FieldDeclarator &FD, 281 Selector GetterSel, 282 Selector SetterSel, 283 const bool isAssign, 284 const bool isReadWrite, 285 const unsigned Attributes, 286 TypeSourceInfo *TInfo, 287 tok::ObjCKeywordKind MethodImplKind, 288 DeclContext *lexicalDC){ 289 IdentifierInfo *PropertyId = FD.D.getIdentifier(); 290 QualType T = TInfo->getType(); 291 292 // Issue a warning if property is 'assign' as default and its object, which is 293 // gc'able conforms to NSCopying protocol 294 if (getLangOptions().getGCMode() != LangOptions::NonGC && 295 isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) 296 if (const ObjCObjectPointerType *ObjPtrTy = 297 T->getAs<ObjCObjectPointerType>()) { 298 ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); 299 if (IDecl) 300 if (ObjCProtocolDecl* PNSCopying = 301 LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) 302 if (IDecl->ClassImplementsProtocol(PNSCopying, true)) 303 Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; 304 } 305 if (T->isObjCObjectType()) 306 Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object); 307 308 DeclContext *DC = cast<DeclContext>(CDecl); 309 ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, 310 FD.D.getIdentifierLoc(), 311 PropertyId, AtLoc, TInfo); 312 313 if (ObjCPropertyDecl *prevDecl = 314 ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { 315 Diag(PDecl->getLocation(), diag::err_duplicate_property); 316 Diag(prevDecl->getLocation(), diag::note_property_declare); 317 PDecl->setInvalidDecl(); 318 } 319 else { 320 DC->addDecl(PDecl); 321 if (lexicalDC) 322 PDecl->setLexicalDeclContext(lexicalDC); 323 } 324 325 if (T->isArrayType() || T->isFunctionType()) { 326 Diag(AtLoc, diag::err_property_type) << T; 327 PDecl->setInvalidDecl(); 328 } 329 330 ProcessDeclAttributes(S, PDecl, FD.D); 331 332 // Regardless of setter/getter attribute, we save the default getter/setter 333 // selector names in anticipation of declaration of setter/getter methods. 334 PDecl->setGetterName(GetterSel); 335 PDecl->setSetterName(SetterSel); 336 337 unsigned attributesAsWritten = 0; 338 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 339 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly; 340 if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) 341 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite; 342 if (Attributes & ObjCDeclSpec::DQ_PR_getter) 343 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter; 344 if (Attributes & ObjCDeclSpec::DQ_PR_setter) 345 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter; 346 if (Attributes & ObjCDeclSpec::DQ_PR_assign) 347 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign; 348 if (Attributes & ObjCDeclSpec::DQ_PR_retain) 349 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain; 350 if (Attributes & ObjCDeclSpec::DQ_PR_strong) 351 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong; 352 if (Attributes & ObjCDeclSpec::DQ_PR_weak) 353 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak; 354 if (Attributes & ObjCDeclSpec::DQ_PR_copy) 355 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy; 356 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 357 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained; 358 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 359 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic; 360 if (Attributes & ObjCDeclSpec::DQ_PR_atomic) 361 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic; 362 363 PDecl->setPropertyAttributesAsWritten( 364 (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten); 365 366 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 367 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 368 369 if (Attributes & ObjCDeclSpec::DQ_PR_getter) 370 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter); 371 372 if (Attributes & ObjCDeclSpec::DQ_PR_setter) 373 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter); 374 375 if (isReadWrite) 376 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 377 378 if (Attributes & ObjCDeclSpec::DQ_PR_retain) 379 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 380 381 if (Attributes & ObjCDeclSpec::DQ_PR_strong) 382 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 383 384 if (Attributes & ObjCDeclSpec::DQ_PR_weak) 385 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak); 386 387 if (Attributes & ObjCDeclSpec::DQ_PR_copy) 388 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 389 390 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 391 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained); 392 393 if (isAssign) 394 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); 395 396 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 397 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); 398 else if (Attributes & ObjCDeclSpec::DQ_PR_atomic) 399 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic); 400 401 // 'unsafe_unretained' is alias for 'assign'. 402 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) 403 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); 404 if (isAssign) 405 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained); 406 407 if (MethodImplKind == tok::objc_required) 408 PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); 409 else if (MethodImplKind == tok::objc_optional) 410 PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); 411 412 return PDecl; 413} 414 415static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, 416 ObjCPropertyDecl *property, 417 ObjCIvarDecl *ivar) { 418 if (property->isInvalidDecl() || ivar->isInvalidDecl()) return; 419 420 QualType propertyType = property->getType(); 421 Qualifiers::ObjCLifetime propertyLifetime = propertyType.getObjCLifetime(); 422 ObjCPropertyDecl::PropertyAttributeKind propertyKind 423 = property->getPropertyAttributes(); 424 425 QualType ivarType = ivar->getType(); 426 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); 427 428 // Case 1: strong properties. 429 if (propertyLifetime == Qualifiers::OCL_Strong || 430 (propertyKind & (ObjCPropertyDecl::OBJC_PR_retain | 431 ObjCPropertyDecl::OBJC_PR_strong | 432 ObjCPropertyDecl::OBJC_PR_copy))) { 433 switch (ivarLifetime) { 434 case Qualifiers::OCL_Strong: 435 // Okay. 436 return; 437 438 case Qualifiers::OCL_None: 439 case Qualifiers::OCL_Autoreleasing: 440 // These aren't valid lifetimes for object ivars; don't diagnose twice. 441 return; 442 443 case Qualifiers::OCL_ExplicitNone: 444 case Qualifiers::OCL_Weak: 445 S.Diag(propertyImplLoc, diag::err_arc_strong_property_ownership) 446 << property->getDeclName() 447 << ivar->getDeclName() 448 << ivarLifetime; 449 break; 450 } 451 452 // Case 2: weak properties. 453 } else if (propertyLifetime == Qualifiers::OCL_Weak || 454 (propertyKind & ObjCPropertyDecl::OBJC_PR_weak)) { 455 switch (ivarLifetime) { 456 case Qualifiers::OCL_Weak: 457 // Okay. 458 return; 459 460 case Qualifiers::OCL_None: 461 case Qualifiers::OCL_Autoreleasing: 462 // These aren't valid lifetimes for object ivars; don't diagnose twice. 463 return; 464 465 case Qualifiers::OCL_ExplicitNone: 466 case Qualifiers::OCL_Strong: 467 S.Diag(propertyImplLoc, diag::error_weak_property) 468 << property->getDeclName() 469 << ivar->getDeclName(); 470 break; 471 } 472 473 // Case 3: assign properties. 474 } else if ((propertyKind & ObjCPropertyDecl::OBJC_PR_assign) && 475 propertyType->isObjCRetainableType()) { 476 switch (ivarLifetime) { 477 case Qualifiers::OCL_ExplicitNone: 478 // Okay. 479 return; 480 481 case Qualifiers::OCL_None: 482 case Qualifiers::OCL_Autoreleasing: 483 // These aren't valid lifetimes for object ivars; don't diagnose twice. 484 return; 485 486 case Qualifiers::OCL_Weak: 487 case Qualifiers::OCL_Strong: 488 S.Diag(propertyImplLoc, diag::err_arc_assign_property_ownership) 489 << property->getDeclName() 490 << ivar->getDeclName(); 491 break; 492 } 493 494 // Any other property should be ignored. 495 } else { 496 return; 497 } 498 499 S.Diag(property->getLocation(), diag::note_property_declare); 500} 501 502 503/// ActOnPropertyImplDecl - This routine performs semantic checks and 504/// builds the AST node for a property implementation declaration; declared 505/// as @synthesize or @dynamic. 506/// 507Decl *Sema::ActOnPropertyImplDecl(Scope *S, 508 SourceLocation AtLoc, 509 SourceLocation PropertyLoc, 510 bool Synthesize, 511 IdentifierInfo *PropertyId, 512 IdentifierInfo *PropertyIvar, 513 SourceLocation PropertyIvarLoc) { 514 ObjCContainerDecl *ClassImpDecl = 515 cast_or_null<ObjCContainerDecl>(CurContext); 516 // Make sure we have a context for the property implementation declaration. 517 if (!ClassImpDecl) { 518 Diag(AtLoc, diag::error_missing_property_context); 519 return 0; 520 } 521 ObjCPropertyDecl *property = 0; 522 ObjCInterfaceDecl* IDecl = 0; 523 // Find the class or category class where this property must have 524 // a declaration. 525 ObjCImplementationDecl *IC = 0; 526 ObjCCategoryImplDecl* CatImplClass = 0; 527 if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) { 528 IDecl = IC->getClassInterface(); 529 // We always synthesize an interface for an implementation 530 // without an interface decl. So, IDecl is always non-zero. 531 assert(IDecl && 532 "ActOnPropertyImplDecl - @implementation without @interface"); 533 534 // Look for this property declaration in the @implementation's @interface 535 property = IDecl->FindPropertyDeclaration(PropertyId); 536 if (!property) { 537 Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); 538 return 0; 539 } 540 unsigned PIkind = property->getPropertyAttributesAsWritten(); 541 if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic | 542 ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) { 543 if (AtLoc.isValid()) 544 Diag(AtLoc, diag::warn_implicit_atomic_property); 545 else 546 Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property); 547 Diag(property->getLocation(), diag::note_property_declare); 548 } 549 550 if (const ObjCCategoryDecl *CD = 551 dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { 552 if (!CD->IsClassExtension()) { 553 Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); 554 Diag(property->getLocation(), diag::note_property_declare); 555 return 0; 556 } 557 } 558 } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { 559 if (Synthesize) { 560 Diag(AtLoc, diag::error_synthesize_category_decl); 561 return 0; 562 } 563 IDecl = CatImplClass->getClassInterface(); 564 if (!IDecl) { 565 Diag(AtLoc, diag::error_missing_property_interface); 566 return 0; 567 } 568 ObjCCategoryDecl *Category = 569 IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); 570 571 // If category for this implementation not found, it is an error which 572 // has already been reported eralier. 573 if (!Category) 574 return 0; 575 // Look for this property declaration in @implementation's category 576 property = Category->FindPropertyDeclaration(PropertyId); 577 if (!property) { 578 Diag(PropertyLoc, diag::error_bad_category_property_decl) 579 << Category->getDeclName(); 580 return 0; 581 } 582 } else { 583 Diag(AtLoc, diag::error_bad_property_context); 584 return 0; 585 } 586 ObjCIvarDecl *Ivar = 0; 587 // Check that we have a valid, previously declared ivar for @synthesize 588 if (Synthesize) { 589 // @synthesize 590 if (!PropertyIvar) 591 PropertyIvar = PropertyId; 592 ObjCPropertyDecl::PropertyAttributeKind kind 593 = property->getPropertyAttributes(); 594 QualType PropType = Context.getCanonicalType(property->getType()); 595 QualType PropertyIvarType = PropType; 596 if (PropType->isReferenceType()) 597 PropertyIvarType = cast<ReferenceType>(PropType)->getPointeeType(); 598 // Check that this is a previously declared 'ivar' in 'IDecl' interface 599 ObjCInterfaceDecl *ClassDeclared; 600 Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); 601 if (!Ivar) { 602 // In ARC, give the ivar a lifetime qualifier based on its 603 // property attributes. 604 if (getLangOptions().ObjCAutoRefCount && 605 !PropertyIvarType.getObjCLifetime()) { 606 607 if (!property->hasWrittenStorageAttribute() && 608 property->getType()->isObjCRetainableType() && 609 !(kind & ObjCPropertyDecl::OBJC_PR_strong) ) { 610 Diag(PropertyLoc, 611 diag::err_arc_objc_property_default_assign_on_object); 612 Diag(property->getLocation(), diag::note_property_declare); 613 } 614 615 // retain/copy have retaining lifetime. 616 if (kind & (ObjCPropertyDecl::OBJC_PR_retain | 617 ObjCPropertyDecl::OBJC_PR_strong | 618 ObjCPropertyDecl::OBJC_PR_copy)) { 619 Qualifiers qs; 620 qs.addObjCLifetime(Qualifiers::OCL_Strong); 621 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 622 } 623 else if (kind & ObjCPropertyDecl::OBJC_PR_weak) { 624 if (!getLangOptions().ObjCRuntimeHasWeak) { 625 Diag(PropertyLoc, diag::err_arc_weak_no_runtime); 626 Diag(property->getLocation(), diag::note_property_declare); 627 } 628 Qualifiers qs; 629 qs.addObjCLifetime(Qualifiers::OCL_Weak); 630 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 631 } 632 else if (kind & ObjCPropertyDecl::OBJC_PR_assign && 633 PropertyIvarType->isObjCRetainableType()) { 634 // assume that an 'assign' property synthesizes __unsafe_unretained 635 // ivar 636 Qualifiers qs; 637 qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone); 638 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 639 } 640 } 641 642 if (kind & ObjCPropertyDecl::OBJC_PR_weak && 643 !getLangOptions().ObjCAutoRefCount && 644 getLangOptions().getGCMode() == LangOptions::NonGC) { 645 Diag(PropertyLoc, diag::error_synthesize_weak_non_arc_or_gc); 646 Diag(property->getLocation(), diag::note_property_declare); 647 } 648 649 Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, 650 PropertyLoc, PropertyLoc, PropertyIvar, 651 PropertyIvarType, /*Dinfo=*/0, 652 ObjCIvarDecl::Private, 653 (Expr *)0, true); 654 ClassImpDecl->addDecl(Ivar); 655 IDecl->makeDeclVisibleInContext(Ivar, false); 656 property->setPropertyIvarDecl(Ivar); 657 658 if (!getLangOptions().ObjCNonFragileABI) 659 Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId; 660 // Note! I deliberately want it to fall thru so, we have a 661 // a property implementation and to avoid future warnings. 662 } else if (getLangOptions().ObjCNonFragileABI && 663 ClassDeclared != IDecl) { 664 Diag(PropertyLoc, diag::error_ivar_in_superclass_use) 665 << property->getDeclName() << Ivar->getDeclName() 666 << ClassDeclared->getDeclName(); 667 Diag(Ivar->getLocation(), diag::note_previous_access_declaration) 668 << Ivar << Ivar->getName(); 669 // Note! I deliberately want it to fall thru so more errors are caught. 670 } 671 QualType IvarType = Context.getCanonicalType(Ivar->getType()); 672 673 // Check that type of property and its ivar are type compatible. 674 if (PropertyIvarType != IvarType) { 675 bool compat = false; 676 if (isa<ObjCObjectPointerType>(PropertyIvarType) 677 && isa<ObjCObjectPointerType>(IvarType)) 678 compat = 679 Context.canAssignObjCInterfaces( 680 PropertyIvarType->getAs<ObjCObjectPointerType>(), 681 IvarType->getAs<ObjCObjectPointerType>()); 682 else { 683 SourceLocation Loc = PropertyIvarLoc; 684 if (Loc.isInvalid()) 685 Loc = PropertyLoc; 686 compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType) 687 == Compatible); 688 } 689 if (!compat) { 690 Diag(PropertyLoc, diag::error_property_ivar_type) 691 << property->getDeclName() << PropType 692 << Ivar->getDeclName() << IvarType; 693 Diag(Ivar->getLocation(), diag::note_ivar_decl); 694 // Note! I deliberately want it to fall thru so, we have a 695 // a property implementation and to avoid future warnings. 696 } 697 698 // FIXME! Rules for properties are somewhat different that those 699 // for assignments. Use a new routine to consolidate all cases; 700 // specifically for property redeclarations as well as for ivars. 701 QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); 702 QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); 703 if (lhsType != rhsType && 704 lhsType->isArithmeticType()) { 705 Diag(PropertyLoc, diag::error_property_ivar_type) 706 << property->getDeclName() << PropType 707 << Ivar->getDeclName() << IvarType; 708 Diag(Ivar->getLocation(), diag::note_ivar_decl); 709 // Fall thru - see previous comment 710 } 711 // __weak is explicit. So it works on Canonical type. 712 if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && 713 getLangOptions().getGCMode() != LangOptions::NonGC)) { 714 Diag(PropertyLoc, diag::error_weak_property) 715 << property->getDeclName() << Ivar->getDeclName(); 716 // Fall thru - see previous comment 717 } 718 // Fall thru - see previous comment 719 if ((property->getType()->isObjCObjectPointerType() || 720 PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && 721 getLangOptions().getGCMode() != LangOptions::NonGC) { 722 Diag(PropertyLoc, diag::error_strong_property) 723 << property->getDeclName() << Ivar->getDeclName(); 724 // Fall thru - see previous comment 725 } 726 } 727 if (getLangOptions().ObjCAutoRefCount) 728 checkARCPropertyImpl(*this, PropertyLoc, property, Ivar); 729 } else if (PropertyIvar) 730 // @dynamic 731 Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl); 732 733 assert (property && "ActOnPropertyImplDecl - property declaration missing"); 734 ObjCPropertyImplDecl *PIDecl = 735 ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, 736 property, 737 (Synthesize ? 738 ObjCPropertyImplDecl::Synthesize 739 : ObjCPropertyImplDecl::Dynamic), 740 Ivar, PropertyIvarLoc); 741 if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { 742 getterMethod->createImplicitParams(Context, IDecl); 743 if (getLangOptions().CPlusPlus && Synthesize && 744 Ivar->getType()->isRecordType()) { 745 // For Objective-C++, need to synthesize the AST for the IVAR object to be 746 // returned by the getter as it must conform to C++'s copy-return rules. 747 // FIXME. Eventually we want to do this for Objective-C as well. 748 ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); 749 DeclRefExpr *SelfExpr = 750 new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(), 751 VK_RValue, SourceLocation()); 752 Expr *IvarRefExpr = 753 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, 754 SelfExpr, true, true); 755 ExprResult Res = 756 PerformCopyInitialization(InitializedEntity::InitializeResult( 757 SourceLocation(), 758 getterMethod->getResultType(), 759 /*NRVO=*/false), 760 SourceLocation(), 761 Owned(IvarRefExpr)); 762 if (!Res.isInvalid()) { 763 Expr *ResExpr = Res.takeAs<Expr>(); 764 if (ResExpr) 765 ResExpr = MaybeCreateExprWithCleanups(ResExpr); 766 PIDecl->setGetterCXXConstructor(ResExpr); 767 } 768 } 769 if (property->hasAttr<NSReturnsNotRetainedAttr>() && 770 !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) { 771 Diag(getterMethod->getLocation(), 772 diag::warn_property_getter_owning_mismatch); 773 Diag(property->getLocation(), diag::note_property_declare); 774 } 775 } 776 if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { 777 setterMethod->createImplicitParams(Context, IDecl); 778 if (getLangOptions().CPlusPlus && Synthesize 779 && Ivar->getType()->isRecordType()) { 780 // FIXME. Eventually we want to do this for Objective-C as well. 781 ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); 782 DeclRefExpr *SelfExpr = 783 new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(), 784 VK_RValue, SourceLocation()); 785 Expr *lhs = 786 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, 787 SelfExpr, true, true); 788 ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); 789 ParmVarDecl *Param = (*P); 790 QualType T = Param->getType(); 791 if (T->isReferenceType()) 792 T = T->getAs<ReferenceType>()->getPointeeType(); 793 Expr *rhs = new (Context) DeclRefExpr(Param, T, 794 VK_LValue, SourceLocation()); 795 ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), 796 BO_Assign, lhs, rhs); 797 PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>()); 798 } 799 } 800 801 if (IC) { 802 if (Synthesize) 803 if (ObjCPropertyImplDecl *PPIDecl = 804 IC->FindPropertyImplIvarDecl(PropertyIvar)) { 805 Diag(PropertyLoc, diag::error_duplicate_ivar_use) 806 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 807 << PropertyIvar; 808 Diag(PPIDecl->getLocation(), diag::note_previous_use); 809 } 810 811 if (ObjCPropertyImplDecl *PPIDecl 812 = IC->FindPropertyImplDecl(PropertyId)) { 813 Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 814 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 815 return 0; 816 } 817 IC->addPropertyImplementation(PIDecl); 818 if (getLangOptions().ObjCDefaultSynthProperties && 819 getLangOptions().ObjCNonFragileABI2) { 820 // Diagnose if an ivar was lazily synthesdized due to a previous 821 // use and if 1) property is @dynamic or 2) property is synthesized 822 // but it requires an ivar of different name. 823 ObjCInterfaceDecl *ClassDeclared=0; 824 ObjCIvarDecl *Ivar = 0; 825 if (!Synthesize) 826 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 827 else { 828 if (PropertyIvar && PropertyIvar != PropertyId) 829 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 830 } 831 // Issue diagnostics only if Ivar belongs to current class. 832 if (Ivar && Ivar->getSynthesize() && 833 IC->getClassInterface() == ClassDeclared) { 834 Diag(Ivar->getLocation(), diag::err_undeclared_var_use) 835 << PropertyId; 836 Ivar->setInvalidDecl(); 837 } 838 } 839 } else { 840 if (Synthesize) 841 if (ObjCPropertyImplDecl *PPIDecl = 842 CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { 843 Diag(PropertyLoc, diag::error_duplicate_ivar_use) 844 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 845 << PropertyIvar; 846 Diag(PPIDecl->getLocation(), diag::note_previous_use); 847 } 848 849 if (ObjCPropertyImplDecl *PPIDecl = 850 CatImplClass->FindPropertyImplDecl(PropertyId)) { 851 Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 852 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 853 return 0; 854 } 855 CatImplClass->addPropertyImplementation(PIDecl); 856 } 857 858 return PIDecl; 859} 860 861//===----------------------------------------------------------------------===// 862// Helper methods. 863//===----------------------------------------------------------------------===// 864 865/// DiagnosePropertyMismatch - Compares two properties for their 866/// attributes and types and warns on a variety of inconsistencies. 867/// 868void 869Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 870 ObjCPropertyDecl *SuperProperty, 871 const IdentifierInfo *inheritedName) { 872 ObjCPropertyDecl::PropertyAttributeKind CAttr = 873 Property->getPropertyAttributes(); 874 ObjCPropertyDecl::PropertyAttributeKind SAttr = 875 SuperProperty->getPropertyAttributes(); 876 if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) 877 && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) 878 Diag(Property->getLocation(), diag::warn_readonly_property) 879 << Property->getDeclName() << inheritedName; 880 if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) 881 != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) 882 Diag(Property->getLocation(), diag::warn_property_attribute) 883 << Property->getDeclName() << "copy" << inheritedName; 884 else { 885 unsigned CAttrRetain = 886 (CAttr & 887 (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); 888 unsigned SAttrRetain = 889 (SAttr & 890 (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); 891 bool CStrong = (CAttrRetain != 0); 892 bool SStrong = (SAttrRetain != 0); 893 if (CStrong != SStrong) 894 Diag(Property->getLocation(), diag::warn_property_attribute) 895 << Property->getDeclName() << "retain (or strong)" << inheritedName; 896 } 897 898 if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) 899 != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) 900 Diag(Property->getLocation(), diag::warn_property_attribute) 901 << Property->getDeclName() << "atomic" << inheritedName; 902 if (Property->getSetterName() != SuperProperty->getSetterName()) 903 Diag(Property->getLocation(), diag::warn_property_attribute) 904 << Property->getDeclName() << "setter" << inheritedName; 905 if (Property->getGetterName() != SuperProperty->getGetterName()) 906 Diag(Property->getLocation(), diag::warn_property_attribute) 907 << Property->getDeclName() << "getter" << inheritedName; 908 909 QualType LHSType = 910 Context.getCanonicalType(SuperProperty->getType()); 911 QualType RHSType = 912 Context.getCanonicalType(Property->getType()); 913 914 if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) { 915 // Do cases not handled in above. 916 // FIXME. For future support of covariant property types, revisit this. 917 bool IncompatibleObjC = false; 918 QualType ConvertedType; 919 if (!isObjCPointerConversion(RHSType, LHSType, 920 ConvertedType, IncompatibleObjC) || 921 IncompatibleObjC) 922 Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) 923 << Property->getType() << SuperProperty->getType() << inheritedName; 924 } 925} 926 927bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 928 ObjCMethodDecl *GetterMethod, 929 SourceLocation Loc) { 930 if (GetterMethod && 931 GetterMethod->getResultType() != property->getType()) { 932 AssignConvertType result = Incompatible; 933 if (property->getType()->isObjCObjectPointerType()) 934 result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(), 935 property->getType()); 936 if (result != Compatible) { 937 Diag(Loc, diag::warn_accessor_property_type_mismatch) 938 << property->getDeclName() 939 << GetterMethod->getSelector(); 940 Diag(GetterMethod->getLocation(), diag::note_declared_at); 941 return true; 942 } 943 } 944 return false; 945} 946 947/// ComparePropertiesInBaseAndSuper - This routine compares property 948/// declarations in base and its super class, if any, and issues 949/// diagnostics in a variety of inconsistent situations. 950/// 951void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { 952 ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); 953 if (!SDecl) 954 return; 955 // FIXME: O(N^2) 956 for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(), 957 E = SDecl->prop_end(); S != E; ++S) { 958 ObjCPropertyDecl *SuperPDecl = (*S); 959 // Does property in super class has declaration in current class? 960 for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(), 961 E = IDecl->prop_end(); I != E; ++I) { 962 ObjCPropertyDecl *PDecl = (*I); 963 if (SuperPDecl->getIdentifier() == PDecl->getIdentifier()) 964 DiagnosePropertyMismatch(PDecl, SuperPDecl, 965 SDecl->getIdentifier()); 966 } 967 } 968} 969 970/// MatchOneProtocolPropertiesInClass - This routine goes thru the list 971/// of properties declared in a protocol and compares their attribute against 972/// the same property declared in the class or category. 973void 974Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, 975 ObjCProtocolDecl *PDecl) { 976 ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); 977 if (!IDecl) { 978 // Category 979 ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); 980 assert (CatDecl && "MatchOneProtocolPropertiesInClass"); 981 if (!CatDecl->IsClassExtension()) 982 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 983 E = PDecl->prop_end(); P != E; ++P) { 984 ObjCPropertyDecl *Pr = (*P); 985 ObjCCategoryDecl::prop_iterator CP, CE; 986 // Is this property already in category's list of properties? 987 for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP) 988 if ((*CP)->getIdentifier() == Pr->getIdentifier()) 989 break; 990 if (CP != CE) 991 // Property protocol already exist in class. Diagnose any mismatch. 992 DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); 993 } 994 return; 995 } 996 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 997 E = PDecl->prop_end(); P != E; ++P) { 998 ObjCPropertyDecl *Pr = (*P); 999 ObjCInterfaceDecl::prop_iterator CP, CE; 1000 // Is this property already in class's list of properties? 1001 for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP) 1002 if ((*CP)->getIdentifier() == Pr->getIdentifier()) 1003 break; 1004 if (CP != CE) 1005 // Property protocol already exist in class. Diagnose any mismatch. 1006 DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); 1007 } 1008} 1009 1010/// CompareProperties - This routine compares properties 1011/// declared in 'ClassOrProtocol' objects (which can be a class or an 1012/// inherited protocol with the list of properties for class/category 'CDecl' 1013/// 1014void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) { 1015 Decl *ClassDecl = ClassOrProtocol; 1016 ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); 1017 1018 if (!IDecl) { 1019 // Category 1020 ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); 1021 assert (CatDecl && "CompareProperties"); 1022 if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 1023 for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(), 1024 E = MDecl->protocol_end(); P != E; ++P) 1025 // Match properties of category with those of protocol (*P) 1026 MatchOneProtocolPropertiesInClass(CatDecl, *P); 1027 1028 // Go thru the list of protocols for this category and recursively match 1029 // their properties with those in the category. 1030 for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(), 1031 E = CatDecl->protocol_end(); P != E; ++P) 1032 CompareProperties(CatDecl, *P); 1033 } else { 1034 ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); 1035 for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), 1036 E = MD->protocol_end(); P != E; ++P) 1037 MatchOneProtocolPropertiesInClass(CatDecl, *P); 1038 } 1039 return; 1040 } 1041 1042 if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { 1043 for (ObjCInterfaceDecl::all_protocol_iterator 1044 P = MDecl->all_referenced_protocol_begin(), 1045 E = MDecl->all_referenced_protocol_end(); P != E; ++P) 1046 // Match properties of class IDecl with those of protocol (*P). 1047 MatchOneProtocolPropertiesInClass(IDecl, *P); 1048 1049 // Go thru the list of protocols for this class and recursively match 1050 // their properties with those declared in the class. 1051 for (ObjCInterfaceDecl::all_protocol_iterator 1052 P = IDecl->all_referenced_protocol_begin(), 1053 E = IDecl->all_referenced_protocol_end(); P != E; ++P) 1054 CompareProperties(IDecl, *P); 1055 } else { 1056 ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); 1057 for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), 1058 E = MD->protocol_end(); P != E; ++P) 1059 MatchOneProtocolPropertiesInClass(IDecl, *P); 1060 } 1061} 1062 1063/// isPropertyReadonly - Return true if property is readonly, by searching 1064/// for the property in the class and in its categories and implementations 1065/// 1066bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, 1067 ObjCInterfaceDecl *IDecl) { 1068 // by far the most common case. 1069 if (!PDecl->isReadOnly()) 1070 return false; 1071 // Even if property is ready only, if interface has a user defined setter, 1072 // it is not considered read only. 1073 if (IDecl->getInstanceMethod(PDecl->getSetterName())) 1074 return false; 1075 1076 // Main class has the property as 'readonly'. Must search 1077 // through the category list to see if the property's 1078 // attribute has been over-ridden to 'readwrite'. 1079 for (ObjCCategoryDecl *Category = IDecl->getCategoryList(); 1080 Category; Category = Category->getNextClassCategory()) { 1081 // Even if property is ready only, if a category has a user defined setter, 1082 // it is not considered read only. 1083 if (Category->getInstanceMethod(PDecl->getSetterName())) 1084 return false; 1085 ObjCPropertyDecl *P = 1086 Category->FindPropertyDeclaration(PDecl->getIdentifier()); 1087 if (P && !P->isReadOnly()) 1088 return false; 1089 } 1090 1091 // Also, check for definition of a setter method in the implementation if 1092 // all else failed. 1093 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) { 1094 if (ObjCImplementationDecl *IMD = 1095 dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) { 1096 if (IMD->getInstanceMethod(PDecl->getSetterName())) 1097 return false; 1098 } else if (ObjCCategoryImplDecl *CIMD = 1099 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 1100 if (CIMD->getInstanceMethod(PDecl->getSetterName())) 1101 return false; 1102 } 1103 } 1104 // Lastly, look through the implementation (if one is in scope). 1105 if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation()) 1106 if (ImpDecl->getInstanceMethod(PDecl->getSetterName())) 1107 return false; 1108 // If all fails, look at the super class. 1109 if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass()) 1110 return isPropertyReadonly(PDecl, SIDecl); 1111 return true; 1112} 1113 1114/// CollectImmediateProperties - This routine collects all properties in 1115/// the class and its conforming protocols; but not those it its super class. 1116void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, 1117 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, 1118 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) { 1119 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 1120 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 1121 E = IDecl->prop_end(); P != E; ++P) { 1122 ObjCPropertyDecl *Prop = (*P); 1123 PropMap[Prop->getIdentifier()] = Prop; 1124 } 1125 // scan through class's protocols. 1126 for (ObjCInterfaceDecl::all_protocol_iterator 1127 PI = IDecl->all_referenced_protocol_begin(), 1128 E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) 1129 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 1130 } 1131 if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { 1132 if (!CATDecl->IsClassExtension()) 1133 for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), 1134 E = CATDecl->prop_end(); P != E; ++P) { 1135 ObjCPropertyDecl *Prop = (*P); 1136 PropMap[Prop->getIdentifier()] = Prop; 1137 } 1138 // scan through class's protocols. 1139 for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(), 1140 E = CATDecl->protocol_end(); PI != E; ++PI) 1141 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 1142 } 1143 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 1144 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 1145 E = PDecl->prop_end(); P != E; ++P) { 1146 ObjCPropertyDecl *Prop = (*P); 1147 ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; 1148 // Exclude property for protocols which conform to class's super-class, 1149 // as super-class has to implement the property. 1150 if (!PropertyFromSuper || PropertyFromSuper != Prop) { 1151 ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; 1152 if (!PropEntry) 1153 PropEntry = Prop; 1154 } 1155 } 1156 // scan through protocol's protocols. 1157 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 1158 E = PDecl->protocol_end(); PI != E; ++PI) 1159 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 1160 } 1161} 1162 1163/// CollectClassPropertyImplementations - This routine collects list of 1164/// properties to be implemented in the class. This includes, class's 1165/// and its conforming protocols' properties. 1166static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl, 1167 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { 1168 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 1169 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 1170 E = IDecl->prop_end(); P != E; ++P) { 1171 ObjCPropertyDecl *Prop = (*P); 1172 PropMap[Prop->getIdentifier()] = Prop; 1173 } 1174 for (ObjCInterfaceDecl::all_protocol_iterator 1175 PI = IDecl->all_referenced_protocol_begin(), 1176 E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) 1177 CollectClassPropertyImplementations((*PI), PropMap); 1178 } 1179 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 1180 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 1181 E = PDecl->prop_end(); P != E; ++P) { 1182 ObjCPropertyDecl *Prop = (*P); 1183 PropMap[Prop->getIdentifier()] = Prop; 1184 } 1185 // scan through protocol's protocols. 1186 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 1187 E = PDecl->protocol_end(); PI != E; ++PI) 1188 CollectClassPropertyImplementations((*PI), PropMap); 1189 } 1190} 1191 1192/// CollectSuperClassPropertyImplementations - This routine collects list of 1193/// properties to be implemented in super class(s) and also coming from their 1194/// conforming protocols. 1195static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, 1196 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { 1197 if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { 1198 while (SDecl) { 1199 CollectClassPropertyImplementations(SDecl, PropMap); 1200 SDecl = SDecl->getSuperClass(); 1201 } 1202 } 1203} 1204 1205/// LookupPropertyDecl - Looks up a property in the current class and all 1206/// its protocols. 1207ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, 1208 IdentifierInfo *II) { 1209 if (const ObjCInterfaceDecl *IDecl = 1210 dyn_cast<ObjCInterfaceDecl>(CDecl)) { 1211 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 1212 E = IDecl->prop_end(); P != E; ++P) { 1213 ObjCPropertyDecl *Prop = (*P); 1214 if (Prop->getIdentifier() == II) 1215 return Prop; 1216 } 1217 // scan through class's protocols. 1218 for (ObjCInterfaceDecl::all_protocol_iterator 1219 PI = IDecl->all_referenced_protocol_begin(), 1220 E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) { 1221 ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 1222 if (Prop) 1223 return Prop; 1224 } 1225 } 1226 else if (const ObjCProtocolDecl *PDecl = 1227 dyn_cast<ObjCProtocolDecl>(CDecl)) { 1228 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 1229 E = PDecl->prop_end(); P != E; ++P) { 1230 ObjCPropertyDecl *Prop = (*P); 1231 if (Prop->getIdentifier() == II) 1232 return Prop; 1233 } 1234 // scan through protocol's protocols. 1235 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 1236 E = PDecl->protocol_end(); PI != E; ++PI) { 1237 ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 1238 if (Prop) 1239 return Prop; 1240 } 1241 } 1242 return 0; 1243} 1244 1245/// DefaultSynthesizeProperties - This routine default synthesizes all 1246/// properties which must be synthesized in class's @implementation. 1247void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, 1248 ObjCInterfaceDecl *IDecl) { 1249 1250 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; 1251 CollectClassPropertyImplementations(IDecl, PropMap); 1252 if (PropMap.empty()) 1253 return; 1254 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; 1255 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 1256 1257 for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 1258 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 1259 ObjCPropertyDecl *Prop = P->second; 1260 // If property to be implemented in the super class, ignore. 1261 if (SuperPropMap[Prop->getIdentifier()]) 1262 continue; 1263 // Is there a matching propery synthesize/dynamic? 1264 if (Prop->isInvalidDecl() || 1265 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 1266 IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) 1267 continue; 1268 // Property may have been synthesized by user. 1269 if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) 1270 continue; 1271 if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { 1272 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) 1273 continue; 1274 if (IMPDecl->getInstanceMethod(Prop->getSetterName())) 1275 continue; 1276 } 1277 1278 1279 // We use invalid SourceLocations for the synthesized ivars since they 1280 // aren't really synthesized at a particular location; they just exist. 1281 // Saying that they are located at the @implementation isn't really going 1282 // to help users. 1283 ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), 1284 true, 1285 Prop->getIdentifier(), Prop->getIdentifier(), 1286 SourceLocation()); 1287 } 1288} 1289 1290void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, 1291 ObjCContainerDecl *CDecl, 1292 const llvm::DenseSet<Selector>& InsMap) { 1293 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; 1294 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) 1295 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 1296 1297 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; 1298 CollectImmediateProperties(CDecl, PropMap, SuperPropMap); 1299 if (PropMap.empty()) 1300 return; 1301 1302 llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; 1303 for (ObjCImplDecl::propimpl_iterator 1304 I = IMPDecl->propimpl_begin(), 1305 EI = IMPDecl->propimpl_end(); I != EI; ++I) 1306 PropImplMap.insert((*I)->getPropertyDecl()); 1307 1308 for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 1309 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 1310 ObjCPropertyDecl *Prop = P->second; 1311 // Is there a matching propery synthesize/dynamic? 1312 if (Prop->isInvalidDecl() || 1313 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 1314 PropImplMap.count(Prop) || Prop->hasAttr<UnavailableAttr>()) 1315 continue; 1316 if (!InsMap.count(Prop->getGetterName())) { 1317 Diag(Prop->getLocation(), 1318 isa<ObjCCategoryDecl>(CDecl) ? 1319 diag::warn_setter_getter_impl_required_in_category : 1320 diag::warn_setter_getter_impl_required) 1321 << Prop->getDeclName() << Prop->getGetterName(); 1322 Diag(IMPDecl->getLocation(), 1323 diag::note_property_impl_required); 1324 } 1325 1326 if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) { 1327 Diag(Prop->getLocation(), 1328 isa<ObjCCategoryDecl>(CDecl) ? 1329 diag::warn_setter_getter_impl_required_in_category : 1330 diag::warn_setter_getter_impl_required) 1331 << Prop->getDeclName() << Prop->getSetterName(); 1332 Diag(IMPDecl->getLocation(), 1333 diag::note_property_impl_required); 1334 } 1335 } 1336} 1337 1338void 1339Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, 1340 ObjCContainerDecl* IDecl) { 1341 // Rules apply in non-GC mode only 1342 if (getLangOptions().getGCMode() != LangOptions::NonGC) 1343 return; 1344 for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), 1345 E = IDecl->prop_end(); 1346 I != E; ++I) { 1347 ObjCPropertyDecl *Property = (*I); 1348 ObjCMethodDecl *GetterMethod = 0; 1349 ObjCMethodDecl *SetterMethod = 0; 1350 bool LookedUpGetterSetter = false; 1351 1352 unsigned Attributes = Property->getPropertyAttributes(); 1353 unsigned AttributesAsWrittern = Property->getPropertyAttributesAsWritten(); 1354 1355 if (!(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_atomic) && 1356 !(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_nonatomic)) { 1357 GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); 1358 SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); 1359 LookedUpGetterSetter = true; 1360 if (GetterMethod) { 1361 Diag(GetterMethod->getLocation(), 1362 diag::warn_default_atomic_custom_getter_setter) 1363 << Property->getIdentifier() << 0; 1364 Diag(Property->getLocation(), diag::note_property_declare); 1365 } 1366 if (SetterMethod) { 1367 Diag(SetterMethod->getLocation(), 1368 diag::warn_default_atomic_custom_getter_setter) 1369 << Property->getIdentifier() << 1; 1370 Diag(Property->getLocation(), diag::note_property_declare); 1371 } 1372 } 1373 1374 // We only care about readwrite atomic property. 1375 if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || 1376 !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) 1377 continue; 1378 if (const ObjCPropertyImplDecl *PIDecl 1379 = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { 1380 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 1381 continue; 1382 if (!LookedUpGetterSetter) { 1383 GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); 1384 SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); 1385 LookedUpGetterSetter = true; 1386 } 1387 if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { 1388 SourceLocation MethodLoc = 1389 (GetterMethod ? GetterMethod->getLocation() 1390 : SetterMethod->getLocation()); 1391 Diag(MethodLoc, diag::warn_atomic_property_rule) 1392 << Property->getIdentifier(); 1393 Diag(Property->getLocation(), diag::note_property_declare); 1394 } 1395 } 1396 } 1397} 1398 1399void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) { 1400 if (getLangOptions().getGCMode() == LangOptions::GCOnly) 1401 return; 1402 1403 for (ObjCImplementationDecl::propimpl_iterator 1404 i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) { 1405 ObjCPropertyImplDecl *PID = *i; 1406 if (PID->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize) 1407 continue; 1408 1409 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 1410 if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() && 1411 !D->getInstanceMethod(PD->getGetterName())) { 1412 ObjCMethodDecl *method = PD->getGetterMethodDecl(); 1413 if (!method) 1414 continue; 1415 ObjCMethodFamily family = method->getMethodFamily(); 1416 if (family == OMF_alloc || family == OMF_copy || 1417 family == OMF_mutableCopy || family == OMF_new) { 1418 if (getLangOptions().ObjCAutoRefCount) 1419 Diag(PID->getLocation(), diag::err_ownin_getter_rule); 1420 else 1421 Diag(PID->getLocation(), diag::warn_ownin_getter_rule); 1422 Diag(PD->getLocation(), diag::note_property_declare); 1423 } 1424 } 1425 } 1426} 1427 1428/// AddPropertyAttrs - Propagates attributes from a property to the 1429/// implicitly-declared getter or setter for that property. 1430static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, 1431 ObjCPropertyDecl *Property) { 1432 // Should we just clone all attributes over? 1433 for (Decl::attr_iterator A = Property->attr_begin(), 1434 AEnd = Property->attr_end(); 1435 A != AEnd; ++A) { 1436 if (isa<DeprecatedAttr>(*A) || 1437 isa<UnavailableAttr>(*A) || 1438 isa<AvailabilityAttr>(*A)) 1439 PropertyMethod->addAttr((*A)->clone(S.Context)); 1440 } 1441} 1442 1443/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 1444/// have the property type and issue diagnostics if they don't. 1445/// Also synthesize a getter/setter method if none exist (and update the 1446/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized 1447/// methods is the "right" thing to do. 1448void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, 1449 ObjCContainerDecl *CD, 1450 ObjCPropertyDecl *redeclaredProperty, 1451 ObjCContainerDecl *lexicalDC) { 1452 1453 ObjCMethodDecl *GetterMethod, *SetterMethod; 1454 1455 GetterMethod = CD->getInstanceMethod(property->getGetterName()); 1456 SetterMethod = CD->getInstanceMethod(property->getSetterName()); 1457 DiagnosePropertyAccessorMismatch(property, GetterMethod, 1458 property->getLocation()); 1459 1460 if (SetterMethod) { 1461 ObjCPropertyDecl::PropertyAttributeKind CAttr = 1462 property->getPropertyAttributes(); 1463 if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && 1464 Context.getCanonicalType(SetterMethod->getResultType()) != 1465 Context.VoidTy) 1466 Diag(SetterMethod->getLocation(), diag::err_setter_type_void); 1467 if (SetterMethod->param_size() != 1 || 1468 ((*SetterMethod->param_begin())->getType() != property->getType())) { 1469 Diag(property->getLocation(), 1470 diag::warn_accessor_property_type_mismatch) 1471 << property->getDeclName() 1472 << SetterMethod->getSelector(); 1473 Diag(SetterMethod->getLocation(), diag::note_declared_at); 1474 } 1475 } 1476 1477 // Synthesize getter/setter methods if none exist. 1478 // Find the default getter and if one not found, add one. 1479 // FIXME: The synthesized property we set here is misleading. We almost always 1480 // synthesize these methods unless the user explicitly provided prototypes 1481 // (which is odd, but allowed). Sema should be typechecking that the 1482 // declarations jive in that situation (which it is not currently). 1483 if (!GetterMethod) { 1484 // No instance method of same name as property getter name was found. 1485 // Declare a getter method and add it to the list of methods 1486 // for this class. 1487 SourceLocation Loc = redeclaredProperty ? 1488 redeclaredProperty->getLocation() : 1489 property->getLocation(); 1490 1491 GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, 1492 property->getGetterName(), 1493 property->getType(), 0, CD, /*isInstance=*/true, 1494 /*isVariadic=*/false, /*isSynthesized=*/true, 1495 /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 1496 (property->getPropertyImplementation() == 1497 ObjCPropertyDecl::Optional) ? 1498 ObjCMethodDecl::Optional : 1499 ObjCMethodDecl::Required); 1500 CD->addDecl(GetterMethod); 1501 1502 AddPropertyAttrs(*this, GetterMethod, property); 1503 1504 // FIXME: Eventually this shouldn't be needed, as the lexical context 1505 // and the real context should be the same. 1506 if (lexicalDC) 1507 GetterMethod->setLexicalDeclContext(lexicalDC); 1508 if (property->hasAttr<NSReturnsNotRetainedAttr>()) 1509 GetterMethod->addAttr( 1510 ::new (Context) NSReturnsNotRetainedAttr(Loc, Context)); 1511 } else 1512 // A user declared getter will be synthesize when @synthesize of 1513 // the property with the same name is seen in the @implementation 1514 GetterMethod->setSynthesized(true); 1515 property->setGetterMethodDecl(GetterMethod); 1516 1517 // Skip setter if property is read-only. 1518 if (!property->isReadOnly()) { 1519 // Find the default setter and if one not found, add one. 1520 if (!SetterMethod) { 1521 // No instance method of same name as property setter name was found. 1522 // Declare a setter method and add it to the list of methods 1523 // for this class. 1524 SourceLocation Loc = redeclaredProperty ? 1525 redeclaredProperty->getLocation() : 1526 property->getLocation(); 1527 1528 SetterMethod = 1529 ObjCMethodDecl::Create(Context, Loc, Loc, 1530 property->getSetterName(), Context.VoidTy, 0, 1531 CD, /*isInstance=*/true, /*isVariadic=*/false, 1532 /*isSynthesized=*/true, 1533 /*isImplicitlyDeclared=*/true, 1534 /*isDefined=*/false, 1535 (property->getPropertyImplementation() == 1536 ObjCPropertyDecl::Optional) ? 1537 ObjCMethodDecl::Optional : 1538 ObjCMethodDecl::Required); 1539 1540 // Invent the arguments for the setter. We don't bother making a 1541 // nice name for the argument. 1542 ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, 1543 Loc, Loc, 1544 property->getIdentifier(), 1545 property->getType().getUnqualifiedType(), 1546 /*TInfo=*/0, 1547 SC_None, 1548 SC_None, 1549 0); 1550 SetterMethod->setMethodParams(Context, &Argument, 1, 1); 1551 1552 AddPropertyAttrs(*this, SetterMethod, property); 1553 1554 CD->addDecl(SetterMethod); 1555 // FIXME: Eventually this shouldn't be needed, as the lexical context 1556 // and the real context should be the same. 1557 if (lexicalDC) 1558 SetterMethod->setLexicalDeclContext(lexicalDC); 1559 } else 1560 // A user declared setter will be synthesize when @synthesize of 1561 // the property with the same name is seen in the @implementation 1562 SetterMethod->setSynthesized(true); 1563 property->setSetterMethodDecl(SetterMethod); 1564 } 1565 // Add any synthesized methods to the global pool. This allows us to 1566 // handle the following, which is supported by GCC (and part of the design). 1567 // 1568 // @interface Foo 1569 // @property double bar; 1570 // @end 1571 // 1572 // void thisIsUnfortunate() { 1573 // id foo; 1574 // double bar = [foo bar]; 1575 // } 1576 // 1577 if (GetterMethod) 1578 AddInstanceMethodToGlobalPool(GetterMethod); 1579 if (SetterMethod) 1580 AddInstanceMethodToGlobalPool(SetterMethod); 1581} 1582 1583void Sema::CheckObjCPropertyAttributes(Decl *PDecl, 1584 SourceLocation Loc, 1585 unsigned &Attributes) { 1586 // FIXME: Improve the reported location. 1587 if (!PDecl || PDecl->isInvalidDecl()) 1588 return; 1589 1590 ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); 1591 QualType PropertyTy = PropertyDecl->getType(); 1592 1593 // readonly and readwrite/assign/retain/copy conflict. 1594 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1595 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | 1596 ObjCDeclSpec::DQ_PR_assign | 1597 ObjCDeclSpec::DQ_PR_unsafe_unretained | 1598 ObjCDeclSpec::DQ_PR_copy | 1599 ObjCDeclSpec::DQ_PR_retain | 1600 ObjCDeclSpec::DQ_PR_strong))) { 1601 const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ? 1602 "readwrite" : 1603 (Attributes & ObjCDeclSpec::DQ_PR_assign) ? 1604 "assign" : 1605 (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ? 1606 "unsafe_unretained" : 1607 (Attributes & ObjCDeclSpec::DQ_PR_copy) ? 1608 "copy" : "retain"; 1609 1610 Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ? 1611 diag::err_objc_property_attr_mutually_exclusive : 1612 diag::warn_objc_property_attr_mutually_exclusive) 1613 << "readonly" << which; 1614 } 1615 1616 // Check for copy or retain on non-object types. 1617 if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | 1618 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) && 1619 !PropertyTy->isObjCRetainableType() && 1620 !PropertyDecl->getAttr<ObjCNSObjectAttr>()) { 1621 Diag(Loc, diag::err_objc_property_requires_object) 1622 << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" : 1623 Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)"); 1624 Attributes &= ~(ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | 1625 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong); 1626 } 1627 1628 // Check for more than one of { assign, copy, retain }. 1629 if (Attributes & ObjCDeclSpec::DQ_PR_assign) { 1630 if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1631 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1632 << "assign" << "copy"; 1633 Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 1634 } 1635 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1636 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1637 << "assign" << "retain"; 1638 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1639 } 1640 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 1641 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1642 << "assign" << "strong"; 1643 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 1644 } 1645 if (getLangOptions().ObjCAutoRefCount && 1646 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 1647 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1648 << "assign" << "weak"; 1649 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1650 } 1651 } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) { 1652 if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1653 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1654 << "unsafe_unretained" << "copy"; 1655 Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 1656 } 1657 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1658 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1659 << "unsafe_unretained" << "retain"; 1660 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1661 } 1662 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 1663 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1664 << "unsafe_unretained" << "strong"; 1665 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 1666 } 1667 if (getLangOptions().ObjCAutoRefCount && 1668 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 1669 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1670 << "unsafe_unretained" << "weak"; 1671 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1672 } 1673 } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1674 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1675 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1676 << "copy" << "retain"; 1677 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1678 } 1679 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 1680 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1681 << "copy" << "strong"; 1682 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 1683 } 1684 if (Attributes & ObjCDeclSpec::DQ_PR_weak) { 1685 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1686 << "copy" << "weak"; 1687 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1688 } 1689 } 1690 else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) && 1691 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 1692 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1693 << "retain" << "weak"; 1694 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1695 } 1696 else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) && 1697 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 1698 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1699 << "strong" << "weak"; 1700 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1701 } 1702 1703 // Warn if user supplied no assignment attribute, property is 1704 // readwrite, and this is an object type. 1705 if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | 1706 ObjCDeclSpec::DQ_PR_unsafe_unretained | 1707 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong | 1708 ObjCDeclSpec::DQ_PR_weak)) && 1709 !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1710 PropertyTy->isObjCObjectPointerType()) { 1711 if (getLangOptions().ObjCAutoRefCount) 1712 // With arc, @property definitions should default to (strong) when 1713 // not specified 1714 PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 1715 else { 1716 // Skip this warning in gc-only mode. 1717 if (getLangOptions().getGCMode() != LangOptions::GCOnly) 1718 Diag(Loc, diag::warn_objc_property_no_assignment_attribute); 1719 1720 // If non-gc code warn that this is likely inappropriate. 1721 if (getLangOptions().getGCMode() == LangOptions::NonGC) 1722 Diag(Loc, diag::warn_objc_property_default_assign_on_object); 1723 } 1724 1725 // FIXME: Implement warning dependent on NSCopying being 1726 // implemented. See also: 1727 // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496> 1728 // (please trim this list while you are at it). 1729 } 1730 1731 if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) 1732 &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly) 1733 && getLangOptions().getGCMode() == LangOptions::GCOnly 1734 && PropertyTy->isBlockPointerType()) 1735 Diag(Loc, diag::warn_objc_property_copy_missing_on_block); 1736} 1737