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