brintos

brintos / llvm-project-archived public Read only

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