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