SemaObjCProperty.cpp revision 9414449e299036efbd411d92266983dfc24e24e9
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 21using namespace clang; 22 23//===----------------------------------------------------------------------===// 24// Grammar actions. 25//===----------------------------------------------------------------------===// 26 27/// Check the internal consistency of a property declaration. 28static 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 72Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, 73 FieldDeclarator &FD, 74 ObjCDeclSpec &ODS, 75 Selector GetterSel, 76 Selector SetterSel, 77 bool *isOverridingProperty, 78 tok::ObjCKeywordKind MethodImplKind, 79 DeclContext *lexicalDC) { 80 unsigned Attributes = ODS.getPropertyAttributes(); 81 TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); 82 QualType T = TSI->getType(); 83 if ((getLangOptions().getGCMode() != LangOptions::NonGC && 84 T.isObjCGCWeak()) || 85 (getLangOptions().ObjCAutoRefCount && 86 T.getObjCLifetime() == Qualifiers::OCL_Weak)) 87 Attributes |= ObjCDeclSpec::DQ_PR_weak; 88 89 bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || 90 // default is readwrite! 91 !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); 92 // property is defaulted to 'assign' if it is readwrite and is 93 // not retain or copy 94 bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || 95 (isReadWrite && 96 !(Attributes & ObjCDeclSpec::DQ_PR_retain) && 97 !(Attributes & ObjCDeclSpec::DQ_PR_strong) && 98 !(Attributes & ObjCDeclSpec::DQ_PR_copy) && 99 !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) && 100 !(Attributes & ObjCDeclSpec::DQ_PR_weak))); 101 102 // Proceed with constructing the ObjCPropertDecls. 103 ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext); 104 105 if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) 106 if (CDecl->IsClassExtension()) { 107 Decl *Res = HandlePropertyInClassExtension(S, AtLoc, 108 FD, GetterSel, SetterSel, 109 isAssign, isReadWrite, 110 Attributes, 111 isOverridingProperty, TSI, 112 MethodImplKind); 113 if (Res) { 114 CheckObjCPropertyAttributes(Res, AtLoc, Attributes); 115 if (getLangOptions().ObjCAutoRefCount) 116 checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res)); 117 } 118 return Res; 119 } 120 121 ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD, 122 GetterSel, SetterSel, 123 isAssign, isReadWrite, 124 Attributes, TSI, MethodImplKind); 125 if (lexicalDC) 126 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 << ((property->getPropertyAttributesAsWritten() 492 & ObjCPropertyDecl::OBJC_PR_assign) != 0); 493 break; 494 } 495 496 // Any other property should be ignored. 497 } else { 498 return; 499 } 500 501 S.Diag(property->getLocation(), diag::note_property_declare); 502} 503 504 505/// ActOnPropertyImplDecl - This routine performs semantic checks and 506/// builds the AST node for a property implementation declaration; declared 507/// as @synthesize or @dynamic. 508/// 509Decl *Sema::ActOnPropertyImplDecl(Scope *S, 510 SourceLocation AtLoc, 511 SourceLocation PropertyLoc, 512 bool Synthesize, 513 IdentifierInfo *PropertyId, 514 IdentifierInfo *PropertyIvar, 515 SourceLocation PropertyIvarLoc) { 516 ObjCContainerDecl *ClassImpDecl = 517 cast_or_null<ObjCContainerDecl>(CurContext); 518 // Make sure we have a context for the property implementation declaration. 519 if (!ClassImpDecl) { 520 Diag(AtLoc, diag::error_missing_property_context); 521 return 0; 522 } 523 ObjCPropertyDecl *property = 0; 524 ObjCInterfaceDecl* IDecl = 0; 525 // Find the class or category class where this property must have 526 // a declaration. 527 ObjCImplementationDecl *IC = 0; 528 ObjCCategoryImplDecl* CatImplClass = 0; 529 if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) { 530 IDecl = IC->getClassInterface(); 531 // We always synthesize an interface for an implementation 532 // without an interface decl. So, IDecl is always non-zero. 533 assert(IDecl && 534 "ActOnPropertyImplDecl - @implementation without @interface"); 535 536 // Look for this property declaration in the @implementation's @interface 537 property = IDecl->FindPropertyDeclaration(PropertyId); 538 if (!property) { 539 Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); 540 return 0; 541 } 542 unsigned PIkind = property->getPropertyAttributesAsWritten(); 543 if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic | 544 ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) { 545 if (AtLoc.isValid()) 546 Diag(AtLoc, diag::warn_implicit_atomic_property); 547 else 548 Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property); 549 Diag(property->getLocation(), diag::note_property_declare); 550 } 551 552 if (const ObjCCategoryDecl *CD = 553 dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { 554 if (!CD->IsClassExtension()) { 555 Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); 556 Diag(property->getLocation(), diag::note_property_declare); 557 return 0; 558 } 559 } 560 } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { 561 if (Synthesize) { 562 Diag(AtLoc, diag::error_synthesize_category_decl); 563 return 0; 564 } 565 IDecl = CatImplClass->getClassInterface(); 566 if (!IDecl) { 567 Diag(AtLoc, diag::error_missing_property_interface); 568 return 0; 569 } 570 ObjCCategoryDecl *Category = 571 IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); 572 573 // If category for this implementation not found, it is an error which 574 // has already been reported eralier. 575 if (!Category) 576 return 0; 577 // Look for this property declaration in @implementation's category 578 property = Category->FindPropertyDeclaration(PropertyId); 579 if (!property) { 580 Diag(PropertyLoc, diag::error_bad_category_property_decl) 581 << Category->getDeclName(); 582 return 0; 583 } 584 } else { 585 Diag(AtLoc, diag::error_bad_property_context); 586 return 0; 587 } 588 ObjCIvarDecl *Ivar = 0; 589 // Check that we have a valid, previously declared ivar for @synthesize 590 if (Synthesize) { 591 // @synthesize 592 if (!PropertyIvar) 593 PropertyIvar = PropertyId; 594 ObjCPropertyDecl::PropertyAttributeKind kind 595 = property->getPropertyAttributes(); 596 QualType PropType = Context.getCanonicalType(property->getType()); 597 QualType PropertyIvarType = PropType; 598 if (PropType->isReferenceType()) 599 PropertyIvarType = cast<ReferenceType>(PropType)->getPointeeType(); 600 // Check that this is a previously declared 'ivar' in 'IDecl' interface 601 ObjCInterfaceDecl *ClassDeclared; 602 Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); 603 if (!Ivar) { 604 // In ARC, give the ivar a lifetime qualifier based on its 605 // property attributes. 606 if (getLangOptions().ObjCAutoRefCount && 607 !PropertyIvarType.getObjCLifetime()) { 608 609 if (!property->hasWrittenStorageAttribute() && 610 property->getType()->isObjCRetainableType() && 611 !(kind & ObjCPropertyDecl::OBJC_PR_strong) ) { 612 Diag(PropertyLoc, 613 diag::err_arc_objc_property_default_assign_on_object); 614 Diag(property->getLocation(), diag::note_property_declare); 615 } 616 617 // retain/copy have retaining lifetime. 618 if (kind & (ObjCPropertyDecl::OBJC_PR_retain | 619 ObjCPropertyDecl::OBJC_PR_strong | 620 ObjCPropertyDecl::OBJC_PR_copy)) { 621 Qualifiers qs; 622 qs.addObjCLifetime(Qualifiers::OCL_Strong); 623 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 624 } 625 else if (kind & ObjCPropertyDecl::OBJC_PR_weak) { 626 if (!getLangOptions().ObjCRuntimeHasWeak) { 627 Diag(PropertyLoc, diag::err_arc_weak_no_runtime); 628 Diag(property->getLocation(), diag::note_property_declare); 629 } 630 Qualifiers qs; 631 qs.addObjCLifetime(Qualifiers::OCL_Weak); 632 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 633 } 634 else if (kind & ObjCPropertyDecl::OBJC_PR_assign && 635 PropertyIvarType->isObjCRetainableType()) { 636 // assume that an 'assign' property synthesizes __unsafe_unretained 637 // ivar 638 Qualifiers qs; 639 qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone); 640 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 641 } 642 } 643 644 if (kind & ObjCPropertyDecl::OBJC_PR_weak && 645 !getLangOptions().ObjCAutoRefCount && 646 getLangOptions().getGCMode() == LangOptions::NonGC) { 647 Diag(PropertyLoc, diag::error_synthesize_weak_non_arc_or_gc); 648 Diag(property->getLocation(), diag::note_property_declare); 649 } 650 651 Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, 652 PropertyLoc, PropertyLoc, PropertyIvar, 653 PropertyIvarType, /*Dinfo=*/0, 654 ObjCIvarDecl::Private, 655 (Expr *)0, true); 656 ClassImpDecl->addDecl(Ivar); 657 IDecl->makeDeclVisibleInContext(Ivar, false); 658 property->setPropertyIvarDecl(Ivar); 659 660 if (!getLangOptions().ObjCNonFragileABI) 661 Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId; 662 // Note! I deliberately want it to fall thru so, we have a 663 // a property implementation and to avoid future warnings. 664 } else if (getLangOptions().ObjCNonFragileABI && 665 ClassDeclared != IDecl) { 666 Diag(PropertyLoc, diag::error_ivar_in_superclass_use) 667 << property->getDeclName() << Ivar->getDeclName() 668 << ClassDeclared->getDeclName(); 669 Diag(Ivar->getLocation(), diag::note_previous_access_declaration) 670 << Ivar << Ivar->getName(); 671 // Note! I deliberately want it to fall thru so more errors are caught. 672 } 673 QualType IvarType = Context.getCanonicalType(Ivar->getType()); 674 675 // Check that type of property and its ivar are type compatible. 676 if (PropertyIvarType != IvarType) { 677 bool compat = false; 678 if (isa<ObjCObjectPointerType>(PropertyIvarType) 679 && isa<ObjCObjectPointerType>(IvarType)) 680 compat = 681 Context.canAssignObjCInterfaces( 682 PropertyIvarType->getAs<ObjCObjectPointerType>(), 683 IvarType->getAs<ObjCObjectPointerType>()); 684 else { 685 SourceLocation Loc = PropertyIvarLoc; 686 if (Loc.isInvalid()) 687 Loc = PropertyLoc; 688 compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType) 689 == Compatible); 690 } 691 if (!compat) { 692 Diag(PropertyLoc, diag::error_property_ivar_type) 693 << property->getDeclName() << PropType 694 << Ivar->getDeclName() << IvarType; 695 Diag(Ivar->getLocation(), diag::note_ivar_decl); 696 // Note! I deliberately want it to fall thru so, we have a 697 // a property implementation and to avoid future warnings. 698 } 699 700 // FIXME! Rules for properties are somewhat different that those 701 // for assignments. Use a new routine to consolidate all cases; 702 // specifically for property redeclarations as well as for ivars. 703 QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); 704 QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); 705 if (lhsType != rhsType && 706 lhsType->isArithmeticType()) { 707 Diag(PropertyLoc, diag::error_property_ivar_type) 708 << property->getDeclName() << PropType 709 << Ivar->getDeclName() << IvarType; 710 Diag(Ivar->getLocation(), diag::note_ivar_decl); 711 // Fall thru - see previous comment 712 } 713 // __weak is explicit. So it works on Canonical type. 714 if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && 715 getLangOptions().getGCMode() != LangOptions::NonGC)) { 716 Diag(PropertyLoc, diag::error_weak_property) 717 << property->getDeclName() << Ivar->getDeclName(); 718 // Fall thru - see previous comment 719 } 720 // Fall thru - see previous comment 721 if ((property->getType()->isObjCObjectPointerType() || 722 PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && 723 getLangOptions().getGCMode() != LangOptions::NonGC) { 724 Diag(PropertyLoc, diag::error_strong_property) 725 << property->getDeclName() << Ivar->getDeclName(); 726 // Fall thru - see previous comment 727 } 728 } 729 if (getLangOptions().ObjCAutoRefCount) 730 checkARCPropertyImpl(*this, PropertyLoc, property, Ivar); 731 } else if (PropertyIvar) 732 // @dynamic 733 Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl); 734 735 assert (property && "ActOnPropertyImplDecl - property declaration missing"); 736 ObjCPropertyImplDecl *PIDecl = 737 ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, 738 property, 739 (Synthesize ? 740 ObjCPropertyImplDecl::Synthesize 741 : ObjCPropertyImplDecl::Dynamic), 742 Ivar, PropertyIvarLoc); 743 if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { 744 getterMethod->createImplicitParams(Context, IDecl); 745 if (getLangOptions().CPlusPlus && Synthesize && 746 Ivar->getType()->isRecordType()) { 747 // For Objective-C++, need to synthesize the AST for the IVAR object to be 748 // returned by the getter as it must conform to C++'s copy-return rules. 749 // FIXME. Eventually we want to do this for Objective-C as well. 750 ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); 751 DeclRefExpr *SelfExpr = 752 new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(), 753 VK_RValue, SourceLocation()); 754 Expr *IvarRefExpr = 755 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, 756 SelfExpr, true, true); 757 ExprResult Res = 758 PerformCopyInitialization(InitializedEntity::InitializeResult( 759 SourceLocation(), 760 getterMethod->getResultType(), 761 /*NRVO=*/false), 762 SourceLocation(), 763 Owned(IvarRefExpr)); 764 if (!Res.isInvalid()) { 765 Expr *ResExpr = Res.takeAs<Expr>(); 766 if (ResExpr) 767 ResExpr = MaybeCreateExprWithCleanups(ResExpr); 768 PIDecl->setGetterCXXConstructor(ResExpr); 769 } 770 } 771 if (property->hasAttr<NSReturnsNotRetainedAttr>() && 772 !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) { 773 Diag(getterMethod->getLocation(), 774 diag::warn_property_getter_owning_mismatch); 775 Diag(property->getLocation(), diag::note_property_declare); 776 } 777 } 778 if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { 779 setterMethod->createImplicitParams(Context, IDecl); 780 if (getLangOptions().CPlusPlus && Synthesize 781 && Ivar->getType()->isRecordType()) { 782 // FIXME. Eventually we want to do this for Objective-C as well. 783 ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); 784 DeclRefExpr *SelfExpr = 785 new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(), 786 VK_RValue, SourceLocation()); 787 Expr *lhs = 788 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, 789 SelfExpr, true, true); 790 ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); 791 ParmVarDecl *Param = (*P); 792 QualType T = Param->getType(); 793 if (T->isReferenceType()) 794 T = T->getAs<ReferenceType>()->getPointeeType(); 795 Expr *rhs = new (Context) DeclRefExpr(Param, T, 796 VK_LValue, SourceLocation()); 797 ExprResult Res = BuildBinOp(S, lhs->getLocEnd(), 798 BO_Assign, lhs, rhs); 799 PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>()); 800 } 801 } 802 803 if (IC) { 804 if (Synthesize) 805 if (ObjCPropertyImplDecl *PPIDecl = 806 IC->FindPropertyImplIvarDecl(PropertyIvar)) { 807 Diag(PropertyLoc, diag::error_duplicate_ivar_use) 808 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 809 << PropertyIvar; 810 Diag(PPIDecl->getLocation(), diag::note_previous_use); 811 } 812 813 if (ObjCPropertyImplDecl *PPIDecl 814 = IC->FindPropertyImplDecl(PropertyId)) { 815 Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 816 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 817 return 0; 818 } 819 IC->addPropertyImplementation(PIDecl); 820 if (getLangOptions().ObjCDefaultSynthProperties && 821 getLangOptions().ObjCNonFragileABI2) { 822 // Diagnose if an ivar was lazily synthesdized due to a previous 823 // use and if 1) property is @dynamic or 2) property is synthesized 824 // but it requires an ivar of different name. 825 ObjCInterfaceDecl *ClassDeclared=0; 826 ObjCIvarDecl *Ivar = 0; 827 if (!Synthesize) 828 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 829 else { 830 if (PropertyIvar && PropertyIvar != PropertyId) 831 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 832 } 833 // Issue diagnostics only if Ivar belongs to current class. 834 if (Ivar && Ivar->getSynthesize() && 835 IC->getClassInterface() == ClassDeclared) { 836 Diag(Ivar->getLocation(), diag::err_undeclared_var_use) 837 << PropertyId; 838 Ivar->setInvalidDecl(); 839 } 840 } 841 } else { 842 if (Synthesize) 843 if (ObjCPropertyImplDecl *PPIDecl = 844 CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { 845 Diag(PropertyLoc, diag::error_duplicate_ivar_use) 846 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 847 << PropertyIvar; 848 Diag(PPIDecl->getLocation(), diag::note_previous_use); 849 } 850 851 if (ObjCPropertyImplDecl *PPIDecl = 852 CatImplClass->FindPropertyImplDecl(PropertyId)) { 853 Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 854 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 855 return 0; 856 } 857 CatImplClass->addPropertyImplementation(PIDecl); 858 } 859 860 return PIDecl; 861} 862 863//===----------------------------------------------------------------------===// 864// Helper methods. 865//===----------------------------------------------------------------------===// 866 867/// DiagnosePropertyMismatch - Compares two properties for their 868/// attributes and types and warns on a variety of inconsistencies. 869/// 870void 871Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 872 ObjCPropertyDecl *SuperProperty, 873 const IdentifierInfo *inheritedName) { 874 ObjCPropertyDecl::PropertyAttributeKind CAttr = 875 Property->getPropertyAttributes(); 876 ObjCPropertyDecl::PropertyAttributeKind SAttr = 877 SuperProperty->getPropertyAttributes(); 878 if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) 879 && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) 880 Diag(Property->getLocation(), diag::warn_readonly_property) 881 << Property->getDeclName() << inheritedName; 882 if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) 883 != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) 884 Diag(Property->getLocation(), diag::warn_property_attribute) 885 << Property->getDeclName() << "copy" << inheritedName; 886 else { 887 unsigned CAttrRetain = 888 (CAttr & 889 (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); 890 unsigned SAttrRetain = 891 (SAttr & 892 (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong)); 893 bool CStrong = (CAttrRetain != 0); 894 bool SStrong = (SAttrRetain != 0); 895 if (CStrong != SStrong) 896 Diag(Property->getLocation(), diag::warn_property_attribute) 897 << Property->getDeclName() << "retain (or strong)" << inheritedName; 898 } 899 900 if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) 901 != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) 902 Diag(Property->getLocation(), diag::warn_property_attribute) 903 << Property->getDeclName() << "atomic" << inheritedName; 904 if (Property->getSetterName() != SuperProperty->getSetterName()) 905 Diag(Property->getLocation(), diag::warn_property_attribute) 906 << Property->getDeclName() << "setter" << inheritedName; 907 if (Property->getGetterName() != SuperProperty->getGetterName()) 908 Diag(Property->getLocation(), diag::warn_property_attribute) 909 << Property->getDeclName() << "getter" << inheritedName; 910 911 QualType LHSType = 912 Context.getCanonicalType(SuperProperty->getType()); 913 QualType RHSType = 914 Context.getCanonicalType(Property->getType()); 915 916 if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) { 917 // Do cases not handled in above. 918 // FIXME. For future support of covariant property types, revisit this. 919 bool IncompatibleObjC = false; 920 QualType ConvertedType; 921 if (!isObjCPointerConversion(RHSType, LHSType, 922 ConvertedType, IncompatibleObjC) || 923 IncompatibleObjC) 924 Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) 925 << Property->getType() << SuperProperty->getType() << inheritedName; 926 } 927} 928 929bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 930 ObjCMethodDecl *GetterMethod, 931 SourceLocation Loc) { 932 if (GetterMethod && 933 GetterMethod->getResultType() != property->getType()) { 934 AssignConvertType result = Incompatible; 935 if (property->getType()->isObjCObjectPointerType()) 936 result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(), 937 property->getType()); 938 if (result != Compatible) { 939 Diag(Loc, diag::warn_accessor_property_type_mismatch) 940 << property->getDeclName() 941 << GetterMethod->getSelector(); 942 Diag(GetterMethod->getLocation(), diag::note_declared_at); 943 return true; 944 } 945 } 946 return false; 947} 948 949/// ComparePropertiesInBaseAndSuper - This routine compares property 950/// declarations in base and its super class, if any, and issues 951/// diagnostics in a variety of inconsistent situations. 952/// 953void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { 954 ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); 955 if (!SDecl) 956 return; 957 // FIXME: O(N^2) 958 for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(), 959 E = SDecl->prop_end(); S != E; ++S) { 960 ObjCPropertyDecl *SuperPDecl = (*S); 961 // Does property in super class has declaration in current class? 962 for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(), 963 E = IDecl->prop_end(); I != E; ++I) { 964 ObjCPropertyDecl *PDecl = (*I); 965 if (SuperPDecl->getIdentifier() == PDecl->getIdentifier()) 966 DiagnosePropertyMismatch(PDecl, SuperPDecl, 967 SDecl->getIdentifier()); 968 } 969 } 970} 971 972/// MatchOneProtocolPropertiesInClass - This routine goes thru the list 973/// of properties declared in a protocol and compares their attribute against 974/// the same property declared in the class or category. 975void 976Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, 977 ObjCProtocolDecl *PDecl) { 978 ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); 979 if (!IDecl) { 980 // Category 981 ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); 982 assert (CatDecl && "MatchOneProtocolPropertiesInClass"); 983 if (!CatDecl->IsClassExtension()) 984 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 985 E = PDecl->prop_end(); P != E; ++P) { 986 ObjCPropertyDecl *Pr = (*P); 987 ObjCCategoryDecl::prop_iterator CP, CE; 988 // Is this property already in category's list of properties? 989 for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP) 990 if ((*CP)->getIdentifier() == Pr->getIdentifier()) 991 break; 992 if (CP != CE) 993 // Property protocol already exist in class. Diagnose any mismatch. 994 DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); 995 } 996 return; 997 } 998 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 999 E = PDecl->prop_end(); P != E; ++P) { 1000 ObjCPropertyDecl *Pr = (*P); 1001 ObjCInterfaceDecl::prop_iterator CP, CE; 1002 // Is this property already in class's list of properties? 1003 for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP) 1004 if ((*CP)->getIdentifier() == Pr->getIdentifier()) 1005 break; 1006 if (CP != CE) 1007 // Property protocol already exist in class. Diagnose any mismatch. 1008 DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); 1009 } 1010} 1011 1012/// CompareProperties - This routine compares properties 1013/// declared in 'ClassOrProtocol' objects (which can be a class or an 1014/// inherited protocol with the list of properties for class/category 'CDecl' 1015/// 1016void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) { 1017 Decl *ClassDecl = ClassOrProtocol; 1018 ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); 1019 1020 if (!IDecl) { 1021 // Category 1022 ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); 1023 assert (CatDecl && "CompareProperties"); 1024 if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 1025 for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(), 1026 E = MDecl->protocol_end(); P != E; ++P) 1027 // Match properties of category with those of protocol (*P) 1028 MatchOneProtocolPropertiesInClass(CatDecl, *P); 1029 1030 // Go thru the list of protocols for this category and recursively match 1031 // their properties with those in the category. 1032 for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(), 1033 E = CatDecl->protocol_end(); P != E; ++P) 1034 CompareProperties(CatDecl, *P); 1035 } else { 1036 ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); 1037 for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), 1038 E = MD->protocol_end(); P != E; ++P) 1039 MatchOneProtocolPropertiesInClass(CatDecl, *P); 1040 } 1041 return; 1042 } 1043 1044 if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { 1045 for (ObjCInterfaceDecl::all_protocol_iterator 1046 P = MDecl->all_referenced_protocol_begin(), 1047 E = MDecl->all_referenced_protocol_end(); P != E; ++P) 1048 // Match properties of class IDecl with those of protocol (*P). 1049 MatchOneProtocolPropertiesInClass(IDecl, *P); 1050 1051 // Go thru the list of protocols for this class and recursively match 1052 // their properties with those declared in the class. 1053 for (ObjCInterfaceDecl::all_protocol_iterator 1054 P = IDecl->all_referenced_protocol_begin(), 1055 E = IDecl->all_referenced_protocol_end(); P != E; ++P) 1056 CompareProperties(IDecl, *P); 1057 } else { 1058 ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); 1059 for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), 1060 E = MD->protocol_end(); P != E; ++P) 1061 MatchOneProtocolPropertiesInClass(IDecl, *P); 1062 } 1063} 1064 1065/// isPropertyReadonly - Return true if property is readonly, by searching 1066/// for the property in the class and in its categories and implementations 1067/// 1068bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, 1069 ObjCInterfaceDecl *IDecl) { 1070 // by far the most common case. 1071 if (!PDecl->isReadOnly()) 1072 return false; 1073 // Even if property is ready only, if interface has a user defined setter, 1074 // it is not considered read only. 1075 if (IDecl->getInstanceMethod(PDecl->getSetterName())) 1076 return false; 1077 1078 // Main class has the property as 'readonly'. Must search 1079 // through the category list to see if the property's 1080 // attribute has been over-ridden to 'readwrite'. 1081 for (ObjCCategoryDecl *Category = IDecl->getCategoryList(); 1082 Category; Category = Category->getNextClassCategory()) { 1083 // Even if property is ready only, if a category has a user defined setter, 1084 // it is not considered read only. 1085 if (Category->getInstanceMethod(PDecl->getSetterName())) 1086 return false; 1087 ObjCPropertyDecl *P = 1088 Category->FindPropertyDeclaration(PDecl->getIdentifier()); 1089 if (P && !P->isReadOnly()) 1090 return false; 1091 } 1092 1093 // Also, check for definition of a setter method in the implementation if 1094 // all else failed. 1095 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) { 1096 if (ObjCImplementationDecl *IMD = 1097 dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) { 1098 if (IMD->getInstanceMethod(PDecl->getSetterName())) 1099 return false; 1100 } else if (ObjCCategoryImplDecl *CIMD = 1101 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 1102 if (CIMD->getInstanceMethod(PDecl->getSetterName())) 1103 return false; 1104 } 1105 } 1106 // Lastly, look through the implementation (if one is in scope). 1107 if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation()) 1108 if (ImpDecl->getInstanceMethod(PDecl->getSetterName())) 1109 return false; 1110 // If all fails, look at the super class. 1111 if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass()) 1112 return isPropertyReadonly(PDecl, SIDecl); 1113 return true; 1114} 1115 1116/// CollectImmediateProperties - This routine collects all properties in 1117/// the class and its conforming protocols; but not those it its super class. 1118void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, 1119 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, 1120 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) { 1121 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 1122 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 1123 E = IDecl->prop_end(); P != E; ++P) { 1124 ObjCPropertyDecl *Prop = (*P); 1125 PropMap[Prop->getIdentifier()] = Prop; 1126 } 1127 // scan through class's protocols. 1128 for (ObjCInterfaceDecl::all_protocol_iterator 1129 PI = IDecl->all_referenced_protocol_begin(), 1130 E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) 1131 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 1132 } 1133 if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { 1134 if (!CATDecl->IsClassExtension()) 1135 for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), 1136 E = CATDecl->prop_end(); P != E; ++P) { 1137 ObjCPropertyDecl *Prop = (*P); 1138 PropMap[Prop->getIdentifier()] = Prop; 1139 } 1140 // scan through class's protocols. 1141 for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(), 1142 E = CATDecl->protocol_end(); PI != E; ++PI) 1143 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 1144 } 1145 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 1146 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 1147 E = PDecl->prop_end(); P != E; ++P) { 1148 ObjCPropertyDecl *Prop = (*P); 1149 ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; 1150 // Exclude property for protocols which conform to class's super-class, 1151 // as super-class has to implement the property. 1152 if (!PropertyFromSuper || PropertyFromSuper != Prop) { 1153 ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; 1154 if (!PropEntry) 1155 PropEntry = Prop; 1156 } 1157 } 1158 // scan through protocol's protocols. 1159 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 1160 E = PDecl->protocol_end(); PI != E; ++PI) 1161 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 1162 } 1163} 1164 1165/// CollectClassPropertyImplementations - This routine collects list of 1166/// properties to be implemented in the class. This includes, class's 1167/// and its conforming protocols' properties. 1168static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl, 1169 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { 1170 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 1171 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 1172 E = IDecl->prop_end(); P != E; ++P) { 1173 ObjCPropertyDecl *Prop = (*P); 1174 PropMap[Prop->getIdentifier()] = Prop; 1175 } 1176 for (ObjCInterfaceDecl::all_protocol_iterator 1177 PI = IDecl->all_referenced_protocol_begin(), 1178 E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) 1179 CollectClassPropertyImplementations((*PI), PropMap); 1180 } 1181 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 1182 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 1183 E = PDecl->prop_end(); P != E; ++P) { 1184 ObjCPropertyDecl *Prop = (*P); 1185 PropMap[Prop->getIdentifier()] = Prop; 1186 } 1187 // scan through protocol's protocols. 1188 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 1189 E = PDecl->protocol_end(); PI != E; ++PI) 1190 CollectClassPropertyImplementations((*PI), PropMap); 1191 } 1192} 1193 1194/// CollectSuperClassPropertyImplementations - This routine collects list of 1195/// properties to be implemented in super class(s) and also coming from their 1196/// conforming protocols. 1197static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, 1198 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { 1199 if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { 1200 while (SDecl) { 1201 CollectClassPropertyImplementations(SDecl, PropMap); 1202 SDecl = SDecl->getSuperClass(); 1203 } 1204 } 1205} 1206 1207/// LookupPropertyDecl - Looks up a property in the current class and all 1208/// its protocols. 1209ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, 1210 IdentifierInfo *II) { 1211 if (const ObjCInterfaceDecl *IDecl = 1212 dyn_cast<ObjCInterfaceDecl>(CDecl)) { 1213 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 1214 E = IDecl->prop_end(); P != E; ++P) { 1215 ObjCPropertyDecl *Prop = (*P); 1216 if (Prop->getIdentifier() == II) 1217 return Prop; 1218 } 1219 // scan through class's protocols. 1220 for (ObjCInterfaceDecl::all_protocol_iterator 1221 PI = IDecl->all_referenced_protocol_begin(), 1222 E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) { 1223 ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 1224 if (Prop) 1225 return Prop; 1226 } 1227 } 1228 else if (const ObjCProtocolDecl *PDecl = 1229 dyn_cast<ObjCProtocolDecl>(CDecl)) { 1230 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 1231 E = PDecl->prop_end(); P != E; ++P) { 1232 ObjCPropertyDecl *Prop = (*P); 1233 if (Prop->getIdentifier() == II) 1234 return Prop; 1235 } 1236 // scan through protocol's protocols. 1237 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 1238 E = PDecl->protocol_end(); PI != E; ++PI) { 1239 ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 1240 if (Prop) 1241 return Prop; 1242 } 1243 } 1244 return 0; 1245} 1246 1247/// DefaultSynthesizeProperties - This routine default synthesizes all 1248/// properties which must be synthesized in class's @implementation. 1249void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, 1250 ObjCInterfaceDecl *IDecl) { 1251 1252 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; 1253 CollectClassPropertyImplementations(IDecl, PropMap); 1254 if (PropMap.empty()) 1255 return; 1256 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; 1257 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 1258 1259 for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 1260 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 1261 ObjCPropertyDecl *Prop = P->second; 1262 // If property to be implemented in the super class, ignore. 1263 if (SuperPropMap[Prop->getIdentifier()]) 1264 continue; 1265 // Is there a matching propery synthesize/dynamic? 1266 if (Prop->isInvalidDecl() || 1267 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 1268 IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) 1269 continue; 1270 // Property may have been synthesized by user. 1271 if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) 1272 continue; 1273 if (IMPDecl->getInstanceMethod(Prop->getGetterName())) { 1274 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly) 1275 continue; 1276 if (IMPDecl->getInstanceMethod(Prop->getSetterName())) 1277 continue; 1278 } 1279 1280 1281 // We use invalid SourceLocations for the synthesized ivars since they 1282 // aren't really synthesized at a particular location; they just exist. 1283 // Saying that they are located at the @implementation isn't really going 1284 // to help users. 1285 ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), 1286 true, 1287 Prop->getIdentifier(), Prop->getIdentifier(), 1288 SourceLocation()); 1289 } 1290} 1291 1292void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, 1293 ObjCContainerDecl *CDecl, 1294 const llvm::DenseSet<Selector>& InsMap) { 1295 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; 1296 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) 1297 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 1298 1299 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; 1300 CollectImmediateProperties(CDecl, PropMap, SuperPropMap); 1301 if (PropMap.empty()) 1302 return; 1303 1304 llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; 1305 for (ObjCImplDecl::propimpl_iterator 1306 I = IMPDecl->propimpl_begin(), 1307 EI = IMPDecl->propimpl_end(); I != EI; ++I) 1308 PropImplMap.insert((*I)->getPropertyDecl()); 1309 1310 for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 1311 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 1312 ObjCPropertyDecl *Prop = P->second; 1313 // Is there a matching propery synthesize/dynamic? 1314 if (Prop->isInvalidDecl() || 1315 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 1316 PropImplMap.count(Prop) || Prop->hasAttr<UnavailableAttr>()) 1317 continue; 1318 if (!InsMap.count(Prop->getGetterName())) { 1319 Diag(Prop->getLocation(), 1320 isa<ObjCCategoryDecl>(CDecl) ? 1321 diag::warn_setter_getter_impl_required_in_category : 1322 diag::warn_setter_getter_impl_required) 1323 << Prop->getDeclName() << Prop->getGetterName(); 1324 Diag(IMPDecl->getLocation(), 1325 diag::note_property_impl_required); 1326 } 1327 1328 if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) { 1329 Diag(Prop->getLocation(), 1330 isa<ObjCCategoryDecl>(CDecl) ? 1331 diag::warn_setter_getter_impl_required_in_category : 1332 diag::warn_setter_getter_impl_required) 1333 << Prop->getDeclName() << Prop->getSetterName(); 1334 Diag(IMPDecl->getLocation(), 1335 diag::note_property_impl_required); 1336 } 1337 } 1338} 1339 1340void 1341Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, 1342 ObjCContainerDecl* IDecl) { 1343 // Rules apply in non-GC mode only 1344 if (getLangOptions().getGCMode() != LangOptions::NonGC) 1345 return; 1346 for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), 1347 E = IDecl->prop_end(); 1348 I != E; ++I) { 1349 ObjCPropertyDecl *Property = (*I); 1350 ObjCMethodDecl *GetterMethod = 0; 1351 ObjCMethodDecl *SetterMethod = 0; 1352 bool LookedUpGetterSetter = false; 1353 1354 unsigned Attributes = Property->getPropertyAttributes(); 1355 unsigned AttributesAsWrittern = Property->getPropertyAttributesAsWritten(); 1356 1357 if (!(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_atomic) && 1358 !(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_nonatomic)) { 1359 GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); 1360 SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); 1361 LookedUpGetterSetter = true; 1362 if (GetterMethod) { 1363 Diag(GetterMethod->getLocation(), 1364 diag::warn_default_atomic_custom_getter_setter) 1365 << Property->getIdentifier() << 0; 1366 Diag(Property->getLocation(), diag::note_property_declare); 1367 } 1368 if (SetterMethod) { 1369 Diag(SetterMethod->getLocation(), 1370 diag::warn_default_atomic_custom_getter_setter) 1371 << Property->getIdentifier() << 1; 1372 Diag(Property->getLocation(), diag::note_property_declare); 1373 } 1374 } 1375 1376 // We only care about readwrite atomic property. 1377 if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || 1378 !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) 1379 continue; 1380 if (const ObjCPropertyImplDecl *PIDecl 1381 = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { 1382 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 1383 continue; 1384 if (!LookedUpGetterSetter) { 1385 GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName()); 1386 SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName()); 1387 LookedUpGetterSetter = true; 1388 } 1389 if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { 1390 SourceLocation MethodLoc = 1391 (GetterMethod ? GetterMethod->getLocation() 1392 : SetterMethod->getLocation()); 1393 Diag(MethodLoc, diag::warn_atomic_property_rule) 1394 << Property->getIdentifier(); 1395 Diag(Property->getLocation(), diag::note_property_declare); 1396 } 1397 } 1398 } 1399} 1400 1401void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) { 1402 if (getLangOptions().getGCMode() == LangOptions::GCOnly) 1403 return; 1404 1405 for (ObjCImplementationDecl::propimpl_iterator 1406 i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) { 1407 ObjCPropertyImplDecl *PID = *i; 1408 if (PID->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize) 1409 continue; 1410 1411 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 1412 if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() && 1413 !D->getInstanceMethod(PD->getGetterName())) { 1414 ObjCMethodDecl *method = PD->getGetterMethodDecl(); 1415 if (!method) 1416 continue; 1417 ObjCMethodFamily family = method->getMethodFamily(); 1418 if (family == OMF_alloc || family == OMF_copy || 1419 family == OMF_mutableCopy || family == OMF_new) { 1420 if (getLangOptions().ObjCAutoRefCount) 1421 Diag(PID->getLocation(), diag::err_ownin_getter_rule); 1422 else 1423 Diag(PID->getLocation(), diag::warn_ownin_getter_rule); 1424 Diag(PD->getLocation(), diag::note_property_declare); 1425 } 1426 } 1427 } 1428} 1429 1430/// AddPropertyAttrs - Propagates attributes from a property to the 1431/// implicitly-declared getter or setter for that property. 1432static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, 1433 ObjCPropertyDecl *Property) { 1434 // Should we just clone all attributes over? 1435 for (Decl::attr_iterator A = Property->attr_begin(), 1436 AEnd = Property->attr_end(); 1437 A != AEnd; ++A) { 1438 if (isa<DeprecatedAttr>(*A) || 1439 isa<UnavailableAttr>(*A) || 1440 isa<AvailabilityAttr>(*A)) 1441 PropertyMethod->addAttr((*A)->clone(S.Context)); 1442 } 1443} 1444 1445/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 1446/// have the property type and issue diagnostics if they don't. 1447/// Also synthesize a getter/setter method if none exist (and update the 1448/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized 1449/// methods is the "right" thing to do. 1450void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, 1451 ObjCContainerDecl *CD, 1452 ObjCPropertyDecl *redeclaredProperty, 1453 ObjCContainerDecl *lexicalDC) { 1454 1455 ObjCMethodDecl *GetterMethod, *SetterMethod; 1456 1457 GetterMethod = CD->getInstanceMethod(property->getGetterName()); 1458 SetterMethod = CD->getInstanceMethod(property->getSetterName()); 1459 DiagnosePropertyAccessorMismatch(property, GetterMethod, 1460 property->getLocation()); 1461 1462 if (SetterMethod) { 1463 ObjCPropertyDecl::PropertyAttributeKind CAttr = 1464 property->getPropertyAttributes(); 1465 if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && 1466 Context.getCanonicalType(SetterMethod->getResultType()) != 1467 Context.VoidTy) 1468 Diag(SetterMethod->getLocation(), diag::err_setter_type_void); 1469 if (SetterMethod->param_size() != 1 || 1470 ((*SetterMethod->param_begin())->getType() != property->getType())) { 1471 Diag(property->getLocation(), 1472 diag::warn_accessor_property_type_mismatch) 1473 << property->getDeclName() 1474 << SetterMethod->getSelector(); 1475 Diag(SetterMethod->getLocation(), diag::note_declared_at); 1476 } 1477 } 1478 1479 // Synthesize getter/setter methods if none exist. 1480 // Find the default getter and if one not found, add one. 1481 // FIXME: The synthesized property we set here is misleading. We almost always 1482 // synthesize these methods unless the user explicitly provided prototypes 1483 // (which is odd, but allowed). Sema should be typechecking that the 1484 // declarations jive in that situation (which it is not currently). 1485 if (!GetterMethod) { 1486 // No instance method of same name as property getter name was found. 1487 // Declare a getter method and add it to the list of methods 1488 // for this class. 1489 SourceLocation Loc = redeclaredProperty ? 1490 redeclaredProperty->getLocation() : 1491 property->getLocation(); 1492 1493 GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc, 1494 property->getGetterName(), 1495 property->getType(), 0, CD, /*isInstance=*/true, 1496 /*isVariadic=*/false, /*isSynthesized=*/true, 1497 /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 1498 (property->getPropertyImplementation() == 1499 ObjCPropertyDecl::Optional) ? 1500 ObjCMethodDecl::Optional : 1501 ObjCMethodDecl::Required); 1502 CD->addDecl(GetterMethod); 1503 1504 AddPropertyAttrs(*this, GetterMethod, property); 1505 1506 // FIXME: Eventually this shouldn't be needed, as the lexical context 1507 // and the real context should be the same. 1508 if (lexicalDC) 1509 GetterMethod->setLexicalDeclContext(lexicalDC); 1510 if (property->hasAttr<NSReturnsNotRetainedAttr>()) 1511 GetterMethod->addAttr( 1512 ::new (Context) NSReturnsNotRetainedAttr(Loc, Context)); 1513 } else 1514 // A user declared getter will be synthesize when @synthesize of 1515 // the property with the same name is seen in the @implementation 1516 GetterMethod->setSynthesized(true); 1517 property->setGetterMethodDecl(GetterMethod); 1518 1519 // Skip setter if property is read-only. 1520 if (!property->isReadOnly()) { 1521 // Find the default setter and if one not found, add one. 1522 if (!SetterMethod) { 1523 // No instance method of same name as property setter name was found. 1524 // Declare a setter method and add it to the list of methods 1525 // for this class. 1526 SourceLocation Loc = redeclaredProperty ? 1527 redeclaredProperty->getLocation() : 1528 property->getLocation(); 1529 1530 SetterMethod = 1531 ObjCMethodDecl::Create(Context, Loc, Loc, 1532 property->getSetterName(), Context.VoidTy, 0, 1533 CD, /*isInstance=*/true, /*isVariadic=*/false, 1534 /*isSynthesized=*/true, 1535 /*isImplicitlyDeclared=*/true, 1536 /*isDefined=*/false, 1537 (property->getPropertyImplementation() == 1538 ObjCPropertyDecl::Optional) ? 1539 ObjCMethodDecl::Optional : 1540 ObjCMethodDecl::Required); 1541 1542 // Invent the arguments for the setter. We don't bother making a 1543 // nice name for the argument. 1544 ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, 1545 Loc, Loc, 1546 property->getIdentifier(), 1547 property->getType().getUnqualifiedType(), 1548 /*TInfo=*/0, 1549 SC_None, 1550 SC_None, 1551 0); 1552 SetterMethod->setMethodParams(Context, &Argument, 1, 1); 1553 1554 AddPropertyAttrs(*this, SetterMethod, property); 1555 1556 CD->addDecl(SetterMethod); 1557 // FIXME: Eventually this shouldn't be needed, as the lexical context 1558 // and the real context should be the same. 1559 if (lexicalDC) 1560 SetterMethod->setLexicalDeclContext(lexicalDC); 1561 } else 1562 // A user declared setter will be synthesize when @synthesize of 1563 // the property with the same name is seen in the @implementation 1564 SetterMethod->setSynthesized(true); 1565 property->setSetterMethodDecl(SetterMethod); 1566 } 1567 // Add any synthesized methods to the global pool. This allows us to 1568 // handle the following, which is supported by GCC (and part of the design). 1569 // 1570 // @interface Foo 1571 // @property double bar; 1572 // @end 1573 // 1574 // void thisIsUnfortunate() { 1575 // id foo; 1576 // double bar = [foo bar]; 1577 // } 1578 // 1579 if (GetterMethod) 1580 AddInstanceMethodToGlobalPool(GetterMethod); 1581 if (SetterMethod) 1582 AddInstanceMethodToGlobalPool(SetterMethod); 1583} 1584 1585void Sema::CheckObjCPropertyAttributes(Decl *PDecl, 1586 SourceLocation Loc, 1587 unsigned &Attributes) { 1588 // FIXME: Improve the reported location. 1589 if (!PDecl || PDecl->isInvalidDecl()) 1590 return; 1591 1592 ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); 1593 QualType PropertyTy = PropertyDecl->getType(); 1594 1595 // readonly and readwrite/assign/retain/copy conflict. 1596 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1597 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | 1598 ObjCDeclSpec::DQ_PR_assign | 1599 ObjCDeclSpec::DQ_PR_unsafe_unretained | 1600 ObjCDeclSpec::DQ_PR_copy | 1601 ObjCDeclSpec::DQ_PR_retain | 1602 ObjCDeclSpec::DQ_PR_strong))) { 1603 const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ? 1604 "readwrite" : 1605 (Attributes & ObjCDeclSpec::DQ_PR_assign) ? 1606 "assign" : 1607 (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ? 1608 "unsafe_unretained" : 1609 (Attributes & ObjCDeclSpec::DQ_PR_copy) ? 1610 "copy" : "retain"; 1611 1612 Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ? 1613 diag::err_objc_property_attr_mutually_exclusive : 1614 diag::warn_objc_property_attr_mutually_exclusive) 1615 << "readonly" << which; 1616 } 1617 1618 // Check for copy or retain on non-object types. 1619 if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | 1620 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) && 1621 !PropertyTy->isObjCRetainableType() && 1622 !PropertyDecl->getAttr<ObjCNSObjectAttr>()) { 1623 Diag(Loc, diag::err_objc_property_requires_object) 1624 << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" : 1625 Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)"); 1626 Attributes &= ~(ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy | 1627 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong); 1628 } 1629 1630 // Check for more than one of { assign, copy, retain }. 1631 if (Attributes & ObjCDeclSpec::DQ_PR_assign) { 1632 if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1633 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1634 << "assign" << "copy"; 1635 Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 1636 } 1637 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1638 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1639 << "assign" << "retain"; 1640 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1641 } 1642 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 1643 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1644 << "assign" << "strong"; 1645 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 1646 } 1647 if (getLangOptions().ObjCAutoRefCount && 1648 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 1649 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1650 << "assign" << "weak"; 1651 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1652 } 1653 } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) { 1654 if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1655 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1656 << "unsafe_unretained" << "copy"; 1657 Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 1658 } 1659 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1660 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1661 << "unsafe_unretained" << "retain"; 1662 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1663 } 1664 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 1665 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1666 << "unsafe_unretained" << "strong"; 1667 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 1668 } 1669 if (getLangOptions().ObjCAutoRefCount && 1670 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 1671 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1672 << "unsafe_unretained" << "weak"; 1673 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1674 } 1675 } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1676 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1677 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1678 << "copy" << "retain"; 1679 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1680 } 1681 if (Attributes & ObjCDeclSpec::DQ_PR_strong) { 1682 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1683 << "copy" << "strong"; 1684 Attributes &= ~ObjCDeclSpec::DQ_PR_strong; 1685 } 1686 if (Attributes & ObjCDeclSpec::DQ_PR_weak) { 1687 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1688 << "copy" << "weak"; 1689 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1690 } 1691 } 1692 else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) && 1693 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 1694 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1695 << "retain" << "weak"; 1696 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1697 } 1698 else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) && 1699 (Attributes & ObjCDeclSpec::DQ_PR_weak)) { 1700 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1701 << "strong" << "weak"; 1702 Attributes &= ~ObjCDeclSpec::DQ_PR_weak; 1703 } 1704 1705 // Warn if user supplied no assignment attribute, property is 1706 // readwrite, and this is an object type. 1707 if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | 1708 ObjCDeclSpec::DQ_PR_unsafe_unretained | 1709 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong | 1710 ObjCDeclSpec::DQ_PR_weak)) && 1711 !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1712 PropertyTy->isObjCObjectPointerType()) { 1713 if (getLangOptions().ObjCAutoRefCount) 1714 // With arc, @property definitions should default to (strong) when 1715 // not specified 1716 PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong); 1717 else { 1718 // Skip this warning in gc-only mode. 1719 if (getLangOptions().getGCMode() != LangOptions::GCOnly) 1720 Diag(Loc, diag::warn_objc_property_no_assignment_attribute); 1721 1722 // If non-gc code warn that this is likely inappropriate. 1723 if (getLangOptions().getGCMode() == LangOptions::NonGC) 1724 Diag(Loc, diag::warn_objc_property_default_assign_on_object); 1725 } 1726 1727 // FIXME: Implement warning dependent on NSCopying being 1728 // implemented. See also: 1729 // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496> 1730 // (please trim this list while you are at it). 1731 } 1732 1733 if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) 1734 &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly) 1735 && getLangOptions().getGCMode() == LangOptions::GCOnly 1736 && PropertyTy->isBlockPointerType()) 1737 Diag(Loc, diag::warn_objc_property_copy_missing_on_block); 1738} 1739