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