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