SemaObjCProperty.cpp revision 738698d9d2e1ab0b1ae6a04874d521814907b8a5
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"), AtLoc)) 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 // Exclude property for protocols which conform to class's super-class, 723 // as super-class has to implement the property. 724 if (!ProtocolConformsToSuperClass(IDecl, (*PI))) 725 CollectImmediateProperties((*PI), PropMap); 726 } 727 if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { 728 if (!CATDecl->IsClassExtension()) 729 for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(), 730 E = CATDecl->prop_end(); P != E; ++P) { 731 ObjCPropertyDecl *Prop = (*P); 732 PropMap[Prop->getIdentifier()] = Prop; 733 } 734 // scan through class's protocols. 735 for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(), 736 E = CATDecl->protocol_end(); PI != E; ++PI) 737 CollectImmediateProperties((*PI), PropMap); 738 } 739 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 740 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 741 E = PDecl->prop_end(); P != E; ++P) { 742 ObjCPropertyDecl *Prop = (*P); 743 ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()]; 744 if (!PropEntry) 745 PropEntry = Prop; 746 } 747 // scan through protocol's protocols. 748 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 749 E = PDecl->protocol_end(); PI != E; ++PI) 750 CollectImmediateProperties((*PI), PropMap); 751 } 752} 753 754/// ProtocolConformsToSuperClass - Returns true if class's given protocol 755/// conforms to one of its super class's protocols. 756bool Sema::ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl, 757 const ObjCProtocolDecl *PDecl) { 758 if (const ObjCInterfaceDecl *CDecl = IDecl->getSuperClass()) { 759 for (ObjCInterfaceDecl::protocol_iterator PI = CDecl->protocol_begin(), 760 E = CDecl->protocol_end(); PI != E; ++PI) { 761 if (ProtocolConformsToProtocol((*PI), PDecl)) 762 return true; 763 return ProtocolConformsToSuperClass(CDecl, PDecl); 764 } 765 } 766 return false; 767} 768 769bool Sema::ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol, 770 const ObjCProtocolDecl *PDecl) { 771 if (PDecl->getIdentifier() == NestedProtocol->getIdentifier()) 772 return true; 773 // scan through protocol's protocols. 774 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 775 E = PDecl->protocol_end(); PI != E; ++PI) 776 if (ProtocolConformsToProtocol(NestedProtocol, (*PI))) 777 return true; 778 return false; 779} 780 781/// LookupPropertyDecl - Looks up a property in the current class and all 782/// its protocols. 783ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, 784 IdentifierInfo *II) { 785 if (const ObjCInterfaceDecl *IDecl = 786 dyn_cast<ObjCInterfaceDecl>(CDecl)) { 787 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), 788 E = IDecl->prop_end(); P != E; ++P) { 789 ObjCPropertyDecl *Prop = (*P); 790 if (Prop->getIdentifier() == II) 791 return Prop; 792 } 793 // scan through class's protocols. 794 for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(), 795 E = IDecl->protocol_end(); PI != E; ++PI) { 796 ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 797 if (Prop) 798 return Prop; 799 } 800 } 801 else if (const ObjCProtocolDecl *PDecl = 802 dyn_cast<ObjCProtocolDecl>(CDecl)) { 803 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), 804 E = PDecl->prop_end(); P != E; ++P) { 805 ObjCPropertyDecl *Prop = (*P); 806 if (Prop->getIdentifier() == II) 807 return Prop; 808 } 809 // scan through protocol's protocols. 810 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), 811 E = PDecl->protocol_end(); PI != E; ++PI) { 812 ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II); 813 if (Prop) 814 return Prop; 815 } 816 } 817 return 0; 818} 819 820 821void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl, 822 ObjCContainerDecl *CDecl, 823 const llvm::DenseSet<Selector>& InsMap) { 824 llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap; 825 CollectImmediateProperties(CDecl, PropMap); 826 if (PropMap.empty()) 827 return; 828 829 llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; 830 for (ObjCImplDecl::propimpl_iterator 831 I = IMPDecl->propimpl_begin(), 832 EI = IMPDecl->propimpl_end(); I != EI; ++I) 833 PropImplMap.insert((*I)->getPropertyDecl()); 834 835 for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator 836 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 837 ObjCPropertyDecl *Prop = P->second; 838 // Is there a matching propery synthesize/dynamic? 839 if (Prop->isInvalidDecl() || 840 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 841 PropImplMap.count(Prop)) 842 continue; 843 if (LangOpts.ObjCNonFragileABI2 && !isa<ObjCCategoryImplDecl>(IMPDecl)) { 844 ActOnPropertyImplDecl(IMPDecl->getLocation(), 845 IMPDecl->getLocation(), 846 true, DeclPtrTy::make(IMPDecl), 847 Prop->getIdentifier(), 848 Prop->getIdentifier()); 849 continue; 850 } 851 if (!InsMap.count(Prop->getGetterName())) { 852 Diag(Prop->getLocation(), 853 isa<ObjCCategoryDecl>(CDecl) ? 854 diag::warn_setter_getter_impl_required_in_category : 855 diag::warn_setter_getter_impl_required) 856 << Prop->getDeclName() << Prop->getGetterName(); 857 Diag(IMPDecl->getLocation(), 858 diag::note_property_impl_required); 859 } 860 861 if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) { 862 Diag(Prop->getLocation(), 863 isa<ObjCCategoryDecl>(CDecl) ? 864 diag::warn_setter_getter_impl_required_in_category : 865 diag::warn_setter_getter_impl_required) 866 << Prop->getDeclName() << Prop->getSetterName(); 867 Diag(IMPDecl->getLocation(), 868 diag::note_property_impl_required); 869 } 870 } 871} 872 873void 874Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl, 875 ObjCContainerDecl* IDecl) { 876 // Rules apply in non-GC mode only 877 if (getLangOptions().getGCMode() != LangOptions::NonGC) 878 return; 879 for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(), 880 E = IDecl->prop_end(); 881 I != E; ++I) { 882 ObjCPropertyDecl *Property = (*I); 883 unsigned Attributes = Property->getPropertyAttributes(); 884 // We only care about readwrite atomic property. 885 if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) || 886 !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite)) 887 continue; 888 if (const ObjCPropertyImplDecl *PIDecl 889 = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) { 890 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 891 continue; 892 ObjCMethodDecl *GetterMethod = 893 IMPDecl->getInstanceMethod(Property->getGetterName()); 894 ObjCMethodDecl *SetterMethod = 895 IMPDecl->getInstanceMethod(Property->getSetterName()); 896 if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) { 897 SourceLocation MethodLoc = 898 (GetterMethod ? GetterMethod->getLocation() 899 : SetterMethod->getLocation()); 900 Diag(MethodLoc, diag::warn_atomic_property_rule) 901 << Property->getIdentifier(); 902 Diag(Property->getLocation(), diag::note_property_declare); 903 } 904 } 905 } 906} 907 908/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 909/// have the property type and issue diagnostics if they don't. 910/// Also synthesize a getter/setter method if none exist (and update the 911/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized 912/// methods is the "right" thing to do. 913void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, 914 ObjCContainerDecl *CD) { 915 ObjCMethodDecl *GetterMethod, *SetterMethod; 916 917 GetterMethod = CD->getInstanceMethod(property->getGetterName()); 918 SetterMethod = CD->getInstanceMethod(property->getSetterName()); 919 DiagnosePropertyAccessorMismatch(property, GetterMethod, 920 property->getLocation()); 921 922 if (SetterMethod) { 923 ObjCPropertyDecl::PropertyAttributeKind CAttr = 924 property->getPropertyAttributes(); 925 if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) && 926 Context.getCanonicalType(SetterMethod->getResultType()) != 927 Context.VoidTy) 928 Diag(SetterMethod->getLocation(), diag::err_setter_type_void); 929 if (SetterMethod->param_size() != 1 || 930 ((*SetterMethod->param_begin())->getType() != property->getType())) { 931 Diag(property->getLocation(), 932 diag::warn_accessor_property_type_mismatch) 933 << property->getDeclName() 934 << SetterMethod->getSelector(); 935 Diag(SetterMethod->getLocation(), diag::note_declared_at); 936 } 937 } 938 939 // Synthesize getter/setter methods if none exist. 940 // Find the default getter and if one not found, add one. 941 // FIXME: The synthesized property we set here is misleading. We almost always 942 // synthesize these methods unless the user explicitly provided prototypes 943 // (which is odd, but allowed). Sema should be typechecking that the 944 // declarations jive in that situation (which it is not currently). 945 if (!GetterMethod) { 946 // No instance method of same name as property getter name was found. 947 // Declare a getter method and add it to the list of methods 948 // for this class. 949 GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), 950 property->getLocation(), property->getGetterName(), 951 property->getType(), 0, CD, true, false, true, 952 (property->getPropertyImplementation() == 953 ObjCPropertyDecl::Optional) ? 954 ObjCMethodDecl::Optional : 955 ObjCMethodDecl::Required); 956 CD->addDecl(GetterMethod); 957 } else 958 // A user declared getter will be synthesize when @synthesize of 959 // the property with the same name is seen in the @implementation 960 GetterMethod->setSynthesized(true); 961 property->setGetterMethodDecl(GetterMethod); 962 963 // Skip setter if property is read-only. 964 if (!property->isReadOnly()) { 965 // Find the default setter and if one not found, add one. 966 if (!SetterMethod) { 967 // No instance method of same name as property setter name was found. 968 // Declare a setter method and add it to the list of methods 969 // for this class. 970 SetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(), 971 property->getLocation(), 972 property->getSetterName(), 973 Context.VoidTy, 0, CD, true, false, true, 974 (property->getPropertyImplementation() == 975 ObjCPropertyDecl::Optional) ? 976 ObjCMethodDecl::Optional : 977 ObjCMethodDecl::Required); 978 // Invent the arguments for the setter. We don't bother making a 979 // nice name for the argument. 980 ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, 981 property->getLocation(), 982 property->getIdentifier(), 983 property->getType(), 984 /*TInfo=*/0, 985 VarDecl::None, 986 VarDecl::None, 987 0); 988 SetterMethod->setMethodParams(Context, &Argument, 1, 1); 989 CD->addDecl(SetterMethod); 990 } else 991 // A user declared setter will be synthesize when @synthesize of 992 // the property with the same name is seen in the @implementation 993 SetterMethod->setSynthesized(true); 994 property->setSetterMethodDecl(SetterMethod); 995 } 996 // Add any synthesized methods to the global pool. This allows us to 997 // handle the following, which is supported by GCC (and part of the design). 998 // 999 // @interface Foo 1000 // @property double bar; 1001 // @end 1002 // 1003 // void thisIsUnfortunate() { 1004 // id foo; 1005 // double bar = [foo bar]; 1006 // } 1007 // 1008 if (GetterMethod) 1009 AddInstanceMethodToGlobalPool(GetterMethod); 1010 if (SetterMethod) 1011 AddInstanceMethodToGlobalPool(SetterMethod); 1012} 1013 1014void Sema::CheckObjCPropertyAttributes(DeclPtrTy PropertyPtrTy, 1015 SourceLocation Loc, 1016 unsigned &Attributes) { 1017 // FIXME: Improve the reported location. 1018 Decl *PDecl = PropertyPtrTy.getAs<Decl>(); 1019 if (!PDecl) 1020 return; 1021 1022 ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); 1023 QualType PropertyTy = PropertyDecl->getType(); 1024 1025 // readonly and readwrite/assign/retain/copy conflict. 1026 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1027 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite | 1028 ObjCDeclSpec::DQ_PR_assign | 1029 ObjCDeclSpec::DQ_PR_copy | 1030 ObjCDeclSpec::DQ_PR_retain))) { 1031 const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ? 1032 "readwrite" : 1033 (Attributes & ObjCDeclSpec::DQ_PR_assign) ? 1034 "assign" : 1035 (Attributes & ObjCDeclSpec::DQ_PR_copy) ? 1036 "copy" : "retain"; 1037 1038 Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ? 1039 diag::err_objc_property_attr_mutually_exclusive : 1040 diag::warn_objc_property_attr_mutually_exclusive) 1041 << "readonly" << which; 1042 } 1043 1044 // Check for copy or retain on non-object types. 1045 if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) && 1046 !PropertyTy->isObjCObjectPointerType() && 1047 !PropertyTy->isBlockPointerType() && 1048 !Context.isObjCNSObjectType(PropertyTy) && 1049 !PropertyDecl->getAttr<ObjCNSObjectAttr>()) { 1050 Diag(Loc, diag::err_objc_property_requires_object) 1051 << (Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain"); 1052 Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain); 1053 } 1054 1055 // Check for more than one of { assign, copy, retain }. 1056 if (Attributes & ObjCDeclSpec::DQ_PR_assign) { 1057 if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1058 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1059 << "assign" << "copy"; 1060 Attributes &= ~ObjCDeclSpec::DQ_PR_copy; 1061 } 1062 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1063 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1064 << "assign" << "retain"; 1065 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1066 } 1067 } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) { 1068 if (Attributes & ObjCDeclSpec::DQ_PR_retain) { 1069 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 1070 << "copy" << "retain"; 1071 Attributes &= ~ObjCDeclSpec::DQ_PR_retain; 1072 } 1073 } 1074 1075 // Warn if user supplied no assignment attribute, property is 1076 // readwrite, and this is an object type. 1077 if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy | 1078 ObjCDeclSpec::DQ_PR_retain)) && 1079 !(Attributes & ObjCDeclSpec::DQ_PR_readonly) && 1080 PropertyTy->isObjCObjectPointerType()) { 1081 // Skip this warning in gc-only mode. 1082 if (getLangOptions().getGCMode() != LangOptions::GCOnly) 1083 Diag(Loc, diag::warn_objc_property_no_assignment_attribute); 1084 1085 // If non-gc code warn that this is likely inappropriate. 1086 if (getLangOptions().getGCMode() == LangOptions::NonGC) 1087 Diag(Loc, diag::warn_objc_property_default_assign_on_object); 1088 1089 // FIXME: Implement warning dependent on NSCopying being 1090 // implemented. See also: 1091 // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496> 1092 // (please trim this list while you are at it). 1093 } 1094 1095 if (!(Attributes & ObjCDeclSpec::DQ_PR_copy) 1096 && getLangOptions().getGCMode() == LangOptions::GCOnly 1097 && PropertyTy->isBlockPointerType()) 1098 Diag(Loc, diag::warn_objc_property_copy_missing_on_block); 1099} 1100