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