SemaObjCProperty.cpp revision cdaa6a8fed16d8bd3987fb4f3304dfb4e52876c3
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/Sema.h" 16#include "clang/Sema/Initialization.h" 17#include "clang/AST/DeclObjC.h" 18#include "clang/AST/ExprObjC.h" 19 20using namespace clang; 21 22//===----------------------------------------------------------------------===// 23// Grammar actions. 24//===----------------------------------------------------------------------===// 25 26Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, 27 FieldDeclarator &FD, 28 ObjCDeclSpec &ODS, 29 Selector GetterSel, 30 Selector SetterSel, 31 Decl *ClassCategory, 32 bool *isOverridingProperty, 33 tok::ObjCKeywordKind MethodImplKind) { 34 unsigned Attributes = ODS.getPropertyAttributes(); 35 bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) || 36 // default is readwrite! 37 !(Attributes & ObjCDeclSpec::DQ_PR_readonly)); 38 // property is defaulted to 'assign' if it is readwrite and is 39 // not retain or copy 40 bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) || 41 (isReadWrite && 42 !(Attributes & ObjCDeclSpec::DQ_PR_retain) && 43 !(Attributes & ObjCDeclSpec::DQ_PR_copy))); 44 45 TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S); 46 QualType T = TSI->getType(); 47 if (T->isReferenceType()) { 48 Diag(AtLoc, diag::error_reference_property); 49 return 0; 50 } 51 // Proceed with constructing the ObjCPropertDecls. 52 ObjCContainerDecl *ClassDecl = 53 cast<ObjCContainerDecl>(ClassCategory); 54 55 if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) 56 if (CDecl->IsClassExtension()) { 57 Decl *Res = HandlePropertyInClassExtension(S, CDecl, AtLoc, 58 FD, GetterSel, SetterSel, 59 isAssign, isReadWrite, 60 Attributes, 61 isOverridingProperty, TSI, 62 MethodImplKind); 63 if (Res) 64 CheckObjCPropertyAttributes(Res, AtLoc, Attributes); 65 return Res; 66 } 67 68 Decl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD, 69 GetterSel, SetterSel, 70 isAssign, isReadWrite, 71 Attributes, TSI, MethodImplKind); 72 // Validate the attributes on the @property. 73 CheckObjCPropertyAttributes(Res, AtLoc, Attributes); 74 return Res; 75} 76 77Decl * 78Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl, 79 SourceLocation AtLoc, FieldDeclarator &FD, 80 Selector GetterSel, Selector SetterSel, 81 const bool isAssign, 82 const bool isReadWrite, 83 const unsigned Attributes, 84 bool *isOverridingProperty, 85 TypeSourceInfo *T, 86 tok::ObjCKeywordKind MethodImplKind) { 87 88 // Diagnose if this property is already in continuation class. 89 DeclContext *DC = cast<DeclContext>(CDecl); 90 IdentifierInfo *PropertyId = FD.D.getIdentifier(); 91 92 if (ObjCPropertyDecl *prevDecl = 93 ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { 94 Diag(AtLoc, diag::err_duplicate_property); 95 Diag(prevDecl->getLocation(), diag::note_property_declare); 96 return 0; 97 } 98 99 // Create a new ObjCPropertyDecl with the DeclContext being 100 // the class extension. 101 ObjCPropertyDecl *PDecl = 102 ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), 103 PropertyId, AtLoc, T); 104 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 105 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 106 if (Attributes & ObjCDeclSpec::DQ_PR_readwrite) 107 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 108 109 DC->addDecl(PDecl); 110 111 // We need to look in the @interface to see if the @property was 112 // already declared. 113 ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); 114 if (!CCPrimary) { 115 Diag(CDecl->getLocation(), diag::err_continuation_class); 116 *isOverridingProperty = true; 117 return 0; 118 } 119 120 // Find the property in continuation class's primary class only. 121 ObjCPropertyDecl *PIDecl = 122 CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId); 123 124 if (!PIDecl) { 125 // No matching property found in the primary class. Just fall thru 126 // and add property to continuation class's primary class. 127 ObjCPropertyDecl *PDecl = 128 CreatePropertyDecl(S, CCPrimary, AtLoc, 129 FD, GetterSel, SetterSel, isAssign, isReadWrite, 130 Attributes, T, MethodImplKind, DC); 131 // Mark written attribute as having no attribute because 132 // this is not a user-written property declaration in primary 133 // class. 134 PDecl->setPropertyAttributesAsWritten(ObjCPropertyDecl::OBJC_PR_noattr); 135 136 // A case of continuation class adding a new property in the class. This 137 // is not what it was meant for. However, gcc supports it and so should we. 138 // Make sure setter/getters are declared here. 139 ProcessPropertyDecl(PDecl, CCPrimary); 140 return PDecl; 141 142 } 143 144 // The property 'PIDecl's readonly attribute will be over-ridden 145 // with continuation class's readwrite property attribute! 146 unsigned PIkind = PIDecl->getPropertyAttributesAsWritten(); 147 if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) { 148 unsigned retainCopyNonatomic = 149 (ObjCPropertyDecl::OBJC_PR_retain | 150 ObjCPropertyDecl::OBJC_PR_copy | 151 ObjCPropertyDecl::OBJC_PR_nonatomic); 152 if ((Attributes & retainCopyNonatomic) != 153 (PIkind & retainCopyNonatomic)) { 154 Diag(AtLoc, diag::warn_property_attr_mismatch); 155 Diag(PIDecl->getLocation(), diag::note_property_declare); 156 } 157 DeclContext *DC = cast<DeclContext>(CCPrimary); 158 if (!ObjCPropertyDecl::findPropertyDecl(DC, 159 PIDecl->getDeclName().getAsIdentifierInfo())) { 160 // Protocol is not in the primary class. Must build one for it. 161 ObjCDeclSpec ProtocolPropertyODS; 162 // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind 163 // and ObjCPropertyDecl::PropertyAttributeKind have identical 164 // values. Should consolidate both into one enum type. 165 ProtocolPropertyODS. 166 setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind) 167 PIkind); 168 169 Decl *ProtocolPtrTy = 170 ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS, 171 PIDecl->getGetterName(), 172 PIDecl->getSetterName(), 173 CCPrimary, isOverridingProperty, 174 MethodImplKind); 175 PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy); 176 } 177 PIDecl->makeitReadWriteAttribute(); 178 if (Attributes & ObjCDeclSpec::DQ_PR_retain) 179 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 180 if (Attributes & ObjCDeclSpec::DQ_PR_copy) 181 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 182 PIDecl->setSetterName(SetterSel); 183 } else { 184 Diag(AtLoc, diag::err_use_continuation_class) 185 << CCPrimary->getDeclName(); 186 Diag(PIDecl->getLocation(), diag::note_property_declare); 187 } 188 *isOverridingProperty = true; 189 // Make sure setter decl is synthesized, and added to primary class's list. 190 ProcessPropertyDecl(PIDecl, CCPrimary); 191 return 0; 192} 193 194ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S, 195 ObjCContainerDecl *CDecl, 196 SourceLocation AtLoc, 197 FieldDeclarator &FD, 198 Selector GetterSel, 199 Selector SetterSel, 200 const bool isAssign, 201 const bool isReadWrite, 202 const unsigned Attributes, 203 TypeSourceInfo *TInfo, 204 tok::ObjCKeywordKind MethodImplKind, 205 DeclContext *lexicalDC){ 206 IdentifierInfo *PropertyId = FD.D.getIdentifier(); 207 QualType T = TInfo->getType(); 208 209 // Issue a warning if property is 'assign' as default and its object, which is 210 // gc'able conforms to NSCopying protocol 211 if (getLangOptions().getGCMode() != LangOptions::NonGC && 212 isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign)) 213 if (const ObjCObjectPointerType *ObjPtrTy = 214 T->getAs<ObjCObjectPointerType>()) { 215 ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); 216 if (IDecl) 217 if (ObjCProtocolDecl* PNSCopying = 218 LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) 219 if (IDecl->ClassImplementsProtocol(PNSCopying, true)) 220 Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; 221 } 222 if (T->isObjCObjectType()) 223 Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object); 224 225 DeclContext *DC = cast<DeclContext>(CDecl); 226 ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, 227 FD.D.getIdentifierLoc(), 228 PropertyId, AtLoc, TInfo); 229 230 if (ObjCPropertyDecl *prevDecl = 231 ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) { 232 Diag(PDecl->getLocation(), diag::err_duplicate_property); 233 Diag(prevDecl->getLocation(), diag::note_property_declare); 234 PDecl->setInvalidDecl(); 235 } 236 else { 237 DC->addDecl(PDecl); 238 if (lexicalDC) 239 PDecl->setLexicalDeclContext(lexicalDC); 240 } 241 242 if (T->isArrayType() || T->isFunctionType()) { 243 Diag(AtLoc, diag::err_property_type) << T; 244 PDecl->setInvalidDecl(); 245 } 246 247 ProcessDeclAttributes(S, PDecl, FD.D); 248 249 // Regardless of setter/getter attribute, we save the default getter/setter 250 // selector names in anticipation of declaration of setter/getter methods. 251 PDecl->setGetterName(GetterSel); 252 PDecl->setSetterName(SetterSel); 253 254 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) 255 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly); 256 257 if (Attributes & ObjCDeclSpec::DQ_PR_getter) 258 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter); 259 260 if (Attributes & ObjCDeclSpec::DQ_PR_setter) 261 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter); 262 263 if (isReadWrite) 264 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite); 265 266 if (Attributes & ObjCDeclSpec::DQ_PR_retain) 267 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain); 268 269 if (Attributes & ObjCDeclSpec::DQ_PR_copy) 270 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy); 271 272 if (isAssign) 273 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign); 274 275 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic) 276 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic); 277 278 PDecl->setPropertyAttributesAsWritten(PDecl->getPropertyAttributes()); 279 280 if (MethodImplKind == tok::objc_required) 281 PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); 282 else if (MethodImplKind == tok::objc_optional) 283 PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); 284 285 return PDecl; 286} 287 288 289/// ActOnPropertyImplDecl - This routine performs semantic checks and 290/// builds the AST node for a property implementation declaration; declared 291/// as @synthesize or @dynamic. 292/// 293Decl *Sema::ActOnPropertyImplDecl(Scope *S, 294 SourceLocation AtLoc, 295 SourceLocation PropertyLoc, 296 bool Synthesize, 297 Decl *ClassCatImpDecl, 298 IdentifierInfo *PropertyId, 299 IdentifierInfo *PropertyIvar) { 300 ObjCContainerDecl *ClassImpDecl = 301 cast_or_null<ObjCContainerDecl>(ClassCatImpDecl); 302 // Make sure we have a context for the property implementation declaration. 303 if (!ClassImpDecl) { 304 Diag(AtLoc, diag::error_missing_property_context); 305 return 0; 306 } 307 ObjCPropertyDecl *property = 0; 308 ObjCInterfaceDecl* IDecl = 0; 309 // Find the class or category class where this property must have 310 // a declaration. 311 ObjCImplementationDecl *IC = 0; 312 ObjCCategoryImplDecl* CatImplClass = 0; 313 if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) { 314 IDecl = IC->getClassInterface(); 315 // We always synthesize an interface for an implementation 316 // without an interface decl. So, IDecl is always non-zero. 317 assert(IDecl && 318 "ActOnPropertyImplDecl - @implementation without @interface"); 319 320 // Look for this property declaration in the @implementation's @interface 321 property = IDecl->FindPropertyDeclaration(PropertyId); 322 if (!property) { 323 Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); 324 return 0; 325 } 326 if (const ObjCCategoryDecl *CD = 327 dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { 328 if (!CD->IsClassExtension()) { 329 Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName(); 330 Diag(property->getLocation(), diag::note_property_declare); 331 return 0; 332 } 333 } 334 } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { 335 if (Synthesize) { 336 Diag(AtLoc, diag::error_synthesize_category_decl); 337 return 0; 338 } 339 IDecl = CatImplClass->getClassInterface(); 340 if (!IDecl) { 341 Diag(AtLoc, diag::error_missing_property_interface); 342 return 0; 343 } 344 ObjCCategoryDecl *Category = 345 IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); 346 347 // If category for this implementation not found, it is an error which 348 // has already been reported eralier. 349 if (!Category) 350 return 0; 351 // Look for this property declaration in @implementation's category 352 property = Category->FindPropertyDeclaration(PropertyId); 353 if (!property) { 354 Diag(PropertyLoc, diag::error_bad_category_property_decl) 355 << Category->getDeclName(); 356 return 0; 357 } 358 } else { 359 Diag(AtLoc, diag::error_bad_property_context); 360 return 0; 361 } 362 ObjCIvarDecl *Ivar = 0; 363 // Check that we have a valid, previously declared ivar for @synthesize 364 if (Synthesize) { 365 // @synthesize 366 if (!PropertyIvar) 367 PropertyIvar = PropertyId; 368 QualType PropType = Context.getCanonicalType(property->getType()); 369 // Check that this is a previously declared 'ivar' in 'IDecl' interface 370 ObjCInterfaceDecl *ClassDeclared; 371 Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); 372 if (!Ivar) { 373 Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, PropertyLoc, 374 PropertyIvar, PropType, /*Dinfo=*/0, 375 ObjCIvarDecl::Protected, 376 (Expr *)0, true); 377 ClassImpDecl->addDecl(Ivar); 378 IDecl->makeDeclVisibleInContext(Ivar, false); 379 property->setPropertyIvarDecl(Ivar); 380 381 if (!getLangOptions().ObjCNonFragileABI) 382 Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId; 383 // Note! I deliberately want it to fall thru so, we have a 384 // a property implementation and to avoid future warnings. 385 } else if (getLangOptions().ObjCNonFragileABI && 386 ClassDeclared != IDecl) { 387 Diag(PropertyLoc, diag::error_ivar_in_superclass_use) 388 << property->getDeclName() << Ivar->getDeclName() 389 << ClassDeclared->getDeclName(); 390 Diag(Ivar->getLocation(), diag::note_previous_access_declaration) 391 << Ivar << Ivar->getName(); 392 // Note! I deliberately want it to fall thru so more errors are caught. 393 } 394 QualType IvarType = Context.getCanonicalType(Ivar->getType()); 395 396 // Check that type of property and its ivar are type compatible. 397 if (PropType != IvarType) { 398 bool compat = false; 399 if (isa<ObjCObjectPointerType>(PropType) 400 && isa<ObjCObjectPointerType>(IvarType)) 401 compat = 402 Context.canAssignObjCInterfaces( 403 PropType->getAs<ObjCObjectPointerType>(), 404 IvarType->getAs<ObjCObjectPointerType>()); 405 else 406 compat = (CheckAssignmentConstraints(PropType, IvarType) == Compatible); 407 if (!compat) { 408 Diag(PropertyLoc, diag::error_property_ivar_type) 409 << property->getDeclName() << PropType 410 << Ivar->getDeclName() << IvarType; 411 Diag(Ivar->getLocation(), diag::note_ivar_decl); 412 // Note! I deliberately want it to fall thru so, we have a 413 // a property implementation and to avoid future warnings. 414 } 415 416 // FIXME! Rules for properties are somewhat different that those 417 // for assignments. Use a new routine to consolidate all cases; 418 // specifically for property redeclarations as well as for ivars. 419 QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType(); 420 QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); 421 if (lhsType != rhsType && 422 lhsType->isArithmeticType()) { 423 Diag(PropertyLoc, diag::error_property_ivar_type) 424 << property->getDeclName() << PropType 425 << Ivar->getDeclName() << IvarType; 426 Diag(Ivar->getLocation(), diag::note_ivar_decl); 427 // Fall thru - see previous comment 428 } 429 // __weak is explicit. So it works on Canonical type. 430 if (PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && 431 getLangOptions().getGCMode() != LangOptions::NonGC) { 432 Diag(PropertyLoc, diag::error_weak_property) 433 << property->getDeclName() << Ivar->getDeclName(); 434 // Fall thru - see previous comment 435 } 436 if ((property->getType()->isObjCObjectPointerType() || 437 PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && 438 getLangOptions().getGCMode() != LangOptions::NonGC) { 439 Diag(PropertyLoc, diag::error_strong_property) 440 << property->getDeclName() << Ivar->getDeclName(); 441 // Fall thru - see previous comment 442 } 443 } 444 } else if (PropertyIvar) 445 // @dynamic 446 Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl); 447 assert (property && "ActOnPropertyImplDecl - property declaration missing"); 448 ObjCPropertyImplDecl *PIDecl = 449 ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc, 450 property, 451 (Synthesize ? 452 ObjCPropertyImplDecl::Synthesize 453 : ObjCPropertyImplDecl::Dynamic), 454 Ivar); 455 if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { 456 getterMethod->createImplicitParams(Context, IDecl); 457 if (getLangOptions().CPlusPlus && Synthesize) { 458 // For Objective-C++, need to synthesize the AST for the IVAR object to be 459 // returned by the getter as it must conform to C++'s copy-return rules. 460 // FIXME. Eventually we want to do this for Objective-C as well. 461 ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); 462 DeclRefExpr *SelfExpr = 463 new (Context) DeclRefExpr(SelfDecl,SelfDecl->getType(), 464 SourceLocation()); 465 Expr *IvarRefExpr = 466 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, 467 SelfExpr, true, true); 468 ExprResult Res = 469 PerformCopyInitialization(InitializedEntity::InitializeResult( 470 SourceLocation(), 471 getterMethod->getResultType(), 472 /*NRVO=*/false), 473 SourceLocation(), 474 Owned(IvarRefExpr)); 475 if (!Res.isInvalid()) { 476 Expr *ResExpr = Res.takeAs<Expr>(); 477 if (ResExpr) 478 ResExpr = MaybeCreateCXXExprWithTemporaries(ResExpr); 479 PIDecl->setGetterCXXConstructor(ResExpr); 480 } 481 } 482 } 483 if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { 484 setterMethod->createImplicitParams(Context, IDecl); 485 if (getLangOptions().CPlusPlus && Synthesize) { 486 // FIXME. Eventually we want to do this for Objective-C as well. 487 ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); 488 DeclRefExpr *SelfExpr = 489 new (Context) DeclRefExpr(SelfDecl,SelfDecl->getType(), 490 SourceLocation()); 491 Expr *lhs = 492 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc, 493 SelfExpr, true, true); 494 ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); 495 ParmVarDecl *Param = (*P); 496 Expr *rhs = new (Context) DeclRefExpr(Param,Param->getType(), 497 SourceLocation()); 498 ExprResult Res = BuildBinOp(S, SourceLocation(), 499 BinaryOperator::Assign, lhs, rhs); 500 PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>()); 501 } 502 } 503 504 if (IC) { 505 if (Synthesize) 506 if (ObjCPropertyImplDecl *PPIDecl = 507 IC->FindPropertyImplIvarDecl(PropertyIvar)) { 508 Diag(PropertyLoc, diag::error_duplicate_ivar_use) 509 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 510 << PropertyIvar; 511 Diag(PPIDecl->getLocation(), diag::note_previous_use); 512 } 513 514 if (ObjCPropertyImplDecl *PPIDecl 515 = IC->FindPropertyImplDecl(PropertyId)) { 516 Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 517 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 518 return 0; 519 } 520 IC->addPropertyImplementation(PIDecl); 521 if (getLangOptions().ObjCNonFragileABI2) { 522 // Diagnose if an ivar was lazily synthesdized due to a previous 523 // use and if 1) property is @dynamic or 2) property is synthesized 524 // but it requires an ivar of different name. 525 ObjCInterfaceDecl *ClassDeclared; 526 ObjCIvarDecl *Ivar = 0; 527 if (!Synthesize) 528 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 529 else { 530 if (PropertyIvar && PropertyIvar != PropertyId) 531 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 532 } 533 // Issue diagnostics only if Ivar belongs to current class. 534 if (Ivar && Ivar->getSynthesize() && 535 IC->getClassInterface() == ClassDeclared) { 536 Diag(Ivar->getLocation(), diag::err_undeclared_var_use) 537 << PropertyId; 538 Ivar->setInvalidDecl(); 539 } 540 } 541 } else { 542 if (Synthesize) 543 if (ObjCPropertyImplDecl *PPIDecl = 544 CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { 545 Diag(PropertyLoc, diag::error_duplicate_ivar_use) 546 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 547 << PropertyIvar; 548 Diag(PPIDecl->getLocation(), diag::note_previous_use); 549 } 550 551 if (ObjCPropertyImplDecl *PPIDecl = 552 CatImplClass->FindPropertyImplDecl(PropertyId)) { 553 Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; 554 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 555 return 0; 556 } 557 CatImplClass->addPropertyImplementation(PIDecl); 558 } 559 560 return PIDecl; 561} 562 563//===----------------------------------------------------------------------===// 564// Helper methods. 565//===----------------------------------------------------------------------===// 566 567/// DiagnosePropertyMismatch - Compares two properties for their 568/// attributes and types and warns on a variety of inconsistencies. 569/// 570void 571Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 572 ObjCPropertyDecl *SuperProperty, 573 const IdentifierInfo *inheritedName) { 574 ObjCPropertyDecl::PropertyAttributeKind CAttr = 575 Property->getPropertyAttributes(); 576 ObjCPropertyDecl::PropertyAttributeKind SAttr = 577 SuperProperty->getPropertyAttributes(); 578 if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly) 579 && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite)) 580 Diag(Property->getLocation(), diag::warn_readonly_property) 581 << Property->getDeclName() << inheritedName; 582 if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy) 583 != (SAttr & ObjCPropertyDecl::OBJC_PR_copy)) 584 Diag(Property->getLocation(), diag::warn_property_attribute) 585 << Property->getDeclName() << "copy" << inheritedName; 586 else if ((CAttr & ObjCPropertyDecl::OBJC_PR_retain) 587 != (SAttr & ObjCPropertyDecl::OBJC_PR_retain)) 588 Diag(Property->getLocation(), diag::warn_property_attribute) 589 << Property->getDeclName() << "retain" << inheritedName; 590 591 if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic) 592 != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) 593 Diag(Property->getLocation(), diag::warn_property_attribute) 594 << Property->getDeclName() << "atomic" << inheritedName; 595 if (Property->getSetterName() != SuperProperty->getSetterName()) 596 Diag(Property->getLocation(), diag::warn_property_attribute) 597 << Property->getDeclName() << "setter" << inheritedName; 598 if (Property->getGetterName() != SuperProperty->getGetterName()) 599 Diag(Property->getLocation(), diag::warn_property_attribute) 600 << Property->getDeclName() << "getter" << inheritedName; 601 602 QualType LHSType = 603 Context.getCanonicalType(SuperProperty->getType()); 604 QualType RHSType = 605 Context.getCanonicalType(Property->getType()); 606 607 if (!Context.typesAreCompatible(LHSType, RHSType)) { 608 // FIXME: Incorporate this test with typesAreCompatible. 609 if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType()) 610 if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false)) 611 return; 612 Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) 613 << Property->getType() << SuperProperty->getType() << inheritedName; 614 } 615} 616 617bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 618 ObjCMethodDecl *GetterMethod, 619 SourceLocation Loc) { 620 if (GetterMethod && 621 GetterMethod->getResultType() != property->getType()) { 622 AssignConvertType result = Incompatible; 623 if (property->getType()->isObjCObjectPointerType()) 624 result = CheckAssignmentConstraints(GetterMethod->getResultType(), 625 property->getType()); 626 if (result != Compatible) { 627 Diag(Loc, diag::warn_accessor_property_type_mismatch) 628 << property->getDeclName() 629 << GetterMethod->getSelector(); 630 Diag(GetterMethod->getLocation(), diag::note_declared_at); 631 return true; 632 } 633 } 634 return false; 635} 636 637/// ComparePropertiesInBaseAndSuper - This routine compares property 638/// declarations in base and its super class, if any, and issues 639/// diagnostics in a variety of inconsistant situations. 640/// 641void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { 642 ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); 643 if (!SDecl) 644 return; 645 // FIXME: O(N^2) 646 for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(), 647 E = SDecl->prop_end(); S != E; ++S) { 648 ObjCPropertyDecl *SuperPDecl = (*S); 649 // Does property in super class has declaration in current class? 650 for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(), 651 E = IDecl->prop_end(); I != E; ++I) { 652 ObjCPropertyDecl *PDecl = (*I); 653 if (SuperPDecl->getIdentifier() == PDecl->getIdentifier()) 654 DiagnosePropertyMismatch(PDecl, SuperPDecl, 655 SDecl->getIdentifier()); 656 } 657 } 658} 659 660/// MatchOneProtocolPropertiesInClass - This routine goes thru the list 661/// of properties declared in a protocol and compares their attribute against 662/// the same property declared in the class or category. 663void 664Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl, 665 ObjCProtocolDecl *PDecl) { 666 ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); 667 if (!IDecl) { 668 // Category 669 ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); 670 assert (CatDecl && "MatchOneProtocolPropertiesInClass"); 671 if (!CatDecl->IsClassExtension()) 672 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 673 E = PDecl->prop_end(); P != E; ++P) { 674 ObjCPropertyDecl *Pr = (*P); 675 ObjCCategoryDecl::prop_iterator CP, CE; 676 // Is this property already in category's list of properties? 677 for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP) 678 if ((*CP)->getIdentifier() == Pr->getIdentifier()) 679 break; 680 if (CP != CE) 681 // Property protocol already exist in class. Diagnose any mismatch. 682 DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); 683 } 684 return; 685 } 686 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 687 E = PDecl->prop_end(); P != E; ++P) { 688 ObjCPropertyDecl *Pr = (*P); 689 ObjCInterfaceDecl::prop_iterator CP, CE; 690 // Is this property already in class's list of properties? 691 for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP) 692 if ((*CP)->getIdentifier() == Pr->getIdentifier()) 693 break; 694 if (CP != CE) 695 // Property protocol already exist in class. Diagnose any mismatch. 696 DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier()); 697 } 698} 699 700/// CompareProperties - This routine compares properties 701/// declared in 'ClassOrProtocol' objects (which can be a class or an 702/// inherited protocol with the list of properties for class/category 'CDecl' 703/// 704void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) { 705 Decl *ClassDecl = ClassOrProtocol; 706 ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl); 707 708 if (!IDecl) { 709 // Category 710 ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); 711 assert (CatDecl && "CompareProperties"); 712 if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 713 for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(), 714 E = MDecl->protocol_end(); P != E; ++P) 715 // Match properties of category with those of protocol (*P) 716 MatchOneProtocolPropertiesInClass(CatDecl, *P); 717 718 // Go thru the list of protocols for this category and recursively match 719 // their properties with those in the category. 720 for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(), 721 E = CatDecl->protocol_end(); P != E; ++P) 722 CompareProperties(CatDecl, *P); 723 } else { 724 ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); 725 for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), 726 E = MD->protocol_end(); P != E; ++P) 727 MatchOneProtocolPropertiesInClass(CatDecl, *P); 728 } 729 return; 730 } 731 732 if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { 733 for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(), 734 E = MDecl->protocol_end(); P != E; ++P) 735 // Match properties of class IDecl with those of protocol (*P). 736 MatchOneProtocolPropertiesInClass(IDecl, *P); 737 738 // Go thru the list of protocols for this class and recursively match 739 // their properties with those declared in the class. 740 for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(), 741 E = IDecl->protocol_end(); P != E; ++P) 742 CompareProperties(IDecl, *P); 743 } else { 744 ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl); 745 for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(), 746 E = MD->protocol_end(); P != E; ++P) 747 MatchOneProtocolPropertiesInClass(IDecl, *P); 748 } 749} 750 751/// isPropertyReadonly - Return true if property is readonly, by searching 752/// for the property in the class and in its categories and implementations 753/// 754bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, 755 ObjCInterfaceDecl *IDecl) { 756 // by far the most common case. 757 if (!PDecl->isReadOnly()) 758 return false; 759 // Even if property is ready only, if interface has a user defined setter, 760 // it is not considered read only. 761 if (IDecl->getInstanceMethod(PDecl->getSetterName())) 762 return false; 763 764 // Main class has the property as 'readonly'. Must search 765 // through the category list to see if the property's 766 // attribute has been over-ridden to 'readwrite'. 767 for (ObjCCategoryDecl *Category = IDecl->getCategoryList(); 768 Category; Category = Category->getNextClassCategory()) { 769 // Even if property is ready only, if a category has a user defined setter, 770 // it is not considered read only. 771 if (Category->getInstanceMethod(PDecl->getSetterName())) 772 return false; 773 ObjCPropertyDecl *P = 774 Category->FindPropertyDeclaration(PDecl->getIdentifier()); 775 if (P && !P->isReadOnly()) 776 return false; 777 } 778 779 // Also, check for definition of a setter method in the implementation if 780 // all else failed. 781 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) { 782 if (ObjCImplementationDecl *IMD = 783 dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) { 784 if (IMD->getInstanceMethod(PDecl->getSetterName())) 785 return false; 786 } else if (ObjCCategoryImplDecl *CIMD = 787 dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { 788 if (CIMD->getInstanceMethod(PDecl->getSetterName())) 789 return false; 790 } 791 } 792 // Lastly, look through the implementation (if one is in scope). 793 if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation()) 794 if (ImpDecl->getInstanceMethod(PDecl->getSetterName())) 795 return false; 796 // If all fails, look at the super class. 797 if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass()) 798 return isPropertyReadonly(PDecl, SIDecl); 799 return true; 800} 801 802/// CollectImmediateProperties - This routine collects all properties in 803/// the class and its conforming protocols; but not those it its super class. 804void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, 805 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap, 806 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) { 807 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 808 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 809 E = IDecl->prop_end(); P != E; ++P) { 810 ObjCPropertyDecl *Prop = (*P); 811 PropMap[Prop->getIdentifier()] = Prop; 812 } 813 // scan through class's protocols. 814 for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), 815 E = IDecl->protocol_end(); PI != E; ++PI) 816 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 817 } 818 if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { 819 if (!CATDecl->IsClassExtension()) 820 for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), 821 E = CATDecl->prop_end(); P != E; ++P) { 822 ObjCPropertyDecl *Prop = (*P); 823 PropMap[Prop->getIdentifier()] = Prop; 824 } 825 // scan through class's protocols. 826 for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(), 827 E = CATDecl->protocol_end(); PI != E; ++PI) 828 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 829 } 830 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 831 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 832 E = PDecl->prop_end(); P != E; ++P) { 833 ObjCPropertyDecl *Prop = (*P); 834 ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()]; 835 // Exclude property for protocols which conform to class's super-class, 836 // as super-class has to implement the property. 837 if (!PropertyFromSuper || PropertyFromSuper != Prop) { 838 ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; 839 if (!PropEntry) 840 PropEntry = Prop; 841 } 842 } 843 // scan through protocol's protocols. 844 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 845 E = PDecl->protocol_end(); PI != E; ++PI) 846 CollectImmediateProperties((*PI), PropMap, SuperPropMap); 847 } 848} 849 850/// CollectClassPropertyImplementations - This routine collects list of 851/// properties to be implemented in the class. This includes, class's 852/// and its conforming protocols' properties. 853static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl, 854 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { 855 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 856 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 857 E = IDecl->prop_end(); P != E; ++P) { 858 ObjCPropertyDecl *Prop = (*P); 859 PropMap[Prop->getIdentifier()] = Prop; 860 } 861 for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), 862 E = IDecl->protocol_end(); PI != E; ++PI) 863 CollectClassPropertyImplementations((*PI), PropMap); 864 } 865 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 866 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 867 E = PDecl->prop_end(); P != E; ++P) { 868 ObjCPropertyDecl *Prop = (*P); 869 PropMap[Prop->getIdentifier()] = Prop; 870 } 871 // scan through protocol's protocols. 872 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 873 E = PDecl->protocol_end(); PI != E; ++PI) 874 CollectClassPropertyImplementations((*PI), PropMap); 875 } 876} 877 878/// CollectSuperClassPropertyImplementations - This routine collects list of 879/// properties to be implemented in super class(s) and also coming from their 880/// conforming protocols. 881static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, 882 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) { 883 if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { 884 while (SDecl) { 885 CollectClassPropertyImplementations(SDecl, PropMap); 886 SDecl = SDecl->getSuperClass(); 887 } 888 } 889} 890 891/// LookupPropertyDecl - Looks up a property in the current class and all 892/// its protocols. 893ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, 894 IdentifierInfo *II) { 895 if (const ObjCInterfaceDecl *IDecl = 896 dyn_cast<ObjCInterfaceDecl>(CDecl)) { 897 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 898 E = IDecl->prop_end(); P != E; ++P) { 899 ObjCPropertyDecl *Prop = (*P); 900 if (Prop->getIdentifier() == II) 901 return Prop; 902 } 903 // scan through class's protocols. 904 for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), 905 E = IDecl->protocol_end(); PI != E; ++PI) { 906 ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 907 if (Prop) 908 return Prop; 909 } 910 } 911 else if (const ObjCProtocolDecl *PDecl = 912 dyn_cast<ObjCProtocolDecl>(CDecl)) { 913 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 914 E = PDecl->prop_end(); P != E; ++P) { 915 ObjCPropertyDecl *Prop = (*P); 916 if (Prop->getIdentifier() == II) 917 return Prop; 918 } 919 // scan through protocol's protocols. 920 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 921 E = PDecl->protocol_end(); PI != E; ++PI) { 922 ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 923 if (Prop) 924 return Prop; 925 } 926 } 927 return 0; 928} 929 930/// DefaultSynthesizeProperties - This routine default synthesizes all 931/// properties which must be synthesized in class's @implementation. 932void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl, 933 ObjCInterfaceDecl *IDecl) { 934 935 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; 936 CollectClassPropertyImplementations(IDecl, PropMap); 937 if (PropMap.empty()) 938 return; 939 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; 940 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 941 942 for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 943 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 944 ObjCPropertyDecl *Prop = P->second; 945 // If property to be implemented in the super class, ignore. 946 if (SuperPropMap[Prop->getIdentifier()]) 947 continue; 948 // Is there a matching propery synthesize/dynamic? 949 if (Prop->isInvalidDecl() || 950 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 951 IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) 952 continue; 953 // Property may have been synthesized by user. 954 if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier())) 955 continue; 956 957 ActOnPropertyImplDecl(S, IMPDecl->getLocation(), IMPDecl->getLocation(), 958 true, IMPDecl, 959 Prop->getIdentifier(), Prop->getIdentifier()); 960 } 961} 962 963void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, 964 ObjCContainerDecl *CDecl, 965 const llvm::DenseSet<Selector>& InsMap) { 966 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap; 967 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) 968 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 969 970 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; 971 CollectImmediateProperties(CDecl, PropMap, SuperPropMap); 972 if (PropMap.empty()) 973 return; 974 975 llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; 976 for (ObjCImplDecl::propimpl_iterator 977 I = IMPDecl->propimpl_begin(), 978 EI = IMPDecl->propimpl_end(); I != EI; ++I) 979 PropImplMap.insert((*I)->getPropertyDecl()); 980 981 for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 982 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 983 ObjCPropertyDecl *Prop = P->second; 984 // Is there a matching propery synthesize/dynamic? 985 if (Prop->isInvalidDecl() || 986 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 987 PropImplMap.count(Prop)) 988 continue; 989 if (!InsMap.count(Prop->getGetterName())) { 990 Diag(Prop->getLocation(), 991 isa<ObjCCategoryDecl>(CDecl) ? 992 diag::warn_setter_getter_impl_required_in_category : 993 diag::warn_setter_getter_impl_required) 994 << Prop->getDeclName() << Prop->getGetterName(); 995 Diag(IMPDecl->getLocation(), 996 diag::note_property_impl_required); 997 } 998 999 if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) { 1000 Diag(Prop->getLocation(), 1001 isa<ObjCCategoryDecl>(CDecl) ? 1002 diag::warn_setter_getter_impl_required_in_category : 1003 diag::warn_setter_getter_impl_required) 1004 << Prop->getDeclName() << Prop->getSetterName(); 1005 Diag(IMPDecl->getLocation(), 1006 diag::note_property_impl_required); 1007 } 1008 } 1009} 1010 1011void 1012Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, 1013 ObjCContainerDecl* IDecl) { 1014 // Rules apply in non-GC mode only 1015 if (getLangOptions().getGCMode() != LangOptions::NonGC) 1016 return; 1017 for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), 1018 E = IDecl->prop_end(); 1019 I != E; ++I) { 1020 ObjCPropertyDecl *Property = (*I); 1021 unsigned Attributes = Property->getPropertyAttributes(); 1022 // We only care about readwrite atomic property. 1023 if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || 1024 !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) 1025 continue; 1026 if (const ObjCPropertyImplDecl *PIDecl 1027 = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { 1028 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 1029 continue; 1030 ObjCMethodDecl *GetterMethod = 1031 IMPDecl->getInstanceMethod(Property->getGetterName()); 1032 ObjCMethodDecl *SetterMethod = 1033 IMPDecl->getInstanceMethod(Property->getSetterName()); 1034 if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { 1035 SourceLocation MethodLoc = 1036 (GetterMethod ? GetterMethod->getLocation() 1037 : SetterMethod->getLocation()); 1038 Diag(MethodLoc, diag::warn_atomic_property_rule) 1039 << Property->getIdentifier(); 1040 Diag(Property->getLocation(), diag::note_property_declare); 1041 } 1042 } 1043 } 1044} 1045 1046/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 1047/// have the property type and issue diagnostics if they don't. 1048/// Also synthesize a getter/setter method if none exist (and update the 1049/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized 1050/// methods is the "right" thing to do. 1051void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, 1052 ObjCContainerDecl *CD) { 1053 ObjCMethodDecl *GetterMethod, *SetterMethod; 1054 1055 GetterMethod = CD->getInstanceMethod(property->getGetterName()); 1056 SetterMethod = CD->getInstanceMethod(property->getSetterName()); 1057 DiagnosePropertyAccessorMismatch(property, GetterMethod, 1058 property->getLocation()); 1059 1060 if (SetterMethod) { 1061 ObjCPropertyDecl::PropertyAttributeKind CAttr = 1062 property->getPropertyAttributes(); 1063 if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && 1064 Context.getCanonicalType(SetterMethod->getResultType()) != 1065 Context.VoidTy) 1066 Diag(SetterMethod->getLocation(), diag::err_setter_type_void); 1067 if (SetterMethod->param_size() != 1 || 1068 ((*SetterMethod->param_begin())->getType() != property->getType())) { 1069 Diag(property->getLocation(), 1070 diag::warn_accessor_property_type_mismatch) 1071 << property->getDeclName() 1072 << SetterMethod->getSelector(); 1073 Diag(SetterMethod->getLocation(), diag::note_declared_at); 1074 } 1075 } 1076 1077 // Synthesize getter/setter methods if none exist. 1078 // Find the default getter and if one not found, add one. 1079 // FIXME: The synthesized property we set here is misleading. We almost always 1080 // synthesize these methods unless the user explicitly provided prototypes 1081 // (which is odd, but allowed). Sema should be typechecking that the 1082 // declarations jive in that situation (which it is not currently). 1083 if (!GetterMethod) { 1084 // No instance method of same name as property getter name was found. 1085 // Declare a getter method and add it to the list of methods 1086 // for this class. 1087 GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), 1088 property->getLocation(), property->getGetterName(), 1089 property->getType(), 0, CD, true, false, true, 1090 false, 1091 (property->getPropertyImplementation() == 1092 ObjCPropertyDecl::Optional) ? 1093 ObjCMethodDecl::Optional : 1094 ObjCMethodDecl::Required); 1095 CD->addDecl(GetterMethod); 1096 // FIXME: Eventually this shouldn't be needed, as the lexical context 1097 // and the real context should be the same. 1098 if (DeclContext *lexicalDC = property->getLexicalDeclContext()) 1099 GetterMethod->setLexicalDeclContext(lexicalDC); 1100 1101 } else 1102 // A user declared getter will be synthesize when @synthesize of 1103 // the property with the same name is seen in the @implementation 1104 GetterMethod->setSynthesized(true); 1105 property->setGetterMethodDecl(GetterMethod); 1106 1107 // Skip setter if property is read-only. 1108 if (!property->isReadOnly()) { 1109 // Find the default setter and if one not found, add one. 1110 if (!SetterMethod) { 1111 // No instance method of same name as property setter name was found. 1112 // Declare a setter method and add it to the list of methods 1113 // for this class. 1114 SetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), 1115 property->getLocation(), 1116 property->getSetterName(), 1117 Context.VoidTy, 0, CD, true, false, true, 1118 false, 1119 (property->getPropertyImplementation() == 1120 ObjCPropertyDecl::Optional) ? 1121 ObjCMethodDecl::Optional : 1122 ObjCMethodDecl::Required); 1123 // Invent the arguments for the setter. We don't bother making a 1124 // nice name for the argument. 1125 ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, 1126 property->getLocation(), 1127 property->getIdentifier(), 1128 property->getType(), 1129 /*TInfo=*/0, 1130 VarDecl::None, 1131 VarDecl::None, 1132 0); 1133 SetterMethod->setMethodParams(Context, &Argument, 1, 1); 1134 CD->addDecl(SetterMethod); 1135 // FIXME: Eventually this shouldn't be needed, as the lexical context 1136 // and the real context should be the same. 1137 if (DeclContext *lexicalDC = property->getLexicalDeclContext()) 1138 SetterMethod->setLexicalDeclContext(lexicalDC); 1139 } else 1140 // A user declared setter will be synthesize when @synthesize of 1141 // the property with the same name is seen in the @implementation 1142 SetterMethod->setSynthesized(true); 1143 property->setSetterMethodDecl(SetterMethod); 1144 } 1145 // Add any synthesized methods to the global pool. This allows us to 1146 // handle the following, which is supported by GCC (and part of the design). 1147 // 1148 // @interface Foo 1149 // @property double bar; 1150 // @end 1151 // 1152 // void thisIsUnfortunate() { 1153 // id foo; 1154 // double bar = [foo bar]; 1155 // } 1156 // 1157 if (GetterMethod) 1158 AddInstanceMethodToGlobalPool(GetterMethod); 1159 if (SetterMethod) 1160 AddInstanceMethodToGlobalPool(SetterMethod); 1161} 1162 1163void Sema::CheckObjCPropertyAttributes(Decl *PDecl, 1164 SourceLocation Loc, 1165 unsigned &Attributes) { 1166 // FIXME: Improve the reported location. 1167 if (!PDecl) 1168 return; 1169 1170 ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); 1171 QualType PropertyTy = PropertyDecl->getType(); 1172 1173 // readonly and readwrite/assign/retain/copy conflict. 1174 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1175 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | 1176 ObjCDeclSpec::DQ_PR_assign | 1177 ObjCDeclSpec::DQ_PR_copy | 1178 ObjCDeclSpec::DQ_PR_retain))) { 1179 const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ? 1180 "readwrite" : 1181 (Attributes & ObjCDeclSpec::DQ_PR_assign) ? 1182 "assign" : 1183 (Attributes & ObjCDeclSpec::DQ_PR_copy) ? 1184 "copy" : "retain"; 1185 1186 Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ? 1187 diag::err_objc_property_attr_mutually_exclusive : 1188 diag::warn_objc_property_attr_mutually_exclusive) 1189 << "readonly" << which; 1190 } 1191 1192 // Check for copy or retain on non-object types. 1193 if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) && 1194 !PropertyTy->isObjCObjectPointerType() && 1195 !PropertyTy->isBlockPointerType() && 1196 !Context.isObjCNSObjectType(PropertyTy) && 1197 !PropertyDecl->getAttr<ObjCNSObjectAttr>()) { 1198 Diag(Loc, diag::err_objc_property_requires_object) 1199 << (Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain"); 1200 Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain); 1201 } 1202 1203 // Check for more than one of { assign, copy, retain }. 1204 if (Attributes & ObjCDeclSpec::DQ_PR_assign) { 1205 if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1206 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1207 << "assign" << "copy"; 1208 Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 1209 } 1210 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1211 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1212 << "assign" << "retain"; 1213 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1214 } 1215 } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1216 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1217 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1218 << "copy" << "retain"; 1219 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1220 } 1221 } 1222 1223 // Warn if user supplied no assignment attribute, property is 1224 // readwrite, and this is an object type. 1225 if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | 1226 ObjCDeclSpec::DQ_PR_retain)) && 1227 !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1228 PropertyTy->isObjCObjectPointerType()) { 1229 // Skip this warning in gc-only mode. 1230 if (getLangOptions().getGCMode() != LangOptions::GCOnly) 1231 Diag(Loc, diag::warn_objc_property_no_assignment_attribute); 1232 1233 // If non-gc code warn that this is likely inappropriate. 1234 if (getLangOptions().getGCMode() == LangOptions::NonGC) 1235 Diag(Loc, diag::warn_objc_property_default_assign_on_object); 1236 1237 // FIXME: Implement warning dependent on NSCopying being 1238 // implemented. See also: 1239 // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496> 1240 // (please trim this list while you are at it). 1241 } 1242 1243 if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) 1244 && getLangOptions().getGCMode() == LangOptions::GCOnly 1245 && PropertyTy->isBlockPointerType()) 1246 Diag(Loc, diag::warn_objc_property_copy_missing_on_block); 1247} 1248