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