1 //===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements semantic analysis for Objective C @property and 10 // @synthesize declarations. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/ASTMutationListener.h" 15 #include "clang/AST/DeclObjC.h" 16 #include "clang/AST/ExprCXX.h" 17 #include "clang/AST/ExprObjC.h" 18 #include "clang/Basic/SourceManager.h" 19 #include "clang/Lex/Lexer.h" 20 #include "clang/Lex/Preprocessor.h" 21 #include "clang/Sema/Initialization.h" 22 #include "clang/Sema/SemaObjC.h" 23 #include "llvm/ADT/DenseSet.h" 24 25 using namespace clang; 26 27 //===----------------------------------------------------------------------===// 28 // Grammar actions. 29 //===----------------------------------------------------------------------===// 30 31 /// getImpliedARCOwnership - Given a set of property attributes and a 32 /// type, infer an expected lifetime. The type's ownership qualification 33 /// is not considered. 34 /// 35 /// Returns OCL_None if the attributes as stated do not imply an ownership. 36 /// Never returns OCL_Autoreleasing. 37 static Qualifiers::ObjCLifetime 38 getImpliedARCOwnership(ObjCPropertyAttribute::Kind attrs, QualType type) { 39 // retain, strong, copy, weak, and unsafe_unretained are only legal 40 // on properties of retainable pointer type. 41 if (attrs & 42 (ObjCPropertyAttribute::kind_retain | ObjCPropertyAttribute::kind_strong | 43 ObjCPropertyAttribute::kind_copy)) { 44 return Qualifiers::OCL_Strong; 45 } else if (attrs & ObjCPropertyAttribute::kind_weak) { 46 return Qualifiers::OCL_Weak; 47 } else if (attrs & ObjCPropertyAttribute::kind_unsafe_unretained) { 48 return Qualifiers::OCL_ExplicitNone; 49 } 50 51 // assign can appear on other types, so we have to check the 52 // property type. 53 if (attrs & ObjCPropertyAttribute::kind_assign && 54 type->isObjCRetainableType()) { 55 return Qualifiers::OCL_ExplicitNone; 56 } 57 58 return Qualifiers::OCL_None; 59 } 60 61 /// Check the internal consistency of a property declaration with 62 /// an explicit ownership qualifier. 63 static void checkPropertyDeclWithOwnership(Sema &S, 64 ObjCPropertyDecl *property) { 65 if (property->isInvalidDecl()) return; 66 67 ObjCPropertyAttribute::Kind propertyKind = property->getPropertyAttributes(); 68 Qualifiers::ObjCLifetime propertyLifetime 69 = property->getType().getObjCLifetime(); 70 71 assert(propertyLifetime != Qualifiers::OCL_None); 72 73 Qualifiers::ObjCLifetime expectedLifetime 74 = getImpliedARCOwnership(propertyKind, property->getType()); 75 if (!expectedLifetime) { 76 // We have a lifetime qualifier but no dominating property 77 // attribute. That's okay, but restore reasonable invariants by 78 // setting the property attribute according to the lifetime 79 // qualifier. 80 ObjCPropertyAttribute::Kind attr; 81 if (propertyLifetime == Qualifiers::OCL_Strong) { 82 attr = ObjCPropertyAttribute::kind_strong; 83 } else if (propertyLifetime == Qualifiers::OCL_Weak) { 84 attr = ObjCPropertyAttribute::kind_weak; 85 } else { 86 assert(propertyLifetime == Qualifiers::OCL_ExplicitNone); 87 attr = ObjCPropertyAttribute::kind_unsafe_unretained; 88 } 89 property->setPropertyAttributes(attr); 90 return; 91 } 92 93 if (propertyLifetime == expectedLifetime) return; 94 95 property->setInvalidDecl(); 96 S.Diag(property->getLocation(), 97 diag::err_arc_inconsistent_property_ownership) 98 << property->getDeclName() 99 << expectedLifetime 100 << propertyLifetime; 101 } 102 103 /// Check this Objective-C property against a property declared in the 104 /// given protocol. 105 static void 106 CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, 107 ObjCProtocolDecl *Proto, 108 llvm::SmallPtrSetImpl<ObjCProtocolDecl *> &Known) { 109 // Have we seen this protocol before? 110 if (!Known.insert(Proto).second) 111 return; 112 113 // Look for a property with the same name. 114 if (ObjCPropertyDecl *ProtoProp = Proto->getProperty( 115 Prop->getIdentifier(), Prop->isInstanceProperty())) { 116 S.ObjC().DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), 117 true); 118 return; 119 } 120 121 // Check this property against any protocols we inherit. 122 for (auto *P : Proto->protocols()) 123 CheckPropertyAgainstProtocol(S, Prop, P, Known); 124 } 125 126 static unsigned deducePropertyOwnershipFromType(Sema &S, QualType T) { 127 // In GC mode, just look for the __weak qualifier. 128 if (S.getLangOpts().getGC() != LangOptions::NonGC) { 129 if (T.isObjCGCWeak()) 130 return ObjCPropertyAttribute::kind_weak; 131 132 // In ARC/MRC, look for an explicit ownership qualifier. 133 // For some reason, this only applies to __weak. 134 } else if (auto ownership = T.getObjCLifetime()) { 135 switch (ownership) { 136 case Qualifiers::OCL_Weak: 137 return ObjCPropertyAttribute::kind_weak; 138 case Qualifiers::OCL_Strong: 139 return ObjCPropertyAttribute::kind_strong; 140 case Qualifiers::OCL_ExplicitNone: 141 return ObjCPropertyAttribute::kind_unsafe_unretained; 142 case Qualifiers::OCL_Autoreleasing: 143 case Qualifiers::OCL_None: 144 return 0; 145 } 146 llvm_unreachable("bad qualifier"); 147 } 148 149 return 0; 150 } 151 152 static const unsigned OwnershipMask = 153 (ObjCPropertyAttribute::kind_assign | ObjCPropertyAttribute::kind_retain | 154 ObjCPropertyAttribute::kind_copy | ObjCPropertyAttribute::kind_weak | 155 ObjCPropertyAttribute::kind_strong | 156 ObjCPropertyAttribute::kind_unsafe_unretained); 157 158 static unsigned getOwnershipRule(unsigned attr) { 159 unsigned result = attr & OwnershipMask; 160 161 // From an ownership perspective, assign and unsafe_unretained are 162 // identical; make sure one also implies the other. 163 if (result & (ObjCPropertyAttribute::kind_assign | 164 ObjCPropertyAttribute::kind_unsafe_unretained)) { 165 result |= ObjCPropertyAttribute::kind_assign | 166 ObjCPropertyAttribute::kind_unsafe_unretained; 167 } 168 169 return result; 170 } 171 172 Decl *SemaObjC::ActOnProperty(Scope *S, SourceLocation AtLoc, 173 SourceLocation LParenLoc, FieldDeclarator &FD, 174 ObjCDeclSpec &ODS, Selector GetterSel, 175 Selector SetterSel, 176 tok::ObjCKeywordKind MethodImplKind, 177 DeclContext *lexicalDC) { 178 unsigned Attributes = ODS.getPropertyAttributes(); 179 FD.D.setObjCWeakProperty((Attributes & ObjCPropertyAttribute::kind_weak) != 180 0); 181 TypeSourceInfo *TSI = SemaRef.GetTypeForDeclarator(FD.D); 182 QualType T = TSI->getType(); 183 if (!getOwnershipRule(Attributes)) { 184 Attributes |= deducePropertyOwnershipFromType(SemaRef, T); 185 } 186 bool isReadWrite = ((Attributes & ObjCPropertyAttribute::kind_readwrite) || 187 // default is readwrite! 188 !(Attributes & ObjCPropertyAttribute::kind_readonly)); 189 190 // Proceed with constructing the ObjCPropertyDecls. 191 ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(SemaRef.CurContext); 192 ObjCPropertyDecl *Res = nullptr; 193 if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 194 if (CDecl->IsClassExtension()) { 195 Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc, 196 FD, 197 GetterSel, ODS.getGetterNameLoc(), 198 SetterSel, ODS.getSetterNameLoc(), 199 isReadWrite, Attributes, 200 ODS.getPropertyAttributes(), 201 T, TSI, MethodImplKind); 202 if (!Res) 203 return nullptr; 204 } 205 } 206 207 if (!Res) { 208 Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD, 209 GetterSel, ODS.getGetterNameLoc(), SetterSel, 210 ODS.getSetterNameLoc(), isReadWrite, Attributes, 211 ODS.getPropertyAttributes(), T, TSI, 212 MethodImplKind); 213 if (lexicalDC) 214 Res->setLexicalDeclContext(lexicalDC); 215 } 216 217 // Validate the attributes on the @property. 218 CheckObjCPropertyAttributes(Res, AtLoc, Attributes, 219 (isa<ObjCInterfaceDecl>(ClassDecl) || 220 isa<ObjCProtocolDecl>(ClassDecl))); 221 222 // Check consistency if the type has explicit ownership qualification. 223 if (Res->getType().getObjCLifetime()) 224 checkPropertyDeclWithOwnership(SemaRef, Res); 225 226 llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos; 227 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { 228 // For a class, compare the property against a property in our superclass. 229 bool FoundInSuper = false; 230 ObjCInterfaceDecl *CurrentInterfaceDecl = IFace; 231 while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) { 232 if (ObjCPropertyDecl *SuperProp = Super->getProperty( 233 Res->getIdentifier(), Res->isInstanceProperty())) { 234 DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false); 235 FoundInSuper = true; 236 break; 237 } 238 CurrentInterfaceDecl = Super; 239 } 240 241 if (FoundInSuper) { 242 // Also compare the property against a property in our protocols. 243 for (auto *P : CurrentInterfaceDecl->protocols()) { 244 CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos); 245 } 246 } else { 247 // Slower path: look in all protocols we referenced. 248 for (auto *P : IFace->all_referenced_protocols()) { 249 CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos); 250 } 251 } 252 } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 253 // We don't check if class extension. Because properties in class extension 254 // are meant to override some of the attributes and checking has already done 255 // when property in class extension is constructed. 256 if (!Cat->IsClassExtension()) 257 for (auto *P : Cat->protocols()) 258 CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos); 259 } else { 260 ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl); 261 for (auto *P : Proto->protocols()) 262 CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos); 263 } 264 265 SemaRef.ActOnDocumentableDecl(Res); 266 return Res; 267 } 268 269 static ObjCPropertyAttribute::Kind 270 makePropertyAttributesAsWritten(unsigned Attributes) { 271 unsigned attributesAsWritten = 0; 272 if (Attributes & ObjCPropertyAttribute::kind_readonly) 273 attributesAsWritten |= ObjCPropertyAttribute::kind_readonly; 274 if (Attributes & ObjCPropertyAttribute::kind_readwrite) 275 attributesAsWritten |= ObjCPropertyAttribute::kind_readwrite; 276 if (Attributes & ObjCPropertyAttribute::kind_getter) 277 attributesAsWritten |= ObjCPropertyAttribute::kind_getter; 278 if (Attributes & ObjCPropertyAttribute::kind_setter) 279 attributesAsWritten |= ObjCPropertyAttribute::kind_setter; 280 if (Attributes & ObjCPropertyAttribute::kind_assign) 281 attributesAsWritten |= ObjCPropertyAttribute::kind_assign; 282 if (Attributes & ObjCPropertyAttribute::kind_retain) 283 attributesAsWritten |= ObjCPropertyAttribute::kind_retain; 284 if (Attributes & ObjCPropertyAttribute::kind_strong) 285 attributesAsWritten |= ObjCPropertyAttribute::kind_strong; 286 if (Attributes & ObjCPropertyAttribute::kind_weak) 287 attributesAsWritten |= ObjCPropertyAttribute::kind_weak; 288 if (Attributes & ObjCPropertyAttribute::kind_copy) 289 attributesAsWritten |= ObjCPropertyAttribute::kind_copy; 290 if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) 291 attributesAsWritten |= ObjCPropertyAttribute::kind_unsafe_unretained; 292 if (Attributes & ObjCPropertyAttribute::kind_nonatomic) 293 attributesAsWritten |= ObjCPropertyAttribute::kind_nonatomic; 294 if (Attributes & ObjCPropertyAttribute::kind_atomic) 295 attributesAsWritten |= ObjCPropertyAttribute::kind_atomic; 296 if (Attributes & ObjCPropertyAttribute::kind_class) 297 attributesAsWritten |= ObjCPropertyAttribute::kind_class; 298 if (Attributes & ObjCPropertyAttribute::kind_direct) 299 attributesAsWritten |= ObjCPropertyAttribute::kind_direct; 300 301 return (ObjCPropertyAttribute::Kind)attributesAsWritten; 302 } 303 304 static bool LocPropertyAttribute( ASTContext &Context, const char *attrName, 305 SourceLocation LParenLoc, SourceLocation &Loc) { 306 if (LParenLoc.isMacroID()) 307 return false; 308 309 SourceManager &SM = Context.getSourceManager(); 310 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(LParenLoc); 311 // Try to load the file buffer. 312 bool invalidTemp = false; 313 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp); 314 if (invalidTemp) 315 return false; 316 const char *tokenBegin = file.data() + locInfo.second; 317 318 // Lex from the start of the given location. 319 Lexer lexer(SM.getLocForStartOfFile(locInfo.first), 320 Context.getLangOpts(), 321 file.begin(), tokenBegin, file.end()); 322 Token Tok; 323 do { 324 lexer.LexFromRawLexer(Tok); 325 if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) { 326 Loc = Tok.getLocation(); 327 return true; 328 } 329 } while (Tok.isNot(tok::r_paren)); 330 return false; 331 } 332 333 /// Check for a mismatch in the atomicity of the given properties. 334 static void checkAtomicPropertyMismatch(Sema &S, 335 ObjCPropertyDecl *OldProperty, 336 ObjCPropertyDecl *NewProperty, 337 bool PropagateAtomicity) { 338 // If the atomicity of both matches, we're done. 339 bool OldIsAtomic = (OldProperty->getPropertyAttributes() & 340 ObjCPropertyAttribute::kind_nonatomic) == 0; 341 bool NewIsAtomic = (NewProperty->getPropertyAttributes() & 342 ObjCPropertyAttribute::kind_nonatomic) == 0; 343 if (OldIsAtomic == NewIsAtomic) return; 344 345 // Determine whether the given property is readonly and implicitly 346 // atomic. 347 auto isImplicitlyReadonlyAtomic = [](ObjCPropertyDecl *Property) -> bool { 348 // Is it readonly? 349 auto Attrs = Property->getPropertyAttributes(); 350 if ((Attrs & ObjCPropertyAttribute::kind_readonly) == 0) 351 return false; 352 353 // Is it nonatomic? 354 if (Attrs & ObjCPropertyAttribute::kind_nonatomic) 355 return false; 356 357 // Was 'atomic' specified directly? 358 if (Property->getPropertyAttributesAsWritten() & 359 ObjCPropertyAttribute::kind_atomic) 360 return false; 361 362 return true; 363 }; 364 365 // If we're allowed to propagate atomicity, and the new property did 366 // not specify atomicity at all, propagate. 367 const unsigned AtomicityMask = (ObjCPropertyAttribute::kind_atomic | 368 ObjCPropertyAttribute::kind_nonatomic); 369 if (PropagateAtomicity && 370 ((NewProperty->getPropertyAttributesAsWritten() & AtomicityMask) == 0)) { 371 unsigned Attrs = NewProperty->getPropertyAttributes(); 372 Attrs = Attrs & ~AtomicityMask; 373 if (OldIsAtomic) 374 Attrs |= ObjCPropertyAttribute::kind_atomic; 375 else 376 Attrs |= ObjCPropertyAttribute::kind_nonatomic; 377 378 NewProperty->overwritePropertyAttributes(Attrs); 379 return; 380 } 381 382 // One of the properties is atomic; if it's a readonly property, and 383 // 'atomic' wasn't explicitly specified, we're okay. 384 if ((OldIsAtomic && isImplicitlyReadonlyAtomic(OldProperty)) || 385 (NewIsAtomic && isImplicitlyReadonlyAtomic(NewProperty))) 386 return; 387 388 // Diagnose the conflict. 389 const IdentifierInfo *OldContextName; 390 auto *OldDC = OldProperty->getDeclContext(); 391 if (auto Category = dyn_cast<ObjCCategoryDecl>(OldDC)) 392 OldContextName = Category->getClassInterface()->getIdentifier(); 393 else 394 OldContextName = cast<ObjCContainerDecl>(OldDC)->getIdentifier(); 395 396 S.Diag(NewProperty->getLocation(), diag::warn_property_attribute) 397 << NewProperty->getDeclName() << "atomic" 398 << OldContextName; 399 S.Diag(OldProperty->getLocation(), diag::note_property_declare); 400 } 401 402 ObjCPropertyDecl *SemaObjC::HandlePropertyInClassExtension( 403 Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, 404 FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc, 405 Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite, 406 unsigned &Attributes, const unsigned AttributesAsWritten, QualType T, 407 TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind) { 408 ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(SemaRef.CurContext); 409 // Diagnose if this property is already in continuation class. 410 DeclContext *DC = SemaRef.CurContext; 411 const IdentifierInfo *PropertyId = FD.D.getIdentifier(); 412 ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface(); 413 414 // We need to look in the @interface to see if the @property was 415 // already declared. 416 if (!CCPrimary) { 417 Diag(CDecl->getLocation(), diag::err_continuation_class); 418 return nullptr; 419 } 420 421 bool isClassProperty = 422 (AttributesAsWritten & ObjCPropertyAttribute::kind_class) || 423 (Attributes & ObjCPropertyAttribute::kind_class); 424 425 // Find the property in the extended class's primary class or 426 // extensions. 427 ObjCPropertyDecl *PIDecl = CCPrimary->FindPropertyVisibleInPrimaryClass( 428 PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty)); 429 430 // If we found a property in an extension, complain. 431 if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) { 432 Diag(AtLoc, diag::err_duplicate_property); 433 Diag(PIDecl->getLocation(), diag::note_property_declare); 434 return nullptr; 435 } 436 437 // Check for consistency with the previous declaration, if there is one. 438 if (PIDecl) { 439 // A readonly property declared in the primary class can be refined 440 // by adding a readwrite property within an extension. 441 // Anything else is an error. 442 if (!(PIDecl->isReadOnly() && isReadWrite)) { 443 // Tailor the diagnostics for the common case where a readwrite 444 // property is declared both in the @interface and the continuation. 445 // This is a common error where the user often intended the original 446 // declaration to be readonly. 447 unsigned diag = 448 (Attributes & ObjCPropertyAttribute::kind_readwrite) && 449 (PIDecl->getPropertyAttributesAsWritten() & 450 ObjCPropertyAttribute::kind_readwrite) 451 ? diag::err_use_continuation_class_redeclaration_readwrite 452 : diag::err_use_continuation_class; 453 Diag(AtLoc, diag) 454 << CCPrimary->getDeclName(); 455 Diag(PIDecl->getLocation(), diag::note_property_declare); 456 return nullptr; 457 } 458 459 // Check for consistency of getters. 460 if (PIDecl->getGetterName() != GetterSel) { 461 // If the getter was written explicitly, complain. 462 if (AttributesAsWritten & ObjCPropertyAttribute::kind_getter) { 463 Diag(AtLoc, diag::warn_property_redecl_getter_mismatch) 464 << PIDecl->getGetterName() << GetterSel; 465 Diag(PIDecl->getLocation(), diag::note_property_declare); 466 } 467 468 // Always adopt the getter from the original declaration. 469 GetterSel = PIDecl->getGetterName(); 470 Attributes |= ObjCPropertyAttribute::kind_getter; 471 } 472 473 // Check consistency of ownership. 474 unsigned ExistingOwnership 475 = getOwnershipRule(PIDecl->getPropertyAttributes()); 476 unsigned NewOwnership = getOwnershipRule(Attributes); 477 if (ExistingOwnership && NewOwnership != ExistingOwnership) { 478 // If the ownership was written explicitly, complain. 479 if (getOwnershipRule(AttributesAsWritten)) { 480 Diag(AtLoc, diag::warn_property_attr_mismatch); 481 Diag(PIDecl->getLocation(), diag::note_property_declare); 482 } 483 484 // Take the ownership from the original property. 485 Attributes = (Attributes & ~OwnershipMask) | ExistingOwnership; 486 } 487 488 // If the redeclaration is 'weak' but the original property is not, 489 if ((Attributes & ObjCPropertyAttribute::kind_weak) && 490 !(PIDecl->getPropertyAttributesAsWritten() & 491 ObjCPropertyAttribute::kind_weak) && 492 PIDecl->getType()->getAs<ObjCObjectPointerType>() && 493 PIDecl->getType().getObjCLifetime() == Qualifiers::OCL_None) { 494 Diag(AtLoc, diag::warn_property_implicitly_mismatched); 495 Diag(PIDecl->getLocation(), diag::note_property_declare); 496 } 497 } 498 499 // Create a new ObjCPropertyDecl with the DeclContext being 500 // the class extension. 501 ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc, 502 FD, GetterSel, GetterNameLoc, 503 SetterSel, SetterNameLoc, 504 isReadWrite, 505 Attributes, AttributesAsWritten, 506 T, TSI, MethodImplKind, DC); 507 ASTContext &Context = getASTContext(); 508 // If there was no declaration of a property with the same name in 509 // the primary class, we're done. 510 if (!PIDecl) { 511 ProcessPropertyDecl(PDecl); 512 return PDecl; 513 } 514 515 if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) { 516 bool IncompatibleObjC = false; 517 QualType ConvertedType; 518 // Relax the strict type matching for property type in continuation class. 519 // Allow property object type of continuation class to be different as long 520 // as it narrows the object type in its primary class property. Note that 521 // this conversion is safe only because the wider type is for a 'readonly' 522 // property in primary class and 'narrowed' type for a 'readwrite' property 523 // in continuation class. 524 QualType PrimaryClassPropertyT = Context.getCanonicalType(PIDecl->getType()); 525 QualType ClassExtPropertyT = Context.getCanonicalType(PDecl->getType()); 526 if (!isa<ObjCObjectPointerType>(PrimaryClassPropertyT) || 527 !isa<ObjCObjectPointerType>(ClassExtPropertyT) || 528 (!SemaRef.isObjCPointerConversion(ClassExtPropertyT, 529 PrimaryClassPropertyT, ConvertedType, 530 IncompatibleObjC)) || 531 IncompatibleObjC) { 532 Diag(AtLoc, 533 diag::err_type_mismatch_continuation_class) << PDecl->getType(); 534 Diag(PIDecl->getLocation(), diag::note_property_declare); 535 return nullptr; 536 } 537 } 538 539 // Check that atomicity of property in class extension matches the previous 540 // declaration. 541 checkAtomicPropertyMismatch(SemaRef, PIDecl, PDecl, true); 542 543 // Make sure getter/setter are appropriately synthesized. 544 ProcessPropertyDecl(PDecl); 545 return PDecl; 546 } 547 548 ObjCPropertyDecl *SemaObjC::CreatePropertyDecl( 549 Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, 550 SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, 551 SourceLocation GetterNameLoc, Selector SetterSel, 552 SourceLocation SetterNameLoc, const bool isReadWrite, 553 const unsigned Attributes, const unsigned AttributesAsWritten, QualType T, 554 TypeSourceInfo *TInfo, tok::ObjCKeywordKind MethodImplKind, 555 DeclContext *lexicalDC) { 556 ASTContext &Context = getASTContext(); 557 const IdentifierInfo *PropertyId = FD.D.getIdentifier(); 558 559 // Property defaults to 'assign' if it is readwrite, unless this is ARC 560 // and the type is retainable. 561 bool isAssign; 562 if (Attributes & (ObjCPropertyAttribute::kind_assign | 563 ObjCPropertyAttribute::kind_unsafe_unretained)) { 564 isAssign = true; 565 } else if (getOwnershipRule(Attributes) || !isReadWrite) { 566 isAssign = false; 567 } else { 568 isAssign = (!getLangOpts().ObjCAutoRefCount || 569 !T->isObjCRetainableType()); 570 } 571 572 // Issue a warning if property is 'assign' as default and its 573 // object, which is gc'able conforms to NSCopying protocol 574 if (getLangOpts().getGC() != LangOptions::NonGC && isAssign && 575 !(Attributes & ObjCPropertyAttribute::kind_assign)) { 576 if (const ObjCObjectPointerType *ObjPtrTy = 577 T->getAs<ObjCObjectPointerType>()) { 578 ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); 579 if (IDecl) 580 if (ObjCProtocolDecl* PNSCopying = 581 LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc)) 582 if (IDecl->ClassImplementsProtocol(PNSCopying, true)) 583 Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId; 584 } 585 } 586 587 if (T->isObjCObjectType()) { 588 SourceLocation StarLoc = TInfo->getTypeLoc().getEndLoc(); 589 StarLoc = SemaRef.getLocForEndOfToken(StarLoc); 590 Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object) 591 << FixItHint::CreateInsertion(StarLoc, "*"); 592 T = Context.getObjCObjectPointerType(T); 593 SourceLocation TLoc = TInfo->getTypeLoc().getBeginLoc(); 594 TInfo = Context.getTrivialTypeSourceInfo(T, TLoc); 595 } 596 597 DeclContext *DC = CDecl; 598 ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, 599 FD.D.getIdentifierLoc(), 600 PropertyId, AtLoc, 601 LParenLoc, T, TInfo); 602 603 bool isClassProperty = 604 (AttributesAsWritten & ObjCPropertyAttribute::kind_class) || 605 (Attributes & ObjCPropertyAttribute::kind_class); 606 // Class property and instance property can have the same name. 607 if (ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl( 608 DC, PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty))) { 609 Diag(PDecl->getLocation(), diag::err_duplicate_property); 610 Diag(prevDecl->getLocation(), diag::note_property_declare); 611 PDecl->setInvalidDecl(); 612 } 613 else { 614 DC->addDecl(PDecl); 615 if (lexicalDC) 616 PDecl->setLexicalDeclContext(lexicalDC); 617 } 618 619 if (T->isArrayType() || T->isFunctionType()) { 620 Diag(AtLoc, diag::err_property_type) << T; 621 PDecl->setInvalidDecl(); 622 } 623 624 // Regardless of setter/getter attribute, we save the default getter/setter 625 // selector names in anticipation of declaration of setter/getter methods. 626 PDecl->setGetterName(GetterSel, GetterNameLoc); 627 PDecl->setSetterName(SetterSel, SetterNameLoc); 628 PDecl->setPropertyAttributesAsWritten( 629 makePropertyAttributesAsWritten(AttributesAsWritten)); 630 631 SemaRef.ProcessDeclAttributes(S, PDecl, FD.D); 632 633 if (Attributes & ObjCPropertyAttribute::kind_readonly) 634 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly); 635 636 if (Attributes & ObjCPropertyAttribute::kind_getter) 637 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_getter); 638 639 if (Attributes & ObjCPropertyAttribute::kind_setter) 640 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_setter); 641 642 if (isReadWrite) 643 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite); 644 645 if (Attributes & ObjCPropertyAttribute::kind_retain) 646 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_retain); 647 648 if (Attributes & ObjCPropertyAttribute::kind_strong) 649 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_strong); 650 651 if (Attributes & ObjCPropertyAttribute::kind_weak) 652 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_weak); 653 654 if (Attributes & ObjCPropertyAttribute::kind_copy) 655 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_copy); 656 657 if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) 658 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained); 659 660 if (isAssign) 661 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_assign); 662 663 // In the semantic attributes, one of nonatomic or atomic is always set. 664 if (Attributes & ObjCPropertyAttribute::kind_nonatomic) 665 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic); 666 else 667 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_atomic); 668 669 // 'unsafe_unretained' is alias for 'assign'. 670 if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) 671 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_assign); 672 if (isAssign) 673 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained); 674 675 if (MethodImplKind == tok::objc_required) 676 PDecl->setPropertyImplementation(ObjCPropertyDecl::Required); 677 else if (MethodImplKind == tok::objc_optional) 678 PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional); 679 680 if (Attributes & ObjCPropertyAttribute::kind_nullability) 681 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_nullability); 682 683 if (Attributes & ObjCPropertyAttribute::kind_null_resettable) 684 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable); 685 686 if (Attributes & ObjCPropertyAttribute::kind_class) 687 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_class); 688 689 if ((Attributes & ObjCPropertyAttribute::kind_direct) || 690 CDecl->hasAttr<ObjCDirectMembersAttr>()) { 691 if (isa<ObjCProtocolDecl>(CDecl)) { 692 Diag(PDecl->getLocation(), diag::err_objc_direct_on_protocol) << true; 693 } else if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) { 694 PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_direct); 695 } else { 696 Diag(PDecl->getLocation(), diag::warn_objc_direct_property_ignored) 697 << PDecl->getDeclName(); 698 } 699 } 700 701 return PDecl; 702 } 703 704 static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, 705 ObjCPropertyDecl *property, 706 ObjCIvarDecl *ivar) { 707 if (property->isInvalidDecl() || ivar->isInvalidDecl()) return; 708 709 QualType ivarType = ivar->getType(); 710 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); 711 712 // The lifetime implied by the property's attributes. 713 Qualifiers::ObjCLifetime propertyLifetime = 714 getImpliedARCOwnership(property->getPropertyAttributes(), 715 property->getType()); 716 717 // We're fine if they match. 718 if (propertyLifetime == ivarLifetime) return; 719 720 // None isn't a valid lifetime for an object ivar in ARC, and 721 // __autoreleasing is never valid; don't diagnose twice. 722 if ((ivarLifetime == Qualifiers::OCL_None && 723 S.getLangOpts().ObjCAutoRefCount) || 724 ivarLifetime == Qualifiers::OCL_Autoreleasing) 725 return; 726 727 // If the ivar is private, and it's implicitly __unsafe_unretained 728 // because of its type, then pretend it was actually implicitly 729 // __strong. This is only sound because we're processing the 730 // property implementation before parsing any method bodies. 731 if (ivarLifetime == Qualifiers::OCL_ExplicitNone && 732 propertyLifetime == Qualifiers::OCL_Strong && 733 ivar->getAccessControl() == ObjCIvarDecl::Private) { 734 SplitQualType split = ivarType.split(); 735 if (split.Quals.hasObjCLifetime()) { 736 assert(ivarType->isObjCARCImplicitlyUnretainedType()); 737 split.Quals.setObjCLifetime(Qualifiers::OCL_Strong); 738 ivarType = S.Context.getQualifiedType(split); 739 ivar->setType(ivarType); 740 return; 741 } 742 } 743 744 switch (propertyLifetime) { 745 case Qualifiers::OCL_Strong: 746 S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership) 747 << property->getDeclName() 748 << ivar->getDeclName() 749 << ivarLifetime; 750 break; 751 752 case Qualifiers::OCL_Weak: 753 S.Diag(ivar->getLocation(), diag::err_weak_property) 754 << property->getDeclName() 755 << ivar->getDeclName(); 756 break; 757 758 case Qualifiers::OCL_ExplicitNone: 759 S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership) 760 << property->getDeclName() << ivar->getDeclName() 761 << ((property->getPropertyAttributesAsWritten() & 762 ObjCPropertyAttribute::kind_assign) != 0); 763 break; 764 765 case Qualifiers::OCL_Autoreleasing: 766 llvm_unreachable("properties cannot be autoreleasing"); 767 768 case Qualifiers::OCL_None: 769 // Any other property should be ignored. 770 return; 771 } 772 773 S.Diag(property->getLocation(), diag::note_property_declare); 774 if (propertyImplLoc.isValid()) 775 S.Diag(propertyImplLoc, diag::note_property_synthesize); 776 } 777 778 /// setImpliedPropertyAttributeForReadOnlyProperty - 779 /// This routine evaludates life-time attributes for a 'readonly' 780 /// property with no known lifetime of its own, using backing 781 /// 'ivar's attribute, if any. If no backing 'ivar', property's 782 /// life-time is assumed 'strong'. 783 static void setImpliedPropertyAttributeForReadOnlyProperty( 784 ObjCPropertyDecl *property, ObjCIvarDecl *ivar) { 785 Qualifiers::ObjCLifetime propertyLifetime = 786 getImpliedARCOwnership(property->getPropertyAttributes(), 787 property->getType()); 788 if (propertyLifetime != Qualifiers::OCL_None) 789 return; 790 791 if (!ivar) { 792 // if no backing ivar, make property 'strong'. 793 property->setPropertyAttributes(ObjCPropertyAttribute::kind_strong); 794 return; 795 } 796 // property assumes owenership of backing ivar. 797 QualType ivarType = ivar->getType(); 798 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime(); 799 if (ivarLifetime == Qualifiers::OCL_Strong) 800 property->setPropertyAttributes(ObjCPropertyAttribute::kind_strong); 801 else if (ivarLifetime == Qualifiers::OCL_Weak) 802 property->setPropertyAttributes(ObjCPropertyAttribute::kind_weak); 803 } 804 805 static bool isIncompatiblePropertyAttribute(unsigned Attr1, unsigned Attr2, 806 ObjCPropertyAttribute::Kind Kind) { 807 return (Attr1 & Kind) != (Attr2 & Kind); 808 } 809 810 static bool areIncompatiblePropertyAttributes(unsigned Attr1, unsigned Attr2, 811 unsigned Kinds) { 812 return ((Attr1 & Kinds) != 0) != ((Attr2 & Kinds) != 0); 813 } 814 815 /// SelectPropertyForSynthesisFromProtocols - Finds the most appropriate 816 /// property declaration that should be synthesised in all of the inherited 817 /// protocols. It also diagnoses properties declared in inherited protocols with 818 /// mismatched types or attributes, since any of them can be candidate for 819 /// synthesis. 820 static ObjCPropertyDecl * 821 SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc, 822 ObjCInterfaceDecl *ClassDecl, 823 ObjCPropertyDecl *Property) { 824 assert(isa<ObjCProtocolDecl>(Property->getDeclContext()) && 825 "Expected a property from a protocol"); 826 ObjCInterfaceDecl::ProtocolPropertySet ProtocolSet; 827 ObjCInterfaceDecl::PropertyDeclOrder Properties; 828 for (const auto *PI : ClassDecl->all_referenced_protocols()) { 829 if (const ObjCProtocolDecl *PDecl = PI->getDefinition()) 830 PDecl->collectInheritedProtocolProperties(Property, ProtocolSet, 831 Properties); 832 } 833 if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass()) { 834 while (SDecl) { 835 for (const auto *PI : SDecl->all_referenced_protocols()) { 836 if (const ObjCProtocolDecl *PDecl = PI->getDefinition()) 837 PDecl->collectInheritedProtocolProperties(Property, ProtocolSet, 838 Properties); 839 } 840 SDecl = SDecl->getSuperClass(); 841 } 842 } 843 844 if (Properties.empty()) 845 return Property; 846 847 ObjCPropertyDecl *OriginalProperty = Property; 848 size_t SelectedIndex = 0; 849 for (const auto &Prop : llvm::enumerate(Properties)) { 850 // Select the 'readwrite' property if such property exists. 851 if (Property->isReadOnly() && !Prop.value()->isReadOnly()) { 852 Property = Prop.value(); 853 SelectedIndex = Prop.index(); 854 } 855 } 856 if (Property != OriginalProperty) { 857 // Check that the old property is compatible with the new one. 858 Properties[SelectedIndex] = OriginalProperty; 859 } 860 861 QualType RHSType = S.Context.getCanonicalType(Property->getType()); 862 unsigned OriginalAttributes = Property->getPropertyAttributesAsWritten(); 863 enum MismatchKind { 864 IncompatibleType = 0, 865 HasNoExpectedAttribute, 866 HasUnexpectedAttribute, 867 DifferentGetter, 868 DifferentSetter 869 }; 870 // Represents a property from another protocol that conflicts with the 871 // selected declaration. 872 struct MismatchingProperty { 873 const ObjCPropertyDecl *Prop; 874 MismatchKind Kind; 875 StringRef AttributeName; 876 }; 877 SmallVector<MismatchingProperty, 4> Mismatches; 878 for (ObjCPropertyDecl *Prop : Properties) { 879 // Verify the property attributes. 880 unsigned Attr = Prop->getPropertyAttributesAsWritten(); 881 if (Attr != OriginalAttributes) { 882 auto Diag = [&](bool OriginalHasAttribute, StringRef AttributeName) { 883 MismatchKind Kind = OriginalHasAttribute ? HasNoExpectedAttribute 884 : HasUnexpectedAttribute; 885 Mismatches.push_back({Prop, Kind, AttributeName}); 886 }; 887 // The ownership might be incompatible unless the property has no explicit 888 // ownership. 889 bool HasOwnership = 890 (Attr & (ObjCPropertyAttribute::kind_retain | 891 ObjCPropertyAttribute::kind_strong | 892 ObjCPropertyAttribute::kind_copy | 893 ObjCPropertyAttribute::kind_assign | 894 ObjCPropertyAttribute::kind_unsafe_unretained | 895 ObjCPropertyAttribute::kind_weak)) != 0; 896 if (HasOwnership && 897 isIncompatiblePropertyAttribute(OriginalAttributes, Attr, 898 ObjCPropertyAttribute::kind_copy)) { 899 Diag(OriginalAttributes & ObjCPropertyAttribute::kind_copy, "copy"); 900 continue; 901 } 902 if (HasOwnership && areIncompatiblePropertyAttributes( 903 OriginalAttributes, Attr, 904 ObjCPropertyAttribute::kind_retain | 905 ObjCPropertyAttribute::kind_strong)) { 906 Diag(OriginalAttributes & (ObjCPropertyAttribute::kind_retain | 907 ObjCPropertyAttribute::kind_strong), 908 "retain (or strong)"); 909 continue; 910 } 911 if (isIncompatiblePropertyAttribute(OriginalAttributes, Attr, 912 ObjCPropertyAttribute::kind_atomic)) { 913 Diag(OriginalAttributes & ObjCPropertyAttribute::kind_atomic, "atomic"); 914 continue; 915 } 916 } 917 if (Property->getGetterName() != Prop->getGetterName()) { 918 Mismatches.push_back({Prop, DifferentGetter, ""}); 919 continue; 920 } 921 if (!Property->isReadOnly() && !Prop->isReadOnly() && 922 Property->getSetterName() != Prop->getSetterName()) { 923 Mismatches.push_back({Prop, DifferentSetter, ""}); 924 continue; 925 } 926 QualType LHSType = S.Context.getCanonicalType(Prop->getType()); 927 if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) { 928 bool IncompatibleObjC = false; 929 QualType ConvertedType; 930 if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC) 931 || IncompatibleObjC) { 932 Mismatches.push_back({Prop, IncompatibleType, ""}); 933 continue; 934 } 935 } 936 } 937 938 if (Mismatches.empty()) 939 return Property; 940 941 // Diagnose incompability. 942 { 943 bool HasIncompatibleAttributes = false; 944 for (const auto &Note : Mismatches) 945 HasIncompatibleAttributes = 946 Note.Kind != IncompatibleType ? true : HasIncompatibleAttributes; 947 // Promote the warning to an error if there are incompatible attributes or 948 // incompatible types together with readwrite/readonly incompatibility. 949 auto Diag = S.Diag(Property->getLocation(), 950 Property != OriginalProperty || HasIncompatibleAttributes 951 ? diag::err_protocol_property_mismatch 952 : diag::warn_protocol_property_mismatch); 953 Diag << Mismatches[0].Kind; 954 switch (Mismatches[0].Kind) { 955 case IncompatibleType: 956 Diag << Property->getType(); 957 break; 958 case HasNoExpectedAttribute: 959 case HasUnexpectedAttribute: 960 Diag << Mismatches[0].AttributeName; 961 break; 962 case DifferentGetter: 963 Diag << Property->getGetterName(); 964 break; 965 case DifferentSetter: 966 Diag << Property->getSetterName(); 967 break; 968 } 969 } 970 for (const auto &Note : Mismatches) { 971 auto Diag = 972 S.Diag(Note.Prop->getLocation(), diag::note_protocol_property_declare) 973 << Note.Kind; 974 switch (Note.Kind) { 975 case IncompatibleType: 976 Diag << Note.Prop->getType(); 977 break; 978 case HasNoExpectedAttribute: 979 case HasUnexpectedAttribute: 980 Diag << Note.AttributeName; 981 break; 982 case DifferentGetter: 983 Diag << Note.Prop->getGetterName(); 984 break; 985 case DifferentSetter: 986 Diag << Note.Prop->getSetterName(); 987 break; 988 } 989 } 990 if (AtLoc.isValid()) 991 S.Diag(AtLoc, diag::note_property_synthesize); 992 993 return Property; 994 } 995 996 /// Determine whether any storage attributes were written on the property. 997 static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop, 998 ObjCPropertyQueryKind QueryKind) { 999 if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true; 1000 1001 // If this is a readwrite property in a class extension that refines 1002 // a readonly property in the original class definition, check it as 1003 // well. 1004 1005 // If it's a readonly property, we're not interested. 1006 if (Prop->isReadOnly()) return false; 1007 1008 // Is it declared in an extension? 1009 auto Category = dyn_cast<ObjCCategoryDecl>(Prop->getDeclContext()); 1010 if (!Category || !Category->IsClassExtension()) return false; 1011 1012 // Find the corresponding property in the primary class definition. 1013 auto OrigClass = Category->getClassInterface(); 1014 for (auto *Found : OrigClass->lookup(Prop->getDeclName())) { 1015 if (ObjCPropertyDecl *OrigProp = dyn_cast<ObjCPropertyDecl>(Found)) 1016 return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask; 1017 } 1018 1019 // Look through all of the protocols. 1020 for (const auto *Proto : OrigClass->all_referenced_protocols()) { 1021 if (ObjCPropertyDecl *OrigProp = Proto->FindPropertyDeclaration( 1022 Prop->getIdentifier(), QueryKind)) 1023 return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask; 1024 } 1025 1026 return false; 1027 } 1028 1029 /// Create a synthesized property accessor stub inside the \@implementation. 1030 static ObjCMethodDecl * 1031 RedeclarePropertyAccessor(ASTContext &Context, ObjCImplementationDecl *Impl, 1032 ObjCMethodDecl *AccessorDecl, SourceLocation AtLoc, 1033 SourceLocation PropertyLoc) { 1034 ObjCMethodDecl *Decl = AccessorDecl; 1035 ObjCMethodDecl *ImplDecl = ObjCMethodDecl::Create( 1036 Context, AtLoc.isValid() ? AtLoc : Decl->getBeginLoc(), 1037 PropertyLoc.isValid() ? PropertyLoc : Decl->getEndLoc(), 1038 Decl->getSelector(), Decl->getReturnType(), 1039 Decl->getReturnTypeSourceInfo(), Impl, Decl->isInstanceMethod(), 1040 Decl->isVariadic(), Decl->isPropertyAccessor(), 1041 /* isSynthesized*/ true, Decl->isImplicit(), Decl->isDefined(), 1042 Decl->getImplementationControl(), Decl->hasRelatedResultType()); 1043 ImplDecl->getMethodFamily(); 1044 if (Decl->hasAttrs()) 1045 ImplDecl->setAttrs(Decl->getAttrs()); 1046 ImplDecl->setSelfDecl(Decl->getSelfDecl()); 1047 ImplDecl->setCmdDecl(Decl->getCmdDecl()); 1048 SmallVector<SourceLocation, 1> SelLocs; 1049 Decl->getSelectorLocs(SelLocs); 1050 ImplDecl->setMethodParams(Context, Decl->parameters(), SelLocs); 1051 ImplDecl->setLexicalDeclContext(Impl); 1052 ImplDecl->setDefined(false); 1053 return ImplDecl; 1054 } 1055 1056 /// ActOnPropertyImplDecl - This routine performs semantic checks and 1057 /// builds the AST node for a property implementation declaration; declared 1058 /// as \@synthesize or \@dynamic. 1059 /// 1060 Decl *SemaObjC::ActOnPropertyImplDecl( 1061 Scope *S, SourceLocation AtLoc, SourceLocation PropertyLoc, bool Synthesize, 1062 IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, 1063 SourceLocation PropertyIvarLoc, ObjCPropertyQueryKind QueryKind) { 1064 ASTContext &Context = getASTContext(); 1065 ObjCContainerDecl *ClassImpDecl = 1066 dyn_cast<ObjCContainerDecl>(SemaRef.CurContext); 1067 // Make sure we have a context for the property implementation declaration. 1068 if (!ClassImpDecl) { 1069 Diag(AtLoc, diag::err_missing_property_context); 1070 return nullptr; 1071 } 1072 if (PropertyIvarLoc.isInvalid()) 1073 PropertyIvarLoc = PropertyLoc; 1074 SourceLocation PropertyDiagLoc = PropertyLoc; 1075 if (PropertyDiagLoc.isInvalid()) 1076 PropertyDiagLoc = ClassImpDecl->getBeginLoc(); 1077 ObjCPropertyDecl *property = nullptr; 1078 ObjCInterfaceDecl *IDecl = nullptr; 1079 // Find the class or category class where this property must have 1080 // a declaration. 1081 ObjCImplementationDecl *IC = nullptr; 1082 ObjCCategoryImplDecl *CatImplClass = nullptr; 1083 if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) { 1084 IDecl = IC->getClassInterface(); 1085 // We always synthesize an interface for an implementation 1086 // without an interface decl. So, IDecl is always non-zero. 1087 assert(IDecl && 1088 "ActOnPropertyImplDecl - @implementation without @interface"); 1089 1090 // Look for this property declaration in the @implementation's @interface 1091 property = IDecl->FindPropertyDeclaration(PropertyId, QueryKind); 1092 if (!property) { 1093 Diag(PropertyLoc, diag::err_bad_property_decl) << IDecl->getDeclName(); 1094 return nullptr; 1095 } 1096 if (property->isClassProperty() && Synthesize) { 1097 Diag(PropertyLoc, diag::err_synthesize_on_class_property) << PropertyId; 1098 return nullptr; 1099 } 1100 unsigned PIkind = property->getPropertyAttributesAsWritten(); 1101 if ((PIkind & (ObjCPropertyAttribute::kind_atomic | 1102 ObjCPropertyAttribute::kind_nonatomic)) == 0) { 1103 if (AtLoc.isValid()) 1104 Diag(AtLoc, diag::warn_implicit_atomic_property); 1105 else 1106 Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property); 1107 Diag(property->getLocation(), diag::note_property_declare); 1108 } 1109 1110 if (const ObjCCategoryDecl *CD = 1111 dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) { 1112 if (!CD->IsClassExtension()) { 1113 Diag(PropertyLoc, diag::err_category_property) << CD->getDeclName(); 1114 Diag(property->getLocation(), diag::note_property_declare); 1115 return nullptr; 1116 } 1117 } 1118 if (Synthesize && (PIkind & ObjCPropertyAttribute::kind_readonly) && 1119 property->hasAttr<IBOutletAttr>() && !AtLoc.isValid()) { 1120 bool ReadWriteProperty = false; 1121 // Search into the class extensions and see if 'readonly property is 1122 // redeclared 'readwrite', then no warning is to be issued. 1123 for (auto *Ext : IDecl->known_extensions()) { 1124 DeclContext::lookup_result R = Ext->lookup(property->getDeclName()); 1125 if (auto *ExtProp = R.find_first<ObjCPropertyDecl>()) { 1126 PIkind = ExtProp->getPropertyAttributesAsWritten(); 1127 if (PIkind & ObjCPropertyAttribute::kind_readwrite) { 1128 ReadWriteProperty = true; 1129 break; 1130 } 1131 } 1132 } 1133 1134 if (!ReadWriteProperty) { 1135 Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property) 1136 << property; 1137 SourceLocation readonlyLoc; 1138 if (LocPropertyAttribute(Context, "readonly", 1139 property->getLParenLoc(), readonlyLoc)) { 1140 SourceLocation endLoc = 1141 readonlyLoc.getLocWithOffset(strlen("readonly")-1); 1142 SourceRange ReadonlySourceRange(readonlyLoc, endLoc); 1143 Diag(property->getLocation(), 1144 diag::note_auto_readonly_iboutlet_fixup_suggest) << 1145 FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite"); 1146 } 1147 } 1148 } 1149 if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext())) 1150 property = SelectPropertyForSynthesisFromProtocols(SemaRef, AtLoc, IDecl, 1151 property); 1152 1153 } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) { 1154 if (Synthesize) { 1155 Diag(AtLoc, diag::err_synthesize_category_decl); 1156 return nullptr; 1157 } 1158 IDecl = CatImplClass->getClassInterface(); 1159 if (!IDecl) { 1160 Diag(AtLoc, diag::err_missing_property_interface); 1161 return nullptr; 1162 } 1163 ObjCCategoryDecl *Category = 1164 IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier()); 1165 1166 // If category for this implementation not found, it is an error which 1167 // has already been reported eralier. 1168 if (!Category) 1169 return nullptr; 1170 // Look for this property declaration in @implementation's category 1171 property = Category->FindPropertyDeclaration(PropertyId, QueryKind); 1172 if (!property) { 1173 Diag(PropertyLoc, diag::err_bad_category_property_decl) 1174 << Category->getDeclName(); 1175 return nullptr; 1176 } 1177 } else { 1178 Diag(AtLoc, diag::err_bad_property_context); 1179 return nullptr; 1180 } 1181 ObjCIvarDecl *Ivar = nullptr; 1182 bool CompleteTypeErr = false; 1183 bool compat = true; 1184 // Check that we have a valid, previously declared ivar for @synthesize 1185 if (Synthesize) { 1186 // @synthesize 1187 if (!PropertyIvar) 1188 PropertyIvar = PropertyId; 1189 // Check that this is a previously declared 'ivar' in 'IDecl' interface 1190 ObjCInterfaceDecl *ClassDeclared; 1191 Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); 1192 QualType PropType = property->getType(); 1193 QualType PropertyIvarType = PropType.getNonReferenceType(); 1194 1195 if (SemaRef.RequireCompleteType(PropertyDiagLoc, PropertyIvarType, 1196 diag::err_incomplete_synthesized_property, 1197 property->getDeclName())) { 1198 Diag(property->getLocation(), diag::note_property_declare); 1199 CompleteTypeErr = true; 1200 } 1201 1202 if (getLangOpts().ObjCAutoRefCount && 1203 (property->getPropertyAttributesAsWritten() & 1204 ObjCPropertyAttribute::kind_readonly) && 1205 PropertyIvarType->isObjCRetainableType()) { 1206 setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar); 1207 } 1208 1209 ObjCPropertyAttribute::Kind kind = property->getPropertyAttributes(); 1210 1211 bool isARCWeak = false; 1212 if (kind & ObjCPropertyAttribute::kind_weak) { 1213 // Add GC __weak to the ivar type if the property is weak. 1214 if (getLangOpts().getGC() != LangOptions::NonGC) { 1215 assert(!getLangOpts().ObjCAutoRefCount); 1216 if (PropertyIvarType.isObjCGCStrong()) { 1217 Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type); 1218 Diag(property->getLocation(), diag::note_property_declare); 1219 } else { 1220 PropertyIvarType = 1221 Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak); 1222 } 1223 1224 // Otherwise, check whether ARC __weak is enabled and works with 1225 // the property type. 1226 } else { 1227 if (!getLangOpts().ObjCWeak) { 1228 // Only complain here when synthesizing an ivar. 1229 if (!Ivar) { 1230 Diag(PropertyDiagLoc, 1231 getLangOpts().ObjCWeakRuntime 1232 ? diag::err_synthesizing_arc_weak_property_disabled 1233 : diag::err_synthesizing_arc_weak_property_no_runtime); 1234 Diag(property->getLocation(), diag::note_property_declare); 1235 } 1236 CompleteTypeErr = true; // suppress later diagnostics about the ivar 1237 } else { 1238 isARCWeak = true; 1239 if (const ObjCObjectPointerType *ObjT = 1240 PropertyIvarType->getAs<ObjCObjectPointerType>()) { 1241 const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl(); 1242 if (ObjI && ObjI->isArcWeakrefUnavailable()) { 1243 Diag(property->getLocation(), 1244 diag::err_arc_weak_unavailable_property) 1245 << PropertyIvarType; 1246 Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class) 1247 << ClassImpDecl->getName(); 1248 } 1249 } 1250 } 1251 } 1252 } 1253 1254 if (AtLoc.isInvalid()) { 1255 // Check when default synthesizing a property that there is 1256 // an ivar matching property name and issue warning; since this 1257 // is the most common case of not using an ivar used for backing 1258 // property in non-default synthesis case. 1259 ObjCInterfaceDecl *ClassDeclared=nullptr; 1260 ObjCIvarDecl *originalIvar = 1261 IDecl->lookupInstanceVariable(property->getIdentifier(), 1262 ClassDeclared); 1263 if (originalIvar) { 1264 Diag(PropertyDiagLoc, 1265 diag::warn_autosynthesis_property_ivar_match) 1266 << PropertyId << (Ivar == nullptr) << PropertyIvar 1267 << originalIvar->getIdentifier(); 1268 Diag(property->getLocation(), diag::note_property_declare); 1269 Diag(originalIvar->getLocation(), diag::note_ivar_decl); 1270 } 1271 } 1272 1273 if (!Ivar) { 1274 // In ARC, give the ivar a lifetime qualifier based on the 1275 // property attributes. 1276 if ((getLangOpts().ObjCAutoRefCount || isARCWeak) && 1277 !PropertyIvarType.getObjCLifetime() && 1278 PropertyIvarType->isObjCRetainableType()) { 1279 1280 // It's an error if we have to do this and the user didn't 1281 // explicitly write an ownership attribute on the property. 1282 if (!hasWrittenStorageAttribute(property, QueryKind) && 1283 !(kind & ObjCPropertyAttribute::kind_strong)) { 1284 Diag(PropertyDiagLoc, 1285 diag::err_arc_objc_property_default_assign_on_object); 1286 Diag(property->getLocation(), diag::note_property_declare); 1287 } else { 1288 Qualifiers::ObjCLifetime lifetime = 1289 getImpliedARCOwnership(kind, PropertyIvarType); 1290 assert(lifetime && "no lifetime for property?"); 1291 1292 Qualifiers qs; 1293 qs.addObjCLifetime(lifetime); 1294 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs); 1295 } 1296 } 1297 1298 Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl, 1299 PropertyIvarLoc,PropertyIvarLoc, PropertyIvar, 1300 PropertyIvarType, /*TInfo=*/nullptr, 1301 ObjCIvarDecl::Private, 1302 (Expr *)nullptr, true); 1303 if (SemaRef.RequireNonAbstractType(PropertyIvarLoc, PropertyIvarType, 1304 diag::err_abstract_type_in_decl, 1305 Sema::AbstractSynthesizedIvarType)) { 1306 Diag(property->getLocation(), diag::note_property_declare); 1307 // An abstract type is as bad as an incomplete type. 1308 CompleteTypeErr = true; 1309 } 1310 if (!CompleteTypeErr) { 1311 const RecordType *RecordTy = PropertyIvarType->getAs<RecordType>(); 1312 if (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()) { 1313 Diag(PropertyIvarLoc, diag::err_synthesize_variable_sized_ivar) 1314 << PropertyIvarType; 1315 CompleteTypeErr = true; // suppress later diagnostics about the ivar 1316 } 1317 } 1318 if (CompleteTypeErr) 1319 Ivar->setInvalidDecl(); 1320 ClassImpDecl->addDecl(Ivar); 1321 IDecl->makeDeclVisibleInContext(Ivar); 1322 1323 if (getLangOpts().ObjCRuntime.isFragile()) 1324 Diag(PropertyDiagLoc, diag::err_missing_property_ivar_decl) 1325 << PropertyId; 1326 // Note! I deliberately want it to fall thru so, we have a 1327 // a property implementation and to avoid future warnings. 1328 } else if (getLangOpts().ObjCRuntime.isNonFragile() && 1329 !declaresSameEntity(ClassDeclared, IDecl)) { 1330 Diag(PropertyDiagLoc, diag::err_ivar_in_superclass_use) 1331 << property->getDeclName() << Ivar->getDeclName() 1332 << ClassDeclared->getDeclName(); 1333 Diag(Ivar->getLocation(), diag::note_previous_access_declaration) 1334 << Ivar << Ivar->getName(); 1335 // Note! I deliberately want it to fall thru so more errors are caught. 1336 } 1337 property->setPropertyIvarDecl(Ivar); 1338 1339 QualType IvarType = Context.getCanonicalType(Ivar->getType()); 1340 1341 // Check that type of property and its ivar are type compatible. 1342 if (!Context.hasSameType(PropertyIvarType, IvarType)) { 1343 if (isa<ObjCObjectPointerType>(PropertyIvarType) 1344 && isa<ObjCObjectPointerType>(IvarType)) 1345 compat = Context.canAssignObjCInterfaces( 1346 PropertyIvarType->castAs<ObjCObjectPointerType>(), 1347 IvarType->castAs<ObjCObjectPointerType>()); 1348 else { 1349 compat = (SemaRef.CheckAssignmentConstraints( 1350 PropertyIvarLoc, PropertyIvarType, IvarType) == 1351 Sema::Compatible); 1352 } 1353 if (!compat) { 1354 Diag(PropertyDiagLoc, diag::err_property_ivar_type) 1355 << property->getDeclName() << PropType 1356 << Ivar->getDeclName() << IvarType; 1357 Diag(Ivar->getLocation(), diag::note_ivar_decl); 1358 // Note! I deliberately want it to fall thru so, we have a 1359 // a property implementation and to avoid future warnings. 1360 } 1361 else { 1362 // FIXME! Rules for properties are somewhat different that those 1363 // for assignments. Use a new routine to consolidate all cases; 1364 // specifically for property redeclarations as well as for ivars. 1365 QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType(); 1366 QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType(); 1367 if (lhsType != rhsType && 1368 lhsType->isArithmeticType()) { 1369 Diag(PropertyDiagLoc, diag::err_property_ivar_type) 1370 << property->getDeclName() << PropType 1371 << Ivar->getDeclName() << IvarType; 1372 Diag(Ivar->getLocation(), diag::note_ivar_decl); 1373 // Fall thru - see previous comment 1374 } 1375 } 1376 // __weak is explicit. So it works on Canonical type. 1377 if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() && 1378 getLangOpts().getGC() != LangOptions::NonGC)) { 1379 Diag(PropertyDiagLoc, diag::err_weak_property) 1380 << property->getDeclName() << Ivar->getDeclName(); 1381 Diag(Ivar->getLocation(), diag::note_ivar_decl); 1382 // Fall thru - see previous comment 1383 } 1384 // Fall thru - see previous comment 1385 if ((property->getType()->isObjCObjectPointerType() || 1386 PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() && 1387 getLangOpts().getGC() != LangOptions::NonGC) { 1388 Diag(PropertyDiagLoc, diag::err_strong_property) 1389 << property->getDeclName() << Ivar->getDeclName(); 1390 // Fall thru - see previous comment 1391 } 1392 } 1393 if (getLangOpts().ObjCAutoRefCount || isARCWeak || 1394 Ivar->getType().getObjCLifetime()) 1395 checkARCPropertyImpl(SemaRef, PropertyLoc, property, Ivar); 1396 } else if (PropertyIvar) 1397 // @dynamic 1398 Diag(PropertyDiagLoc, diag::err_dynamic_property_ivar_decl); 1399 1400 assert (property && "ActOnPropertyImplDecl - property declaration missing"); 1401 ObjCPropertyImplDecl *PIDecl = ObjCPropertyImplDecl::Create( 1402 Context, SemaRef.CurContext, AtLoc, PropertyLoc, property, 1403 (Synthesize ? ObjCPropertyImplDecl::Synthesize 1404 : ObjCPropertyImplDecl::Dynamic), 1405 Ivar, PropertyIvarLoc); 1406 1407 if (CompleteTypeErr || !compat) 1408 PIDecl->setInvalidDecl(); 1409 1410 if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) { 1411 getterMethod->createImplicitParams(Context, IDecl); 1412 1413 // Redeclare the getter within the implementation as DeclContext. 1414 if (Synthesize) { 1415 // If the method hasn't been overridden, create a synthesized implementation. 1416 ObjCMethodDecl *OMD = ClassImpDecl->getMethod( 1417 getterMethod->getSelector(), getterMethod->isInstanceMethod()); 1418 if (!OMD) 1419 OMD = RedeclarePropertyAccessor(Context, IC, getterMethod, AtLoc, 1420 PropertyLoc); 1421 PIDecl->setGetterMethodDecl(OMD); 1422 } 1423 1424 if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && 1425 Ivar->getType()->isRecordType()) { 1426 // For Objective-C++, need to synthesize the AST for the IVAR object to be 1427 // returned by the getter as it must conform to C++'s copy-return rules. 1428 // FIXME. Eventually we want to do this for Objective-C as well. 1429 Sema::SynthesizedFunctionScope Scope(SemaRef, getterMethod); 1430 ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl(); 1431 DeclRefExpr *SelfExpr = new (Context) 1432 DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, 1433 PropertyDiagLoc); 1434 SemaRef.MarkDeclRefReferenced(SelfExpr); 1435 Expr *LoadSelfExpr = ImplicitCastExpr::Create( 1436 Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr, 1437 VK_PRValue, FPOptionsOverride()); 1438 Expr *IvarRefExpr = 1439 new (Context) ObjCIvarRefExpr(Ivar, 1440 Ivar->getUsageType(SelfDecl->getType()), 1441 PropertyDiagLoc, 1442 Ivar->getLocation(), 1443 LoadSelfExpr, true, true); 1444 ExprResult Res = SemaRef.PerformCopyInitialization( 1445 InitializedEntity::InitializeResult(PropertyDiagLoc, 1446 getterMethod->getReturnType()), 1447 PropertyDiagLoc, IvarRefExpr); 1448 if (!Res.isInvalid()) { 1449 Expr *ResExpr = Res.getAs<Expr>(); 1450 if (ResExpr) 1451 ResExpr = SemaRef.MaybeCreateExprWithCleanups(ResExpr); 1452 PIDecl->setGetterCXXConstructor(ResExpr); 1453 } 1454 } 1455 if (property->hasAttr<NSReturnsNotRetainedAttr>() && 1456 !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) { 1457 Diag(getterMethod->getLocation(), 1458 diag::warn_property_getter_owning_mismatch); 1459 Diag(property->getLocation(), diag::note_property_declare); 1460 } 1461 if (getLangOpts().ObjCAutoRefCount && Synthesize) 1462 switch (getterMethod->getMethodFamily()) { 1463 case OMF_retain: 1464 case OMF_retainCount: 1465 case OMF_release: 1466 case OMF_autorelease: 1467 Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def) 1468 << 1 << getterMethod->getSelector(); 1469 break; 1470 default: 1471 break; 1472 } 1473 } 1474 1475 if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) { 1476 setterMethod->createImplicitParams(Context, IDecl); 1477 1478 // Redeclare the setter within the implementation as DeclContext. 1479 if (Synthesize) { 1480 ObjCMethodDecl *OMD = ClassImpDecl->getMethod( 1481 setterMethod->getSelector(), setterMethod->isInstanceMethod()); 1482 if (!OMD) 1483 OMD = RedeclarePropertyAccessor(Context, IC, setterMethod, 1484 AtLoc, PropertyLoc); 1485 PIDecl->setSetterMethodDecl(OMD); 1486 } 1487 1488 if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr && 1489 Ivar->getType()->isRecordType()) { 1490 // FIXME. Eventually we want to do this for Objective-C as well. 1491 Sema::SynthesizedFunctionScope Scope(SemaRef, setterMethod); 1492 ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl(); 1493 DeclRefExpr *SelfExpr = new (Context) 1494 DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue, 1495 PropertyDiagLoc); 1496 SemaRef.MarkDeclRefReferenced(SelfExpr); 1497 Expr *LoadSelfExpr = ImplicitCastExpr::Create( 1498 Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr, 1499 VK_PRValue, FPOptionsOverride()); 1500 Expr *lhs = 1501 new (Context) ObjCIvarRefExpr(Ivar, 1502 Ivar->getUsageType(SelfDecl->getType()), 1503 PropertyDiagLoc, 1504 Ivar->getLocation(), 1505 LoadSelfExpr, true, true); 1506 ObjCMethodDecl::param_iterator P = setterMethod->param_begin(); 1507 ParmVarDecl *Param = (*P); 1508 QualType T = Param->getType().getNonReferenceType(); 1509 DeclRefExpr *rhs = new (Context) 1510 DeclRefExpr(Context, Param, false, T, VK_LValue, PropertyDiagLoc); 1511 SemaRef.MarkDeclRefReferenced(rhs); 1512 ExprResult Res = 1513 SemaRef.BuildBinOp(S, PropertyDiagLoc, BO_Assign, lhs, rhs); 1514 if (property->getPropertyAttributes() & 1515 ObjCPropertyAttribute::kind_atomic) { 1516 Expr *callExpr = Res.getAs<Expr>(); 1517 if (const CXXOperatorCallExpr *CXXCE = 1518 dyn_cast_or_null<CXXOperatorCallExpr>(callExpr)) 1519 if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee()) 1520 if (!FuncDecl->isTrivial()) 1521 if (property->getType()->isReferenceType()) { 1522 Diag(PropertyDiagLoc, 1523 diag::err_atomic_property_nontrivial_assign_op) 1524 << property->getType(); 1525 Diag(FuncDecl->getBeginLoc(), diag::note_callee_decl) 1526 << FuncDecl; 1527 } 1528 } 1529 PIDecl->setSetterCXXAssignment(Res.getAs<Expr>()); 1530 } 1531 } 1532 1533 if (IC) { 1534 if (Synthesize) 1535 if (ObjCPropertyImplDecl *PPIDecl = 1536 IC->FindPropertyImplIvarDecl(PropertyIvar)) { 1537 Diag(PropertyLoc, diag::err_duplicate_ivar_use) 1538 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 1539 << PropertyIvar; 1540 Diag(PPIDecl->getLocation(), diag::note_previous_use); 1541 } 1542 1543 if (ObjCPropertyImplDecl *PPIDecl 1544 = IC->FindPropertyImplDecl(PropertyId, QueryKind)) { 1545 Diag(PropertyLoc, diag::err_property_implemented) << PropertyId; 1546 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 1547 return nullptr; 1548 } 1549 IC->addPropertyImplementation(PIDecl); 1550 if (getLangOpts().ObjCDefaultSynthProperties && 1551 getLangOpts().ObjCRuntime.isNonFragile() && 1552 !IDecl->isObjCRequiresPropertyDefs()) { 1553 // Diagnose if an ivar was lazily synthesdized due to a previous 1554 // use and if 1) property is @dynamic or 2) property is synthesized 1555 // but it requires an ivar of different name. 1556 ObjCInterfaceDecl *ClassDeclared=nullptr; 1557 ObjCIvarDecl *Ivar = nullptr; 1558 if (!Synthesize) 1559 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 1560 else { 1561 if (PropertyIvar && PropertyIvar != PropertyId) 1562 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared); 1563 } 1564 // Issue diagnostics only if Ivar belongs to current class. 1565 if (Ivar && Ivar->getSynthesize() && 1566 declaresSameEntity(IC->getClassInterface(), ClassDeclared)) { 1567 Diag(Ivar->getLocation(), diag::err_undeclared_var_use) 1568 << PropertyId; 1569 Ivar->setInvalidDecl(); 1570 } 1571 } 1572 } else { 1573 if (Synthesize) 1574 if (ObjCPropertyImplDecl *PPIDecl = 1575 CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { 1576 Diag(PropertyDiagLoc, diag::err_duplicate_ivar_use) 1577 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() 1578 << PropertyIvar; 1579 Diag(PPIDecl->getLocation(), diag::note_previous_use); 1580 } 1581 1582 if (ObjCPropertyImplDecl *PPIDecl = 1583 CatImplClass->FindPropertyImplDecl(PropertyId, QueryKind)) { 1584 Diag(PropertyDiagLoc, diag::err_property_implemented) << PropertyId; 1585 Diag(PPIDecl->getLocation(), diag::note_previous_declaration); 1586 return nullptr; 1587 } 1588 CatImplClass->addPropertyImplementation(PIDecl); 1589 } 1590 1591 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic && 1592 PIDecl->getPropertyDecl() && 1593 PIDecl->getPropertyDecl()->isDirectProperty()) { 1594 Diag(PropertyLoc, diag::err_objc_direct_dynamic_property); 1595 Diag(PIDecl->getPropertyDecl()->getLocation(), 1596 diag::note_previous_declaration); 1597 return nullptr; 1598 } 1599 1600 return PIDecl; 1601 } 1602 1603 //===----------------------------------------------------------------------===// 1604 // Helper methods. 1605 //===----------------------------------------------------------------------===// 1606 1607 /// DiagnosePropertyMismatch - Compares two properties for their 1608 /// attributes and types and warns on a variety of inconsistencies. 1609 /// 1610 void SemaObjC::DiagnosePropertyMismatch(ObjCPropertyDecl *Property, 1611 ObjCPropertyDecl *SuperProperty, 1612 const IdentifierInfo *inheritedName, 1613 bool OverridingProtocolProperty) { 1614 ASTContext &Context = getASTContext(); 1615 ObjCPropertyAttribute::Kind CAttr = Property->getPropertyAttributes(); 1616 ObjCPropertyAttribute::Kind SAttr = SuperProperty->getPropertyAttributes(); 1617 1618 // We allow readonly properties without an explicit ownership 1619 // (assign/unsafe_unretained/weak/retain/strong/copy) in super class 1620 // to be overridden by a property with any explicit ownership in the subclass. 1621 if (!OverridingProtocolProperty && 1622 !getOwnershipRule(SAttr) && getOwnershipRule(CAttr)) 1623 ; 1624 else { 1625 if ((CAttr & ObjCPropertyAttribute::kind_readonly) && 1626 (SAttr & ObjCPropertyAttribute::kind_readwrite)) 1627 Diag(Property->getLocation(), diag::warn_readonly_property) 1628 << Property->getDeclName() << inheritedName; 1629 if ((CAttr & ObjCPropertyAttribute::kind_copy) != 1630 (SAttr & ObjCPropertyAttribute::kind_copy)) 1631 Diag(Property->getLocation(), diag::warn_property_attribute) 1632 << Property->getDeclName() << "copy" << inheritedName; 1633 else if (!(SAttr & ObjCPropertyAttribute::kind_readonly)) { 1634 unsigned CAttrRetain = (CAttr & (ObjCPropertyAttribute::kind_retain | 1635 ObjCPropertyAttribute::kind_strong)); 1636 unsigned SAttrRetain = (SAttr & (ObjCPropertyAttribute::kind_retain | 1637 ObjCPropertyAttribute::kind_strong)); 1638 bool CStrong = (CAttrRetain != 0); 1639 bool SStrong = (SAttrRetain != 0); 1640 if (CStrong != SStrong) 1641 Diag(Property->getLocation(), diag::warn_property_attribute) 1642 << Property->getDeclName() << "retain (or strong)" << inheritedName; 1643 } 1644 } 1645 1646 // Check for nonatomic; note that nonatomic is effectively 1647 // meaningless for readonly properties, so don't diagnose if the 1648 // atomic property is 'readonly'. 1649 checkAtomicPropertyMismatch(SemaRef, SuperProperty, Property, false); 1650 // Readonly properties from protocols can be implemented as "readwrite" 1651 // with a custom setter name. 1652 if (Property->getSetterName() != SuperProperty->getSetterName() && 1653 !(SuperProperty->isReadOnly() && 1654 isa<ObjCProtocolDecl>(SuperProperty->getDeclContext()))) { 1655 Diag(Property->getLocation(), diag::warn_property_attribute) 1656 << Property->getDeclName() << "setter" << inheritedName; 1657 Diag(SuperProperty->getLocation(), diag::note_property_declare); 1658 } 1659 if (Property->getGetterName() != SuperProperty->getGetterName()) { 1660 Diag(Property->getLocation(), diag::warn_property_attribute) 1661 << Property->getDeclName() << "getter" << inheritedName; 1662 Diag(SuperProperty->getLocation(), diag::note_property_declare); 1663 } 1664 1665 QualType LHSType = 1666 Context.getCanonicalType(SuperProperty->getType()); 1667 QualType RHSType = 1668 Context.getCanonicalType(Property->getType()); 1669 1670 if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) { 1671 // Do cases not handled in above. 1672 // FIXME. For future support of covariant property types, revisit this. 1673 bool IncompatibleObjC = false; 1674 QualType ConvertedType; 1675 if (!SemaRef.isObjCPointerConversion(RHSType, LHSType, ConvertedType, 1676 IncompatibleObjC) || 1677 IncompatibleObjC) { 1678 Diag(Property->getLocation(), diag::warn_property_types_are_incompatible) 1679 << Property->getType() << SuperProperty->getType() << inheritedName; 1680 Diag(SuperProperty->getLocation(), diag::note_property_declare); 1681 } 1682 } 1683 } 1684 1685 bool SemaObjC::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 1686 ObjCMethodDecl *GetterMethod, 1687 SourceLocation Loc) { 1688 ASTContext &Context = getASTContext(); 1689 if (!GetterMethod) 1690 return false; 1691 QualType GetterType = GetterMethod->getReturnType().getNonReferenceType(); 1692 QualType PropertyRValueType = 1693 property->getType().getNonReferenceType().getAtomicUnqualifiedType(); 1694 bool compat = Context.hasSameType(PropertyRValueType, GetterType); 1695 if (!compat) { 1696 const ObjCObjectPointerType *propertyObjCPtr = nullptr; 1697 const ObjCObjectPointerType *getterObjCPtr = nullptr; 1698 if ((propertyObjCPtr = 1699 PropertyRValueType->getAs<ObjCObjectPointerType>()) && 1700 (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>())) 1701 compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr); 1702 else if (SemaRef.CheckAssignmentConstraints( 1703 Loc, GetterType, PropertyRValueType) != Sema::Compatible) { 1704 Diag(Loc, diag::err_property_accessor_type) 1705 << property->getDeclName() << PropertyRValueType 1706 << GetterMethod->getSelector() << GetterType; 1707 Diag(GetterMethod->getLocation(), diag::note_declared_at); 1708 return true; 1709 } else { 1710 compat = true; 1711 QualType lhsType = Context.getCanonicalType(PropertyRValueType); 1712 QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType(); 1713 if (lhsType != rhsType && lhsType->isArithmeticType()) 1714 compat = false; 1715 } 1716 } 1717 1718 if (!compat) { 1719 Diag(Loc, diag::warn_accessor_property_type_mismatch) 1720 << property->getDeclName() 1721 << GetterMethod->getSelector(); 1722 Diag(GetterMethod->getLocation(), diag::note_declared_at); 1723 return true; 1724 } 1725 1726 return false; 1727 } 1728 1729 /// CollectImmediateProperties - This routine collects all properties in 1730 /// the class and its conforming protocols; but not those in its super class. 1731 static void 1732 CollectImmediateProperties(ObjCContainerDecl *CDecl, 1733 ObjCContainerDecl::PropertyMap &PropMap, 1734 ObjCContainerDecl::PropertyMap &SuperPropMap, 1735 bool CollectClassPropsOnly = false, 1736 bool IncludeProtocols = true) { 1737 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 1738 for (auto *Prop : IDecl->properties()) { 1739 if (CollectClassPropsOnly && !Prop->isClassProperty()) 1740 continue; 1741 PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = 1742 Prop; 1743 } 1744 1745 // Collect the properties from visible extensions. 1746 for (auto *Ext : IDecl->visible_extensions()) 1747 CollectImmediateProperties(Ext, PropMap, SuperPropMap, 1748 CollectClassPropsOnly, IncludeProtocols); 1749 1750 if (IncludeProtocols) { 1751 // Scan through class's protocols. 1752 for (auto *PI : IDecl->all_referenced_protocols()) 1753 CollectImmediateProperties(PI, PropMap, SuperPropMap, 1754 CollectClassPropsOnly); 1755 } 1756 } 1757 if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { 1758 for (auto *Prop : CATDecl->properties()) { 1759 if (CollectClassPropsOnly && !Prop->isClassProperty()) 1760 continue; 1761 PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = 1762 Prop; 1763 } 1764 if (IncludeProtocols) { 1765 // Scan through class's protocols. 1766 for (auto *PI : CATDecl->protocols()) 1767 CollectImmediateProperties(PI, PropMap, SuperPropMap, 1768 CollectClassPropsOnly); 1769 } 1770 } 1771 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { 1772 for (auto *Prop : PDecl->properties()) { 1773 if (CollectClassPropsOnly && !Prop->isClassProperty()) 1774 continue; 1775 ObjCPropertyDecl *PropertyFromSuper = 1776 SuperPropMap[std::make_pair(Prop->getIdentifier(), 1777 Prop->isClassProperty())]; 1778 // Exclude property for protocols which conform to class's super-class, 1779 // as super-class has to implement the property. 1780 if (!PropertyFromSuper || 1781 PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) { 1782 ObjCPropertyDecl *&PropEntry = 1783 PropMap[std::make_pair(Prop->getIdentifier(), 1784 Prop->isClassProperty())]; 1785 if (!PropEntry) 1786 PropEntry = Prop; 1787 } 1788 } 1789 // Scan through protocol's protocols. 1790 for (auto *PI : PDecl->protocols()) 1791 CollectImmediateProperties(PI, PropMap, SuperPropMap, 1792 CollectClassPropsOnly); 1793 } 1794 } 1795 1796 /// CollectSuperClassPropertyImplementations - This routine collects list of 1797 /// properties to be implemented in super class(s) and also coming from their 1798 /// conforming protocols. 1799 static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, 1800 ObjCInterfaceDecl::PropertyMap &PropMap) { 1801 if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) { 1802 while (SDecl) { 1803 SDecl->collectPropertiesToImplement(PropMap); 1804 SDecl = SDecl->getSuperClass(); 1805 } 1806 } 1807 } 1808 1809 /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is 1810 /// an ivar synthesized for 'Method' and 'Method' is a property accessor 1811 /// declared in class 'IFace'. 1812 bool SemaObjC::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, 1813 ObjCMethodDecl *Method, 1814 ObjCIvarDecl *IV) { 1815 if (!IV->getSynthesize()) 1816 return false; 1817 ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(), 1818 Method->isInstanceMethod()); 1819 if (!IMD || !IMD->isPropertyAccessor()) 1820 return false; 1821 1822 // look up a property declaration whose one of its accessors is implemented 1823 // by this method. 1824 for (const auto *Property : IFace->instance_properties()) { 1825 if ((Property->getGetterName() == IMD->getSelector() || 1826 Property->getSetterName() == IMD->getSelector()) && 1827 (Property->getPropertyIvarDecl() == IV)) 1828 return true; 1829 } 1830 // Also look up property declaration in class extension whose one of its 1831 // accessors is implemented by this method. 1832 for (const auto *Ext : IFace->known_extensions()) 1833 for (const auto *Property : Ext->instance_properties()) 1834 if ((Property->getGetterName() == IMD->getSelector() || 1835 Property->getSetterName() == IMD->getSelector()) && 1836 (Property->getPropertyIvarDecl() == IV)) 1837 return true; 1838 return false; 1839 } 1840 1841 static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl, 1842 ObjCPropertyDecl *Prop) { 1843 bool SuperClassImplementsGetter = false; 1844 bool SuperClassImplementsSetter = false; 1845 if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) 1846 SuperClassImplementsSetter = true; 1847 1848 while (IDecl->getSuperClass()) { 1849 ObjCInterfaceDecl *SDecl = IDecl->getSuperClass(); 1850 if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName())) 1851 SuperClassImplementsGetter = true; 1852 1853 if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName())) 1854 SuperClassImplementsSetter = true; 1855 if (SuperClassImplementsGetter && SuperClassImplementsSetter) 1856 return true; 1857 IDecl = IDecl->getSuperClass(); 1858 } 1859 return false; 1860 } 1861 1862 /// Default synthesizes all properties which must be synthesized 1863 /// in class's \@implementation. 1864 void SemaObjC::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, 1865 ObjCInterfaceDecl *IDecl, 1866 SourceLocation AtEnd) { 1867 ASTContext &Context = getASTContext(); 1868 ObjCInterfaceDecl::PropertyMap PropMap; 1869 IDecl->collectPropertiesToImplement(PropMap); 1870 if (PropMap.empty()) 1871 return; 1872 ObjCInterfaceDecl::PropertyMap SuperPropMap; 1873 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap); 1874 1875 for (const auto &PropEntry : PropMap) { 1876 ObjCPropertyDecl *Prop = PropEntry.second; 1877 // Is there a matching property synthesize/dynamic? 1878 if (Prop->isInvalidDecl() || 1879 Prop->isClassProperty() || 1880 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional) 1881 continue; 1882 // Property may have been synthesized by user. 1883 if (IMPDecl->FindPropertyImplDecl( 1884 Prop->getIdentifier(), Prop->getQueryKind())) 1885 continue; 1886 ObjCMethodDecl *ImpMethod = IMPDecl->getInstanceMethod(Prop->getGetterName()); 1887 if (ImpMethod && !ImpMethod->getBody()) { 1888 if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly) 1889 continue; 1890 ImpMethod = IMPDecl->getInstanceMethod(Prop->getSetterName()); 1891 if (ImpMethod && !ImpMethod->getBody()) 1892 continue; 1893 } 1894 if (ObjCPropertyImplDecl *PID = 1895 IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) { 1896 Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property) 1897 << Prop->getIdentifier(); 1898 if (PID->getLocation().isValid()) 1899 Diag(PID->getLocation(), diag::note_property_synthesize); 1900 continue; 1901 } 1902 ObjCPropertyDecl *PropInSuperClass = 1903 SuperPropMap[std::make_pair(Prop->getIdentifier(), 1904 Prop->isClassProperty())]; 1905 if (ObjCProtocolDecl *Proto = 1906 dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) { 1907 // We won't auto-synthesize properties declared in protocols. 1908 // Suppress the warning if class's superclass implements property's 1909 // getter and implements property's setter (if readwrite property). 1910 // Or, if property is going to be implemented in its super class. 1911 if (!SuperClassImplementsProperty(IDecl, Prop) && !PropInSuperClass) { 1912 Diag(IMPDecl->getLocation(), 1913 diag::warn_auto_synthesizing_protocol_property) 1914 << Prop << Proto; 1915 Diag(Prop->getLocation(), diag::note_property_declare); 1916 std::string FixIt = 1917 (Twine("@synthesize ") + Prop->getName() + ";\n\n").str(); 1918 Diag(AtEnd, diag::note_add_synthesize_directive) 1919 << FixItHint::CreateInsertion(AtEnd, FixIt); 1920 } 1921 continue; 1922 } 1923 // If property to be implemented in the super class, ignore. 1924 if (PropInSuperClass) { 1925 if ((Prop->getPropertyAttributes() & 1926 ObjCPropertyAttribute::kind_readwrite) && 1927 (PropInSuperClass->getPropertyAttributes() & 1928 ObjCPropertyAttribute::kind_readonly) && 1929 !IMPDecl->getInstanceMethod(Prop->getSetterName()) && 1930 !IDecl->HasUserDeclaredSetterMethod(Prop)) { 1931 Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property) 1932 << Prop->getIdentifier(); 1933 Diag(PropInSuperClass->getLocation(), diag::note_property_declare); 1934 } else { 1935 Diag(Prop->getLocation(), diag::warn_autosynthesis_property_in_superclass) 1936 << Prop->getIdentifier(); 1937 Diag(PropInSuperClass->getLocation(), diag::note_property_declare); 1938 Diag(IMPDecl->getLocation(), diag::note_while_in_implementation); 1939 } 1940 continue; 1941 } 1942 // We use invalid SourceLocations for the synthesized ivars since they 1943 // aren't really synthesized at a particular location; they just exist. 1944 // Saying that they are located at the @implementation isn't really going 1945 // to help users. 1946 ObjCPropertyImplDecl *PIDecl = dyn_cast_or_null<ObjCPropertyImplDecl>( 1947 ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(), 1948 true, 1949 /* property = */ Prop->getIdentifier(), 1950 /* ivar = */ Prop->getDefaultSynthIvarName(Context), 1951 Prop->getLocation(), Prop->getQueryKind())); 1952 if (PIDecl && !Prop->isUnavailable()) { 1953 Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis); 1954 Diag(IMPDecl->getLocation(), diag::note_while_in_implementation); 1955 } 1956 } 1957 } 1958 1959 void SemaObjC::DefaultSynthesizeProperties(Scope *S, Decl *D, 1960 SourceLocation AtEnd) { 1961 if (!getLangOpts().ObjCDefaultSynthProperties || 1962 getLangOpts().ObjCRuntime.isFragile()) 1963 return; 1964 ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D); 1965 if (!IC) 1966 return; 1967 if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) 1968 if (!IDecl->isObjCRequiresPropertyDefs()) 1969 DefaultSynthesizeProperties(S, IC, IDecl, AtEnd); 1970 } 1971 1972 static void DiagnoseUnimplementedAccessor( 1973 Sema &S, ObjCInterfaceDecl *PrimaryClass, Selector Method, 1974 ObjCImplDecl *IMPDecl, ObjCContainerDecl *CDecl, ObjCCategoryDecl *C, 1975 ObjCPropertyDecl *Prop, 1976 llvm::SmallPtrSet<const ObjCMethodDecl *, 8> &SMap) { 1977 // Check to see if we have a corresponding selector in SMap and with the 1978 // right method type. 1979 auto I = llvm::find_if(SMap, [&](const ObjCMethodDecl *x) { 1980 return x->getSelector() == Method && 1981 x->isClassMethod() == Prop->isClassProperty(); 1982 }); 1983 // When reporting on missing property setter/getter implementation in 1984 // categories, do not report when they are declared in primary class, 1985 // class's protocol, or one of it super classes. This is because, 1986 // the class is going to implement them. 1987 if (I == SMap.end() && 1988 (PrimaryClass == nullptr || 1989 !PrimaryClass->lookupPropertyAccessor(Method, C, 1990 Prop->isClassProperty()))) { 1991 unsigned diag = 1992 isa<ObjCCategoryDecl>(CDecl) 1993 ? (Prop->isClassProperty() 1994 ? diag::warn_impl_required_in_category_for_class_property 1995 : diag::warn_setter_getter_impl_required_in_category) 1996 : (Prop->isClassProperty() 1997 ? diag::warn_impl_required_for_class_property 1998 : diag::warn_setter_getter_impl_required); 1999 S.Diag(IMPDecl->getLocation(), diag) << Prop->getDeclName() << Method; 2000 S.Diag(Prop->getLocation(), diag::note_property_declare); 2001 if (S.LangOpts.ObjCDefaultSynthProperties && 2002 S.LangOpts.ObjCRuntime.isNonFragile()) 2003 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl)) 2004 if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs()) 2005 S.Diag(RID->getLocation(), diag::note_suppressed_class_declare); 2006 } 2007 } 2008 2009 void SemaObjC::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl, 2010 ObjCContainerDecl *CDecl, 2011 bool SynthesizeProperties) { 2012 ObjCContainerDecl::PropertyMap PropMap; 2013 ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); 2014 2015 // Since we don't synthesize class properties, we should emit diagnose even 2016 // if SynthesizeProperties is true. 2017 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; 2018 // Gather properties which need not be implemented in this class 2019 // or category. 2020 if (!IDecl) 2021 if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { 2022 // For categories, no need to implement properties declared in 2023 // its primary class (and its super classes) if property is 2024 // declared in one of those containers. 2025 if ((IDecl = C->getClassInterface())) { 2026 IDecl->collectPropertiesToImplement(NoNeedToImplPropMap); 2027 } 2028 } 2029 if (IDecl) 2030 CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap); 2031 2032 // When SynthesizeProperties is true, we only check class properties. 2033 CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap, 2034 SynthesizeProperties/*CollectClassPropsOnly*/); 2035 2036 // Scan the @interface to see if any of the protocols it adopts 2037 // require an explicit implementation, via attribute 2038 // 'objc_protocol_requires_explicit_implementation'. 2039 if (IDecl) { 2040 std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap; 2041 2042 for (auto *PDecl : IDecl->all_referenced_protocols()) { 2043 if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) 2044 continue; 2045 // Lazily construct a set of all the properties in the @interface 2046 // of the class, without looking at the superclass. We cannot 2047 // use the call to CollectImmediateProperties() above as that 2048 // utilizes information from the super class's properties as well 2049 // as scans the adopted protocols. This work only triggers for protocols 2050 // with the attribute, which is very rare, and only occurs when 2051 // analyzing the @implementation. 2052 if (!LazyMap) { 2053 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; 2054 LazyMap.reset(new ObjCContainerDecl::PropertyMap()); 2055 CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap, 2056 /* CollectClassPropsOnly */ false, 2057 /* IncludeProtocols */ false); 2058 } 2059 // Add the properties of 'PDecl' to the list of properties that 2060 // need to be implemented. 2061 for (auto *PropDecl : PDecl->properties()) { 2062 if ((*LazyMap)[std::make_pair(PropDecl->getIdentifier(), 2063 PropDecl->isClassProperty())]) 2064 continue; 2065 PropMap[std::make_pair(PropDecl->getIdentifier(), 2066 PropDecl->isClassProperty())] = PropDecl; 2067 } 2068 } 2069 } 2070 2071 if (PropMap.empty()) 2072 return; 2073 2074 llvm::DenseSet<ObjCPropertyDecl *> PropImplMap; 2075 for (const auto *I : IMPDecl->property_impls()) 2076 PropImplMap.insert(I->getPropertyDecl()); 2077 2078 llvm::SmallPtrSet<const ObjCMethodDecl *, 8> InsMap; 2079 // Collect property accessors implemented in current implementation. 2080 for (const auto *I : IMPDecl->methods()) 2081 InsMap.insert(I); 2082 2083 ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl); 2084 ObjCInterfaceDecl *PrimaryClass = nullptr; 2085 if (C && !C->IsClassExtension()) 2086 if ((PrimaryClass = C->getClassInterface())) 2087 // Report unimplemented properties in the category as well. 2088 if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) { 2089 // When reporting on missing setter/getters, do not report when 2090 // setter/getter is implemented in category's primary class 2091 // implementation. 2092 for (const auto *I : IMP->methods()) 2093 InsMap.insert(I); 2094 } 2095 2096 for (ObjCContainerDecl::PropertyMap::iterator 2097 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) { 2098 ObjCPropertyDecl *Prop = P->second; 2099 // Is there a matching property synthesize/dynamic? 2100 if (Prop->isInvalidDecl() || 2101 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional || 2102 PropImplMap.count(Prop) || 2103 Prop->getAvailability() == AR_Unavailable) 2104 continue; 2105 2106 // Diagnose unimplemented getters and setters. 2107 DiagnoseUnimplementedAccessor(SemaRef, PrimaryClass, Prop->getGetterName(), 2108 IMPDecl, CDecl, C, Prop, InsMap); 2109 if (!Prop->isReadOnly()) 2110 DiagnoseUnimplementedAccessor(SemaRef, PrimaryClass, 2111 Prop->getSetterName(), IMPDecl, CDecl, C, 2112 Prop, InsMap); 2113 } 2114 } 2115 2116 void SemaObjC::diagnoseNullResettableSynthesizedSetters( 2117 const ObjCImplDecl *impDecl) { 2118 for (const auto *propertyImpl : impDecl->property_impls()) { 2119 const auto *property = propertyImpl->getPropertyDecl(); 2120 // Warn about null_resettable properties with synthesized setters, 2121 // because the setter won't properly handle nil. 2122 if (propertyImpl->getPropertyImplementation() == 2123 ObjCPropertyImplDecl::Synthesize && 2124 (property->getPropertyAttributes() & 2125 ObjCPropertyAttribute::kind_null_resettable) && 2126 property->getGetterMethodDecl() && property->getSetterMethodDecl()) { 2127 auto *getterImpl = propertyImpl->getGetterMethodDecl(); 2128 auto *setterImpl = propertyImpl->getSetterMethodDecl(); 2129 if ((!getterImpl || getterImpl->isSynthesizedAccessorStub()) && 2130 (!setterImpl || setterImpl->isSynthesizedAccessorStub())) { 2131 SourceLocation loc = propertyImpl->getLocation(); 2132 if (loc.isInvalid()) 2133 loc = impDecl->getBeginLoc(); 2134 2135 Diag(loc, diag::warn_null_resettable_setter) 2136 << setterImpl->getSelector() << property->getDeclName(); 2137 } 2138 } 2139 } 2140 } 2141 2142 void SemaObjC::AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl, 2143 ObjCInterfaceDecl *IDecl) { 2144 // Rules apply in non-GC mode only 2145 if (getLangOpts().getGC() != LangOptions::NonGC) 2146 return; 2147 ObjCContainerDecl::PropertyMap PM; 2148 for (auto *Prop : IDecl->properties()) 2149 PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; 2150 for (const auto *Ext : IDecl->known_extensions()) 2151 for (auto *Prop : Ext->properties()) 2152 PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop; 2153 2154 for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end(); 2155 I != E; ++I) { 2156 const ObjCPropertyDecl *Property = I->second; 2157 ObjCMethodDecl *GetterMethod = nullptr; 2158 ObjCMethodDecl *SetterMethod = nullptr; 2159 2160 unsigned Attributes = Property->getPropertyAttributes(); 2161 unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten(); 2162 2163 if (!(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic) && 2164 !(AttributesAsWritten & ObjCPropertyAttribute::kind_nonatomic)) { 2165 GetterMethod = Property->isClassProperty() ? 2166 IMPDecl->getClassMethod(Property->getGetterName()) : 2167 IMPDecl->getInstanceMethod(Property->getGetterName()); 2168 SetterMethod = Property->isClassProperty() ? 2169 IMPDecl->getClassMethod(Property->getSetterName()) : 2170 IMPDecl->getInstanceMethod(Property->getSetterName()); 2171 if (GetterMethod && GetterMethod->isSynthesizedAccessorStub()) 2172 GetterMethod = nullptr; 2173 if (SetterMethod && SetterMethod->isSynthesizedAccessorStub()) 2174 SetterMethod = nullptr; 2175 if (GetterMethod) { 2176 Diag(GetterMethod->getLocation(), 2177 diag::warn_default_atomic_custom_getter_setter) 2178 << Property->getIdentifier() << 0; 2179 Diag(Property->getLocation(), diag::note_property_declare); 2180 } 2181 if (SetterMethod) { 2182 Diag(SetterMethod->getLocation(), 2183 diag::warn_default_atomic_custom_getter_setter) 2184 << Property->getIdentifier() << 1; 2185 Diag(Property->getLocation(), diag::note_property_declare); 2186 } 2187 } 2188 2189 // We only care about readwrite atomic property. 2190 if ((Attributes & ObjCPropertyAttribute::kind_nonatomic) || 2191 !(Attributes & ObjCPropertyAttribute::kind_readwrite)) 2192 continue; 2193 if (const ObjCPropertyImplDecl *PIDecl = IMPDecl->FindPropertyImplDecl( 2194 Property->getIdentifier(), Property->getQueryKind())) { 2195 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 2196 continue; 2197 GetterMethod = PIDecl->getGetterMethodDecl(); 2198 SetterMethod = PIDecl->getSetterMethodDecl(); 2199 if (GetterMethod && GetterMethod->isSynthesizedAccessorStub()) 2200 GetterMethod = nullptr; 2201 if (SetterMethod && SetterMethod->isSynthesizedAccessorStub()) 2202 SetterMethod = nullptr; 2203 if ((bool)GetterMethod ^ (bool)SetterMethod) { 2204 SourceLocation MethodLoc = 2205 (GetterMethod ? GetterMethod->getLocation() 2206 : SetterMethod->getLocation()); 2207 Diag(MethodLoc, diag::warn_atomic_property_rule) 2208 << Property->getIdentifier() << (GetterMethod != nullptr) 2209 << (SetterMethod != nullptr); 2210 // fixit stuff. 2211 if (Property->getLParenLoc().isValid() && 2212 !(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic)) { 2213 // @property () ... case. 2214 SourceLocation AfterLParen = 2215 SemaRef.getLocForEndOfToken(Property->getLParenLoc()); 2216 StringRef NonatomicStr = AttributesAsWritten? "nonatomic, " 2217 : "nonatomic"; 2218 Diag(Property->getLocation(), 2219 diag::note_atomic_property_fixup_suggest) 2220 << FixItHint::CreateInsertion(AfterLParen, NonatomicStr); 2221 } else if (Property->getLParenLoc().isInvalid()) { 2222 //@property id etc. 2223 SourceLocation startLoc = 2224 Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc(); 2225 Diag(Property->getLocation(), 2226 diag::note_atomic_property_fixup_suggest) 2227 << FixItHint::CreateInsertion(startLoc, "(nonatomic) "); 2228 } else 2229 Diag(MethodLoc, diag::note_atomic_property_fixup_suggest); 2230 Diag(Property->getLocation(), diag::note_property_declare); 2231 } 2232 } 2233 } 2234 } 2235 2236 void SemaObjC::DiagnoseOwningPropertyGetterSynthesis( 2237 const ObjCImplementationDecl *D) { 2238 if (getLangOpts().getGC() == LangOptions::GCOnly) 2239 return; 2240 2241 for (const auto *PID : D->property_impls()) { 2242 const ObjCPropertyDecl *PD = PID->getPropertyDecl(); 2243 if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() && 2244 !PD->isClassProperty()) { 2245 ObjCMethodDecl *IM = PID->getGetterMethodDecl(); 2246 if (IM && !IM->isSynthesizedAccessorStub()) 2247 continue; 2248 ObjCMethodDecl *method = PD->getGetterMethodDecl(); 2249 if (!method) 2250 continue; 2251 ObjCMethodFamily family = method->getMethodFamily(); 2252 if (family == OMF_alloc || family == OMF_copy || 2253 family == OMF_mutableCopy || family == OMF_new) { 2254 if (getLangOpts().ObjCAutoRefCount) 2255 Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule); 2256 else 2257 Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule); 2258 2259 // Look for a getter explicitly declared alongside the property. 2260 // If we find one, use its location for the note. 2261 SourceLocation noteLoc = PD->getLocation(); 2262 SourceLocation fixItLoc; 2263 for (auto *getterRedecl : method->redecls()) { 2264 if (getterRedecl->isImplicit()) 2265 continue; 2266 if (getterRedecl->getDeclContext() != PD->getDeclContext()) 2267 continue; 2268 noteLoc = getterRedecl->getLocation(); 2269 fixItLoc = getterRedecl->getEndLoc(); 2270 } 2271 2272 Preprocessor &PP = SemaRef.getPreprocessor(); 2273 TokenValue tokens[] = { 2274 tok::kw___attribute, tok::l_paren, tok::l_paren, 2275 PP.getIdentifierInfo("objc_method_family"), tok::l_paren, 2276 PP.getIdentifierInfo("none"), tok::r_paren, 2277 tok::r_paren, tok::r_paren 2278 }; 2279 StringRef spelling = "__attribute__((objc_method_family(none)))"; 2280 StringRef macroName = PP.getLastMacroWithSpelling(noteLoc, tokens); 2281 if (!macroName.empty()) 2282 spelling = macroName; 2283 2284 auto noteDiag = Diag(noteLoc, diag::note_cocoa_naming_declare_family) 2285 << method->getDeclName() << spelling; 2286 if (fixItLoc.isValid()) { 2287 SmallString<64> fixItText(" "); 2288 fixItText += spelling; 2289 noteDiag << FixItHint::CreateInsertion(fixItLoc, fixItText); 2290 } 2291 } 2292 } 2293 } 2294 } 2295 2296 void SemaObjC::DiagnoseMissingDesignatedInitOverrides( 2297 const ObjCImplementationDecl *ImplD, const ObjCInterfaceDecl *IFD) { 2298 assert(IFD->hasDesignatedInitializers()); 2299 const ObjCInterfaceDecl *SuperD = IFD->getSuperClass(); 2300 if (!SuperD) 2301 return; 2302 2303 SelectorSet InitSelSet; 2304 for (const auto *I : ImplD->instance_methods()) 2305 if (I->getMethodFamily() == OMF_init) 2306 InitSelSet.insert(I->getSelector()); 2307 2308 SmallVector<const ObjCMethodDecl *, 8> DesignatedInits; 2309 SuperD->getDesignatedInitializers(DesignatedInits); 2310 for (SmallVector<const ObjCMethodDecl *, 8>::iterator 2311 I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) { 2312 const ObjCMethodDecl *MD = *I; 2313 if (!InitSelSet.count(MD->getSelector())) { 2314 // Don't emit a diagnostic if the overriding method in the subclass is 2315 // marked as unavailable. 2316 bool Ignore = false; 2317 if (auto *IMD = IFD->getInstanceMethod(MD->getSelector())) { 2318 Ignore = IMD->isUnavailable(); 2319 } else { 2320 // Check the methods declared in the class extensions too. 2321 for (auto *Ext : IFD->visible_extensions()) 2322 if (auto *IMD = Ext->getInstanceMethod(MD->getSelector())) { 2323 Ignore = IMD->isUnavailable(); 2324 break; 2325 } 2326 } 2327 if (!Ignore) { 2328 Diag(ImplD->getLocation(), 2329 diag::warn_objc_implementation_missing_designated_init_override) 2330 << MD->getSelector(); 2331 Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here); 2332 } 2333 } 2334 } 2335 } 2336 2337 /// AddPropertyAttrs - Propagates attributes from a property to the 2338 /// implicitly-declared getter or setter for that property. 2339 static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, 2340 ObjCPropertyDecl *Property) { 2341 // Should we just clone all attributes over? 2342 for (const auto *A : Property->attrs()) { 2343 if (isa<DeprecatedAttr>(A) || 2344 isa<UnavailableAttr>(A) || 2345 isa<AvailabilityAttr>(A)) 2346 PropertyMethod->addAttr(A->clone(S.Context)); 2347 } 2348 } 2349 2350 /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods 2351 /// have the property type and issue diagnostics if they don't. 2352 /// Also synthesize a getter/setter method if none exist (and update the 2353 /// appropriate lookup tables. 2354 void SemaObjC::ProcessPropertyDecl(ObjCPropertyDecl *property) { 2355 ASTContext &Context = getASTContext(); 2356 ObjCMethodDecl *GetterMethod, *SetterMethod; 2357 ObjCContainerDecl *CD = cast<ObjCContainerDecl>(property->getDeclContext()); 2358 if (CD->isInvalidDecl()) 2359 return; 2360 2361 bool IsClassProperty = property->isClassProperty(); 2362 GetterMethod = IsClassProperty ? 2363 CD->getClassMethod(property->getGetterName()) : 2364 CD->getInstanceMethod(property->getGetterName()); 2365 2366 // if setter or getter is not found in class extension, it might be 2367 // in the primary class. 2368 if (!GetterMethod) 2369 if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) 2370 if (CatDecl->IsClassExtension()) 2371 GetterMethod = IsClassProperty ? CatDecl->getClassInterface()-> 2372 getClassMethod(property->getGetterName()) : 2373 CatDecl->getClassInterface()-> 2374 getInstanceMethod(property->getGetterName()); 2375 2376 SetterMethod = IsClassProperty ? 2377 CD->getClassMethod(property->getSetterName()) : 2378 CD->getInstanceMethod(property->getSetterName()); 2379 if (!SetterMethod) 2380 if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) 2381 if (CatDecl->IsClassExtension()) 2382 SetterMethod = IsClassProperty ? CatDecl->getClassInterface()-> 2383 getClassMethod(property->getSetterName()) : 2384 CatDecl->getClassInterface()-> 2385 getInstanceMethod(property->getSetterName()); 2386 DiagnosePropertyAccessorMismatch(property, GetterMethod, 2387 property->getLocation()); 2388 2389 // synthesizing accessors must not result in a direct method that is not 2390 // monomorphic 2391 if (!GetterMethod) { 2392 if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) { 2393 auto *ExistingGetter = CatDecl->getClassInterface()->lookupMethod( 2394 property->getGetterName(), !IsClassProperty, true, false, CatDecl); 2395 if (ExistingGetter) { 2396 if (ExistingGetter->isDirectMethod() || property->isDirectProperty()) { 2397 Diag(property->getLocation(), diag::err_objc_direct_duplicate_decl) 2398 << property->isDirectProperty() << 1 /* property */ 2399 << ExistingGetter->isDirectMethod() 2400 << ExistingGetter->getDeclName(); 2401 Diag(ExistingGetter->getLocation(), diag::note_previous_declaration); 2402 } 2403 } 2404 } 2405 } 2406 2407 if (!property->isReadOnly() && !SetterMethod) { 2408 if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) { 2409 auto *ExistingSetter = CatDecl->getClassInterface()->lookupMethod( 2410 property->getSetterName(), !IsClassProperty, true, false, CatDecl); 2411 if (ExistingSetter) { 2412 if (ExistingSetter->isDirectMethod() || property->isDirectProperty()) { 2413 Diag(property->getLocation(), diag::err_objc_direct_duplicate_decl) 2414 << property->isDirectProperty() << 1 /* property */ 2415 << ExistingSetter->isDirectMethod() 2416 << ExistingSetter->getDeclName(); 2417 Diag(ExistingSetter->getLocation(), diag::note_previous_declaration); 2418 } 2419 } 2420 } 2421 } 2422 2423 if (!property->isReadOnly() && SetterMethod) { 2424 if (Context.getCanonicalType(SetterMethod->getReturnType()) != 2425 Context.VoidTy) 2426 Diag(SetterMethod->getLocation(), diag::err_setter_type_void); 2427 if (SetterMethod->param_size() != 1 || 2428 !Context.hasSameUnqualifiedType( 2429 (*SetterMethod->param_begin())->getType().getNonReferenceType(), 2430 property->getType().getNonReferenceType())) { 2431 Diag(property->getLocation(), 2432 diag::warn_accessor_property_type_mismatch) 2433 << property->getDeclName() 2434 << SetterMethod->getSelector(); 2435 Diag(SetterMethod->getLocation(), diag::note_declared_at); 2436 } 2437 } 2438 2439 // Synthesize getter/setter methods if none exist. 2440 // Find the default getter and if one not found, add one. 2441 // FIXME: The synthesized property we set here is misleading. We almost always 2442 // synthesize these methods unless the user explicitly provided prototypes 2443 // (which is odd, but allowed). Sema should be typechecking that the 2444 // declarations jive in that situation (which it is not currently). 2445 if (!GetterMethod) { 2446 // No instance/class method of same name as property getter name was found. 2447 // Declare a getter method and add it to the list of methods 2448 // for this class. 2449 SourceLocation Loc = property->getLocation(); 2450 2451 // The getter returns the declared property type with all qualifiers 2452 // removed. 2453 QualType resultTy = property->getType().getAtomicUnqualifiedType(); 2454 2455 // If the property is null_resettable, the getter returns nonnull. 2456 if (property->getPropertyAttributes() & 2457 ObjCPropertyAttribute::kind_null_resettable) { 2458 QualType modifiedTy = resultTy; 2459 if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) { 2460 if (*nullability == NullabilityKind::Unspecified) 2461 resultTy = Context.getAttributedType(NullabilityKind::NonNull, 2462 modifiedTy, modifiedTy); 2463 } 2464 } 2465 2466 GetterMethod = ObjCMethodDecl::Create( 2467 Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD, 2468 !IsClassProperty, /*isVariadic=*/false, 2469 /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false, 2470 /*isImplicitlyDeclared=*/true, /*isDefined=*/false, 2471 (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) 2472 ? ObjCImplementationControl::Optional 2473 : ObjCImplementationControl::Required); 2474 CD->addDecl(GetterMethod); 2475 2476 AddPropertyAttrs(SemaRef, GetterMethod, property); 2477 2478 if (property->isDirectProperty()) 2479 GetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc)); 2480 2481 if (property->hasAttr<NSReturnsNotRetainedAttr>()) 2482 GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context, 2483 Loc)); 2484 2485 if (property->hasAttr<ObjCReturnsInnerPointerAttr>()) 2486 GetterMethod->addAttr( 2487 ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc)); 2488 2489 if (const SectionAttr *SA = property->getAttr<SectionAttr>()) 2490 GetterMethod->addAttr(SectionAttr::CreateImplicit( 2491 Context, SA->getName(), Loc, SectionAttr::GNU_section)); 2492 2493 SemaRef.ProcessAPINotes(GetterMethod); 2494 2495 if (getLangOpts().ObjCAutoRefCount) 2496 CheckARCMethodDecl(GetterMethod); 2497 } else 2498 // A user declared getter will be synthesize when @synthesize of 2499 // the property with the same name is seen in the @implementation 2500 GetterMethod->setPropertyAccessor(true); 2501 2502 GetterMethod->createImplicitParams(Context, 2503 GetterMethod->getClassInterface()); 2504 property->setGetterMethodDecl(GetterMethod); 2505 2506 // Skip setter if property is read-only. 2507 if (!property->isReadOnly()) { 2508 // Find the default setter and if one not found, add one. 2509 if (!SetterMethod) { 2510 // No instance/class method of same name as property setter name was 2511 // found. 2512 // Declare a setter method and add it to the list of methods 2513 // for this class. 2514 SourceLocation Loc = property->getLocation(); 2515 2516 SetterMethod = ObjCMethodDecl::Create( 2517 Context, Loc, Loc, property->getSetterName(), Context.VoidTy, nullptr, 2518 CD, !IsClassProperty, 2519 /*isVariadic=*/false, 2520 /*isPropertyAccessor=*/true, 2521 /*isSynthesizedAccessorStub=*/false, 2522 /*isImplicitlyDeclared=*/true, 2523 /*isDefined=*/false, 2524 (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) 2525 ? ObjCImplementationControl::Optional 2526 : ObjCImplementationControl::Required); 2527 2528 // Remove all qualifiers from the setter's parameter type. 2529 QualType paramTy = 2530 property->getType().getUnqualifiedType().getAtomicUnqualifiedType(); 2531 2532 // If the property is null_resettable, the setter accepts a 2533 // nullable value. 2534 if (property->getPropertyAttributes() & 2535 ObjCPropertyAttribute::kind_null_resettable) { 2536 QualType modifiedTy = paramTy; 2537 if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){ 2538 if (*nullability == NullabilityKind::Unspecified) 2539 paramTy = Context.getAttributedType(NullabilityKind::Nullable, 2540 modifiedTy, modifiedTy); 2541 } 2542 } 2543 2544 // Invent the arguments for the setter. We don't bother making a 2545 // nice name for the argument. 2546 ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod, 2547 Loc, Loc, 2548 property->getIdentifier(), 2549 paramTy, 2550 /*TInfo=*/nullptr, 2551 SC_None, 2552 nullptr); 2553 SetterMethod->setMethodParams(Context, Argument, {}); 2554 2555 AddPropertyAttrs(SemaRef, SetterMethod, property); 2556 2557 if (property->isDirectProperty()) 2558 SetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc)); 2559 2560 CD->addDecl(SetterMethod); 2561 if (const SectionAttr *SA = property->getAttr<SectionAttr>()) 2562 SetterMethod->addAttr(SectionAttr::CreateImplicit( 2563 Context, SA->getName(), Loc, SectionAttr::GNU_section)); 2564 2565 SemaRef.ProcessAPINotes(SetterMethod); 2566 2567 // It's possible for the user to have set a very odd custom 2568 // setter selector that causes it to have a method family. 2569 if (getLangOpts().ObjCAutoRefCount) 2570 CheckARCMethodDecl(SetterMethod); 2571 } else 2572 // A user declared setter will be synthesize when @synthesize of 2573 // the property with the same name is seen in the @implementation 2574 SetterMethod->setPropertyAccessor(true); 2575 2576 SetterMethod->createImplicitParams(Context, 2577 SetterMethod->getClassInterface()); 2578 property->setSetterMethodDecl(SetterMethod); 2579 } 2580 // Add any synthesized methods to the global pool. This allows us to 2581 // handle the following, which is supported by GCC (and part of the design). 2582 // 2583 // @interface Foo 2584 // @property double bar; 2585 // @end 2586 // 2587 // void thisIsUnfortunate() { 2588 // id foo; 2589 // double bar = [foo bar]; 2590 // } 2591 // 2592 if (!IsClassProperty) { 2593 if (GetterMethod) 2594 AddInstanceMethodToGlobalPool(GetterMethod); 2595 if (SetterMethod) 2596 AddInstanceMethodToGlobalPool(SetterMethod); 2597 } else { 2598 if (GetterMethod) 2599 AddFactoryMethodToGlobalPool(GetterMethod); 2600 if (SetterMethod) 2601 AddFactoryMethodToGlobalPool(SetterMethod); 2602 } 2603 2604 ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD); 2605 if (!CurrentClass) { 2606 if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CD)) 2607 CurrentClass = Cat->getClassInterface(); 2608 else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(CD)) 2609 CurrentClass = Impl->getClassInterface(); 2610 } 2611 if (GetterMethod) 2612 CheckObjCMethodOverrides(GetterMethod, CurrentClass, SemaObjC::RTC_Unknown); 2613 if (SetterMethod) 2614 CheckObjCMethodOverrides(SetterMethod, CurrentClass, SemaObjC::RTC_Unknown); 2615 } 2616 2617 void SemaObjC::CheckObjCPropertyAttributes(Decl *PDecl, SourceLocation Loc, 2618 unsigned &Attributes, 2619 bool propertyInPrimaryClass) { 2620 // FIXME: Improve the reported location. 2621 if (!PDecl || PDecl->isInvalidDecl()) 2622 return; 2623 2624 if ((Attributes & ObjCPropertyAttribute::kind_readonly) && 2625 (Attributes & ObjCPropertyAttribute::kind_readwrite)) 2626 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2627 << "readonly" << "readwrite"; 2628 2629 ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl); 2630 QualType PropertyTy = PropertyDecl->getType(); 2631 2632 // Check for copy or retain on non-object types. 2633 if ((Attributes & 2634 (ObjCPropertyAttribute::kind_weak | ObjCPropertyAttribute::kind_copy | 2635 ObjCPropertyAttribute::kind_retain | 2636 ObjCPropertyAttribute::kind_strong)) && 2637 !PropertyTy->isObjCRetainableType() && 2638 !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) { 2639 Diag(Loc, diag::err_objc_property_requires_object) 2640 << (Attributes & ObjCPropertyAttribute::kind_weak 2641 ? "weak" 2642 : Attributes & ObjCPropertyAttribute::kind_copy 2643 ? "copy" 2644 : "retain (or strong)"); 2645 Attributes &= 2646 ~(ObjCPropertyAttribute::kind_weak | ObjCPropertyAttribute::kind_copy | 2647 ObjCPropertyAttribute::kind_retain | 2648 ObjCPropertyAttribute::kind_strong); 2649 PropertyDecl->setInvalidDecl(); 2650 } 2651 2652 // Check for assign on object types. 2653 if ((Attributes & ObjCPropertyAttribute::kind_assign) && 2654 !(Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) && 2655 PropertyTy->isObjCRetainableType() && 2656 !PropertyTy->isObjCARCImplicitlyUnretainedType()) { 2657 Diag(Loc, diag::warn_objc_property_assign_on_object); 2658 } 2659 2660 // Check for more than one of { assign, copy, retain }. 2661 if (Attributes & ObjCPropertyAttribute::kind_assign) { 2662 if (Attributes & ObjCPropertyAttribute::kind_copy) { 2663 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2664 << "assign" << "copy"; 2665 Attributes &= ~ObjCPropertyAttribute::kind_copy; 2666 } 2667 if (Attributes & ObjCPropertyAttribute::kind_retain) { 2668 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2669 << "assign" << "retain"; 2670 Attributes &= ~ObjCPropertyAttribute::kind_retain; 2671 } 2672 if (Attributes & ObjCPropertyAttribute::kind_strong) { 2673 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2674 << "assign" << "strong"; 2675 Attributes &= ~ObjCPropertyAttribute::kind_strong; 2676 } 2677 if (getLangOpts().ObjCAutoRefCount && 2678 (Attributes & ObjCPropertyAttribute::kind_weak)) { 2679 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2680 << "assign" << "weak"; 2681 Attributes &= ~ObjCPropertyAttribute::kind_weak; 2682 } 2683 if (PropertyDecl->hasAttr<IBOutletCollectionAttr>()) 2684 Diag(Loc, diag::warn_iboutletcollection_property_assign); 2685 } else if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) { 2686 if (Attributes & ObjCPropertyAttribute::kind_copy) { 2687 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2688 << "unsafe_unretained" << "copy"; 2689 Attributes &= ~ObjCPropertyAttribute::kind_copy; 2690 } 2691 if (Attributes & ObjCPropertyAttribute::kind_retain) { 2692 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2693 << "unsafe_unretained" << "retain"; 2694 Attributes &= ~ObjCPropertyAttribute::kind_retain; 2695 } 2696 if (Attributes & ObjCPropertyAttribute::kind_strong) { 2697 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2698 << "unsafe_unretained" << "strong"; 2699 Attributes &= ~ObjCPropertyAttribute::kind_strong; 2700 } 2701 if (getLangOpts().ObjCAutoRefCount && 2702 (Attributes & ObjCPropertyAttribute::kind_weak)) { 2703 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2704 << "unsafe_unretained" << "weak"; 2705 Attributes &= ~ObjCPropertyAttribute::kind_weak; 2706 } 2707 } else if (Attributes & ObjCPropertyAttribute::kind_copy) { 2708 if (Attributes & ObjCPropertyAttribute::kind_retain) { 2709 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2710 << "copy" << "retain"; 2711 Attributes &= ~ObjCPropertyAttribute::kind_retain; 2712 } 2713 if (Attributes & ObjCPropertyAttribute::kind_strong) { 2714 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2715 << "copy" << "strong"; 2716 Attributes &= ~ObjCPropertyAttribute::kind_strong; 2717 } 2718 if (Attributes & ObjCPropertyAttribute::kind_weak) { 2719 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2720 << "copy" << "weak"; 2721 Attributes &= ~ObjCPropertyAttribute::kind_weak; 2722 } 2723 } else if ((Attributes & ObjCPropertyAttribute::kind_retain) && 2724 (Attributes & ObjCPropertyAttribute::kind_weak)) { 2725 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "retain" 2726 << "weak"; 2727 Attributes &= ~ObjCPropertyAttribute::kind_retain; 2728 } else if ((Attributes & ObjCPropertyAttribute::kind_strong) && 2729 (Attributes & ObjCPropertyAttribute::kind_weak)) { 2730 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "strong" 2731 << "weak"; 2732 Attributes &= ~ObjCPropertyAttribute::kind_weak; 2733 } 2734 2735 if (Attributes & ObjCPropertyAttribute::kind_weak) { 2736 // 'weak' and 'nonnull' are mutually exclusive. 2737 if (auto nullability = PropertyTy->getNullability()) { 2738 if (*nullability == NullabilityKind::NonNull) 2739 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) 2740 << "nonnull" << "weak"; 2741 } 2742 } 2743 2744 if ((Attributes & ObjCPropertyAttribute::kind_atomic) && 2745 (Attributes & ObjCPropertyAttribute::kind_nonatomic)) { 2746 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "atomic" 2747 << "nonatomic"; 2748 Attributes &= ~ObjCPropertyAttribute::kind_atomic; 2749 } 2750 2751 // Warn if user supplied no assignment attribute, property is 2752 // readwrite, and this is an object type. 2753 if (!getOwnershipRule(Attributes) && PropertyTy->isObjCRetainableType()) { 2754 if (Attributes & ObjCPropertyAttribute::kind_readonly) { 2755 // do nothing 2756 } else if (getLangOpts().ObjCAutoRefCount) { 2757 // With arc, @property definitions should default to strong when 2758 // not specified. 2759 PropertyDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_strong); 2760 } else if (PropertyTy->isObjCObjectPointerType()) { 2761 bool isAnyClassTy = (PropertyTy->isObjCClassType() || 2762 PropertyTy->isObjCQualifiedClassType()); 2763 // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to 2764 // issue any warning. 2765 if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC) 2766 ; 2767 else if (propertyInPrimaryClass) { 2768 // Don't issue warning on property with no life time in class 2769 // extension as it is inherited from property in primary class. 2770 // Skip this warning in gc-only mode. 2771 if (getLangOpts().getGC() != LangOptions::GCOnly) 2772 Diag(Loc, diag::warn_objc_property_no_assignment_attribute); 2773 2774 // If non-gc code warn that this is likely inappropriate. 2775 if (getLangOpts().getGC() == LangOptions::NonGC) 2776 Diag(Loc, diag::warn_objc_property_default_assign_on_object); 2777 } 2778 } 2779 2780 // FIXME: Implement warning dependent on NSCopying being 2781 // implemented. 2782 } 2783 2784 if (!(Attributes & ObjCPropertyAttribute::kind_copy) && 2785 !(Attributes & ObjCPropertyAttribute::kind_readonly) && 2786 getLangOpts().getGC() == LangOptions::GCOnly && 2787 PropertyTy->isBlockPointerType()) 2788 Diag(Loc, diag::warn_objc_property_copy_missing_on_block); 2789 else if ((Attributes & ObjCPropertyAttribute::kind_retain) && 2790 !(Attributes & ObjCPropertyAttribute::kind_readonly) && 2791 !(Attributes & ObjCPropertyAttribute::kind_strong) && 2792 PropertyTy->isBlockPointerType()) 2793 Diag(Loc, diag::warn_objc_property_retain_of_block); 2794 2795 if ((Attributes & ObjCPropertyAttribute::kind_readonly) && 2796 (Attributes & ObjCPropertyAttribute::kind_setter)) 2797 Diag(Loc, diag::warn_objc_readonly_property_has_setter); 2798 } 2799