xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/SemaObjCProperty.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file implements semantic analysis for Objective C @property and
100b57cec5SDimitry Andric //  @synthesize declarations.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/AST/ASTMutationListener.h"
150b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
160b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
170b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h"
180b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
190b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
200b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
210b57cec5SDimitry Andric #include "clang/Sema/Initialization.h"
22*0fca6ea1SDimitry Andric #include "clang/Sema/SemaInternal.h"
23*0fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h"
240b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace clang;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
300b57cec5SDimitry Andric // Grammar actions.
310b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric /// getImpliedARCOwnership - Given a set of property attributes and a
340b57cec5SDimitry Andric /// type, infer an expected lifetime.  The type's ownership qualification
350b57cec5SDimitry Andric /// is not considered.
360b57cec5SDimitry Andric ///
370b57cec5SDimitry Andric /// Returns OCL_None if the attributes as stated do not imply an ownership.
380b57cec5SDimitry Andric /// Never returns OCL_Autoreleasing.
395ffd83dbSDimitry Andric static Qualifiers::ObjCLifetime
405ffd83dbSDimitry Andric getImpliedARCOwnership(ObjCPropertyAttribute::Kind attrs, QualType type) {
410b57cec5SDimitry Andric   // retain, strong, copy, weak, and unsafe_unretained are only legal
420b57cec5SDimitry Andric   // on properties of retainable pointer type.
435ffd83dbSDimitry Andric   if (attrs &
445ffd83dbSDimitry Andric       (ObjCPropertyAttribute::kind_retain | ObjCPropertyAttribute::kind_strong |
455ffd83dbSDimitry Andric        ObjCPropertyAttribute::kind_copy)) {
460b57cec5SDimitry Andric     return Qualifiers::OCL_Strong;
475ffd83dbSDimitry Andric   } else if (attrs & ObjCPropertyAttribute::kind_weak) {
480b57cec5SDimitry Andric     return Qualifiers::OCL_Weak;
495ffd83dbSDimitry Andric   } else if (attrs & ObjCPropertyAttribute::kind_unsafe_unretained) {
500b57cec5SDimitry Andric     return Qualifiers::OCL_ExplicitNone;
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   // assign can appear on other types, so we have to check the
540b57cec5SDimitry Andric   // property type.
555ffd83dbSDimitry Andric   if (attrs & ObjCPropertyAttribute::kind_assign &&
560b57cec5SDimitry Andric       type->isObjCRetainableType()) {
570b57cec5SDimitry Andric     return Qualifiers::OCL_ExplicitNone;
580b57cec5SDimitry Andric   }
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   return Qualifiers::OCL_None;
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric /// Check the internal consistency of a property declaration with
640b57cec5SDimitry Andric /// an explicit ownership qualifier.
650b57cec5SDimitry Andric static void checkPropertyDeclWithOwnership(Sema &S,
660b57cec5SDimitry Andric                                            ObjCPropertyDecl *property) {
670b57cec5SDimitry Andric   if (property->isInvalidDecl()) return;
680b57cec5SDimitry Andric 
695ffd83dbSDimitry Andric   ObjCPropertyAttribute::Kind propertyKind = property->getPropertyAttributes();
700b57cec5SDimitry Andric   Qualifiers::ObjCLifetime propertyLifetime
710b57cec5SDimitry Andric     = property->getType().getObjCLifetime();
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric   assert(propertyLifetime != Qualifiers::OCL_None);
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   Qualifiers::ObjCLifetime expectedLifetime
760b57cec5SDimitry Andric     = getImpliedARCOwnership(propertyKind, property->getType());
770b57cec5SDimitry Andric   if (!expectedLifetime) {
780b57cec5SDimitry Andric     // We have a lifetime qualifier but no dominating property
790b57cec5SDimitry Andric     // attribute.  That's okay, but restore reasonable invariants by
800b57cec5SDimitry Andric     // setting the property attribute according to the lifetime
810b57cec5SDimitry Andric     // qualifier.
825ffd83dbSDimitry Andric     ObjCPropertyAttribute::Kind attr;
830b57cec5SDimitry Andric     if (propertyLifetime == Qualifiers::OCL_Strong) {
845ffd83dbSDimitry Andric       attr = ObjCPropertyAttribute::kind_strong;
850b57cec5SDimitry Andric     } else if (propertyLifetime == Qualifiers::OCL_Weak) {
865ffd83dbSDimitry Andric       attr = ObjCPropertyAttribute::kind_weak;
870b57cec5SDimitry Andric     } else {
880b57cec5SDimitry Andric       assert(propertyLifetime == Qualifiers::OCL_ExplicitNone);
895ffd83dbSDimitry Andric       attr = ObjCPropertyAttribute::kind_unsafe_unretained;
900b57cec5SDimitry Andric     }
910b57cec5SDimitry Andric     property->setPropertyAttributes(attr);
920b57cec5SDimitry Andric     return;
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   if (propertyLifetime == expectedLifetime) return;
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   property->setInvalidDecl();
980b57cec5SDimitry Andric   S.Diag(property->getLocation(),
990b57cec5SDimitry Andric          diag::err_arc_inconsistent_property_ownership)
1000b57cec5SDimitry Andric     << property->getDeclName()
1010b57cec5SDimitry Andric     << expectedLifetime
1020b57cec5SDimitry Andric     << propertyLifetime;
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric /// Check this Objective-C property against a property declared in the
1060b57cec5SDimitry Andric /// given protocol.
1070b57cec5SDimitry Andric static void
1080b57cec5SDimitry Andric CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
1090b57cec5SDimitry Andric                              ObjCProtocolDecl *Proto,
1100b57cec5SDimitry Andric                              llvm::SmallPtrSetImpl<ObjCProtocolDecl *> &Known) {
1110b57cec5SDimitry Andric   // Have we seen this protocol before?
1120b57cec5SDimitry Andric   if (!Known.insert(Proto).second)
1130b57cec5SDimitry Andric     return;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // Look for a property with the same name.
11604eeddc0SDimitry Andric   if (ObjCPropertyDecl *ProtoProp = Proto->getProperty(
11704eeddc0SDimitry Andric           Prop->getIdentifier(), Prop->isInstanceProperty())) {
118*0fca6ea1SDimitry Andric     S.ObjC().DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(),
119*0fca6ea1SDimitry Andric                                       true);
1200b57cec5SDimitry Andric     return;
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   // Check this property against any protocols we inherit.
1240b57cec5SDimitry Andric   for (auto *P : Proto->protocols())
1250b57cec5SDimitry Andric     CheckPropertyAgainstProtocol(S, Prop, P, Known);
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric static unsigned deducePropertyOwnershipFromType(Sema &S, QualType T) {
1290b57cec5SDimitry Andric   // In GC mode, just look for the __weak qualifier.
1300b57cec5SDimitry Andric   if (S.getLangOpts().getGC() != LangOptions::NonGC) {
1315ffd83dbSDimitry Andric     if (T.isObjCGCWeak())
1325ffd83dbSDimitry Andric       return ObjCPropertyAttribute::kind_weak;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric     // In ARC/MRC, look for an explicit ownership qualifier.
1350b57cec5SDimitry Andric     // For some reason, this only applies to __weak.
1360b57cec5SDimitry Andric   } else if (auto ownership = T.getObjCLifetime()) {
1370b57cec5SDimitry Andric     switch (ownership) {
1380b57cec5SDimitry Andric     case Qualifiers::OCL_Weak:
1395ffd83dbSDimitry Andric       return ObjCPropertyAttribute::kind_weak;
1400b57cec5SDimitry Andric     case Qualifiers::OCL_Strong:
1415ffd83dbSDimitry Andric       return ObjCPropertyAttribute::kind_strong;
1420b57cec5SDimitry Andric     case Qualifiers::OCL_ExplicitNone:
1435ffd83dbSDimitry Andric       return ObjCPropertyAttribute::kind_unsafe_unretained;
1440b57cec5SDimitry Andric     case Qualifiers::OCL_Autoreleasing:
1450b57cec5SDimitry Andric     case Qualifiers::OCL_None:
1460b57cec5SDimitry Andric       return 0;
1470b57cec5SDimitry Andric     }
1480b57cec5SDimitry Andric     llvm_unreachable("bad qualifier");
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   return 0;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric static const unsigned OwnershipMask =
1555ffd83dbSDimitry Andric     (ObjCPropertyAttribute::kind_assign | ObjCPropertyAttribute::kind_retain |
1565ffd83dbSDimitry Andric      ObjCPropertyAttribute::kind_copy | ObjCPropertyAttribute::kind_weak |
1575ffd83dbSDimitry Andric      ObjCPropertyAttribute::kind_strong |
1585ffd83dbSDimitry Andric      ObjCPropertyAttribute::kind_unsafe_unretained);
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric static unsigned getOwnershipRule(unsigned attr) {
1610b57cec5SDimitry Andric   unsigned result = attr & OwnershipMask;
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   // From an ownership perspective, assign and unsafe_unretained are
1640b57cec5SDimitry Andric   // identical; make sure one also implies the other.
1655ffd83dbSDimitry Andric   if (result & (ObjCPropertyAttribute::kind_assign |
1665ffd83dbSDimitry Andric                 ObjCPropertyAttribute::kind_unsafe_unretained)) {
1675ffd83dbSDimitry Andric     result |= ObjCPropertyAttribute::kind_assign |
1685ffd83dbSDimitry Andric               ObjCPropertyAttribute::kind_unsafe_unretained;
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   return result;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
174*0fca6ea1SDimitry Andric Decl *SemaObjC::ActOnProperty(Scope *S, SourceLocation AtLoc,
175*0fca6ea1SDimitry Andric                               SourceLocation LParenLoc, FieldDeclarator &FD,
176*0fca6ea1SDimitry Andric                               ObjCDeclSpec &ODS, Selector GetterSel,
1770b57cec5SDimitry Andric                               Selector SetterSel,
1780b57cec5SDimitry Andric                               tok::ObjCKeywordKind MethodImplKind,
1790b57cec5SDimitry Andric                               DeclContext *lexicalDC) {
1800b57cec5SDimitry Andric   unsigned Attributes = ODS.getPropertyAttributes();
1815ffd83dbSDimitry Andric   FD.D.setObjCWeakProperty((Attributes & ObjCPropertyAttribute::kind_weak) !=
1825ffd83dbSDimitry Andric                            0);
183*0fca6ea1SDimitry Andric   TypeSourceInfo *TSI = SemaRef.GetTypeForDeclarator(FD.D);
1840b57cec5SDimitry Andric   QualType T = TSI->getType();
1850b57cec5SDimitry Andric   if (!getOwnershipRule(Attributes)) {
186*0fca6ea1SDimitry Andric     Attributes |= deducePropertyOwnershipFromType(SemaRef, T);
1870b57cec5SDimitry Andric   }
1885ffd83dbSDimitry Andric   bool isReadWrite = ((Attributes & ObjCPropertyAttribute::kind_readwrite) ||
1890b57cec5SDimitry Andric                       // default is readwrite!
1905ffd83dbSDimitry Andric                       !(Attributes & ObjCPropertyAttribute::kind_readonly));
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   // Proceed with constructing the ObjCPropertyDecls.
193*0fca6ea1SDimitry Andric   ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(SemaRef.CurContext);
1940b57cec5SDimitry Andric   ObjCPropertyDecl *Res = nullptr;
1950b57cec5SDimitry Andric   if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
1960b57cec5SDimitry Andric     if (CDecl->IsClassExtension()) {
1970b57cec5SDimitry Andric       Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
1980b57cec5SDimitry Andric                                            FD,
1990b57cec5SDimitry Andric                                            GetterSel, ODS.getGetterNameLoc(),
2000b57cec5SDimitry Andric                                            SetterSel, ODS.getSetterNameLoc(),
2010b57cec5SDimitry Andric                                            isReadWrite, Attributes,
2020b57cec5SDimitry Andric                                            ODS.getPropertyAttributes(),
2030b57cec5SDimitry Andric                                            T, TSI, MethodImplKind);
2040b57cec5SDimitry Andric       if (!Res)
2050b57cec5SDimitry Andric         return nullptr;
2060b57cec5SDimitry Andric     }
2070b57cec5SDimitry Andric   }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   if (!Res) {
2100b57cec5SDimitry Andric     Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
2110b57cec5SDimitry Andric                              GetterSel, ODS.getGetterNameLoc(), SetterSel,
2120b57cec5SDimitry Andric                              ODS.getSetterNameLoc(), isReadWrite, Attributes,
2130b57cec5SDimitry Andric                              ODS.getPropertyAttributes(), T, TSI,
2140b57cec5SDimitry Andric                              MethodImplKind);
2150b57cec5SDimitry Andric     if (lexicalDC)
2160b57cec5SDimitry Andric       Res->setLexicalDeclContext(lexicalDC);
2170b57cec5SDimitry Andric   }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   // Validate the attributes on the @property.
2200b57cec5SDimitry Andric   CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
2210b57cec5SDimitry Andric                               (isa<ObjCInterfaceDecl>(ClassDecl) ||
2220b57cec5SDimitry Andric                                isa<ObjCProtocolDecl>(ClassDecl)));
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   // Check consistency if the type has explicit ownership qualification.
2250b57cec5SDimitry Andric   if (Res->getType().getObjCLifetime())
226*0fca6ea1SDimitry Andric     checkPropertyDeclWithOwnership(SemaRef, Res);
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos;
2290b57cec5SDimitry Andric   if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
2300b57cec5SDimitry Andric     // For a class, compare the property against a property in our superclass.
2310b57cec5SDimitry Andric     bool FoundInSuper = false;
2320b57cec5SDimitry Andric     ObjCInterfaceDecl *CurrentInterfaceDecl = IFace;
2330b57cec5SDimitry Andric     while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) {
23404eeddc0SDimitry Andric       if (ObjCPropertyDecl *SuperProp = Super->getProperty(
23504eeddc0SDimitry Andric               Res->getIdentifier(), Res->isInstanceProperty())) {
2360b57cec5SDimitry Andric         DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
2370b57cec5SDimitry Andric         FoundInSuper = true;
2380b57cec5SDimitry Andric         break;
2390b57cec5SDimitry Andric       }
2400b57cec5SDimitry Andric       CurrentInterfaceDecl = Super;
2410b57cec5SDimitry Andric     }
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric     if (FoundInSuper) {
2440b57cec5SDimitry Andric       // Also compare the property against a property in our protocols.
2450b57cec5SDimitry Andric       for (auto *P : CurrentInterfaceDecl->protocols()) {
246*0fca6ea1SDimitry Andric         CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos);
2470b57cec5SDimitry Andric       }
2480b57cec5SDimitry Andric     } else {
2490b57cec5SDimitry Andric       // Slower path: look in all protocols we referenced.
2500b57cec5SDimitry Andric       for (auto *P : IFace->all_referenced_protocols()) {
251*0fca6ea1SDimitry Andric         CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos);
2520b57cec5SDimitry Andric       }
2530b57cec5SDimitry Andric     }
2540b57cec5SDimitry Andric   } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
2550b57cec5SDimitry Andric     // We don't check if class extension. Because properties in class extension
2560b57cec5SDimitry Andric     // are meant to override some of the attributes and checking has already done
2570b57cec5SDimitry Andric     // when property in class extension is constructed.
2580b57cec5SDimitry Andric     if (!Cat->IsClassExtension())
2590b57cec5SDimitry Andric       for (auto *P : Cat->protocols())
260*0fca6ea1SDimitry Andric         CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos);
2610b57cec5SDimitry Andric   } else {
2620b57cec5SDimitry Andric     ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
2630b57cec5SDimitry Andric     for (auto *P : Proto->protocols())
264*0fca6ea1SDimitry Andric       CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos);
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric 
267*0fca6ea1SDimitry Andric   SemaRef.ActOnDocumentableDecl(Res);
2680b57cec5SDimitry Andric   return Res;
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
2715ffd83dbSDimitry Andric static ObjCPropertyAttribute::Kind
2720b57cec5SDimitry Andric makePropertyAttributesAsWritten(unsigned Attributes) {
2730b57cec5SDimitry Andric   unsigned attributesAsWritten = 0;
2745ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_readonly)
2755ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_readonly;
2765ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_readwrite)
2775ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_readwrite;
2785ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_getter)
2795ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_getter;
2805ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_setter)
2815ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_setter;
2825ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_assign)
2835ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_assign;
2845ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_retain)
2855ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_retain;
2865ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_strong)
2875ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_strong;
2885ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_weak)
2895ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_weak;
2905ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_copy)
2915ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_copy;
2925ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained)
2935ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_unsafe_unretained;
2945ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
2955ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_nonatomic;
2965ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_atomic)
2975ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_atomic;
2985ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_class)
2995ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_class;
3005ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_direct)
3015ffd83dbSDimitry Andric     attributesAsWritten |= ObjCPropertyAttribute::kind_direct;
3020b57cec5SDimitry Andric 
3035ffd83dbSDimitry Andric   return (ObjCPropertyAttribute::Kind)attributesAsWritten;
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
3070b57cec5SDimitry Andric                                  SourceLocation LParenLoc, SourceLocation &Loc) {
3080b57cec5SDimitry Andric   if (LParenLoc.isMacroID())
3090b57cec5SDimitry Andric     return false;
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric   SourceManager &SM = Context.getSourceManager();
3120b57cec5SDimitry Andric   std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(LParenLoc);
3130b57cec5SDimitry Andric   // Try to load the file buffer.
3140b57cec5SDimitry Andric   bool invalidTemp = false;
3150b57cec5SDimitry Andric   StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
3160b57cec5SDimitry Andric   if (invalidTemp)
3170b57cec5SDimitry Andric     return false;
3180b57cec5SDimitry Andric   const char *tokenBegin = file.data() + locInfo.second;
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   // Lex from the start of the given location.
3210b57cec5SDimitry Andric   Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
3220b57cec5SDimitry Andric               Context.getLangOpts(),
3230b57cec5SDimitry Andric               file.begin(), tokenBegin, file.end());
3240b57cec5SDimitry Andric   Token Tok;
3250b57cec5SDimitry Andric   do {
3260b57cec5SDimitry Andric     lexer.LexFromRawLexer(Tok);
3270b57cec5SDimitry Andric     if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) {
3280b57cec5SDimitry Andric       Loc = Tok.getLocation();
3290b57cec5SDimitry Andric       return true;
3300b57cec5SDimitry Andric     }
3310b57cec5SDimitry Andric   } while (Tok.isNot(tok::r_paren));
3320b57cec5SDimitry Andric   return false;
3330b57cec5SDimitry Andric }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric /// Check for a mismatch in the atomicity of the given properties.
3360b57cec5SDimitry Andric static void checkAtomicPropertyMismatch(Sema &S,
3370b57cec5SDimitry Andric                                         ObjCPropertyDecl *OldProperty,
3380b57cec5SDimitry Andric                                         ObjCPropertyDecl *NewProperty,
3390b57cec5SDimitry Andric                                         bool PropagateAtomicity) {
3400b57cec5SDimitry Andric   // If the atomicity of both matches, we're done.
3415ffd83dbSDimitry Andric   bool OldIsAtomic = (OldProperty->getPropertyAttributes() &
3425ffd83dbSDimitry Andric                       ObjCPropertyAttribute::kind_nonatomic) == 0;
3435ffd83dbSDimitry Andric   bool NewIsAtomic = (NewProperty->getPropertyAttributes() &
3445ffd83dbSDimitry Andric                       ObjCPropertyAttribute::kind_nonatomic) == 0;
3450b57cec5SDimitry Andric   if (OldIsAtomic == NewIsAtomic) return;
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   // Determine whether the given property is readonly and implicitly
3480b57cec5SDimitry Andric   // atomic.
3490b57cec5SDimitry Andric   auto isImplicitlyReadonlyAtomic = [](ObjCPropertyDecl *Property) -> bool {
3500b57cec5SDimitry Andric     // Is it readonly?
3510b57cec5SDimitry Andric     auto Attrs = Property->getPropertyAttributes();
3525ffd83dbSDimitry Andric     if ((Attrs & ObjCPropertyAttribute::kind_readonly) == 0)
3535ffd83dbSDimitry Andric       return false;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric     // Is it nonatomic?
3565ffd83dbSDimitry Andric     if (Attrs & ObjCPropertyAttribute::kind_nonatomic)
3575ffd83dbSDimitry Andric       return false;
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric     // Was 'atomic' specified directly?
3600b57cec5SDimitry Andric     if (Property->getPropertyAttributesAsWritten() &
3615ffd83dbSDimitry Andric         ObjCPropertyAttribute::kind_atomic)
3620b57cec5SDimitry Andric       return false;
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric     return true;
3650b57cec5SDimitry Andric   };
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   // If we're allowed to propagate atomicity, and the new property did
3680b57cec5SDimitry Andric   // not specify atomicity at all, propagate.
3695ffd83dbSDimitry Andric   const unsigned AtomicityMask = (ObjCPropertyAttribute::kind_atomic |
3705ffd83dbSDimitry Andric                                   ObjCPropertyAttribute::kind_nonatomic);
3710b57cec5SDimitry Andric   if (PropagateAtomicity &&
3720b57cec5SDimitry Andric       ((NewProperty->getPropertyAttributesAsWritten() & AtomicityMask) == 0)) {
3730b57cec5SDimitry Andric     unsigned Attrs = NewProperty->getPropertyAttributes();
3740b57cec5SDimitry Andric     Attrs = Attrs & ~AtomicityMask;
3750b57cec5SDimitry Andric     if (OldIsAtomic)
3765ffd83dbSDimitry Andric       Attrs |= ObjCPropertyAttribute::kind_atomic;
3770b57cec5SDimitry Andric     else
3785ffd83dbSDimitry Andric       Attrs |= ObjCPropertyAttribute::kind_nonatomic;
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric     NewProperty->overwritePropertyAttributes(Attrs);
3810b57cec5SDimitry Andric     return;
3820b57cec5SDimitry Andric   }
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   // One of the properties is atomic; if it's a readonly property, and
3850b57cec5SDimitry Andric   // 'atomic' wasn't explicitly specified, we're okay.
3860b57cec5SDimitry Andric   if ((OldIsAtomic && isImplicitlyReadonlyAtomic(OldProperty)) ||
3870b57cec5SDimitry Andric       (NewIsAtomic && isImplicitlyReadonlyAtomic(NewProperty)))
3880b57cec5SDimitry Andric     return;
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric   // Diagnose the conflict.
3910b57cec5SDimitry Andric   const IdentifierInfo *OldContextName;
3920b57cec5SDimitry Andric   auto *OldDC = OldProperty->getDeclContext();
3930b57cec5SDimitry Andric   if (auto Category = dyn_cast<ObjCCategoryDecl>(OldDC))
3940b57cec5SDimitry Andric     OldContextName = Category->getClassInterface()->getIdentifier();
3950b57cec5SDimitry Andric   else
3960b57cec5SDimitry Andric     OldContextName = cast<ObjCContainerDecl>(OldDC)->getIdentifier();
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   S.Diag(NewProperty->getLocation(), diag::warn_property_attribute)
3990b57cec5SDimitry Andric     << NewProperty->getDeclName() << "atomic"
4000b57cec5SDimitry Andric     << OldContextName;
4010b57cec5SDimitry Andric   S.Diag(OldProperty->getLocation(), diag::note_property_declare);
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric 
404*0fca6ea1SDimitry Andric ObjCPropertyDecl *SemaObjC::HandlePropertyInClassExtension(
405*0fca6ea1SDimitry Andric     Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc,
406*0fca6ea1SDimitry Andric     FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc,
407*0fca6ea1SDimitry Andric     Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite,
408*0fca6ea1SDimitry Andric     unsigned &Attributes, const unsigned AttributesAsWritten, QualType T,
409*0fca6ea1SDimitry Andric     TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind) {
410*0fca6ea1SDimitry Andric   ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(SemaRef.CurContext);
4110b57cec5SDimitry Andric   // Diagnose if this property is already in continuation class.
412*0fca6ea1SDimitry Andric   DeclContext *DC = SemaRef.CurContext;
413*0fca6ea1SDimitry Andric   const IdentifierInfo *PropertyId = FD.D.getIdentifier();
4140b57cec5SDimitry Andric   ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   // We need to look in the @interface to see if the @property was
4170b57cec5SDimitry Andric   // already declared.
4180b57cec5SDimitry Andric   if (!CCPrimary) {
4190b57cec5SDimitry Andric     Diag(CDecl->getLocation(), diag::err_continuation_class);
4200b57cec5SDimitry Andric     return nullptr;
4210b57cec5SDimitry Andric   }
4220b57cec5SDimitry Andric 
4235ffd83dbSDimitry Andric   bool isClassProperty =
4245ffd83dbSDimitry Andric       (AttributesAsWritten & ObjCPropertyAttribute::kind_class) ||
4255ffd83dbSDimitry Andric       (Attributes & ObjCPropertyAttribute::kind_class);
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   // Find the property in the extended class's primary class or
4280b57cec5SDimitry Andric   // extensions.
4290b57cec5SDimitry Andric   ObjCPropertyDecl *PIDecl = CCPrimary->FindPropertyVisibleInPrimaryClass(
4300b57cec5SDimitry Andric       PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty));
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric   // If we found a property in an extension, complain.
4330b57cec5SDimitry Andric   if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) {
4340b57cec5SDimitry Andric     Diag(AtLoc, diag::err_duplicate_property);
4350b57cec5SDimitry Andric     Diag(PIDecl->getLocation(), diag::note_property_declare);
4360b57cec5SDimitry Andric     return nullptr;
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   // Check for consistency with the previous declaration, if there is one.
4400b57cec5SDimitry Andric   if (PIDecl) {
4410b57cec5SDimitry Andric     // A readonly property declared in the primary class can be refined
4420b57cec5SDimitry Andric     // by adding a readwrite property within an extension.
4430b57cec5SDimitry Andric     // Anything else is an error.
4440b57cec5SDimitry Andric     if (!(PIDecl->isReadOnly() && isReadWrite)) {
4450b57cec5SDimitry Andric       // Tailor the diagnostics for the common case where a readwrite
4460b57cec5SDimitry Andric       // property is declared both in the @interface and the continuation.
4470b57cec5SDimitry Andric       // This is a common error where the user often intended the original
4480b57cec5SDimitry Andric       // declaration to be readonly.
4490b57cec5SDimitry Andric       unsigned diag =
4505ffd83dbSDimitry Andric           (Attributes & ObjCPropertyAttribute::kind_readwrite) &&
4510b57cec5SDimitry Andric                   (PIDecl->getPropertyAttributesAsWritten() &
4525ffd83dbSDimitry Andric                    ObjCPropertyAttribute::kind_readwrite)
4530b57cec5SDimitry Andric               ? diag::err_use_continuation_class_redeclaration_readwrite
4540b57cec5SDimitry Andric               : diag::err_use_continuation_class;
4550b57cec5SDimitry Andric       Diag(AtLoc, diag)
4560b57cec5SDimitry Andric         << CCPrimary->getDeclName();
4570b57cec5SDimitry Andric       Diag(PIDecl->getLocation(), diag::note_property_declare);
4580b57cec5SDimitry Andric       return nullptr;
4590b57cec5SDimitry Andric     }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric     // Check for consistency of getters.
4620b57cec5SDimitry Andric     if (PIDecl->getGetterName() != GetterSel) {
4630b57cec5SDimitry Andric      // If the getter was written explicitly, complain.
4645ffd83dbSDimitry Andric      if (AttributesAsWritten & ObjCPropertyAttribute::kind_getter) {
4650b57cec5SDimitry Andric        Diag(AtLoc, diag::warn_property_redecl_getter_mismatch)
4660b57cec5SDimitry Andric            << PIDecl->getGetterName() << GetterSel;
4670b57cec5SDimitry Andric        Diag(PIDecl->getLocation(), diag::note_property_declare);
4680b57cec5SDimitry Andric      }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric       // Always adopt the getter from the original declaration.
4710b57cec5SDimitry Andric       GetterSel = PIDecl->getGetterName();
4725ffd83dbSDimitry Andric       Attributes |= ObjCPropertyAttribute::kind_getter;
4730b57cec5SDimitry Andric     }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric     // Check consistency of ownership.
4760b57cec5SDimitry Andric     unsigned ExistingOwnership
4770b57cec5SDimitry Andric       = getOwnershipRule(PIDecl->getPropertyAttributes());
4780b57cec5SDimitry Andric     unsigned NewOwnership = getOwnershipRule(Attributes);
4790b57cec5SDimitry Andric     if (ExistingOwnership && NewOwnership != ExistingOwnership) {
4800b57cec5SDimitry Andric       // If the ownership was written explicitly, complain.
4810b57cec5SDimitry Andric       if (getOwnershipRule(AttributesAsWritten)) {
4820b57cec5SDimitry Andric         Diag(AtLoc, diag::warn_property_attr_mismatch);
4830b57cec5SDimitry Andric         Diag(PIDecl->getLocation(), diag::note_property_declare);
4840b57cec5SDimitry Andric       }
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric       // Take the ownership from the original property.
4870b57cec5SDimitry Andric       Attributes = (Attributes & ~OwnershipMask) | ExistingOwnership;
4880b57cec5SDimitry Andric     }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric     // If the redeclaration is 'weak' but the original property is not,
4915ffd83dbSDimitry Andric     if ((Attributes & ObjCPropertyAttribute::kind_weak) &&
4925ffd83dbSDimitry Andric         !(PIDecl->getPropertyAttributesAsWritten() &
4935ffd83dbSDimitry Andric           ObjCPropertyAttribute::kind_weak) &&
4940b57cec5SDimitry Andric         PIDecl->getType()->getAs<ObjCObjectPointerType>() &&
4950b57cec5SDimitry Andric         PIDecl->getType().getObjCLifetime() == Qualifiers::OCL_None) {
4960b57cec5SDimitry Andric       Diag(AtLoc, diag::warn_property_implicitly_mismatched);
4970b57cec5SDimitry Andric       Diag(PIDecl->getLocation(), diag::note_property_declare);
4980b57cec5SDimitry Andric     }
4990b57cec5SDimitry Andric   }
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   // Create a new ObjCPropertyDecl with the DeclContext being
5020b57cec5SDimitry Andric   // the class extension.
5030b57cec5SDimitry Andric   ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc,
5040b57cec5SDimitry Andric                                                FD, GetterSel, GetterNameLoc,
5050b57cec5SDimitry Andric                                                SetterSel, SetterNameLoc,
5060b57cec5SDimitry Andric                                                isReadWrite,
5070b57cec5SDimitry Andric                                                Attributes, AttributesAsWritten,
5080b57cec5SDimitry Andric                                                T, TSI, MethodImplKind, DC);
509*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
5100b57cec5SDimitry Andric   // If there was no declaration of a property with the same name in
5110b57cec5SDimitry Andric   // the primary class, we're done.
5120b57cec5SDimitry Andric   if (!PIDecl) {
5130b57cec5SDimitry Andric     ProcessPropertyDecl(PDecl);
5140b57cec5SDimitry Andric     return PDecl;
5150b57cec5SDimitry Andric   }
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
5180b57cec5SDimitry Andric     bool IncompatibleObjC = false;
5190b57cec5SDimitry Andric     QualType ConvertedType;
5200b57cec5SDimitry Andric     // Relax the strict type matching for property type in continuation class.
5210b57cec5SDimitry Andric     // Allow property object type of continuation class to be different as long
5220b57cec5SDimitry Andric     // as it narrows the object type in its primary class property. Note that
5230b57cec5SDimitry Andric     // this conversion is safe only because the wider type is for a 'readonly'
5240b57cec5SDimitry Andric     // property in primary class and 'narrowed' type for a 'readwrite' property
5250b57cec5SDimitry Andric     // in continuation class.
5260b57cec5SDimitry Andric     QualType PrimaryClassPropertyT = Context.getCanonicalType(PIDecl->getType());
5270b57cec5SDimitry Andric     QualType ClassExtPropertyT = Context.getCanonicalType(PDecl->getType());
5280b57cec5SDimitry Andric     if (!isa<ObjCObjectPointerType>(PrimaryClassPropertyT) ||
5290b57cec5SDimitry Andric         !isa<ObjCObjectPointerType>(ClassExtPropertyT) ||
530*0fca6ea1SDimitry Andric         (!SemaRef.isObjCPointerConversion(ClassExtPropertyT,
531*0fca6ea1SDimitry Andric                                           PrimaryClassPropertyT, ConvertedType,
532*0fca6ea1SDimitry Andric                                           IncompatibleObjC)) ||
533*0fca6ea1SDimitry Andric         IncompatibleObjC) {
5340b57cec5SDimitry Andric       Diag(AtLoc,
5350b57cec5SDimitry Andric           diag::err_type_mismatch_continuation_class) << PDecl->getType();
5360b57cec5SDimitry Andric       Diag(PIDecl->getLocation(), diag::note_property_declare);
5370b57cec5SDimitry Andric       return nullptr;
5380b57cec5SDimitry Andric     }
5390b57cec5SDimitry Andric   }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   // Check that atomicity of property in class extension matches the previous
5420b57cec5SDimitry Andric   // declaration.
543*0fca6ea1SDimitry Andric   checkAtomicPropertyMismatch(SemaRef, PIDecl, PDecl, true);
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric   // Make sure getter/setter are appropriately synthesized.
5460b57cec5SDimitry Andric   ProcessPropertyDecl(PDecl);
5470b57cec5SDimitry Andric   return PDecl;
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric 
550*0fca6ea1SDimitry Andric ObjCPropertyDecl *SemaObjC::CreatePropertyDecl(
551*0fca6ea1SDimitry Andric     Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc,
552*0fca6ea1SDimitry Andric     SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel,
553*0fca6ea1SDimitry Andric     SourceLocation GetterNameLoc, Selector SetterSel,
554*0fca6ea1SDimitry Andric     SourceLocation SetterNameLoc, const bool isReadWrite,
555*0fca6ea1SDimitry Andric     const unsigned Attributes, const unsigned AttributesAsWritten, QualType T,
556*0fca6ea1SDimitry Andric     TypeSourceInfo *TInfo, tok::ObjCKeywordKind MethodImplKind,
5570b57cec5SDimitry Andric     DeclContext *lexicalDC) {
558*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
559*0fca6ea1SDimitry Andric   const IdentifierInfo *PropertyId = FD.D.getIdentifier();
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   // Property defaults to 'assign' if it is readwrite, unless this is ARC
5620b57cec5SDimitry Andric   // and the type is retainable.
5630b57cec5SDimitry Andric   bool isAssign;
5645ffd83dbSDimitry Andric   if (Attributes & (ObjCPropertyAttribute::kind_assign |
5655ffd83dbSDimitry Andric                     ObjCPropertyAttribute::kind_unsafe_unretained)) {
5660b57cec5SDimitry Andric     isAssign = true;
5670b57cec5SDimitry Andric   } else if (getOwnershipRule(Attributes) || !isReadWrite) {
5680b57cec5SDimitry Andric     isAssign = false;
5690b57cec5SDimitry Andric   } else {
5700b57cec5SDimitry Andric     isAssign = (!getLangOpts().ObjCAutoRefCount ||
5710b57cec5SDimitry Andric                 !T->isObjCRetainableType());
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   // Issue a warning if property is 'assign' as default and its
5750b57cec5SDimitry Andric   // object, which is gc'able conforms to NSCopying protocol
5765ffd83dbSDimitry Andric   if (getLangOpts().getGC() != LangOptions::NonGC && isAssign &&
5775ffd83dbSDimitry Andric       !(Attributes & ObjCPropertyAttribute::kind_assign)) {
5780b57cec5SDimitry Andric     if (const ObjCObjectPointerType *ObjPtrTy =
5790b57cec5SDimitry Andric           T->getAs<ObjCObjectPointerType>()) {
5800b57cec5SDimitry Andric       ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
5810b57cec5SDimitry Andric       if (IDecl)
5820b57cec5SDimitry Andric         if (ObjCProtocolDecl* PNSCopying =
5830b57cec5SDimitry Andric             LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
5840b57cec5SDimitry Andric           if (IDecl->ClassImplementsProtocol(PNSCopying, true))
5850b57cec5SDimitry Andric             Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
5860b57cec5SDimitry Andric     }
5870b57cec5SDimitry Andric   }
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric   if (T->isObjCObjectType()) {
5900b57cec5SDimitry Andric     SourceLocation StarLoc = TInfo->getTypeLoc().getEndLoc();
591*0fca6ea1SDimitry Andric     StarLoc = SemaRef.getLocForEndOfToken(StarLoc);
5920b57cec5SDimitry Andric     Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
5930b57cec5SDimitry Andric       << FixItHint::CreateInsertion(StarLoc, "*");
5940b57cec5SDimitry Andric     T = Context.getObjCObjectPointerType(T);
5950b57cec5SDimitry Andric     SourceLocation TLoc = TInfo->getTypeLoc().getBeginLoc();
5960b57cec5SDimitry Andric     TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
5970b57cec5SDimitry Andric   }
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric   DeclContext *DC = CDecl;
6000b57cec5SDimitry Andric   ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
6010b57cec5SDimitry Andric                                                      FD.D.getIdentifierLoc(),
6020b57cec5SDimitry Andric                                                      PropertyId, AtLoc,
6030b57cec5SDimitry Andric                                                      LParenLoc, T, TInfo);
6040b57cec5SDimitry Andric 
6055ffd83dbSDimitry Andric   bool isClassProperty =
6065ffd83dbSDimitry Andric       (AttributesAsWritten & ObjCPropertyAttribute::kind_class) ||
6075ffd83dbSDimitry Andric       (Attributes & ObjCPropertyAttribute::kind_class);
6080b57cec5SDimitry Andric   // Class property and instance property can have the same name.
6090b57cec5SDimitry Andric   if (ObjCPropertyDecl *prevDecl = ObjCPropertyDecl::findPropertyDecl(
6100b57cec5SDimitry Andric           DC, PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty))) {
6110b57cec5SDimitry Andric     Diag(PDecl->getLocation(), diag::err_duplicate_property);
6120b57cec5SDimitry Andric     Diag(prevDecl->getLocation(), diag::note_property_declare);
6130b57cec5SDimitry Andric     PDecl->setInvalidDecl();
6140b57cec5SDimitry Andric   }
6150b57cec5SDimitry Andric   else {
6160b57cec5SDimitry Andric     DC->addDecl(PDecl);
6170b57cec5SDimitry Andric     if (lexicalDC)
6180b57cec5SDimitry Andric       PDecl->setLexicalDeclContext(lexicalDC);
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   if (T->isArrayType() || T->isFunctionType()) {
6220b57cec5SDimitry Andric     Diag(AtLoc, diag::err_property_type) << T;
6230b57cec5SDimitry Andric     PDecl->setInvalidDecl();
6240b57cec5SDimitry Andric   }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   // Regardless of setter/getter attribute, we save the default getter/setter
6270b57cec5SDimitry Andric   // selector names in anticipation of declaration of setter/getter methods.
6280b57cec5SDimitry Andric   PDecl->setGetterName(GetterSel, GetterNameLoc);
6290b57cec5SDimitry Andric   PDecl->setSetterName(SetterSel, SetterNameLoc);
6300b57cec5SDimitry Andric   PDecl->setPropertyAttributesAsWritten(
6310b57cec5SDimitry Andric                           makePropertyAttributesAsWritten(AttributesAsWritten));
6320b57cec5SDimitry Andric 
633*0fca6ea1SDimitry Andric   SemaRef.ProcessDeclAttributes(S, PDecl, FD.D);
634*0fca6ea1SDimitry Andric 
6355ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_readonly)
6365ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly);
6370b57cec5SDimitry Andric 
6385ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_getter)
6395ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_getter);
6400b57cec5SDimitry Andric 
6415ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_setter)
6425ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_setter);
6430b57cec5SDimitry Andric 
6440b57cec5SDimitry Andric   if (isReadWrite)
6455ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite);
6460b57cec5SDimitry Andric 
6475ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_retain)
6485ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_retain);
6490b57cec5SDimitry Andric 
6505ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_strong)
6515ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
6520b57cec5SDimitry Andric 
6535ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_weak)
6545ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_weak);
6550b57cec5SDimitry Andric 
6565ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_copy)
6575ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_copy);
6580b57cec5SDimitry Andric 
6595ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained)
6605ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained);
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric   if (isAssign)
6635ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_assign);
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   // In the semantic attributes, one of nonatomic or atomic is always set.
6665ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_nonatomic)
6675ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic);
6680b57cec5SDimitry Andric   else
6695ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_atomic);
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric   // 'unsafe_unretained' is alias for 'assign'.
6725ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained)
6735ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_assign);
6740b57cec5SDimitry Andric   if (isAssign)
6755ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained);
6760b57cec5SDimitry Andric 
6770b57cec5SDimitry Andric   if (MethodImplKind == tok::objc_required)
6780b57cec5SDimitry Andric     PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
6790b57cec5SDimitry Andric   else if (MethodImplKind == tok::objc_optional)
6800b57cec5SDimitry Andric     PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
6810b57cec5SDimitry Andric 
6825ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_nullability)
6835ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_nullability);
6840b57cec5SDimitry Andric 
6855ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_null_resettable)
6865ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable);
6870b57cec5SDimitry Andric 
6885ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_class)
6895ffd83dbSDimitry Andric     PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_class);
6900b57cec5SDimitry Andric 
6915ffd83dbSDimitry Andric   if ((Attributes & ObjCPropertyAttribute::kind_direct) ||
692480093f4SDimitry Andric       CDecl->hasAttr<ObjCDirectMembersAttr>()) {
693480093f4SDimitry Andric     if (isa<ObjCProtocolDecl>(CDecl)) {
694480093f4SDimitry Andric       Diag(PDecl->getLocation(), diag::err_objc_direct_on_protocol) << true;
695480093f4SDimitry Andric     } else if (getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
6965ffd83dbSDimitry Andric       PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_direct);
697480093f4SDimitry Andric     } else {
698480093f4SDimitry Andric       Diag(PDecl->getLocation(), diag::warn_objc_direct_property_ignored)
699480093f4SDimitry Andric           << PDecl->getDeclName();
700480093f4SDimitry Andric     }
701480093f4SDimitry Andric   }
702480093f4SDimitry Andric 
7030b57cec5SDimitry Andric   return PDecl;
7040b57cec5SDimitry Andric }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
7070b57cec5SDimitry Andric                                  ObjCPropertyDecl *property,
7080b57cec5SDimitry Andric                                  ObjCIvarDecl *ivar) {
7090b57cec5SDimitry Andric   if (property->isInvalidDecl() || ivar->isInvalidDecl()) return;
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric   QualType ivarType = ivar->getType();
7120b57cec5SDimitry Andric   Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric   // The lifetime implied by the property's attributes.
7150b57cec5SDimitry Andric   Qualifiers::ObjCLifetime propertyLifetime =
7160b57cec5SDimitry Andric     getImpliedARCOwnership(property->getPropertyAttributes(),
7170b57cec5SDimitry Andric                            property->getType());
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric   // We're fine if they match.
7200b57cec5SDimitry Andric   if (propertyLifetime == ivarLifetime) return;
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric   // None isn't a valid lifetime for an object ivar in ARC, and
7230b57cec5SDimitry Andric   // __autoreleasing is never valid; don't diagnose twice.
7240b57cec5SDimitry Andric   if ((ivarLifetime == Qualifiers::OCL_None &&
7250b57cec5SDimitry Andric        S.getLangOpts().ObjCAutoRefCount) ||
7260b57cec5SDimitry Andric       ivarLifetime == Qualifiers::OCL_Autoreleasing)
7270b57cec5SDimitry Andric     return;
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   // If the ivar is private, and it's implicitly __unsafe_unretained
730a7dea167SDimitry Andric   // because of its type, then pretend it was actually implicitly
7310b57cec5SDimitry Andric   // __strong.  This is only sound because we're processing the
7320b57cec5SDimitry Andric   // property implementation before parsing any method bodies.
7330b57cec5SDimitry Andric   if (ivarLifetime == Qualifiers::OCL_ExplicitNone &&
7340b57cec5SDimitry Andric       propertyLifetime == Qualifiers::OCL_Strong &&
7350b57cec5SDimitry Andric       ivar->getAccessControl() == ObjCIvarDecl::Private) {
7360b57cec5SDimitry Andric     SplitQualType split = ivarType.split();
7370b57cec5SDimitry Andric     if (split.Quals.hasObjCLifetime()) {
7380b57cec5SDimitry Andric       assert(ivarType->isObjCARCImplicitlyUnretainedType());
7390b57cec5SDimitry Andric       split.Quals.setObjCLifetime(Qualifiers::OCL_Strong);
7400b57cec5SDimitry Andric       ivarType = S.Context.getQualifiedType(split);
7410b57cec5SDimitry Andric       ivar->setType(ivarType);
7420b57cec5SDimitry Andric       return;
7430b57cec5SDimitry Andric     }
7440b57cec5SDimitry Andric   }
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   switch (propertyLifetime) {
7470b57cec5SDimitry Andric   case Qualifiers::OCL_Strong:
7480b57cec5SDimitry Andric     S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership)
7490b57cec5SDimitry Andric       << property->getDeclName()
7500b57cec5SDimitry Andric       << ivar->getDeclName()
7510b57cec5SDimitry Andric       << ivarLifetime;
7520b57cec5SDimitry Andric     break;
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric   case Qualifiers::OCL_Weak:
7550b57cec5SDimitry Andric     S.Diag(ivar->getLocation(), diag::err_weak_property)
7560b57cec5SDimitry Andric       << property->getDeclName()
7570b57cec5SDimitry Andric       << ivar->getDeclName();
7580b57cec5SDimitry Andric     break;
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   case Qualifiers::OCL_ExplicitNone:
7610b57cec5SDimitry Andric     S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership)
7625ffd83dbSDimitry Andric         << property->getDeclName() << ivar->getDeclName()
7635ffd83dbSDimitry Andric         << ((property->getPropertyAttributesAsWritten() &
7645ffd83dbSDimitry Andric              ObjCPropertyAttribute::kind_assign) != 0);
7650b57cec5SDimitry Andric     break;
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric   case Qualifiers::OCL_Autoreleasing:
7680b57cec5SDimitry Andric     llvm_unreachable("properties cannot be autoreleasing");
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric   case Qualifiers::OCL_None:
7710b57cec5SDimitry Andric     // Any other property should be ignored.
7720b57cec5SDimitry Andric     return;
7730b57cec5SDimitry Andric   }
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric   S.Diag(property->getLocation(), diag::note_property_declare);
7760b57cec5SDimitry Andric   if (propertyImplLoc.isValid())
7770b57cec5SDimitry Andric     S.Diag(propertyImplLoc, diag::note_property_synthesize);
7780b57cec5SDimitry Andric }
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric /// setImpliedPropertyAttributeForReadOnlyProperty -
7810b57cec5SDimitry Andric /// This routine evaludates life-time attributes for a 'readonly'
7820b57cec5SDimitry Andric /// property with no known lifetime of its own, using backing
7830b57cec5SDimitry Andric /// 'ivar's attribute, if any. If no backing 'ivar', property's
7840b57cec5SDimitry Andric /// life-time is assumed 'strong'.
7850b57cec5SDimitry Andric static void setImpliedPropertyAttributeForReadOnlyProperty(
7860b57cec5SDimitry Andric               ObjCPropertyDecl *property, ObjCIvarDecl *ivar) {
7870b57cec5SDimitry Andric   Qualifiers::ObjCLifetime propertyLifetime =
7880b57cec5SDimitry Andric     getImpliedARCOwnership(property->getPropertyAttributes(),
7890b57cec5SDimitry Andric                            property->getType());
7900b57cec5SDimitry Andric   if (propertyLifetime != Qualifiers::OCL_None)
7910b57cec5SDimitry Andric     return;
7920b57cec5SDimitry Andric 
7930b57cec5SDimitry Andric   if (!ivar) {
7940b57cec5SDimitry Andric     // if no backing ivar, make property 'strong'.
7955ffd83dbSDimitry Andric     property->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
7960b57cec5SDimitry Andric     return;
7970b57cec5SDimitry Andric   }
7980b57cec5SDimitry Andric   // property assumes owenership of backing ivar.
7990b57cec5SDimitry Andric   QualType ivarType = ivar->getType();
8000b57cec5SDimitry Andric   Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
8010b57cec5SDimitry Andric   if (ivarLifetime == Qualifiers::OCL_Strong)
8025ffd83dbSDimitry Andric     property->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
8030b57cec5SDimitry Andric   else if (ivarLifetime == Qualifiers::OCL_Weak)
8045ffd83dbSDimitry Andric     property->setPropertyAttributes(ObjCPropertyAttribute::kind_weak);
8050b57cec5SDimitry Andric }
8060b57cec5SDimitry Andric 
8075ffd83dbSDimitry Andric static bool isIncompatiblePropertyAttribute(unsigned Attr1, unsigned Attr2,
8085ffd83dbSDimitry Andric                                             ObjCPropertyAttribute::Kind Kind) {
8090b57cec5SDimitry Andric   return (Attr1 & Kind) != (Attr2 & Kind);
8100b57cec5SDimitry Andric }
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric static bool areIncompatiblePropertyAttributes(unsigned Attr1, unsigned Attr2,
8130b57cec5SDimitry Andric                                               unsigned Kinds) {
8140b57cec5SDimitry Andric   return ((Attr1 & Kinds) != 0) != ((Attr2 & Kinds) != 0);
8150b57cec5SDimitry Andric }
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric /// SelectPropertyForSynthesisFromProtocols - Finds the most appropriate
8180b57cec5SDimitry Andric /// property declaration that should be synthesised in all of the inherited
8190b57cec5SDimitry Andric /// protocols. It also diagnoses properties declared in inherited protocols with
8200b57cec5SDimitry Andric /// mismatched types or attributes, since any of them can be candidate for
8210b57cec5SDimitry Andric /// synthesis.
8220b57cec5SDimitry Andric static ObjCPropertyDecl *
8230b57cec5SDimitry Andric SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc,
8240b57cec5SDimitry Andric                                         ObjCInterfaceDecl *ClassDecl,
8250b57cec5SDimitry Andric                                         ObjCPropertyDecl *Property) {
8260b57cec5SDimitry Andric   assert(isa<ObjCProtocolDecl>(Property->getDeclContext()) &&
8270b57cec5SDimitry Andric          "Expected a property from a protocol");
8280b57cec5SDimitry Andric   ObjCInterfaceDecl::ProtocolPropertySet ProtocolSet;
8290b57cec5SDimitry Andric   ObjCInterfaceDecl::PropertyDeclOrder Properties;
8300b57cec5SDimitry Andric   for (const auto *PI : ClassDecl->all_referenced_protocols()) {
8310b57cec5SDimitry Andric     if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
8320b57cec5SDimitry Andric       PDecl->collectInheritedProtocolProperties(Property, ProtocolSet,
8330b57cec5SDimitry Andric                                                 Properties);
8340b57cec5SDimitry Andric   }
8350b57cec5SDimitry Andric   if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass()) {
8360b57cec5SDimitry Andric     while (SDecl) {
8370b57cec5SDimitry Andric       for (const auto *PI : SDecl->all_referenced_protocols()) {
8380b57cec5SDimitry Andric         if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
8390b57cec5SDimitry Andric           PDecl->collectInheritedProtocolProperties(Property, ProtocolSet,
8400b57cec5SDimitry Andric                                                     Properties);
8410b57cec5SDimitry Andric       }
8420b57cec5SDimitry Andric       SDecl = SDecl->getSuperClass();
8430b57cec5SDimitry Andric     }
8440b57cec5SDimitry Andric   }
8450b57cec5SDimitry Andric 
8460b57cec5SDimitry Andric   if (Properties.empty())
8470b57cec5SDimitry Andric     return Property;
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric   ObjCPropertyDecl *OriginalProperty = Property;
8500b57cec5SDimitry Andric   size_t SelectedIndex = 0;
8510b57cec5SDimitry Andric   for (const auto &Prop : llvm::enumerate(Properties)) {
8520b57cec5SDimitry Andric     // Select the 'readwrite' property if such property exists.
8530b57cec5SDimitry Andric     if (Property->isReadOnly() && !Prop.value()->isReadOnly()) {
8540b57cec5SDimitry Andric       Property = Prop.value();
8550b57cec5SDimitry Andric       SelectedIndex = Prop.index();
8560b57cec5SDimitry Andric     }
8570b57cec5SDimitry Andric   }
8580b57cec5SDimitry Andric   if (Property != OriginalProperty) {
8590b57cec5SDimitry Andric     // Check that the old property is compatible with the new one.
8600b57cec5SDimitry Andric     Properties[SelectedIndex] = OriginalProperty;
8610b57cec5SDimitry Andric   }
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric   QualType RHSType = S.Context.getCanonicalType(Property->getType());
8640b57cec5SDimitry Andric   unsigned OriginalAttributes = Property->getPropertyAttributesAsWritten();
8650b57cec5SDimitry Andric   enum MismatchKind {
8660b57cec5SDimitry Andric     IncompatibleType = 0,
8670b57cec5SDimitry Andric     HasNoExpectedAttribute,
8680b57cec5SDimitry Andric     HasUnexpectedAttribute,
8690b57cec5SDimitry Andric     DifferentGetter,
8700b57cec5SDimitry Andric     DifferentSetter
8710b57cec5SDimitry Andric   };
8720b57cec5SDimitry Andric   // Represents a property from another protocol that conflicts with the
8730b57cec5SDimitry Andric   // selected declaration.
8740b57cec5SDimitry Andric   struct MismatchingProperty {
8750b57cec5SDimitry Andric     const ObjCPropertyDecl *Prop;
8760b57cec5SDimitry Andric     MismatchKind Kind;
8770b57cec5SDimitry Andric     StringRef AttributeName;
8780b57cec5SDimitry Andric   };
8790b57cec5SDimitry Andric   SmallVector<MismatchingProperty, 4> Mismatches;
8800b57cec5SDimitry Andric   for (ObjCPropertyDecl *Prop : Properties) {
8810b57cec5SDimitry Andric     // Verify the property attributes.
8820b57cec5SDimitry Andric     unsigned Attr = Prop->getPropertyAttributesAsWritten();
8830b57cec5SDimitry Andric     if (Attr != OriginalAttributes) {
8840b57cec5SDimitry Andric       auto Diag = [&](bool OriginalHasAttribute, StringRef AttributeName) {
8850b57cec5SDimitry Andric         MismatchKind Kind = OriginalHasAttribute ? HasNoExpectedAttribute
8860b57cec5SDimitry Andric                                                  : HasUnexpectedAttribute;
8870b57cec5SDimitry Andric         Mismatches.push_back({Prop, Kind, AttributeName});
8880b57cec5SDimitry Andric       };
8890b57cec5SDimitry Andric       // The ownership might be incompatible unless the property has no explicit
8900b57cec5SDimitry Andric       // ownership.
8915ffd83dbSDimitry Andric       bool HasOwnership =
8925ffd83dbSDimitry Andric           (Attr & (ObjCPropertyAttribute::kind_retain |
8935ffd83dbSDimitry Andric                    ObjCPropertyAttribute::kind_strong |
8945ffd83dbSDimitry Andric                    ObjCPropertyAttribute::kind_copy |
8955ffd83dbSDimitry Andric                    ObjCPropertyAttribute::kind_assign |
8965ffd83dbSDimitry Andric                    ObjCPropertyAttribute::kind_unsafe_unretained |
8975ffd83dbSDimitry Andric                    ObjCPropertyAttribute::kind_weak)) != 0;
8980b57cec5SDimitry Andric       if (HasOwnership &&
8990b57cec5SDimitry Andric           isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
9005ffd83dbSDimitry Andric                                           ObjCPropertyAttribute::kind_copy)) {
9015ffd83dbSDimitry Andric         Diag(OriginalAttributes & ObjCPropertyAttribute::kind_copy, "copy");
9020b57cec5SDimitry Andric         continue;
9030b57cec5SDimitry Andric       }
9040b57cec5SDimitry Andric       if (HasOwnership && areIncompatiblePropertyAttributes(
9050b57cec5SDimitry Andric                               OriginalAttributes, Attr,
9065ffd83dbSDimitry Andric                               ObjCPropertyAttribute::kind_retain |
9075ffd83dbSDimitry Andric                                   ObjCPropertyAttribute::kind_strong)) {
9085ffd83dbSDimitry Andric         Diag(OriginalAttributes & (ObjCPropertyAttribute::kind_retain |
9095ffd83dbSDimitry Andric                                    ObjCPropertyAttribute::kind_strong),
9100b57cec5SDimitry Andric              "retain (or strong)");
9110b57cec5SDimitry Andric         continue;
9120b57cec5SDimitry Andric       }
9130b57cec5SDimitry Andric       if (isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
9145ffd83dbSDimitry Andric                                           ObjCPropertyAttribute::kind_atomic)) {
9155ffd83dbSDimitry Andric         Diag(OriginalAttributes & ObjCPropertyAttribute::kind_atomic, "atomic");
9160b57cec5SDimitry Andric         continue;
9170b57cec5SDimitry Andric       }
9180b57cec5SDimitry Andric     }
9190b57cec5SDimitry Andric     if (Property->getGetterName() != Prop->getGetterName()) {
9200b57cec5SDimitry Andric       Mismatches.push_back({Prop, DifferentGetter, ""});
9210b57cec5SDimitry Andric       continue;
9220b57cec5SDimitry Andric     }
9230b57cec5SDimitry Andric     if (!Property->isReadOnly() && !Prop->isReadOnly() &&
9240b57cec5SDimitry Andric         Property->getSetterName() != Prop->getSetterName()) {
9250b57cec5SDimitry Andric       Mismatches.push_back({Prop, DifferentSetter, ""});
9260b57cec5SDimitry Andric       continue;
9270b57cec5SDimitry Andric     }
9280b57cec5SDimitry Andric     QualType LHSType = S.Context.getCanonicalType(Prop->getType());
9290b57cec5SDimitry Andric     if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) {
9300b57cec5SDimitry Andric       bool IncompatibleObjC = false;
9310b57cec5SDimitry Andric       QualType ConvertedType;
9320b57cec5SDimitry Andric       if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC)
9330b57cec5SDimitry Andric           || IncompatibleObjC) {
9340b57cec5SDimitry Andric         Mismatches.push_back({Prop, IncompatibleType, ""});
9350b57cec5SDimitry Andric         continue;
9360b57cec5SDimitry Andric       }
9370b57cec5SDimitry Andric     }
9380b57cec5SDimitry Andric   }
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric   if (Mismatches.empty())
9410b57cec5SDimitry Andric     return Property;
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric   // Diagnose incompability.
9440b57cec5SDimitry Andric   {
9450b57cec5SDimitry Andric     bool HasIncompatibleAttributes = false;
9460b57cec5SDimitry Andric     for (const auto &Note : Mismatches)
9470b57cec5SDimitry Andric       HasIncompatibleAttributes =
9480b57cec5SDimitry Andric           Note.Kind != IncompatibleType ? true : HasIncompatibleAttributes;
9490b57cec5SDimitry Andric     // Promote the warning to an error if there are incompatible attributes or
9500b57cec5SDimitry Andric     // incompatible types together with readwrite/readonly incompatibility.
9510b57cec5SDimitry Andric     auto Diag = S.Diag(Property->getLocation(),
9520b57cec5SDimitry Andric                        Property != OriginalProperty || HasIncompatibleAttributes
9530b57cec5SDimitry Andric                            ? diag::err_protocol_property_mismatch
9540b57cec5SDimitry Andric                            : diag::warn_protocol_property_mismatch);
9550b57cec5SDimitry Andric     Diag << Mismatches[0].Kind;
9560b57cec5SDimitry Andric     switch (Mismatches[0].Kind) {
9570b57cec5SDimitry Andric     case IncompatibleType:
9580b57cec5SDimitry Andric       Diag << Property->getType();
9590b57cec5SDimitry Andric       break;
9600b57cec5SDimitry Andric     case HasNoExpectedAttribute:
9610b57cec5SDimitry Andric     case HasUnexpectedAttribute:
9620b57cec5SDimitry Andric       Diag << Mismatches[0].AttributeName;
9630b57cec5SDimitry Andric       break;
9640b57cec5SDimitry Andric     case DifferentGetter:
9650b57cec5SDimitry Andric       Diag << Property->getGetterName();
9660b57cec5SDimitry Andric       break;
9670b57cec5SDimitry Andric     case DifferentSetter:
9680b57cec5SDimitry Andric       Diag << Property->getSetterName();
9690b57cec5SDimitry Andric       break;
9700b57cec5SDimitry Andric     }
9710b57cec5SDimitry Andric   }
9720b57cec5SDimitry Andric   for (const auto &Note : Mismatches) {
9730b57cec5SDimitry Andric     auto Diag =
9740b57cec5SDimitry Andric         S.Diag(Note.Prop->getLocation(), diag::note_protocol_property_declare)
9750b57cec5SDimitry Andric         << Note.Kind;
9760b57cec5SDimitry Andric     switch (Note.Kind) {
9770b57cec5SDimitry Andric     case IncompatibleType:
9780b57cec5SDimitry Andric       Diag << Note.Prop->getType();
9790b57cec5SDimitry Andric       break;
9800b57cec5SDimitry Andric     case HasNoExpectedAttribute:
9810b57cec5SDimitry Andric     case HasUnexpectedAttribute:
9820b57cec5SDimitry Andric       Diag << Note.AttributeName;
9830b57cec5SDimitry Andric       break;
9840b57cec5SDimitry Andric     case DifferentGetter:
9850b57cec5SDimitry Andric       Diag << Note.Prop->getGetterName();
9860b57cec5SDimitry Andric       break;
9870b57cec5SDimitry Andric     case DifferentSetter:
9880b57cec5SDimitry Andric       Diag << Note.Prop->getSetterName();
9890b57cec5SDimitry Andric       break;
9900b57cec5SDimitry Andric     }
9910b57cec5SDimitry Andric   }
9920b57cec5SDimitry Andric   if (AtLoc.isValid())
9930b57cec5SDimitry Andric     S.Diag(AtLoc, diag::note_property_synthesize);
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric   return Property;
9960b57cec5SDimitry Andric }
9970b57cec5SDimitry Andric 
9980b57cec5SDimitry Andric /// Determine whether any storage attributes were written on the property.
9990b57cec5SDimitry Andric static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop,
10000b57cec5SDimitry Andric                                        ObjCPropertyQueryKind QueryKind) {
10010b57cec5SDimitry Andric   if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true;
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric   // If this is a readwrite property in a class extension that refines
10040b57cec5SDimitry Andric   // a readonly property in the original class definition, check it as
10050b57cec5SDimitry Andric   // well.
10060b57cec5SDimitry Andric 
10070b57cec5SDimitry Andric   // If it's a readonly property, we're not interested.
10080b57cec5SDimitry Andric   if (Prop->isReadOnly()) return false;
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric   // Is it declared in an extension?
10110b57cec5SDimitry Andric   auto Category = dyn_cast<ObjCCategoryDecl>(Prop->getDeclContext());
10120b57cec5SDimitry Andric   if (!Category || !Category->IsClassExtension()) return false;
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   // Find the corresponding property in the primary class definition.
10150b57cec5SDimitry Andric   auto OrigClass = Category->getClassInterface();
1016bdd1243dSDimitry Andric   for (auto *Found : OrigClass->lookup(Prop->getDeclName())) {
10170b57cec5SDimitry Andric     if (ObjCPropertyDecl *OrigProp = dyn_cast<ObjCPropertyDecl>(Found))
10180b57cec5SDimitry Andric       return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
10190b57cec5SDimitry Andric   }
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric   // Look through all of the protocols.
10220b57cec5SDimitry Andric   for (const auto *Proto : OrigClass->all_referenced_protocols()) {
10230b57cec5SDimitry Andric     if (ObjCPropertyDecl *OrigProp = Proto->FindPropertyDeclaration(
10240b57cec5SDimitry Andric             Prop->getIdentifier(), QueryKind))
10250b57cec5SDimitry Andric       return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
10260b57cec5SDimitry Andric   }
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric   return false;
10290b57cec5SDimitry Andric }
10300b57cec5SDimitry Andric 
1031480093f4SDimitry Andric /// Create a synthesized property accessor stub inside the \@implementation.
1032480093f4SDimitry Andric static ObjCMethodDecl *
1033480093f4SDimitry Andric RedeclarePropertyAccessor(ASTContext &Context, ObjCImplementationDecl *Impl,
1034480093f4SDimitry Andric                           ObjCMethodDecl *AccessorDecl, SourceLocation AtLoc,
1035480093f4SDimitry Andric                           SourceLocation PropertyLoc) {
1036480093f4SDimitry Andric   ObjCMethodDecl *Decl = AccessorDecl;
1037480093f4SDimitry Andric   ObjCMethodDecl *ImplDecl = ObjCMethodDecl::Create(
1038480093f4SDimitry Andric       Context, AtLoc.isValid() ? AtLoc : Decl->getBeginLoc(),
1039480093f4SDimitry Andric       PropertyLoc.isValid() ? PropertyLoc : Decl->getEndLoc(),
1040480093f4SDimitry Andric       Decl->getSelector(), Decl->getReturnType(),
1041480093f4SDimitry Andric       Decl->getReturnTypeSourceInfo(), Impl, Decl->isInstanceMethod(),
1042480093f4SDimitry Andric       Decl->isVariadic(), Decl->isPropertyAccessor(),
1043480093f4SDimitry Andric       /* isSynthesized*/ true, Decl->isImplicit(), Decl->isDefined(),
1044480093f4SDimitry Andric       Decl->getImplementationControl(), Decl->hasRelatedResultType());
1045480093f4SDimitry Andric   ImplDecl->getMethodFamily();
1046480093f4SDimitry Andric   if (Decl->hasAttrs())
1047480093f4SDimitry Andric     ImplDecl->setAttrs(Decl->getAttrs());
1048480093f4SDimitry Andric   ImplDecl->setSelfDecl(Decl->getSelfDecl());
1049480093f4SDimitry Andric   ImplDecl->setCmdDecl(Decl->getCmdDecl());
1050480093f4SDimitry Andric   SmallVector<SourceLocation, 1> SelLocs;
1051480093f4SDimitry Andric   Decl->getSelectorLocs(SelLocs);
1052480093f4SDimitry Andric   ImplDecl->setMethodParams(Context, Decl->parameters(), SelLocs);
1053480093f4SDimitry Andric   ImplDecl->setLexicalDeclContext(Impl);
1054480093f4SDimitry Andric   ImplDecl->setDefined(false);
1055480093f4SDimitry Andric   return ImplDecl;
1056480093f4SDimitry Andric }
1057480093f4SDimitry Andric 
10580b57cec5SDimitry Andric /// ActOnPropertyImplDecl - This routine performs semantic checks and
10590b57cec5SDimitry Andric /// builds the AST node for a property implementation declaration; declared
10600b57cec5SDimitry Andric /// as \@synthesize or \@dynamic.
10610b57cec5SDimitry Andric ///
1062*0fca6ea1SDimitry Andric Decl *SemaObjC::ActOnPropertyImplDecl(
1063*0fca6ea1SDimitry Andric     Scope *S, SourceLocation AtLoc, SourceLocation PropertyLoc, bool Synthesize,
1064*0fca6ea1SDimitry Andric     IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar,
1065*0fca6ea1SDimitry Andric     SourceLocation PropertyIvarLoc, ObjCPropertyQueryKind QueryKind) {
1066*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
10670b57cec5SDimitry Andric   ObjCContainerDecl *ClassImpDecl =
1068*0fca6ea1SDimitry Andric       dyn_cast<ObjCContainerDecl>(SemaRef.CurContext);
10690b57cec5SDimitry Andric   // Make sure we have a context for the property implementation declaration.
10700b57cec5SDimitry Andric   if (!ClassImpDecl) {
10710b57cec5SDimitry Andric     Diag(AtLoc, diag::err_missing_property_context);
10720b57cec5SDimitry Andric     return nullptr;
10730b57cec5SDimitry Andric   }
10740b57cec5SDimitry Andric   if (PropertyIvarLoc.isInvalid())
10750b57cec5SDimitry Andric     PropertyIvarLoc = PropertyLoc;
10760b57cec5SDimitry Andric   SourceLocation PropertyDiagLoc = PropertyLoc;
10770b57cec5SDimitry Andric   if (PropertyDiagLoc.isInvalid())
10780b57cec5SDimitry Andric     PropertyDiagLoc = ClassImpDecl->getBeginLoc();
10790b57cec5SDimitry Andric   ObjCPropertyDecl *property = nullptr;
10800b57cec5SDimitry Andric   ObjCInterfaceDecl *IDecl = nullptr;
10810b57cec5SDimitry Andric   // Find the class or category class where this property must have
10820b57cec5SDimitry Andric   // a declaration.
10830b57cec5SDimitry Andric   ObjCImplementationDecl *IC = nullptr;
10840b57cec5SDimitry Andric   ObjCCategoryImplDecl *CatImplClass = nullptr;
10850b57cec5SDimitry Andric   if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
10860b57cec5SDimitry Andric     IDecl = IC->getClassInterface();
10870b57cec5SDimitry Andric     // We always synthesize an interface for an implementation
10880b57cec5SDimitry Andric     // without an interface decl. So, IDecl is always non-zero.
10890b57cec5SDimitry Andric     assert(IDecl &&
10900b57cec5SDimitry Andric            "ActOnPropertyImplDecl - @implementation without @interface");
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric     // Look for this property declaration in the @implementation's @interface
10930b57cec5SDimitry Andric     property = IDecl->FindPropertyDeclaration(PropertyId, QueryKind);
10940b57cec5SDimitry Andric     if (!property) {
10950b57cec5SDimitry Andric       Diag(PropertyLoc, diag::err_bad_property_decl) << IDecl->getDeclName();
10960b57cec5SDimitry Andric       return nullptr;
10970b57cec5SDimitry Andric     }
10980b57cec5SDimitry Andric     if (property->isClassProperty() && Synthesize) {
10990b57cec5SDimitry Andric       Diag(PropertyLoc, diag::err_synthesize_on_class_property) << PropertyId;
11000b57cec5SDimitry Andric       return nullptr;
11010b57cec5SDimitry Andric     }
11020b57cec5SDimitry Andric     unsigned PIkind = property->getPropertyAttributesAsWritten();
11035ffd83dbSDimitry Andric     if ((PIkind & (ObjCPropertyAttribute::kind_atomic |
11045ffd83dbSDimitry Andric                    ObjCPropertyAttribute::kind_nonatomic)) == 0) {
11050b57cec5SDimitry Andric       if (AtLoc.isValid())
11060b57cec5SDimitry Andric         Diag(AtLoc, diag::warn_implicit_atomic_property);
11070b57cec5SDimitry Andric       else
11080b57cec5SDimitry Andric         Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
11090b57cec5SDimitry Andric       Diag(property->getLocation(), diag::note_property_declare);
11100b57cec5SDimitry Andric     }
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric     if (const ObjCCategoryDecl *CD =
11130b57cec5SDimitry Andric         dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
11140b57cec5SDimitry Andric       if (!CD->IsClassExtension()) {
11150b57cec5SDimitry Andric         Diag(PropertyLoc, diag::err_category_property) << CD->getDeclName();
11160b57cec5SDimitry Andric         Diag(property->getLocation(), diag::note_property_declare);
11170b57cec5SDimitry Andric         return nullptr;
11180b57cec5SDimitry Andric       }
11190b57cec5SDimitry Andric     }
11205ffd83dbSDimitry Andric     if (Synthesize && (PIkind & ObjCPropertyAttribute::kind_readonly) &&
11215ffd83dbSDimitry Andric         property->hasAttr<IBOutletAttr>() && !AtLoc.isValid()) {
11220b57cec5SDimitry Andric       bool ReadWriteProperty = false;
11230b57cec5SDimitry Andric       // Search into the class extensions and see if 'readonly property is
11240b57cec5SDimitry Andric       // redeclared 'readwrite', then no warning is to be issued.
11250b57cec5SDimitry Andric       for (auto *Ext : IDecl->known_extensions()) {
11260b57cec5SDimitry Andric         DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
1127fe6060f1SDimitry Andric         if (auto *ExtProp = R.find_first<ObjCPropertyDecl>()) {
11280b57cec5SDimitry Andric           PIkind = ExtProp->getPropertyAttributesAsWritten();
11295ffd83dbSDimitry Andric           if (PIkind & ObjCPropertyAttribute::kind_readwrite) {
11300b57cec5SDimitry Andric             ReadWriteProperty = true;
11310b57cec5SDimitry Andric             break;
11320b57cec5SDimitry Andric           }
11330b57cec5SDimitry Andric         }
11340b57cec5SDimitry Andric       }
11350b57cec5SDimitry Andric 
11360b57cec5SDimitry Andric       if (!ReadWriteProperty) {
11370b57cec5SDimitry Andric         Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
11380b57cec5SDimitry Andric             << property;
11390b57cec5SDimitry Andric         SourceLocation readonlyLoc;
11400b57cec5SDimitry Andric         if (LocPropertyAttribute(Context, "readonly",
11410b57cec5SDimitry Andric                                  property->getLParenLoc(), readonlyLoc)) {
11420b57cec5SDimitry Andric           SourceLocation endLoc =
11430b57cec5SDimitry Andric             readonlyLoc.getLocWithOffset(strlen("readonly")-1);
11440b57cec5SDimitry Andric           SourceRange ReadonlySourceRange(readonlyLoc, endLoc);
11450b57cec5SDimitry Andric           Diag(property->getLocation(),
11460b57cec5SDimitry Andric                diag::note_auto_readonly_iboutlet_fixup_suggest) <<
11470b57cec5SDimitry Andric           FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
11480b57cec5SDimitry Andric         }
11490b57cec5SDimitry Andric       }
11500b57cec5SDimitry Andric     }
11510b57cec5SDimitry Andric     if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext()))
1152*0fca6ea1SDimitry Andric       property = SelectPropertyForSynthesisFromProtocols(SemaRef, AtLoc, IDecl,
11530b57cec5SDimitry Andric                                                          property);
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric   } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
11560b57cec5SDimitry Andric     if (Synthesize) {
11570b57cec5SDimitry Andric       Diag(AtLoc, diag::err_synthesize_category_decl);
11580b57cec5SDimitry Andric       return nullptr;
11590b57cec5SDimitry Andric     }
11600b57cec5SDimitry Andric     IDecl = CatImplClass->getClassInterface();
11610b57cec5SDimitry Andric     if (!IDecl) {
11620b57cec5SDimitry Andric       Diag(AtLoc, diag::err_missing_property_interface);
11630b57cec5SDimitry Andric       return nullptr;
11640b57cec5SDimitry Andric     }
11650b57cec5SDimitry Andric     ObjCCategoryDecl *Category =
11660b57cec5SDimitry Andric     IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
11670b57cec5SDimitry Andric 
11680b57cec5SDimitry Andric     // If category for this implementation not found, it is an error which
11690b57cec5SDimitry Andric     // has already been reported eralier.
11700b57cec5SDimitry Andric     if (!Category)
11710b57cec5SDimitry Andric       return nullptr;
11720b57cec5SDimitry Andric     // Look for this property declaration in @implementation's category
11730b57cec5SDimitry Andric     property = Category->FindPropertyDeclaration(PropertyId, QueryKind);
11740b57cec5SDimitry Andric     if (!property) {
11750b57cec5SDimitry Andric       Diag(PropertyLoc, diag::err_bad_category_property_decl)
11760b57cec5SDimitry Andric       << Category->getDeclName();
11770b57cec5SDimitry Andric       return nullptr;
11780b57cec5SDimitry Andric     }
11790b57cec5SDimitry Andric   } else {
11800b57cec5SDimitry Andric     Diag(AtLoc, diag::err_bad_property_context);
11810b57cec5SDimitry Andric     return nullptr;
11820b57cec5SDimitry Andric   }
11830b57cec5SDimitry Andric   ObjCIvarDecl *Ivar = nullptr;
11840b57cec5SDimitry Andric   bool CompleteTypeErr = false;
11850b57cec5SDimitry Andric   bool compat = true;
11860b57cec5SDimitry Andric   // Check that we have a valid, previously declared ivar for @synthesize
11870b57cec5SDimitry Andric   if (Synthesize) {
11880b57cec5SDimitry Andric     // @synthesize
11890b57cec5SDimitry Andric     if (!PropertyIvar)
11900b57cec5SDimitry Andric       PropertyIvar = PropertyId;
11910b57cec5SDimitry Andric     // Check that this is a previously declared 'ivar' in 'IDecl' interface
11920b57cec5SDimitry Andric     ObjCInterfaceDecl *ClassDeclared;
11930b57cec5SDimitry Andric     Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
11940b57cec5SDimitry Andric     QualType PropType = property->getType();
11950b57cec5SDimitry Andric     QualType PropertyIvarType = PropType.getNonReferenceType();
11960b57cec5SDimitry Andric 
1197*0fca6ea1SDimitry Andric     if (SemaRef.RequireCompleteType(PropertyDiagLoc, PropertyIvarType,
11980b57cec5SDimitry Andric                                     diag::err_incomplete_synthesized_property,
11990b57cec5SDimitry Andric                                     property->getDeclName())) {
12000b57cec5SDimitry Andric       Diag(property->getLocation(), diag::note_property_declare);
12010b57cec5SDimitry Andric       CompleteTypeErr = true;
12020b57cec5SDimitry Andric     }
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric     if (getLangOpts().ObjCAutoRefCount &&
12050b57cec5SDimitry Andric         (property->getPropertyAttributesAsWritten() &
12065ffd83dbSDimitry Andric          ObjCPropertyAttribute::kind_readonly) &&
12070b57cec5SDimitry Andric         PropertyIvarType->isObjCRetainableType()) {
12080b57cec5SDimitry Andric       setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar);
12090b57cec5SDimitry Andric     }
12100b57cec5SDimitry Andric 
12115ffd83dbSDimitry Andric     ObjCPropertyAttribute::Kind kind = property->getPropertyAttributes();
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric     bool isARCWeak = false;
12145ffd83dbSDimitry Andric     if (kind & ObjCPropertyAttribute::kind_weak) {
12150b57cec5SDimitry Andric       // Add GC __weak to the ivar type if the property is weak.
12160b57cec5SDimitry Andric       if (getLangOpts().getGC() != LangOptions::NonGC) {
12170b57cec5SDimitry Andric         assert(!getLangOpts().ObjCAutoRefCount);
12180b57cec5SDimitry Andric         if (PropertyIvarType.isObjCGCStrong()) {
12190b57cec5SDimitry Andric           Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
12200b57cec5SDimitry Andric           Diag(property->getLocation(), diag::note_property_declare);
12210b57cec5SDimitry Andric         } else {
12220b57cec5SDimitry Andric           PropertyIvarType =
12230b57cec5SDimitry Andric             Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
12240b57cec5SDimitry Andric         }
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric       // Otherwise, check whether ARC __weak is enabled and works with
12270b57cec5SDimitry Andric       // the property type.
12280b57cec5SDimitry Andric       } else {
12290b57cec5SDimitry Andric         if (!getLangOpts().ObjCWeak) {
12300b57cec5SDimitry Andric           // Only complain here when synthesizing an ivar.
12310b57cec5SDimitry Andric           if (!Ivar) {
12320b57cec5SDimitry Andric             Diag(PropertyDiagLoc,
12330b57cec5SDimitry Andric                  getLangOpts().ObjCWeakRuntime
12340b57cec5SDimitry Andric                    ? diag::err_synthesizing_arc_weak_property_disabled
12350b57cec5SDimitry Andric                    : diag::err_synthesizing_arc_weak_property_no_runtime);
12360b57cec5SDimitry Andric             Diag(property->getLocation(), diag::note_property_declare);
12370b57cec5SDimitry Andric           }
12380b57cec5SDimitry Andric           CompleteTypeErr = true; // suppress later diagnostics about the ivar
12390b57cec5SDimitry Andric         } else {
12400b57cec5SDimitry Andric           isARCWeak = true;
12410b57cec5SDimitry Andric           if (const ObjCObjectPointerType *ObjT =
12420b57cec5SDimitry Andric                 PropertyIvarType->getAs<ObjCObjectPointerType>()) {
12430b57cec5SDimitry Andric             const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
12440b57cec5SDimitry Andric             if (ObjI && ObjI->isArcWeakrefUnavailable()) {
12450b57cec5SDimitry Andric               Diag(property->getLocation(),
12460b57cec5SDimitry Andric                    diag::err_arc_weak_unavailable_property)
12470b57cec5SDimitry Andric                 << PropertyIvarType;
12480b57cec5SDimitry Andric               Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
12490b57cec5SDimitry Andric                 << ClassImpDecl->getName();
12500b57cec5SDimitry Andric             }
12510b57cec5SDimitry Andric           }
12520b57cec5SDimitry Andric         }
12530b57cec5SDimitry Andric       }
12540b57cec5SDimitry Andric     }
12550b57cec5SDimitry Andric 
12560b57cec5SDimitry Andric     if (AtLoc.isInvalid()) {
12570b57cec5SDimitry Andric       // Check when default synthesizing a property that there is
12580b57cec5SDimitry Andric       // an ivar matching property name and issue warning; since this
12590b57cec5SDimitry Andric       // is the most common case of not using an ivar used for backing
12600b57cec5SDimitry Andric       // property in non-default synthesis case.
12610b57cec5SDimitry Andric       ObjCInterfaceDecl *ClassDeclared=nullptr;
12620b57cec5SDimitry Andric       ObjCIvarDecl *originalIvar =
12630b57cec5SDimitry Andric       IDecl->lookupInstanceVariable(property->getIdentifier(),
12640b57cec5SDimitry Andric                                     ClassDeclared);
12650b57cec5SDimitry Andric       if (originalIvar) {
12660b57cec5SDimitry Andric         Diag(PropertyDiagLoc,
12670b57cec5SDimitry Andric              diag::warn_autosynthesis_property_ivar_match)
12680b57cec5SDimitry Andric         << PropertyId << (Ivar == nullptr) << PropertyIvar
12690b57cec5SDimitry Andric         << originalIvar->getIdentifier();
12700b57cec5SDimitry Andric         Diag(property->getLocation(), diag::note_property_declare);
12710b57cec5SDimitry Andric         Diag(originalIvar->getLocation(), diag::note_ivar_decl);
12720b57cec5SDimitry Andric       }
12730b57cec5SDimitry Andric     }
12740b57cec5SDimitry Andric 
12750b57cec5SDimitry Andric     if (!Ivar) {
12760b57cec5SDimitry Andric       // In ARC, give the ivar a lifetime qualifier based on the
12770b57cec5SDimitry Andric       // property attributes.
12780b57cec5SDimitry Andric       if ((getLangOpts().ObjCAutoRefCount || isARCWeak) &&
12790b57cec5SDimitry Andric           !PropertyIvarType.getObjCLifetime() &&
12800b57cec5SDimitry Andric           PropertyIvarType->isObjCRetainableType()) {
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric         // It's an error if we have to do this and the user didn't
12830b57cec5SDimitry Andric         // explicitly write an ownership attribute on the property.
12840b57cec5SDimitry Andric         if (!hasWrittenStorageAttribute(property, QueryKind) &&
12855ffd83dbSDimitry Andric             !(kind & ObjCPropertyAttribute::kind_strong)) {
12860b57cec5SDimitry Andric           Diag(PropertyDiagLoc,
12870b57cec5SDimitry Andric                diag::err_arc_objc_property_default_assign_on_object);
12880b57cec5SDimitry Andric           Diag(property->getLocation(), diag::note_property_declare);
12890b57cec5SDimitry Andric         } else {
12900b57cec5SDimitry Andric           Qualifiers::ObjCLifetime lifetime =
12910b57cec5SDimitry Andric             getImpliedARCOwnership(kind, PropertyIvarType);
12920b57cec5SDimitry Andric           assert(lifetime && "no lifetime for property?");
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric           Qualifiers qs;
12950b57cec5SDimitry Andric           qs.addObjCLifetime(lifetime);
12960b57cec5SDimitry Andric           PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
12970b57cec5SDimitry Andric         }
12980b57cec5SDimitry Andric       }
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric       Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
13010b57cec5SDimitry Andric                                   PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
13020b57cec5SDimitry Andric                                   PropertyIvarType, /*TInfo=*/nullptr,
13030b57cec5SDimitry Andric                                   ObjCIvarDecl::Private,
13040b57cec5SDimitry Andric                                   (Expr *)nullptr, true);
1305*0fca6ea1SDimitry Andric       if (SemaRef.RequireNonAbstractType(PropertyIvarLoc, PropertyIvarType,
13060b57cec5SDimitry Andric                                          diag::err_abstract_type_in_decl,
1307*0fca6ea1SDimitry Andric                                          Sema::AbstractSynthesizedIvarType)) {
13080b57cec5SDimitry Andric         Diag(property->getLocation(), diag::note_property_declare);
13090b57cec5SDimitry Andric         // An abstract type is as bad as an incomplete type.
13100b57cec5SDimitry Andric         CompleteTypeErr = true;
13110b57cec5SDimitry Andric       }
13120b57cec5SDimitry Andric       if (!CompleteTypeErr) {
13130b57cec5SDimitry Andric         const RecordType *RecordTy = PropertyIvarType->getAs<RecordType>();
13140b57cec5SDimitry Andric         if (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()) {
13150b57cec5SDimitry Andric           Diag(PropertyIvarLoc, diag::err_synthesize_variable_sized_ivar)
13160b57cec5SDimitry Andric             << PropertyIvarType;
13170b57cec5SDimitry Andric           CompleteTypeErr = true; // suppress later diagnostics about the ivar
13180b57cec5SDimitry Andric         }
13190b57cec5SDimitry Andric       }
13200b57cec5SDimitry Andric       if (CompleteTypeErr)
13210b57cec5SDimitry Andric         Ivar->setInvalidDecl();
13220b57cec5SDimitry Andric       ClassImpDecl->addDecl(Ivar);
13230b57cec5SDimitry Andric       IDecl->makeDeclVisibleInContext(Ivar);
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric       if (getLangOpts().ObjCRuntime.isFragile())
13260b57cec5SDimitry Andric         Diag(PropertyDiagLoc, diag::err_missing_property_ivar_decl)
13270b57cec5SDimitry Andric             << PropertyId;
13280b57cec5SDimitry Andric       // Note! I deliberately want it to fall thru so, we have a
13290b57cec5SDimitry Andric       // a property implementation and to avoid future warnings.
13300b57cec5SDimitry Andric     } else if (getLangOpts().ObjCRuntime.isNonFragile() &&
13310b57cec5SDimitry Andric                !declaresSameEntity(ClassDeclared, IDecl)) {
13320b57cec5SDimitry Andric       Diag(PropertyDiagLoc, diag::err_ivar_in_superclass_use)
13330b57cec5SDimitry Andric       << property->getDeclName() << Ivar->getDeclName()
13340b57cec5SDimitry Andric       << ClassDeclared->getDeclName();
13350b57cec5SDimitry Andric       Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
13360b57cec5SDimitry Andric       << Ivar << Ivar->getName();
13370b57cec5SDimitry Andric       // Note! I deliberately want it to fall thru so more errors are caught.
13380b57cec5SDimitry Andric     }
13390b57cec5SDimitry Andric     property->setPropertyIvarDecl(Ivar);
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric     QualType IvarType = Context.getCanonicalType(Ivar->getType());
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric     // Check that type of property and its ivar are type compatible.
13440b57cec5SDimitry Andric     if (!Context.hasSameType(PropertyIvarType, IvarType)) {
13450b57cec5SDimitry Andric       if (isa<ObjCObjectPointerType>(PropertyIvarType)
13460b57cec5SDimitry Andric           && isa<ObjCObjectPointerType>(IvarType))
134706c3fb27SDimitry Andric         compat = Context.canAssignObjCInterfaces(
134806c3fb27SDimitry Andric             PropertyIvarType->castAs<ObjCObjectPointerType>(),
134906c3fb27SDimitry Andric             IvarType->castAs<ObjCObjectPointerType>());
13500b57cec5SDimitry Andric       else {
1351*0fca6ea1SDimitry Andric         compat = (SemaRef.CheckAssignmentConstraints(
1352*0fca6ea1SDimitry Andric                       PropertyIvarLoc, PropertyIvarType, IvarType) ==
1353*0fca6ea1SDimitry Andric                   Sema::Compatible);
13540b57cec5SDimitry Andric       }
13550b57cec5SDimitry Andric       if (!compat) {
13560b57cec5SDimitry Andric         Diag(PropertyDiagLoc, diag::err_property_ivar_type)
13570b57cec5SDimitry Andric           << property->getDeclName() << PropType
13580b57cec5SDimitry Andric           << Ivar->getDeclName() << IvarType;
13590b57cec5SDimitry Andric         Diag(Ivar->getLocation(), diag::note_ivar_decl);
13600b57cec5SDimitry Andric         // Note! I deliberately want it to fall thru so, we have a
13610b57cec5SDimitry Andric         // a property implementation and to avoid future warnings.
13620b57cec5SDimitry Andric       }
13630b57cec5SDimitry Andric       else {
13640b57cec5SDimitry Andric         // FIXME! Rules for properties are somewhat different that those
13650b57cec5SDimitry Andric         // for assignments. Use a new routine to consolidate all cases;
13660b57cec5SDimitry Andric         // specifically for property redeclarations as well as for ivars.
13670b57cec5SDimitry Andric         QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
13680b57cec5SDimitry Andric         QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
13690b57cec5SDimitry Andric         if (lhsType != rhsType &&
13700b57cec5SDimitry Andric             lhsType->isArithmeticType()) {
13710b57cec5SDimitry Andric           Diag(PropertyDiagLoc, diag::err_property_ivar_type)
13720b57cec5SDimitry Andric             << property->getDeclName() << PropType
13730b57cec5SDimitry Andric             << Ivar->getDeclName() << IvarType;
13740b57cec5SDimitry Andric           Diag(Ivar->getLocation(), diag::note_ivar_decl);
13750b57cec5SDimitry Andric           // Fall thru - see previous comment
13760b57cec5SDimitry Andric         }
13770b57cec5SDimitry Andric       }
13780b57cec5SDimitry Andric       // __weak is explicit. So it works on Canonical type.
13790b57cec5SDimitry Andric       if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
13800b57cec5SDimitry Andric            getLangOpts().getGC() != LangOptions::NonGC)) {
13810b57cec5SDimitry Andric         Diag(PropertyDiagLoc, diag::err_weak_property)
13820b57cec5SDimitry Andric         << property->getDeclName() << Ivar->getDeclName();
13830b57cec5SDimitry Andric         Diag(Ivar->getLocation(), diag::note_ivar_decl);
13840b57cec5SDimitry Andric         // Fall thru - see previous comment
13850b57cec5SDimitry Andric       }
13860b57cec5SDimitry Andric       // Fall thru - see previous comment
13870b57cec5SDimitry Andric       if ((property->getType()->isObjCObjectPointerType() ||
13880b57cec5SDimitry Andric            PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
13890b57cec5SDimitry Andric           getLangOpts().getGC() != LangOptions::NonGC) {
13900b57cec5SDimitry Andric         Diag(PropertyDiagLoc, diag::err_strong_property)
13910b57cec5SDimitry Andric         << property->getDeclName() << Ivar->getDeclName();
13920b57cec5SDimitry Andric         // Fall thru - see previous comment
13930b57cec5SDimitry Andric       }
13940b57cec5SDimitry Andric     }
13950b57cec5SDimitry Andric     if (getLangOpts().ObjCAutoRefCount || isARCWeak ||
13960b57cec5SDimitry Andric         Ivar->getType().getObjCLifetime())
1397*0fca6ea1SDimitry Andric       checkARCPropertyImpl(SemaRef, PropertyLoc, property, Ivar);
13980b57cec5SDimitry Andric   } else if (PropertyIvar)
13990b57cec5SDimitry Andric     // @dynamic
14000b57cec5SDimitry Andric     Diag(PropertyDiagLoc, diag::err_dynamic_property_ivar_decl);
14010b57cec5SDimitry Andric 
14020b57cec5SDimitry Andric   assert (property && "ActOnPropertyImplDecl - property declaration missing");
1403*0fca6ea1SDimitry Andric   ObjCPropertyImplDecl *PIDecl = ObjCPropertyImplDecl::Create(
1404*0fca6ea1SDimitry Andric       Context, SemaRef.CurContext, AtLoc, PropertyLoc, property,
1405*0fca6ea1SDimitry Andric       (Synthesize ? ObjCPropertyImplDecl::Synthesize
14060b57cec5SDimitry Andric                   : ObjCPropertyImplDecl::Dynamic),
14070b57cec5SDimitry Andric       Ivar, PropertyIvarLoc);
14080b57cec5SDimitry Andric 
14090b57cec5SDimitry Andric   if (CompleteTypeErr || !compat)
14100b57cec5SDimitry Andric     PIDecl->setInvalidDecl();
14110b57cec5SDimitry Andric 
14120b57cec5SDimitry Andric   if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
14130b57cec5SDimitry Andric     getterMethod->createImplicitParams(Context, IDecl);
1414480093f4SDimitry Andric 
1415480093f4SDimitry Andric     // Redeclare the getter within the implementation as DeclContext.
1416480093f4SDimitry Andric     if (Synthesize) {
1417480093f4SDimitry Andric       // If the method hasn't been overridden, create a synthesized implementation.
1418480093f4SDimitry Andric       ObjCMethodDecl *OMD = ClassImpDecl->getMethod(
1419480093f4SDimitry Andric           getterMethod->getSelector(), getterMethod->isInstanceMethod());
1420480093f4SDimitry Andric       if (!OMD)
1421480093f4SDimitry Andric         OMD = RedeclarePropertyAccessor(Context, IC, getterMethod, AtLoc,
1422480093f4SDimitry Andric                                         PropertyLoc);
1423480093f4SDimitry Andric       PIDecl->setGetterMethodDecl(OMD);
1424480093f4SDimitry Andric     }
1425480093f4SDimitry Andric 
14260b57cec5SDimitry Andric     if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
14270b57cec5SDimitry Andric         Ivar->getType()->isRecordType()) {
14280b57cec5SDimitry Andric       // For Objective-C++, need to synthesize the AST for the IVAR object to be
14290b57cec5SDimitry Andric       // returned by the getter as it must conform to C++'s copy-return rules.
14300b57cec5SDimitry Andric       // FIXME. Eventually we want to do this for Objective-C as well.
1431*0fca6ea1SDimitry Andric       Sema::SynthesizedFunctionScope Scope(SemaRef, getterMethod);
14320b57cec5SDimitry Andric       ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
14330b57cec5SDimitry Andric       DeclRefExpr *SelfExpr = new (Context)
14340b57cec5SDimitry Andric           DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
14350b57cec5SDimitry Andric                       PropertyDiagLoc);
1436*0fca6ea1SDimitry Andric       SemaRef.MarkDeclRefReferenced(SelfExpr);
1437e8d8bef9SDimitry Andric       Expr *LoadSelfExpr = ImplicitCastExpr::Create(
1438e8d8bef9SDimitry Andric           Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
1439fe6060f1SDimitry Andric           VK_PRValue, FPOptionsOverride());
14400b57cec5SDimitry Andric       Expr *IvarRefExpr =
14410b57cec5SDimitry Andric         new (Context) ObjCIvarRefExpr(Ivar,
14420b57cec5SDimitry Andric                                       Ivar->getUsageType(SelfDecl->getType()),
14430b57cec5SDimitry Andric                                       PropertyDiagLoc,
14440b57cec5SDimitry Andric                                       Ivar->getLocation(),
14450b57cec5SDimitry Andric                                       LoadSelfExpr, true, true);
1446*0fca6ea1SDimitry Andric       ExprResult Res = SemaRef.PerformCopyInitialization(
14470b57cec5SDimitry Andric           InitializedEntity::InitializeResult(PropertyDiagLoc,
144828a41182SDimitry Andric                                               getterMethod->getReturnType()),
14490b57cec5SDimitry Andric           PropertyDiagLoc, IvarRefExpr);
14500b57cec5SDimitry Andric       if (!Res.isInvalid()) {
14510b57cec5SDimitry Andric         Expr *ResExpr = Res.getAs<Expr>();
14520b57cec5SDimitry Andric         if (ResExpr)
1453*0fca6ea1SDimitry Andric           ResExpr = SemaRef.MaybeCreateExprWithCleanups(ResExpr);
14540b57cec5SDimitry Andric         PIDecl->setGetterCXXConstructor(ResExpr);
14550b57cec5SDimitry Andric       }
14560b57cec5SDimitry Andric     }
14570b57cec5SDimitry Andric     if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
14580b57cec5SDimitry Andric         !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
14590b57cec5SDimitry Andric       Diag(getterMethod->getLocation(),
14600b57cec5SDimitry Andric            diag::warn_property_getter_owning_mismatch);
14610b57cec5SDimitry Andric       Diag(property->getLocation(), diag::note_property_declare);
14620b57cec5SDimitry Andric     }
14630b57cec5SDimitry Andric     if (getLangOpts().ObjCAutoRefCount && Synthesize)
14640b57cec5SDimitry Andric       switch (getterMethod->getMethodFamily()) {
14650b57cec5SDimitry Andric         case OMF_retain:
14660b57cec5SDimitry Andric         case OMF_retainCount:
14670b57cec5SDimitry Andric         case OMF_release:
14680b57cec5SDimitry Andric         case OMF_autorelease:
14690b57cec5SDimitry Andric           Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def)
14700b57cec5SDimitry Andric             << 1 << getterMethod->getSelector();
14710b57cec5SDimitry Andric           break;
14720b57cec5SDimitry Andric         default:
14730b57cec5SDimitry Andric           break;
14740b57cec5SDimitry Andric       }
14750b57cec5SDimitry Andric   }
1476480093f4SDimitry Andric 
14770b57cec5SDimitry Andric   if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
14780b57cec5SDimitry Andric     setterMethod->createImplicitParams(Context, IDecl);
1479480093f4SDimitry Andric 
1480480093f4SDimitry Andric     // Redeclare the setter within the implementation as DeclContext.
1481480093f4SDimitry Andric     if (Synthesize) {
1482480093f4SDimitry Andric       ObjCMethodDecl *OMD = ClassImpDecl->getMethod(
1483480093f4SDimitry Andric           setterMethod->getSelector(), setterMethod->isInstanceMethod());
1484480093f4SDimitry Andric       if (!OMD)
1485480093f4SDimitry Andric         OMD = RedeclarePropertyAccessor(Context, IC, setterMethod,
1486480093f4SDimitry Andric                                         AtLoc, PropertyLoc);
1487480093f4SDimitry Andric       PIDecl->setSetterMethodDecl(OMD);
1488480093f4SDimitry Andric     }
1489480093f4SDimitry Andric 
14900b57cec5SDimitry Andric     if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
14910b57cec5SDimitry Andric         Ivar->getType()->isRecordType()) {
14920b57cec5SDimitry Andric       // FIXME. Eventually we want to do this for Objective-C as well.
1493*0fca6ea1SDimitry Andric       Sema::SynthesizedFunctionScope Scope(SemaRef, setterMethod);
14940b57cec5SDimitry Andric       ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
14950b57cec5SDimitry Andric       DeclRefExpr *SelfExpr = new (Context)
14960b57cec5SDimitry Andric           DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
14970b57cec5SDimitry Andric                       PropertyDiagLoc);
1498*0fca6ea1SDimitry Andric       SemaRef.MarkDeclRefReferenced(SelfExpr);
1499e8d8bef9SDimitry Andric       Expr *LoadSelfExpr = ImplicitCastExpr::Create(
1500e8d8bef9SDimitry Andric           Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
1501fe6060f1SDimitry Andric           VK_PRValue, FPOptionsOverride());
15020b57cec5SDimitry Andric       Expr *lhs =
15030b57cec5SDimitry Andric         new (Context) ObjCIvarRefExpr(Ivar,
15040b57cec5SDimitry Andric                                       Ivar->getUsageType(SelfDecl->getType()),
15050b57cec5SDimitry Andric                                       PropertyDiagLoc,
15060b57cec5SDimitry Andric                                       Ivar->getLocation(),
15070b57cec5SDimitry Andric                                       LoadSelfExpr, true, true);
15080b57cec5SDimitry Andric       ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
15090b57cec5SDimitry Andric       ParmVarDecl *Param = (*P);
15100b57cec5SDimitry Andric       QualType T = Param->getType().getNonReferenceType();
15110b57cec5SDimitry Andric       DeclRefExpr *rhs = new (Context)
15120b57cec5SDimitry Andric           DeclRefExpr(Context, Param, false, T, VK_LValue, PropertyDiagLoc);
1513*0fca6ea1SDimitry Andric       SemaRef.MarkDeclRefReferenced(rhs);
1514*0fca6ea1SDimitry Andric       ExprResult Res =
1515*0fca6ea1SDimitry Andric           SemaRef.BuildBinOp(S, PropertyDiagLoc, BO_Assign, lhs, rhs);
15160b57cec5SDimitry Andric       if (property->getPropertyAttributes() &
15175ffd83dbSDimitry Andric           ObjCPropertyAttribute::kind_atomic) {
15180b57cec5SDimitry Andric         Expr *callExpr = Res.getAs<Expr>();
15190b57cec5SDimitry Andric         if (const CXXOperatorCallExpr *CXXCE =
15200b57cec5SDimitry Andric               dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
15210b57cec5SDimitry Andric           if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
15220b57cec5SDimitry Andric             if (!FuncDecl->isTrivial())
15230b57cec5SDimitry Andric               if (property->getType()->isReferenceType()) {
15240b57cec5SDimitry Andric                 Diag(PropertyDiagLoc,
15250b57cec5SDimitry Andric                      diag::err_atomic_property_nontrivial_assign_op)
15260b57cec5SDimitry Andric                     << property->getType();
15270b57cec5SDimitry Andric                 Diag(FuncDecl->getBeginLoc(), diag::note_callee_decl)
15280b57cec5SDimitry Andric                     << FuncDecl;
15290b57cec5SDimitry Andric               }
15300b57cec5SDimitry Andric       }
15310b57cec5SDimitry Andric       PIDecl->setSetterCXXAssignment(Res.getAs<Expr>());
15320b57cec5SDimitry Andric     }
15330b57cec5SDimitry Andric   }
15340b57cec5SDimitry Andric 
15350b57cec5SDimitry Andric   if (IC) {
15360b57cec5SDimitry Andric     if (Synthesize)
15370b57cec5SDimitry Andric       if (ObjCPropertyImplDecl *PPIDecl =
15380b57cec5SDimitry Andric           IC->FindPropertyImplIvarDecl(PropertyIvar)) {
15390b57cec5SDimitry Andric         Diag(PropertyLoc, diag::err_duplicate_ivar_use)
15400b57cec5SDimitry Andric         << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
15410b57cec5SDimitry Andric         << PropertyIvar;
15420b57cec5SDimitry Andric         Diag(PPIDecl->getLocation(), diag::note_previous_use);
15430b57cec5SDimitry Andric       }
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric     if (ObjCPropertyImplDecl *PPIDecl
15460b57cec5SDimitry Andric         = IC->FindPropertyImplDecl(PropertyId, QueryKind)) {
15470b57cec5SDimitry Andric       Diag(PropertyLoc, diag::err_property_implemented) << PropertyId;
15480b57cec5SDimitry Andric       Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
15490b57cec5SDimitry Andric       return nullptr;
15500b57cec5SDimitry Andric     }
15510b57cec5SDimitry Andric     IC->addPropertyImplementation(PIDecl);
15520b57cec5SDimitry Andric     if (getLangOpts().ObjCDefaultSynthProperties &&
15530b57cec5SDimitry Andric         getLangOpts().ObjCRuntime.isNonFragile() &&
15540b57cec5SDimitry Andric         !IDecl->isObjCRequiresPropertyDefs()) {
15550b57cec5SDimitry Andric       // Diagnose if an ivar was lazily synthesdized due to a previous
15560b57cec5SDimitry Andric       // use and if 1) property is @dynamic or 2) property is synthesized
15570b57cec5SDimitry Andric       // but it requires an ivar of different name.
15580b57cec5SDimitry Andric       ObjCInterfaceDecl *ClassDeclared=nullptr;
15590b57cec5SDimitry Andric       ObjCIvarDecl *Ivar = nullptr;
15600b57cec5SDimitry Andric       if (!Synthesize)
15610b57cec5SDimitry Andric         Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
15620b57cec5SDimitry Andric       else {
15630b57cec5SDimitry Andric         if (PropertyIvar && PropertyIvar != PropertyId)
15640b57cec5SDimitry Andric           Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
15650b57cec5SDimitry Andric       }
15660b57cec5SDimitry Andric       // Issue diagnostics only if Ivar belongs to current class.
15670b57cec5SDimitry Andric       if (Ivar && Ivar->getSynthesize() &&
15680b57cec5SDimitry Andric           declaresSameEntity(IC->getClassInterface(), ClassDeclared)) {
15690b57cec5SDimitry Andric         Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
15700b57cec5SDimitry Andric         << PropertyId;
15710b57cec5SDimitry Andric         Ivar->setInvalidDecl();
15720b57cec5SDimitry Andric       }
15730b57cec5SDimitry Andric     }
15740b57cec5SDimitry Andric   } else {
15750b57cec5SDimitry Andric     if (Synthesize)
15760b57cec5SDimitry Andric       if (ObjCPropertyImplDecl *PPIDecl =
15770b57cec5SDimitry Andric           CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
15780b57cec5SDimitry Andric         Diag(PropertyDiagLoc, diag::err_duplicate_ivar_use)
15790b57cec5SDimitry Andric         << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
15800b57cec5SDimitry Andric         << PropertyIvar;
15810b57cec5SDimitry Andric         Diag(PPIDecl->getLocation(), diag::note_previous_use);
15820b57cec5SDimitry Andric       }
15830b57cec5SDimitry Andric 
15840b57cec5SDimitry Andric     if (ObjCPropertyImplDecl *PPIDecl =
15850b57cec5SDimitry Andric         CatImplClass->FindPropertyImplDecl(PropertyId, QueryKind)) {
15860b57cec5SDimitry Andric       Diag(PropertyDiagLoc, diag::err_property_implemented) << PropertyId;
15870b57cec5SDimitry Andric       Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
15880b57cec5SDimitry Andric       return nullptr;
15890b57cec5SDimitry Andric     }
15900b57cec5SDimitry Andric     CatImplClass->addPropertyImplementation(PIDecl);
15910b57cec5SDimitry Andric   }
15920b57cec5SDimitry Andric 
15935ffd83dbSDimitry Andric   if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic &&
15945ffd83dbSDimitry Andric       PIDecl->getPropertyDecl() &&
15955ffd83dbSDimitry Andric       PIDecl->getPropertyDecl()->isDirectProperty()) {
15965ffd83dbSDimitry Andric     Diag(PropertyLoc, diag::err_objc_direct_dynamic_property);
15975ffd83dbSDimitry Andric     Diag(PIDecl->getPropertyDecl()->getLocation(),
15985ffd83dbSDimitry Andric          diag::note_previous_declaration);
15995ffd83dbSDimitry Andric     return nullptr;
16005ffd83dbSDimitry Andric   }
16015ffd83dbSDimitry Andric 
16020b57cec5SDimitry Andric   return PIDecl;
16030b57cec5SDimitry Andric }
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
16060b57cec5SDimitry Andric // Helper methods.
16070b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
16080b57cec5SDimitry Andric 
16090b57cec5SDimitry Andric /// DiagnosePropertyMismatch - Compares two properties for their
16100b57cec5SDimitry Andric /// attributes and types and warns on a variety of inconsistencies.
16110b57cec5SDimitry Andric ///
1612*0fca6ea1SDimitry Andric void SemaObjC::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
16130b57cec5SDimitry Andric                                         ObjCPropertyDecl *SuperProperty,
16140b57cec5SDimitry Andric                                         const IdentifierInfo *inheritedName,
16150b57cec5SDimitry Andric                                         bool OverridingProtocolProperty) {
1616*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
16175ffd83dbSDimitry Andric   ObjCPropertyAttribute::Kind CAttr = Property->getPropertyAttributes();
16185ffd83dbSDimitry Andric   ObjCPropertyAttribute::Kind SAttr = SuperProperty->getPropertyAttributes();
16190b57cec5SDimitry Andric 
16200b57cec5SDimitry Andric   // We allow readonly properties without an explicit ownership
16210b57cec5SDimitry Andric   // (assign/unsafe_unretained/weak/retain/strong/copy) in super class
16220b57cec5SDimitry Andric   // to be overridden by a property with any explicit ownership in the subclass.
16230b57cec5SDimitry Andric   if (!OverridingProtocolProperty &&
16240b57cec5SDimitry Andric       !getOwnershipRule(SAttr) && getOwnershipRule(CAttr))
16250b57cec5SDimitry Andric     ;
16260b57cec5SDimitry Andric   else {
16275ffd83dbSDimitry Andric     if ((CAttr & ObjCPropertyAttribute::kind_readonly) &&
16285ffd83dbSDimitry Andric         (SAttr & ObjCPropertyAttribute::kind_readwrite))
16290b57cec5SDimitry Andric       Diag(Property->getLocation(), diag::warn_readonly_property)
16300b57cec5SDimitry Andric         << Property->getDeclName() << inheritedName;
16315ffd83dbSDimitry Andric     if ((CAttr & ObjCPropertyAttribute::kind_copy) !=
16325ffd83dbSDimitry Andric         (SAttr & ObjCPropertyAttribute::kind_copy))
16330b57cec5SDimitry Andric       Diag(Property->getLocation(), diag::warn_property_attribute)
16340b57cec5SDimitry Andric         << Property->getDeclName() << "copy" << inheritedName;
16355ffd83dbSDimitry Andric     else if (!(SAttr & ObjCPropertyAttribute::kind_readonly)) {
16365ffd83dbSDimitry Andric       unsigned CAttrRetain = (CAttr & (ObjCPropertyAttribute::kind_retain |
16375ffd83dbSDimitry Andric                                        ObjCPropertyAttribute::kind_strong));
16385ffd83dbSDimitry Andric       unsigned SAttrRetain = (SAttr & (ObjCPropertyAttribute::kind_retain |
16395ffd83dbSDimitry Andric                                        ObjCPropertyAttribute::kind_strong));
16400b57cec5SDimitry Andric       bool CStrong = (CAttrRetain != 0);
16410b57cec5SDimitry Andric       bool SStrong = (SAttrRetain != 0);
16420b57cec5SDimitry Andric       if (CStrong != SStrong)
16430b57cec5SDimitry Andric         Diag(Property->getLocation(), diag::warn_property_attribute)
16440b57cec5SDimitry Andric           << Property->getDeclName() << "retain (or strong)" << inheritedName;
16450b57cec5SDimitry Andric     }
16460b57cec5SDimitry Andric   }
16470b57cec5SDimitry Andric 
16480b57cec5SDimitry Andric   // Check for nonatomic; note that nonatomic is effectively
16490b57cec5SDimitry Andric   // meaningless for readonly properties, so don't diagnose if the
16500b57cec5SDimitry Andric   // atomic property is 'readonly'.
1651*0fca6ea1SDimitry Andric   checkAtomicPropertyMismatch(SemaRef, SuperProperty, Property, false);
16520b57cec5SDimitry Andric   // Readonly properties from protocols can be implemented as "readwrite"
16530b57cec5SDimitry Andric   // with a custom setter name.
16540b57cec5SDimitry Andric   if (Property->getSetterName() != SuperProperty->getSetterName() &&
16550b57cec5SDimitry Andric       !(SuperProperty->isReadOnly() &&
16560b57cec5SDimitry Andric         isa<ObjCProtocolDecl>(SuperProperty->getDeclContext()))) {
16570b57cec5SDimitry Andric     Diag(Property->getLocation(), diag::warn_property_attribute)
16580b57cec5SDimitry Andric       << Property->getDeclName() << "setter" << inheritedName;
16590b57cec5SDimitry Andric     Diag(SuperProperty->getLocation(), diag::note_property_declare);
16600b57cec5SDimitry Andric   }
16610b57cec5SDimitry Andric   if (Property->getGetterName() != SuperProperty->getGetterName()) {
16620b57cec5SDimitry Andric     Diag(Property->getLocation(), diag::warn_property_attribute)
16630b57cec5SDimitry Andric       << Property->getDeclName() << "getter" << inheritedName;
16640b57cec5SDimitry Andric     Diag(SuperProperty->getLocation(), diag::note_property_declare);
16650b57cec5SDimitry Andric   }
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric   QualType LHSType =
16680b57cec5SDimitry Andric     Context.getCanonicalType(SuperProperty->getType());
16690b57cec5SDimitry Andric   QualType RHSType =
16700b57cec5SDimitry Andric     Context.getCanonicalType(Property->getType());
16710b57cec5SDimitry Andric 
16720b57cec5SDimitry Andric   if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) {
16730b57cec5SDimitry Andric     // Do cases not handled in above.
16740b57cec5SDimitry Andric     // FIXME. For future support of covariant property types, revisit this.
16750b57cec5SDimitry Andric     bool IncompatibleObjC = false;
16760b57cec5SDimitry Andric     QualType ConvertedType;
1677*0fca6ea1SDimitry Andric     if (!SemaRef.isObjCPointerConversion(RHSType, LHSType, ConvertedType,
1678*0fca6ea1SDimitry Andric                                          IncompatibleObjC) ||
16790b57cec5SDimitry Andric         IncompatibleObjC) {
16800b57cec5SDimitry Andric       Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
16810b57cec5SDimitry Andric           << Property->getType() << SuperProperty->getType() << inheritedName;
16820b57cec5SDimitry Andric       Diag(SuperProperty->getLocation(), diag::note_property_declare);
16830b57cec5SDimitry Andric     }
16840b57cec5SDimitry Andric   }
16850b57cec5SDimitry Andric }
16860b57cec5SDimitry Andric 
1687*0fca6ea1SDimitry Andric bool SemaObjC::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
16880b57cec5SDimitry Andric                                                 ObjCMethodDecl *GetterMethod,
16890b57cec5SDimitry Andric                                                 SourceLocation Loc) {
1690*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
16910b57cec5SDimitry Andric   if (!GetterMethod)
16920b57cec5SDimitry Andric     return false;
16930b57cec5SDimitry Andric   QualType GetterType = GetterMethod->getReturnType().getNonReferenceType();
16940b57cec5SDimitry Andric   QualType PropertyRValueType =
16950b57cec5SDimitry Andric       property->getType().getNonReferenceType().getAtomicUnqualifiedType();
16960b57cec5SDimitry Andric   bool compat = Context.hasSameType(PropertyRValueType, GetterType);
16970b57cec5SDimitry Andric   if (!compat) {
16980b57cec5SDimitry Andric     const ObjCObjectPointerType *propertyObjCPtr = nullptr;
16990b57cec5SDimitry Andric     const ObjCObjectPointerType *getterObjCPtr = nullptr;
17000b57cec5SDimitry Andric     if ((propertyObjCPtr =
17010b57cec5SDimitry Andric              PropertyRValueType->getAs<ObjCObjectPointerType>()) &&
17020b57cec5SDimitry Andric         (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>()))
17030b57cec5SDimitry Andric       compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr);
1704*0fca6ea1SDimitry Andric     else if (SemaRef.CheckAssignmentConstraints(
1705*0fca6ea1SDimitry Andric                  Loc, GetterType, PropertyRValueType) != Sema::Compatible) {
17060b57cec5SDimitry Andric       Diag(Loc, diag::err_property_accessor_type)
17070b57cec5SDimitry Andric           << property->getDeclName() << PropertyRValueType
17080b57cec5SDimitry Andric           << GetterMethod->getSelector() << GetterType;
17090b57cec5SDimitry Andric       Diag(GetterMethod->getLocation(), diag::note_declared_at);
17100b57cec5SDimitry Andric       return true;
17110b57cec5SDimitry Andric     } else {
17120b57cec5SDimitry Andric       compat = true;
17130b57cec5SDimitry Andric       QualType lhsType = Context.getCanonicalType(PropertyRValueType);
17140b57cec5SDimitry Andric       QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType();
17150b57cec5SDimitry Andric       if (lhsType != rhsType && lhsType->isArithmeticType())
17160b57cec5SDimitry Andric         compat = false;
17170b57cec5SDimitry Andric     }
17180b57cec5SDimitry Andric   }
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric   if (!compat) {
17210b57cec5SDimitry Andric     Diag(Loc, diag::warn_accessor_property_type_mismatch)
17220b57cec5SDimitry Andric     << property->getDeclName()
17230b57cec5SDimitry Andric     << GetterMethod->getSelector();
17240b57cec5SDimitry Andric     Diag(GetterMethod->getLocation(), diag::note_declared_at);
17250b57cec5SDimitry Andric     return true;
17260b57cec5SDimitry Andric   }
17270b57cec5SDimitry Andric 
17280b57cec5SDimitry Andric   return false;
17290b57cec5SDimitry Andric }
17300b57cec5SDimitry Andric 
17310b57cec5SDimitry Andric /// CollectImmediateProperties - This routine collects all properties in
17320b57cec5SDimitry Andric /// the class and its conforming protocols; but not those in its super class.
17330b57cec5SDimitry Andric static void
17340b57cec5SDimitry Andric CollectImmediateProperties(ObjCContainerDecl *CDecl,
17350b57cec5SDimitry Andric                            ObjCContainerDecl::PropertyMap &PropMap,
17360b57cec5SDimitry Andric                            ObjCContainerDecl::PropertyMap &SuperPropMap,
17370b57cec5SDimitry Andric                            bool CollectClassPropsOnly = false,
17380b57cec5SDimitry Andric                            bool IncludeProtocols = true) {
17390b57cec5SDimitry Andric   if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
17400b57cec5SDimitry Andric     for (auto *Prop : IDecl->properties()) {
17410b57cec5SDimitry Andric       if (CollectClassPropsOnly && !Prop->isClassProperty())
17420b57cec5SDimitry Andric         continue;
17430b57cec5SDimitry Andric       PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] =
17440b57cec5SDimitry Andric           Prop;
17450b57cec5SDimitry Andric     }
17460b57cec5SDimitry Andric 
17470b57cec5SDimitry Andric     // Collect the properties from visible extensions.
17480b57cec5SDimitry Andric     for (auto *Ext : IDecl->visible_extensions())
17490b57cec5SDimitry Andric       CollectImmediateProperties(Ext, PropMap, SuperPropMap,
17500b57cec5SDimitry Andric                                  CollectClassPropsOnly, IncludeProtocols);
17510b57cec5SDimitry Andric 
17520b57cec5SDimitry Andric     if (IncludeProtocols) {
17530b57cec5SDimitry Andric       // Scan through class's protocols.
17540b57cec5SDimitry Andric       for (auto *PI : IDecl->all_referenced_protocols())
17550b57cec5SDimitry Andric         CollectImmediateProperties(PI, PropMap, SuperPropMap,
17560b57cec5SDimitry Andric                                    CollectClassPropsOnly);
17570b57cec5SDimitry Andric     }
17580b57cec5SDimitry Andric   }
17590b57cec5SDimitry Andric   if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
17600b57cec5SDimitry Andric     for (auto *Prop : CATDecl->properties()) {
17610b57cec5SDimitry Andric       if (CollectClassPropsOnly && !Prop->isClassProperty())
17620b57cec5SDimitry Andric         continue;
17630b57cec5SDimitry Andric       PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] =
17640b57cec5SDimitry Andric           Prop;
17650b57cec5SDimitry Andric     }
17660b57cec5SDimitry Andric     if (IncludeProtocols) {
17670b57cec5SDimitry Andric       // Scan through class's protocols.
17680b57cec5SDimitry Andric       for (auto *PI : CATDecl->protocols())
17690b57cec5SDimitry Andric         CollectImmediateProperties(PI, PropMap, SuperPropMap,
17700b57cec5SDimitry Andric                                    CollectClassPropsOnly);
17710b57cec5SDimitry Andric     }
17720b57cec5SDimitry Andric   }
17730b57cec5SDimitry Andric   else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
17740b57cec5SDimitry Andric     for (auto *Prop : PDecl->properties()) {
17750b57cec5SDimitry Andric       if (CollectClassPropsOnly && !Prop->isClassProperty())
17760b57cec5SDimitry Andric         continue;
17770b57cec5SDimitry Andric       ObjCPropertyDecl *PropertyFromSuper =
17780b57cec5SDimitry Andric           SuperPropMap[std::make_pair(Prop->getIdentifier(),
17790b57cec5SDimitry Andric                                       Prop->isClassProperty())];
17800b57cec5SDimitry Andric       // Exclude property for protocols which conform to class's super-class,
17810b57cec5SDimitry Andric       // as super-class has to implement the property.
17820b57cec5SDimitry Andric       if (!PropertyFromSuper ||
17830b57cec5SDimitry Andric           PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) {
17840b57cec5SDimitry Andric         ObjCPropertyDecl *&PropEntry =
17850b57cec5SDimitry Andric             PropMap[std::make_pair(Prop->getIdentifier(),
17860b57cec5SDimitry Andric                                    Prop->isClassProperty())];
17870b57cec5SDimitry Andric         if (!PropEntry)
17880b57cec5SDimitry Andric           PropEntry = Prop;
17890b57cec5SDimitry Andric       }
17900b57cec5SDimitry Andric     }
17910b57cec5SDimitry Andric     // Scan through protocol's protocols.
17920b57cec5SDimitry Andric     for (auto *PI : PDecl->protocols())
17930b57cec5SDimitry Andric       CollectImmediateProperties(PI, PropMap, SuperPropMap,
17940b57cec5SDimitry Andric                                  CollectClassPropsOnly);
17950b57cec5SDimitry Andric   }
17960b57cec5SDimitry Andric }
17970b57cec5SDimitry Andric 
17980b57cec5SDimitry Andric /// CollectSuperClassPropertyImplementations - This routine collects list of
17990b57cec5SDimitry Andric /// properties to be implemented in super class(s) and also coming from their
18000b57cec5SDimitry Andric /// conforming protocols.
18010b57cec5SDimitry Andric static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
18020b57cec5SDimitry Andric                                     ObjCInterfaceDecl::PropertyMap &PropMap) {
18030b57cec5SDimitry Andric   if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
18040b57cec5SDimitry Andric     while (SDecl) {
1805bdd1243dSDimitry Andric       SDecl->collectPropertiesToImplement(PropMap);
18060b57cec5SDimitry Andric       SDecl = SDecl->getSuperClass();
18070b57cec5SDimitry Andric     }
18080b57cec5SDimitry Andric   }
18090b57cec5SDimitry Andric }
18100b57cec5SDimitry Andric 
18110b57cec5SDimitry Andric /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
18120b57cec5SDimitry Andric /// an ivar synthesized for 'Method' and 'Method' is a property accessor
18130b57cec5SDimitry Andric /// declared in class 'IFace'.
1814*0fca6ea1SDimitry Andric bool SemaObjC::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
1815*0fca6ea1SDimitry Andric                                               ObjCMethodDecl *Method,
1816*0fca6ea1SDimitry Andric                                               ObjCIvarDecl *IV) {
18170b57cec5SDimitry Andric   if (!IV->getSynthesize())
18180b57cec5SDimitry Andric     return false;
18190b57cec5SDimitry Andric   ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(),
18200b57cec5SDimitry Andric                                             Method->isInstanceMethod());
18210b57cec5SDimitry Andric   if (!IMD || !IMD->isPropertyAccessor())
18220b57cec5SDimitry Andric     return false;
18230b57cec5SDimitry Andric 
18240b57cec5SDimitry Andric   // look up a property declaration whose one of its accessors is implemented
18250b57cec5SDimitry Andric   // by this method.
18260b57cec5SDimitry Andric   for (const auto *Property : IFace->instance_properties()) {
18270b57cec5SDimitry Andric     if ((Property->getGetterName() == IMD->getSelector() ||
18280b57cec5SDimitry Andric          Property->getSetterName() == IMD->getSelector()) &&
18290b57cec5SDimitry Andric         (Property->getPropertyIvarDecl() == IV))
18300b57cec5SDimitry Andric       return true;
18310b57cec5SDimitry Andric   }
18320b57cec5SDimitry Andric   // Also look up property declaration in class extension whose one of its
18330b57cec5SDimitry Andric   // accessors is implemented by this method.
18340b57cec5SDimitry Andric   for (const auto *Ext : IFace->known_extensions())
18350b57cec5SDimitry Andric     for (const auto *Property : Ext->instance_properties())
18360b57cec5SDimitry Andric       if ((Property->getGetterName() == IMD->getSelector() ||
18370b57cec5SDimitry Andric            Property->getSetterName() == IMD->getSelector()) &&
18380b57cec5SDimitry Andric           (Property->getPropertyIvarDecl() == IV))
18390b57cec5SDimitry Andric         return true;
18400b57cec5SDimitry Andric   return false;
18410b57cec5SDimitry Andric }
18420b57cec5SDimitry Andric 
18430b57cec5SDimitry Andric static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl,
18440b57cec5SDimitry Andric                                          ObjCPropertyDecl *Prop) {
18450b57cec5SDimitry Andric   bool SuperClassImplementsGetter = false;
18460b57cec5SDimitry Andric   bool SuperClassImplementsSetter = false;
18475ffd83dbSDimitry Andric   if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly)
18480b57cec5SDimitry Andric     SuperClassImplementsSetter = true;
18490b57cec5SDimitry Andric 
18500b57cec5SDimitry Andric   while (IDecl->getSuperClass()) {
18510b57cec5SDimitry Andric     ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
18520b57cec5SDimitry Andric     if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName()))
18530b57cec5SDimitry Andric       SuperClassImplementsGetter = true;
18540b57cec5SDimitry Andric 
18550b57cec5SDimitry Andric     if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName()))
18560b57cec5SDimitry Andric       SuperClassImplementsSetter = true;
18570b57cec5SDimitry Andric     if (SuperClassImplementsGetter && SuperClassImplementsSetter)
18580b57cec5SDimitry Andric       return true;
18590b57cec5SDimitry Andric     IDecl = IDecl->getSuperClass();
18600b57cec5SDimitry Andric   }
18610b57cec5SDimitry Andric   return false;
18620b57cec5SDimitry Andric }
18630b57cec5SDimitry Andric 
18640b57cec5SDimitry Andric /// Default synthesizes all properties which must be synthesized
18650b57cec5SDimitry Andric /// in class's \@implementation.
1866*0fca6ea1SDimitry Andric void SemaObjC::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl,
18670b57cec5SDimitry Andric                                            ObjCInterfaceDecl *IDecl,
18680b57cec5SDimitry Andric                                            SourceLocation AtEnd) {
1869*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
18700b57cec5SDimitry Andric   ObjCInterfaceDecl::PropertyMap PropMap;
1871bdd1243dSDimitry Andric   IDecl->collectPropertiesToImplement(PropMap);
18720b57cec5SDimitry Andric   if (PropMap.empty())
18730b57cec5SDimitry Andric     return;
18740b57cec5SDimitry Andric   ObjCInterfaceDecl::PropertyMap SuperPropMap;
18750b57cec5SDimitry Andric   CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
18760b57cec5SDimitry Andric 
1877bdd1243dSDimitry Andric   for (const auto &PropEntry : PropMap) {
1878bdd1243dSDimitry Andric     ObjCPropertyDecl *Prop = PropEntry.second;
18790b57cec5SDimitry Andric     // Is there a matching property synthesize/dynamic?
18800b57cec5SDimitry Andric     if (Prop->isInvalidDecl() ||
18810b57cec5SDimitry Andric         Prop->isClassProperty() ||
18820b57cec5SDimitry Andric         Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional)
18830b57cec5SDimitry Andric       continue;
18840b57cec5SDimitry Andric     // Property may have been synthesized by user.
18850b57cec5SDimitry Andric     if (IMPDecl->FindPropertyImplDecl(
18860b57cec5SDimitry Andric             Prop->getIdentifier(), Prop->getQueryKind()))
18870b57cec5SDimitry Andric       continue;
1888480093f4SDimitry Andric     ObjCMethodDecl *ImpMethod = IMPDecl->getInstanceMethod(Prop->getGetterName());
1889480093f4SDimitry Andric     if (ImpMethod && !ImpMethod->getBody()) {
18905ffd83dbSDimitry Andric       if (Prop->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly)
18910b57cec5SDimitry Andric         continue;
1892480093f4SDimitry Andric       ImpMethod = IMPDecl->getInstanceMethod(Prop->getSetterName());
1893480093f4SDimitry Andric       if (ImpMethod && !ImpMethod->getBody())
18940b57cec5SDimitry Andric         continue;
18950b57cec5SDimitry Andric     }
18960b57cec5SDimitry Andric     if (ObjCPropertyImplDecl *PID =
18970b57cec5SDimitry Andric         IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
18980b57cec5SDimitry Andric       Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
18990b57cec5SDimitry Andric         << Prop->getIdentifier();
19000b57cec5SDimitry Andric       if (PID->getLocation().isValid())
19010b57cec5SDimitry Andric         Diag(PID->getLocation(), diag::note_property_synthesize);
19020b57cec5SDimitry Andric       continue;
19030b57cec5SDimitry Andric     }
19040b57cec5SDimitry Andric     ObjCPropertyDecl *PropInSuperClass =
19050b57cec5SDimitry Andric         SuperPropMap[std::make_pair(Prop->getIdentifier(),
19060b57cec5SDimitry Andric                                     Prop->isClassProperty())];
19070b57cec5SDimitry Andric     if (ObjCProtocolDecl *Proto =
19080b57cec5SDimitry Andric           dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) {
19090b57cec5SDimitry Andric       // We won't auto-synthesize properties declared in protocols.
19100b57cec5SDimitry Andric       // Suppress the warning if class's superclass implements property's
19110b57cec5SDimitry Andric       // getter and implements property's setter (if readwrite property).
19120b57cec5SDimitry Andric       // Or, if property is going to be implemented in its super class.
19130b57cec5SDimitry Andric       if (!SuperClassImplementsProperty(IDecl, Prop) && !PropInSuperClass) {
19140b57cec5SDimitry Andric         Diag(IMPDecl->getLocation(),
19150b57cec5SDimitry Andric              diag::warn_auto_synthesizing_protocol_property)
19160b57cec5SDimitry Andric           << Prop << Proto;
19170b57cec5SDimitry Andric         Diag(Prop->getLocation(), diag::note_property_declare);
19180b57cec5SDimitry Andric         std::string FixIt =
19190b57cec5SDimitry Andric             (Twine("@synthesize ") + Prop->getName() + ";\n\n").str();
19200b57cec5SDimitry Andric         Diag(AtEnd, diag::note_add_synthesize_directive)
19210b57cec5SDimitry Andric             << FixItHint::CreateInsertion(AtEnd, FixIt);
19220b57cec5SDimitry Andric       }
19230b57cec5SDimitry Andric       continue;
19240b57cec5SDimitry Andric     }
19250b57cec5SDimitry Andric     // If property to be implemented in the super class, ignore.
19260b57cec5SDimitry Andric     if (PropInSuperClass) {
19275ffd83dbSDimitry Andric       if ((Prop->getPropertyAttributes() &
19285ffd83dbSDimitry Andric            ObjCPropertyAttribute::kind_readwrite) &&
19290b57cec5SDimitry Andric           (PropInSuperClass->getPropertyAttributes() &
19305ffd83dbSDimitry Andric            ObjCPropertyAttribute::kind_readonly) &&
19310b57cec5SDimitry Andric           !IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
19320b57cec5SDimitry Andric           !IDecl->HasUserDeclaredSetterMethod(Prop)) {
19330b57cec5SDimitry Andric         Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
19340b57cec5SDimitry Andric         << Prop->getIdentifier();
19350b57cec5SDimitry Andric         Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
19365ffd83dbSDimitry Andric       } else {
19370b57cec5SDimitry Andric         Diag(Prop->getLocation(), diag::warn_autosynthesis_property_in_superclass)
19380b57cec5SDimitry Andric         << Prop->getIdentifier();
19390b57cec5SDimitry Andric         Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
19400b57cec5SDimitry Andric         Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
19410b57cec5SDimitry Andric       }
19420b57cec5SDimitry Andric       continue;
19430b57cec5SDimitry Andric     }
19440b57cec5SDimitry Andric     // We use invalid SourceLocations for the synthesized ivars since they
19450b57cec5SDimitry Andric     // aren't really synthesized at a particular location; they just exist.
19460b57cec5SDimitry Andric     // Saying that they are located at the @implementation isn't really going
19470b57cec5SDimitry Andric     // to help users.
19480b57cec5SDimitry Andric     ObjCPropertyImplDecl *PIDecl = dyn_cast_or_null<ObjCPropertyImplDecl>(
19490b57cec5SDimitry Andric       ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(),
19500b57cec5SDimitry Andric                             true,
19510b57cec5SDimitry Andric                             /* property = */ Prop->getIdentifier(),
19520b57cec5SDimitry Andric                             /* ivar = */ Prop->getDefaultSynthIvarName(Context),
19530b57cec5SDimitry Andric                             Prop->getLocation(), Prop->getQueryKind()));
19540b57cec5SDimitry Andric     if (PIDecl && !Prop->isUnavailable()) {
19550b57cec5SDimitry Andric       Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis);
19560b57cec5SDimitry Andric       Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
19570b57cec5SDimitry Andric     }
19580b57cec5SDimitry Andric   }
19590b57cec5SDimitry Andric }
19600b57cec5SDimitry Andric 
1961*0fca6ea1SDimitry Andric void SemaObjC::DefaultSynthesizeProperties(Scope *S, Decl *D,
19620b57cec5SDimitry Andric                                            SourceLocation AtEnd) {
1963*0fca6ea1SDimitry Andric   if (!getLangOpts().ObjCDefaultSynthProperties ||
1964*0fca6ea1SDimitry Andric       getLangOpts().ObjCRuntime.isFragile())
19650b57cec5SDimitry Andric     return;
19660b57cec5SDimitry Andric   ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D);
19670b57cec5SDimitry Andric   if (!IC)
19680b57cec5SDimitry Andric     return;
19690b57cec5SDimitry Andric   if (ObjCInterfaceDecl* IDecl = IC->getClassInterface())
19700b57cec5SDimitry Andric     if (!IDecl->isObjCRequiresPropertyDefs())
19710b57cec5SDimitry Andric       DefaultSynthesizeProperties(S, IC, IDecl, AtEnd);
19720b57cec5SDimitry Andric }
19730b57cec5SDimitry Andric 
19740b57cec5SDimitry Andric static void DiagnoseUnimplementedAccessor(
19750b57cec5SDimitry Andric     Sema &S, ObjCInterfaceDecl *PrimaryClass, Selector Method,
19760b57cec5SDimitry Andric     ObjCImplDecl *IMPDecl, ObjCContainerDecl *CDecl, ObjCCategoryDecl *C,
19770b57cec5SDimitry Andric     ObjCPropertyDecl *Prop,
19780b57cec5SDimitry Andric     llvm::SmallPtrSet<const ObjCMethodDecl *, 8> &SMap) {
19790b57cec5SDimitry Andric   // Check to see if we have a corresponding selector in SMap and with the
19800b57cec5SDimitry Andric   // right method type.
19810b57cec5SDimitry Andric   auto I = llvm::find_if(SMap, [&](const ObjCMethodDecl *x) {
19820b57cec5SDimitry Andric     return x->getSelector() == Method &&
19830b57cec5SDimitry Andric            x->isClassMethod() == Prop->isClassProperty();
19840b57cec5SDimitry Andric   });
19850b57cec5SDimitry Andric   // When reporting on missing property setter/getter implementation in
19860b57cec5SDimitry Andric   // categories, do not report when they are declared in primary class,
19870b57cec5SDimitry Andric   // class's protocol, or one of it super classes. This is because,
19880b57cec5SDimitry Andric   // the class is going to implement them.
19890b57cec5SDimitry Andric   if (I == SMap.end() &&
19900b57cec5SDimitry Andric       (PrimaryClass == nullptr ||
19910b57cec5SDimitry Andric        !PrimaryClass->lookupPropertyAccessor(Method, C,
19920b57cec5SDimitry Andric                                              Prop->isClassProperty()))) {
19930b57cec5SDimitry Andric     unsigned diag =
19940b57cec5SDimitry Andric         isa<ObjCCategoryDecl>(CDecl)
19950b57cec5SDimitry Andric             ? (Prop->isClassProperty()
19960b57cec5SDimitry Andric                    ? diag::warn_impl_required_in_category_for_class_property
19970b57cec5SDimitry Andric                    : diag::warn_setter_getter_impl_required_in_category)
19980b57cec5SDimitry Andric             : (Prop->isClassProperty()
19990b57cec5SDimitry Andric                    ? diag::warn_impl_required_for_class_property
20000b57cec5SDimitry Andric                    : diag::warn_setter_getter_impl_required);
20010b57cec5SDimitry Andric     S.Diag(IMPDecl->getLocation(), diag) << Prop->getDeclName() << Method;
20020b57cec5SDimitry Andric     S.Diag(Prop->getLocation(), diag::note_property_declare);
20030b57cec5SDimitry Andric     if (S.LangOpts.ObjCDefaultSynthProperties &&
20040b57cec5SDimitry Andric         S.LangOpts.ObjCRuntime.isNonFragile())
20050b57cec5SDimitry Andric       if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
20060b57cec5SDimitry Andric         if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
20070b57cec5SDimitry Andric           S.Diag(RID->getLocation(), diag::note_suppressed_class_declare);
20080b57cec5SDimitry Andric   }
20090b57cec5SDimitry Andric }
20100b57cec5SDimitry Andric 
2011*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl,
20120b57cec5SDimitry Andric                                                ObjCContainerDecl *CDecl,
20130b57cec5SDimitry Andric                                                bool SynthesizeProperties) {
20140b57cec5SDimitry Andric   ObjCContainerDecl::PropertyMap PropMap;
20150b57cec5SDimitry Andric   ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric   // Since we don't synthesize class properties, we should emit diagnose even
20180b57cec5SDimitry Andric   // if SynthesizeProperties is true.
20190b57cec5SDimitry Andric   ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
20200b57cec5SDimitry Andric   // Gather properties which need not be implemented in this class
20210b57cec5SDimitry Andric   // or category.
20220b57cec5SDimitry Andric   if (!IDecl)
20230b57cec5SDimitry Andric     if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
20240b57cec5SDimitry Andric       // For categories, no need to implement properties declared in
20250b57cec5SDimitry Andric       // its primary class (and its super classes) if property is
20260b57cec5SDimitry Andric       // declared in one of those containers.
20270b57cec5SDimitry Andric       if ((IDecl = C->getClassInterface())) {
2028bdd1243dSDimitry Andric         IDecl->collectPropertiesToImplement(NoNeedToImplPropMap);
20290b57cec5SDimitry Andric       }
20300b57cec5SDimitry Andric     }
20310b57cec5SDimitry Andric   if (IDecl)
20320b57cec5SDimitry Andric     CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
20330b57cec5SDimitry Andric 
20340b57cec5SDimitry Andric   // When SynthesizeProperties is true, we only check class properties.
20350b57cec5SDimitry Andric   CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap,
20360b57cec5SDimitry Andric                              SynthesizeProperties/*CollectClassPropsOnly*/);
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric   // Scan the @interface to see if any of the protocols it adopts
20390b57cec5SDimitry Andric   // require an explicit implementation, via attribute
20400b57cec5SDimitry Andric   // 'objc_protocol_requires_explicit_implementation'.
20410b57cec5SDimitry Andric   if (IDecl) {
20420b57cec5SDimitry Andric     std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap;
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric     for (auto *PDecl : IDecl->all_referenced_protocols()) {
20450b57cec5SDimitry Andric       if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
20460b57cec5SDimitry Andric         continue;
20470b57cec5SDimitry Andric       // Lazily construct a set of all the properties in the @interface
20480b57cec5SDimitry Andric       // of the class, without looking at the superclass.  We cannot
20490b57cec5SDimitry Andric       // use the call to CollectImmediateProperties() above as that
20500b57cec5SDimitry Andric       // utilizes information from the super class's properties as well
20510b57cec5SDimitry Andric       // as scans the adopted protocols.  This work only triggers for protocols
20520b57cec5SDimitry Andric       // with the attribute, which is very rare, and only occurs when
20530b57cec5SDimitry Andric       // analyzing the @implementation.
20540b57cec5SDimitry Andric       if (!LazyMap) {
20550b57cec5SDimitry Andric         ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
20560b57cec5SDimitry Andric         LazyMap.reset(new ObjCContainerDecl::PropertyMap());
20570b57cec5SDimitry Andric         CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap,
20580b57cec5SDimitry Andric                                    /* CollectClassPropsOnly */ false,
20590b57cec5SDimitry Andric                                    /* IncludeProtocols */ false);
20600b57cec5SDimitry Andric       }
20610b57cec5SDimitry Andric       // Add the properties of 'PDecl' to the list of properties that
20620b57cec5SDimitry Andric       // need to be implemented.
20630b57cec5SDimitry Andric       for (auto *PropDecl : PDecl->properties()) {
20640b57cec5SDimitry Andric         if ((*LazyMap)[std::make_pair(PropDecl->getIdentifier(),
20650b57cec5SDimitry Andric                                       PropDecl->isClassProperty())])
20660b57cec5SDimitry Andric           continue;
20670b57cec5SDimitry Andric         PropMap[std::make_pair(PropDecl->getIdentifier(),
20680b57cec5SDimitry Andric                                PropDecl->isClassProperty())] = PropDecl;
20690b57cec5SDimitry Andric       }
20700b57cec5SDimitry Andric     }
20710b57cec5SDimitry Andric   }
20720b57cec5SDimitry Andric 
20730b57cec5SDimitry Andric   if (PropMap.empty())
20740b57cec5SDimitry Andric     return;
20750b57cec5SDimitry Andric 
20760b57cec5SDimitry Andric   llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
20770b57cec5SDimitry Andric   for (const auto *I : IMPDecl->property_impls())
20780b57cec5SDimitry Andric     PropImplMap.insert(I->getPropertyDecl());
20790b57cec5SDimitry Andric 
20800b57cec5SDimitry Andric   llvm::SmallPtrSet<const ObjCMethodDecl *, 8> InsMap;
20810b57cec5SDimitry Andric   // Collect property accessors implemented in current implementation.
20820b57cec5SDimitry Andric   for (const auto *I : IMPDecl->methods())
20830b57cec5SDimitry Andric     InsMap.insert(I);
20840b57cec5SDimitry Andric 
20850b57cec5SDimitry Andric   ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
20860b57cec5SDimitry Andric   ObjCInterfaceDecl *PrimaryClass = nullptr;
20870b57cec5SDimitry Andric   if (C && !C->IsClassExtension())
20880b57cec5SDimitry Andric     if ((PrimaryClass = C->getClassInterface()))
20890b57cec5SDimitry Andric       // Report unimplemented properties in the category as well.
20900b57cec5SDimitry Andric       if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) {
20910b57cec5SDimitry Andric         // When reporting on missing setter/getters, do not report when
20920b57cec5SDimitry Andric         // setter/getter is implemented in category's primary class
20930b57cec5SDimitry Andric         // implementation.
20940b57cec5SDimitry Andric         for (const auto *I : IMP->methods())
20950b57cec5SDimitry Andric           InsMap.insert(I);
20960b57cec5SDimitry Andric       }
20970b57cec5SDimitry Andric 
20980b57cec5SDimitry Andric   for (ObjCContainerDecl::PropertyMap::iterator
20990b57cec5SDimitry Andric        P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
21000b57cec5SDimitry Andric     ObjCPropertyDecl *Prop = P->second;
21010b57cec5SDimitry Andric     // Is there a matching property synthesize/dynamic?
21020b57cec5SDimitry Andric     if (Prop->isInvalidDecl() ||
21030b57cec5SDimitry Andric         Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
21040b57cec5SDimitry Andric         PropImplMap.count(Prop) ||
21050b57cec5SDimitry Andric         Prop->getAvailability() == AR_Unavailable)
21060b57cec5SDimitry Andric       continue;
21070b57cec5SDimitry Andric 
21080b57cec5SDimitry Andric     // Diagnose unimplemented getters and setters.
2109*0fca6ea1SDimitry Andric     DiagnoseUnimplementedAccessor(SemaRef, PrimaryClass, Prop->getGetterName(),
21100b57cec5SDimitry Andric                                   IMPDecl, CDecl, C, Prop, InsMap);
2111*0fca6ea1SDimitry Andric     if (!Prop->isReadOnly())
2112*0fca6ea1SDimitry Andric       DiagnoseUnimplementedAccessor(SemaRef, PrimaryClass,
2113*0fca6ea1SDimitry Andric                                     Prop->getSetterName(), IMPDecl, CDecl, C,
2114*0fca6ea1SDimitry Andric                                     Prop, InsMap);
21150b57cec5SDimitry Andric   }
21160b57cec5SDimitry Andric }
21170b57cec5SDimitry Andric 
2118*0fca6ea1SDimitry Andric void SemaObjC::diagnoseNullResettableSynthesizedSetters(
2119*0fca6ea1SDimitry Andric     const ObjCImplDecl *impDecl) {
21200b57cec5SDimitry Andric   for (const auto *propertyImpl : impDecl->property_impls()) {
21210b57cec5SDimitry Andric     const auto *property = propertyImpl->getPropertyDecl();
21220b57cec5SDimitry Andric     // Warn about null_resettable properties with synthesized setters,
21230b57cec5SDimitry Andric     // because the setter won't properly handle nil.
21245ffd83dbSDimitry Andric     if (propertyImpl->getPropertyImplementation() ==
21255ffd83dbSDimitry Andric             ObjCPropertyImplDecl::Synthesize &&
21260b57cec5SDimitry Andric         (property->getPropertyAttributes() &
21275ffd83dbSDimitry Andric          ObjCPropertyAttribute::kind_null_resettable) &&
21285ffd83dbSDimitry Andric         property->getGetterMethodDecl() && property->getSetterMethodDecl()) {
2129480093f4SDimitry Andric       auto *getterImpl = propertyImpl->getGetterMethodDecl();
2130480093f4SDimitry Andric       auto *setterImpl = propertyImpl->getSetterMethodDecl();
2131480093f4SDimitry Andric       if ((!getterImpl || getterImpl->isSynthesizedAccessorStub()) &&
2132480093f4SDimitry Andric           (!setterImpl || setterImpl->isSynthesizedAccessorStub())) {
21330b57cec5SDimitry Andric         SourceLocation loc = propertyImpl->getLocation();
21340b57cec5SDimitry Andric         if (loc.isInvalid())
21350b57cec5SDimitry Andric           loc = impDecl->getBeginLoc();
21360b57cec5SDimitry Andric 
21370b57cec5SDimitry Andric         Diag(loc, diag::warn_null_resettable_setter)
2138480093f4SDimitry Andric           << setterImpl->getSelector() << property->getDeclName();
21390b57cec5SDimitry Andric       }
21400b57cec5SDimitry Andric     }
21410b57cec5SDimitry Andric   }
21420b57cec5SDimitry Andric }
21430b57cec5SDimitry Andric 
2144*0fca6ea1SDimitry Andric void SemaObjC::AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl,
21450b57cec5SDimitry Andric                                                ObjCInterfaceDecl *IDecl) {
21460b57cec5SDimitry Andric   // Rules apply in non-GC mode only
21470b57cec5SDimitry Andric   if (getLangOpts().getGC() != LangOptions::NonGC)
21480b57cec5SDimitry Andric     return;
21490b57cec5SDimitry Andric   ObjCContainerDecl::PropertyMap PM;
21500b57cec5SDimitry Andric   for (auto *Prop : IDecl->properties())
21510b57cec5SDimitry Andric     PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
21520b57cec5SDimitry Andric   for (const auto *Ext : IDecl->known_extensions())
21530b57cec5SDimitry Andric     for (auto *Prop : Ext->properties())
21540b57cec5SDimitry Andric       PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
21550b57cec5SDimitry Andric 
21560b57cec5SDimitry Andric   for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end();
21570b57cec5SDimitry Andric        I != E; ++I) {
21580b57cec5SDimitry Andric     const ObjCPropertyDecl *Property = I->second;
21590b57cec5SDimitry Andric     ObjCMethodDecl *GetterMethod = nullptr;
21600b57cec5SDimitry Andric     ObjCMethodDecl *SetterMethod = nullptr;
21610b57cec5SDimitry Andric 
21620b57cec5SDimitry Andric     unsigned Attributes = Property->getPropertyAttributes();
21630b57cec5SDimitry Andric     unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten();
21640b57cec5SDimitry Andric 
21655ffd83dbSDimitry Andric     if (!(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic) &&
21665ffd83dbSDimitry Andric         !(AttributesAsWritten & ObjCPropertyAttribute::kind_nonatomic)) {
21670b57cec5SDimitry Andric       GetterMethod = Property->isClassProperty() ?
21680b57cec5SDimitry Andric                      IMPDecl->getClassMethod(Property->getGetterName()) :
21690b57cec5SDimitry Andric                      IMPDecl->getInstanceMethod(Property->getGetterName());
21700b57cec5SDimitry Andric       SetterMethod = Property->isClassProperty() ?
21710b57cec5SDimitry Andric                      IMPDecl->getClassMethod(Property->getSetterName()) :
21720b57cec5SDimitry Andric                      IMPDecl->getInstanceMethod(Property->getSetterName());
2173480093f4SDimitry Andric       if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
2174480093f4SDimitry Andric         GetterMethod = nullptr;
2175480093f4SDimitry Andric       if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
2176480093f4SDimitry Andric         SetterMethod = nullptr;
21770b57cec5SDimitry Andric       if (GetterMethod) {
21780b57cec5SDimitry Andric         Diag(GetterMethod->getLocation(),
21790b57cec5SDimitry Andric              diag::warn_default_atomic_custom_getter_setter)
21800b57cec5SDimitry Andric           << Property->getIdentifier() << 0;
21810b57cec5SDimitry Andric         Diag(Property->getLocation(), diag::note_property_declare);
21820b57cec5SDimitry Andric       }
21830b57cec5SDimitry Andric       if (SetterMethod) {
21840b57cec5SDimitry Andric         Diag(SetterMethod->getLocation(),
21850b57cec5SDimitry Andric              diag::warn_default_atomic_custom_getter_setter)
21860b57cec5SDimitry Andric           << Property->getIdentifier() << 1;
21870b57cec5SDimitry Andric         Diag(Property->getLocation(), diag::note_property_declare);
21880b57cec5SDimitry Andric       }
21890b57cec5SDimitry Andric     }
21900b57cec5SDimitry Andric 
21910b57cec5SDimitry Andric     // We only care about readwrite atomic property.
21925ffd83dbSDimitry Andric     if ((Attributes & ObjCPropertyAttribute::kind_nonatomic) ||
21935ffd83dbSDimitry Andric         !(Attributes & ObjCPropertyAttribute::kind_readwrite))
21940b57cec5SDimitry Andric       continue;
21950b57cec5SDimitry Andric     if (const ObjCPropertyImplDecl *PIDecl = IMPDecl->FindPropertyImplDecl(
21960b57cec5SDimitry Andric             Property->getIdentifier(), Property->getQueryKind())) {
21970b57cec5SDimitry Andric       if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
21980b57cec5SDimitry Andric         continue;
2199480093f4SDimitry Andric       GetterMethod = PIDecl->getGetterMethodDecl();
2200480093f4SDimitry Andric       SetterMethod = PIDecl->getSetterMethodDecl();
2201480093f4SDimitry Andric       if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
2202480093f4SDimitry Andric         GetterMethod = nullptr;
2203480093f4SDimitry Andric       if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
2204480093f4SDimitry Andric         SetterMethod = nullptr;
2205480093f4SDimitry Andric       if ((bool)GetterMethod ^ (bool)SetterMethod) {
22060b57cec5SDimitry Andric         SourceLocation MethodLoc =
22070b57cec5SDimitry Andric           (GetterMethod ? GetterMethod->getLocation()
22080b57cec5SDimitry Andric                         : SetterMethod->getLocation());
22090b57cec5SDimitry Andric         Diag(MethodLoc, diag::warn_atomic_property_rule)
22100b57cec5SDimitry Andric           << Property->getIdentifier() << (GetterMethod != nullptr)
22110b57cec5SDimitry Andric           << (SetterMethod != nullptr);
22120b57cec5SDimitry Andric         // fixit stuff.
22130b57cec5SDimitry Andric         if (Property->getLParenLoc().isValid() &&
22145ffd83dbSDimitry Andric             !(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic)) {
22150b57cec5SDimitry Andric           // @property () ... case.
22160b57cec5SDimitry Andric           SourceLocation AfterLParen =
2217*0fca6ea1SDimitry Andric               SemaRef.getLocForEndOfToken(Property->getLParenLoc());
22180b57cec5SDimitry Andric           StringRef NonatomicStr = AttributesAsWritten? "nonatomic, "
22190b57cec5SDimitry Andric                                                       : "nonatomic";
22200b57cec5SDimitry Andric           Diag(Property->getLocation(),
22210b57cec5SDimitry Andric                diag::note_atomic_property_fixup_suggest)
22220b57cec5SDimitry Andric             << FixItHint::CreateInsertion(AfterLParen, NonatomicStr);
22230b57cec5SDimitry Andric         } else if (Property->getLParenLoc().isInvalid()) {
22240b57cec5SDimitry Andric           //@property id etc.
22250b57cec5SDimitry Andric           SourceLocation startLoc =
22260b57cec5SDimitry Andric             Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
22270b57cec5SDimitry Andric           Diag(Property->getLocation(),
22280b57cec5SDimitry Andric                diag::note_atomic_property_fixup_suggest)
22290b57cec5SDimitry Andric             << FixItHint::CreateInsertion(startLoc, "(nonatomic) ");
22305ffd83dbSDimitry Andric         } else
22310b57cec5SDimitry Andric           Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
22320b57cec5SDimitry Andric         Diag(Property->getLocation(), diag::note_property_declare);
22330b57cec5SDimitry Andric       }
22340b57cec5SDimitry Andric     }
22350b57cec5SDimitry Andric   }
22360b57cec5SDimitry Andric }
22370b57cec5SDimitry Andric 
2238*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseOwningPropertyGetterSynthesis(
2239*0fca6ea1SDimitry Andric     const ObjCImplementationDecl *D) {
22400b57cec5SDimitry Andric   if (getLangOpts().getGC() == LangOptions::GCOnly)
22410b57cec5SDimitry Andric     return;
22420b57cec5SDimitry Andric 
22430b57cec5SDimitry Andric   for (const auto *PID : D->property_impls()) {
22440b57cec5SDimitry Andric     const ObjCPropertyDecl *PD = PID->getPropertyDecl();
22450b57cec5SDimitry Andric     if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
2246480093f4SDimitry Andric         !PD->isClassProperty()) {
2247480093f4SDimitry Andric       ObjCMethodDecl *IM = PID->getGetterMethodDecl();
2248480093f4SDimitry Andric       if (IM && !IM->isSynthesizedAccessorStub())
2249480093f4SDimitry Andric         continue;
22500b57cec5SDimitry Andric       ObjCMethodDecl *method = PD->getGetterMethodDecl();
22510b57cec5SDimitry Andric       if (!method)
22520b57cec5SDimitry Andric         continue;
22530b57cec5SDimitry Andric       ObjCMethodFamily family = method->getMethodFamily();
22540b57cec5SDimitry Andric       if (family == OMF_alloc || family == OMF_copy ||
22550b57cec5SDimitry Andric           family == OMF_mutableCopy || family == OMF_new) {
22560b57cec5SDimitry Andric         if (getLangOpts().ObjCAutoRefCount)
22570b57cec5SDimitry Andric           Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule);
22580b57cec5SDimitry Andric         else
22590b57cec5SDimitry Andric           Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule);
22600b57cec5SDimitry Andric 
22610b57cec5SDimitry Andric         // Look for a getter explicitly declared alongside the property.
22620b57cec5SDimitry Andric         // If we find one, use its location for the note.
22630b57cec5SDimitry Andric         SourceLocation noteLoc = PD->getLocation();
22640b57cec5SDimitry Andric         SourceLocation fixItLoc;
22650b57cec5SDimitry Andric         for (auto *getterRedecl : method->redecls()) {
22660b57cec5SDimitry Andric           if (getterRedecl->isImplicit())
22670b57cec5SDimitry Andric             continue;
22680b57cec5SDimitry Andric           if (getterRedecl->getDeclContext() != PD->getDeclContext())
22690b57cec5SDimitry Andric             continue;
22700b57cec5SDimitry Andric           noteLoc = getterRedecl->getLocation();
22710b57cec5SDimitry Andric           fixItLoc = getterRedecl->getEndLoc();
22720b57cec5SDimitry Andric         }
22730b57cec5SDimitry Andric 
2274*0fca6ea1SDimitry Andric         Preprocessor &PP = SemaRef.getPreprocessor();
22750b57cec5SDimitry Andric         TokenValue tokens[] = {
22760b57cec5SDimitry Andric           tok::kw___attribute, tok::l_paren, tok::l_paren,
22770b57cec5SDimitry Andric           PP.getIdentifierInfo("objc_method_family"), tok::l_paren,
22780b57cec5SDimitry Andric           PP.getIdentifierInfo("none"), tok::r_paren,
22790b57cec5SDimitry Andric           tok::r_paren, tok::r_paren
22800b57cec5SDimitry Andric         };
22810b57cec5SDimitry Andric         StringRef spelling = "__attribute__((objc_method_family(none)))";
22820b57cec5SDimitry Andric         StringRef macroName = PP.getLastMacroWithSpelling(noteLoc, tokens);
22830b57cec5SDimitry Andric         if (!macroName.empty())
22840b57cec5SDimitry Andric           spelling = macroName;
22850b57cec5SDimitry Andric 
22860b57cec5SDimitry Andric         auto noteDiag = Diag(noteLoc, diag::note_cocoa_naming_declare_family)
22870b57cec5SDimitry Andric             << method->getDeclName() << spelling;
22880b57cec5SDimitry Andric         if (fixItLoc.isValid()) {
22890b57cec5SDimitry Andric           SmallString<64> fixItText(" ");
22900b57cec5SDimitry Andric           fixItText += spelling;
22910b57cec5SDimitry Andric           noteDiag << FixItHint::CreateInsertion(fixItLoc, fixItText);
22920b57cec5SDimitry Andric         }
22930b57cec5SDimitry Andric       }
22940b57cec5SDimitry Andric     }
22950b57cec5SDimitry Andric   }
22960b57cec5SDimitry Andric }
22970b57cec5SDimitry Andric 
2298*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseMissingDesignatedInitOverrides(
2299*0fca6ea1SDimitry Andric     const ObjCImplementationDecl *ImplD, const ObjCInterfaceDecl *IFD) {
23000b57cec5SDimitry Andric   assert(IFD->hasDesignatedInitializers());
23010b57cec5SDimitry Andric   const ObjCInterfaceDecl *SuperD = IFD->getSuperClass();
23020b57cec5SDimitry Andric   if (!SuperD)
23030b57cec5SDimitry Andric     return;
23040b57cec5SDimitry Andric 
23050b57cec5SDimitry Andric   SelectorSet InitSelSet;
23060b57cec5SDimitry Andric   for (const auto *I : ImplD->instance_methods())
23070b57cec5SDimitry Andric     if (I->getMethodFamily() == OMF_init)
23080b57cec5SDimitry Andric       InitSelSet.insert(I->getSelector());
23090b57cec5SDimitry Andric 
23100b57cec5SDimitry Andric   SmallVector<const ObjCMethodDecl *, 8> DesignatedInits;
23110b57cec5SDimitry Andric   SuperD->getDesignatedInitializers(DesignatedInits);
23120b57cec5SDimitry Andric   for (SmallVector<const ObjCMethodDecl *, 8>::iterator
23130b57cec5SDimitry Andric          I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) {
23140b57cec5SDimitry Andric     const ObjCMethodDecl *MD = *I;
23150b57cec5SDimitry Andric     if (!InitSelSet.count(MD->getSelector())) {
23160b57cec5SDimitry Andric       // Don't emit a diagnostic if the overriding method in the subclass is
23170b57cec5SDimitry Andric       // marked as unavailable.
23180b57cec5SDimitry Andric       bool Ignore = false;
23190b57cec5SDimitry Andric       if (auto *IMD = IFD->getInstanceMethod(MD->getSelector())) {
23200b57cec5SDimitry Andric         Ignore = IMD->isUnavailable();
23210b57cec5SDimitry Andric       } else {
23220b57cec5SDimitry Andric         // Check the methods declared in the class extensions too.
23230b57cec5SDimitry Andric         for (auto *Ext : IFD->visible_extensions())
23240b57cec5SDimitry Andric           if (auto *IMD = Ext->getInstanceMethod(MD->getSelector())) {
23250b57cec5SDimitry Andric             Ignore = IMD->isUnavailable();
23260b57cec5SDimitry Andric             break;
23270b57cec5SDimitry Andric           }
23280b57cec5SDimitry Andric       }
23290b57cec5SDimitry Andric       if (!Ignore) {
23300b57cec5SDimitry Andric         Diag(ImplD->getLocation(),
23310b57cec5SDimitry Andric              diag::warn_objc_implementation_missing_designated_init_override)
23320b57cec5SDimitry Andric           << MD->getSelector();
23330b57cec5SDimitry Andric         Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
23340b57cec5SDimitry Andric       }
23350b57cec5SDimitry Andric     }
23360b57cec5SDimitry Andric   }
23370b57cec5SDimitry Andric }
23380b57cec5SDimitry Andric 
23390b57cec5SDimitry Andric /// AddPropertyAttrs - Propagates attributes from a property to the
23400b57cec5SDimitry Andric /// implicitly-declared getter or setter for that property.
23410b57cec5SDimitry Andric static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
23420b57cec5SDimitry Andric                              ObjCPropertyDecl *Property) {
23430b57cec5SDimitry Andric   // Should we just clone all attributes over?
23440b57cec5SDimitry Andric   for (const auto *A : Property->attrs()) {
23450b57cec5SDimitry Andric     if (isa<DeprecatedAttr>(A) ||
23460b57cec5SDimitry Andric         isa<UnavailableAttr>(A) ||
23470b57cec5SDimitry Andric         isa<AvailabilityAttr>(A))
23480b57cec5SDimitry Andric       PropertyMethod->addAttr(A->clone(S.Context));
23490b57cec5SDimitry Andric   }
23500b57cec5SDimitry Andric }
23510b57cec5SDimitry Andric 
23520b57cec5SDimitry Andric /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
23530b57cec5SDimitry Andric /// have the property type and issue diagnostics if they don't.
23540b57cec5SDimitry Andric /// Also synthesize a getter/setter method if none exist (and update the
23550b57cec5SDimitry Andric /// appropriate lookup tables.
2356*0fca6ea1SDimitry Andric void SemaObjC::ProcessPropertyDecl(ObjCPropertyDecl *property) {
2357*0fca6ea1SDimitry Andric   ASTContext &Context = getASTContext();
23580b57cec5SDimitry Andric   ObjCMethodDecl *GetterMethod, *SetterMethod;
23590b57cec5SDimitry Andric   ObjCContainerDecl *CD = cast<ObjCContainerDecl>(property->getDeclContext());
23600b57cec5SDimitry Andric   if (CD->isInvalidDecl())
23610b57cec5SDimitry Andric     return;
23620b57cec5SDimitry Andric 
23630b57cec5SDimitry Andric   bool IsClassProperty = property->isClassProperty();
23640b57cec5SDimitry Andric   GetterMethod = IsClassProperty ?
23650b57cec5SDimitry Andric     CD->getClassMethod(property->getGetterName()) :
23660b57cec5SDimitry Andric     CD->getInstanceMethod(property->getGetterName());
23670b57cec5SDimitry Andric 
23680b57cec5SDimitry Andric   // if setter or getter is not found in class extension, it might be
23690b57cec5SDimitry Andric   // in the primary class.
23700b57cec5SDimitry Andric   if (!GetterMethod)
23710b57cec5SDimitry Andric     if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
23720b57cec5SDimitry Andric       if (CatDecl->IsClassExtension())
23730b57cec5SDimitry Andric         GetterMethod = IsClassProperty ? CatDecl->getClassInterface()->
23740b57cec5SDimitry Andric                          getClassMethod(property->getGetterName()) :
23750b57cec5SDimitry Andric                        CatDecl->getClassInterface()->
23760b57cec5SDimitry Andric                          getInstanceMethod(property->getGetterName());
23770b57cec5SDimitry Andric 
23780b57cec5SDimitry Andric   SetterMethod = IsClassProperty ?
23790b57cec5SDimitry Andric                  CD->getClassMethod(property->getSetterName()) :
23800b57cec5SDimitry Andric                  CD->getInstanceMethod(property->getSetterName());
23810b57cec5SDimitry Andric   if (!SetterMethod)
23820b57cec5SDimitry Andric     if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
23830b57cec5SDimitry Andric       if (CatDecl->IsClassExtension())
23840b57cec5SDimitry Andric         SetterMethod = IsClassProperty ? CatDecl->getClassInterface()->
23850b57cec5SDimitry Andric                           getClassMethod(property->getSetterName()) :
23860b57cec5SDimitry Andric                        CatDecl->getClassInterface()->
23870b57cec5SDimitry Andric                           getInstanceMethod(property->getSetterName());
23880b57cec5SDimitry Andric   DiagnosePropertyAccessorMismatch(property, GetterMethod,
23890b57cec5SDimitry Andric                                    property->getLocation());
23900b57cec5SDimitry Andric 
23915ffd83dbSDimitry Andric   // synthesizing accessors must not result in a direct method that is not
23925ffd83dbSDimitry Andric   // monomorphic
23935ffd83dbSDimitry Andric   if (!GetterMethod) {
23945ffd83dbSDimitry Andric     if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) {
23955ffd83dbSDimitry Andric       auto *ExistingGetter = CatDecl->getClassInterface()->lookupMethod(
23965ffd83dbSDimitry Andric           property->getGetterName(), !IsClassProperty, true, false, CatDecl);
23975ffd83dbSDimitry Andric       if (ExistingGetter) {
23985ffd83dbSDimitry Andric         if (ExistingGetter->isDirectMethod() || property->isDirectProperty()) {
23995ffd83dbSDimitry Andric           Diag(property->getLocation(), diag::err_objc_direct_duplicate_decl)
24005ffd83dbSDimitry Andric               << property->isDirectProperty() << 1 /* property */
24015ffd83dbSDimitry Andric               << ExistingGetter->isDirectMethod()
24025ffd83dbSDimitry Andric               << ExistingGetter->getDeclName();
24035ffd83dbSDimitry Andric           Diag(ExistingGetter->getLocation(), diag::note_previous_declaration);
24045ffd83dbSDimitry Andric         }
24055ffd83dbSDimitry Andric       }
24065ffd83dbSDimitry Andric     }
24075ffd83dbSDimitry Andric   }
24085ffd83dbSDimitry Andric 
24095ffd83dbSDimitry Andric   if (!property->isReadOnly() && !SetterMethod) {
24105ffd83dbSDimitry Andric     if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) {
24115ffd83dbSDimitry Andric       auto *ExistingSetter = CatDecl->getClassInterface()->lookupMethod(
24125ffd83dbSDimitry Andric           property->getSetterName(), !IsClassProperty, true, false, CatDecl);
24135ffd83dbSDimitry Andric       if (ExistingSetter) {
24145ffd83dbSDimitry Andric         if (ExistingSetter->isDirectMethod() || property->isDirectProperty()) {
24155ffd83dbSDimitry Andric           Diag(property->getLocation(), diag::err_objc_direct_duplicate_decl)
24165ffd83dbSDimitry Andric               << property->isDirectProperty() << 1 /* property */
24175ffd83dbSDimitry Andric               << ExistingSetter->isDirectMethod()
24185ffd83dbSDimitry Andric               << ExistingSetter->getDeclName();
24195ffd83dbSDimitry Andric           Diag(ExistingSetter->getLocation(), diag::note_previous_declaration);
24205ffd83dbSDimitry Andric         }
24215ffd83dbSDimitry Andric       }
24225ffd83dbSDimitry Andric     }
24235ffd83dbSDimitry Andric   }
24245ffd83dbSDimitry Andric 
24250b57cec5SDimitry Andric   if (!property->isReadOnly() && SetterMethod) {
24260b57cec5SDimitry Andric     if (Context.getCanonicalType(SetterMethod->getReturnType()) !=
24270b57cec5SDimitry Andric         Context.VoidTy)
24280b57cec5SDimitry Andric       Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
24290b57cec5SDimitry Andric     if (SetterMethod->param_size() != 1 ||
24300b57cec5SDimitry Andric         !Context.hasSameUnqualifiedType(
24310b57cec5SDimitry Andric           (*SetterMethod->param_begin())->getType().getNonReferenceType(),
24320b57cec5SDimitry Andric           property->getType().getNonReferenceType())) {
24330b57cec5SDimitry Andric       Diag(property->getLocation(),
24340b57cec5SDimitry Andric            diag::warn_accessor_property_type_mismatch)
24350b57cec5SDimitry Andric         << property->getDeclName()
24360b57cec5SDimitry Andric         << SetterMethod->getSelector();
24370b57cec5SDimitry Andric       Diag(SetterMethod->getLocation(), diag::note_declared_at);
24380b57cec5SDimitry Andric     }
24390b57cec5SDimitry Andric   }
24400b57cec5SDimitry Andric 
24410b57cec5SDimitry Andric   // Synthesize getter/setter methods if none exist.
24420b57cec5SDimitry Andric   // Find the default getter and if one not found, add one.
24430b57cec5SDimitry Andric   // FIXME: The synthesized property we set here is misleading. We almost always
24440b57cec5SDimitry Andric   // synthesize these methods unless the user explicitly provided prototypes
24450b57cec5SDimitry Andric   // (which is odd, but allowed). Sema should be typechecking that the
24460b57cec5SDimitry Andric   // declarations jive in that situation (which it is not currently).
24470b57cec5SDimitry Andric   if (!GetterMethod) {
24480b57cec5SDimitry Andric     // No instance/class method of same name as property getter name was found.
24490b57cec5SDimitry Andric     // Declare a getter method and add it to the list of methods
24500b57cec5SDimitry Andric     // for this class.
24510b57cec5SDimitry Andric     SourceLocation Loc = property->getLocation();
24520b57cec5SDimitry Andric 
24530b57cec5SDimitry Andric     // The getter returns the declared property type with all qualifiers
24540b57cec5SDimitry Andric     // removed.
24550b57cec5SDimitry Andric     QualType resultTy = property->getType().getAtomicUnqualifiedType();
24560b57cec5SDimitry Andric 
24570b57cec5SDimitry Andric     // If the property is null_resettable, the getter returns nonnull.
24580b57cec5SDimitry Andric     if (property->getPropertyAttributes() &
24595ffd83dbSDimitry Andric         ObjCPropertyAttribute::kind_null_resettable) {
24600b57cec5SDimitry Andric       QualType modifiedTy = resultTy;
24610b57cec5SDimitry Andric       if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
24620b57cec5SDimitry Andric         if (*nullability == NullabilityKind::Unspecified)
24630b57cec5SDimitry Andric           resultTy = Context.getAttributedType(attr::TypeNonNull,
24640b57cec5SDimitry Andric                                                modifiedTy, modifiedTy);
24650b57cec5SDimitry Andric       }
24660b57cec5SDimitry Andric     }
24670b57cec5SDimitry Andric 
2468480093f4SDimitry Andric     GetterMethod = ObjCMethodDecl::Create(
2469480093f4SDimitry Andric         Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD,
24700b57cec5SDimitry Andric         !IsClassProperty, /*isVariadic=*/false,
2471480093f4SDimitry Andric         /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
24720b57cec5SDimitry Andric         /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
2473480093f4SDimitry Andric         (property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
24745f757f3fSDimitry Andric             ? ObjCImplementationControl::Optional
24755f757f3fSDimitry Andric             : ObjCImplementationControl::Required);
24760b57cec5SDimitry Andric     CD->addDecl(GetterMethod);
24770b57cec5SDimitry Andric 
2478*0fca6ea1SDimitry Andric     AddPropertyAttrs(SemaRef, GetterMethod, property);
24790b57cec5SDimitry Andric 
2480480093f4SDimitry Andric     if (property->isDirectProperty())
2481480093f4SDimitry Andric       GetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc));
2482480093f4SDimitry Andric 
24830b57cec5SDimitry Andric     if (property->hasAttr<NSReturnsNotRetainedAttr>())
24840b57cec5SDimitry Andric       GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
24850b57cec5SDimitry Andric                                                                      Loc));
24860b57cec5SDimitry Andric 
24870b57cec5SDimitry Andric     if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
24880b57cec5SDimitry Andric       GetterMethod->addAttr(
24890b57cec5SDimitry Andric         ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
24900b57cec5SDimitry Andric 
24910b57cec5SDimitry Andric     if (const SectionAttr *SA = property->getAttr<SectionAttr>())
2492a7dea167SDimitry Andric       GetterMethod->addAttr(SectionAttr::CreateImplicit(
249306c3fb27SDimitry Andric           Context, SA->getName(), Loc, SectionAttr::GNU_section));
24940b57cec5SDimitry Andric 
2495*0fca6ea1SDimitry Andric     SemaRef.ProcessAPINotes(GetterMethod);
2496*0fca6ea1SDimitry Andric 
24970b57cec5SDimitry Andric     if (getLangOpts().ObjCAutoRefCount)
24980b57cec5SDimitry Andric       CheckARCMethodDecl(GetterMethod);
24990b57cec5SDimitry Andric   } else
25000b57cec5SDimitry Andric     // A user declared getter will be synthesize when @synthesize of
25010b57cec5SDimitry Andric     // the property with the same name is seen in the @implementation
25020b57cec5SDimitry Andric     GetterMethod->setPropertyAccessor(true);
2503480093f4SDimitry Andric 
2504480093f4SDimitry Andric   GetterMethod->createImplicitParams(Context,
2505480093f4SDimitry Andric                                      GetterMethod->getClassInterface());
25060b57cec5SDimitry Andric   property->setGetterMethodDecl(GetterMethod);
25070b57cec5SDimitry Andric 
25080b57cec5SDimitry Andric   // Skip setter if property is read-only.
25090b57cec5SDimitry Andric   if (!property->isReadOnly()) {
25100b57cec5SDimitry Andric     // Find the default setter and if one not found, add one.
25110b57cec5SDimitry Andric     if (!SetterMethod) {
25120b57cec5SDimitry Andric       // No instance/class method of same name as property setter name was
25130b57cec5SDimitry Andric       // found.
25140b57cec5SDimitry Andric       // Declare a setter method and add it to the list of methods
25150b57cec5SDimitry Andric       // for this class.
25160b57cec5SDimitry Andric       SourceLocation Loc = property->getLocation();
25170b57cec5SDimitry Andric 
25185f757f3fSDimitry Andric       SetterMethod = ObjCMethodDecl::Create(
25195f757f3fSDimitry Andric           Context, Loc, Loc, property->getSetterName(), Context.VoidTy, nullptr,
25205f757f3fSDimitry Andric           CD, !IsClassProperty,
25210b57cec5SDimitry Andric           /*isVariadic=*/false,
25220b57cec5SDimitry Andric           /*isPropertyAccessor=*/true,
2523480093f4SDimitry Andric           /*isSynthesizedAccessorStub=*/false,
25240b57cec5SDimitry Andric           /*isImplicitlyDeclared=*/true,
25250b57cec5SDimitry Andric           /*isDefined=*/false,
25265f757f3fSDimitry Andric           (property->getPropertyImplementation() == ObjCPropertyDecl::Optional)
25275f757f3fSDimitry Andric               ? ObjCImplementationControl::Optional
25285f757f3fSDimitry Andric               : ObjCImplementationControl::Required);
25290b57cec5SDimitry Andric 
25300b57cec5SDimitry Andric       // Remove all qualifiers from the setter's parameter type.
25310b57cec5SDimitry Andric       QualType paramTy =
25320b57cec5SDimitry Andric           property->getType().getUnqualifiedType().getAtomicUnqualifiedType();
25330b57cec5SDimitry Andric 
25340b57cec5SDimitry Andric       // If the property is null_resettable, the setter accepts a
25350b57cec5SDimitry Andric       // nullable value.
25360b57cec5SDimitry Andric       if (property->getPropertyAttributes() &
25375ffd83dbSDimitry Andric           ObjCPropertyAttribute::kind_null_resettable) {
25380b57cec5SDimitry Andric         QualType modifiedTy = paramTy;
25390b57cec5SDimitry Andric         if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
25400b57cec5SDimitry Andric           if (*nullability == NullabilityKind::Unspecified)
25410b57cec5SDimitry Andric             paramTy = Context.getAttributedType(attr::TypeNullable,
25420b57cec5SDimitry Andric                                                 modifiedTy, modifiedTy);
25430b57cec5SDimitry Andric         }
25440b57cec5SDimitry Andric       }
25450b57cec5SDimitry Andric 
25460b57cec5SDimitry Andric       // Invent the arguments for the setter. We don't bother making a
25470b57cec5SDimitry Andric       // nice name for the argument.
25480b57cec5SDimitry Andric       ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
25490b57cec5SDimitry Andric                                                   Loc, Loc,
25500b57cec5SDimitry Andric                                                   property->getIdentifier(),
25510b57cec5SDimitry Andric                                                   paramTy,
25520b57cec5SDimitry Andric                                                   /*TInfo=*/nullptr,
25530b57cec5SDimitry Andric                                                   SC_None,
25540b57cec5SDimitry Andric                                                   nullptr);
2555bdd1243dSDimitry Andric       SetterMethod->setMethodParams(Context, Argument, std::nullopt);
25560b57cec5SDimitry Andric 
2557*0fca6ea1SDimitry Andric       AddPropertyAttrs(SemaRef, SetterMethod, property);
25580b57cec5SDimitry Andric 
2559480093f4SDimitry Andric       if (property->isDirectProperty())
2560480093f4SDimitry Andric         SetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc));
2561480093f4SDimitry Andric 
25620b57cec5SDimitry Andric       CD->addDecl(SetterMethod);
25630b57cec5SDimitry Andric       if (const SectionAttr *SA = property->getAttr<SectionAttr>())
2564a7dea167SDimitry Andric         SetterMethod->addAttr(SectionAttr::CreateImplicit(
256506c3fb27SDimitry Andric             Context, SA->getName(), Loc, SectionAttr::GNU_section));
2566*0fca6ea1SDimitry Andric 
2567*0fca6ea1SDimitry Andric       SemaRef.ProcessAPINotes(SetterMethod);
2568*0fca6ea1SDimitry Andric 
25690b57cec5SDimitry Andric       // It's possible for the user to have set a very odd custom
25700b57cec5SDimitry Andric       // setter selector that causes it to have a method family.
25710b57cec5SDimitry Andric       if (getLangOpts().ObjCAutoRefCount)
25720b57cec5SDimitry Andric         CheckARCMethodDecl(SetterMethod);
25730b57cec5SDimitry Andric     } else
25740b57cec5SDimitry Andric       // A user declared setter will be synthesize when @synthesize of
25750b57cec5SDimitry Andric       // the property with the same name is seen in the @implementation
25760b57cec5SDimitry Andric       SetterMethod->setPropertyAccessor(true);
2577480093f4SDimitry Andric 
2578480093f4SDimitry Andric     SetterMethod->createImplicitParams(Context,
2579480093f4SDimitry Andric                                        SetterMethod->getClassInterface());
25800b57cec5SDimitry Andric     property->setSetterMethodDecl(SetterMethod);
25810b57cec5SDimitry Andric   }
25820b57cec5SDimitry Andric   // Add any synthesized methods to the global pool. This allows us to
25830b57cec5SDimitry Andric   // handle the following, which is supported by GCC (and part of the design).
25840b57cec5SDimitry Andric   //
25850b57cec5SDimitry Andric   // @interface Foo
25860b57cec5SDimitry Andric   // @property double bar;
25870b57cec5SDimitry Andric   // @end
25880b57cec5SDimitry Andric   //
25890b57cec5SDimitry Andric   // void thisIsUnfortunate() {
25900b57cec5SDimitry Andric   //   id foo;
25910b57cec5SDimitry Andric   //   double bar = [foo bar];
25920b57cec5SDimitry Andric   // }
25930b57cec5SDimitry Andric   //
25940b57cec5SDimitry Andric   if (!IsClassProperty) {
25950b57cec5SDimitry Andric     if (GetterMethod)
25960b57cec5SDimitry Andric       AddInstanceMethodToGlobalPool(GetterMethod);
25970b57cec5SDimitry Andric     if (SetterMethod)
25980b57cec5SDimitry Andric       AddInstanceMethodToGlobalPool(SetterMethod);
25990b57cec5SDimitry Andric   } else {
26000b57cec5SDimitry Andric     if (GetterMethod)
26010b57cec5SDimitry Andric       AddFactoryMethodToGlobalPool(GetterMethod);
26020b57cec5SDimitry Andric     if (SetterMethod)
26030b57cec5SDimitry Andric       AddFactoryMethodToGlobalPool(SetterMethod);
26040b57cec5SDimitry Andric   }
26050b57cec5SDimitry Andric 
26060b57cec5SDimitry Andric   ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD);
26070b57cec5SDimitry Andric   if (!CurrentClass) {
26080b57cec5SDimitry Andric     if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CD))
26090b57cec5SDimitry Andric       CurrentClass = Cat->getClassInterface();
26100b57cec5SDimitry Andric     else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(CD))
26110b57cec5SDimitry Andric       CurrentClass = Impl->getClassInterface();
26120b57cec5SDimitry Andric   }
26130b57cec5SDimitry Andric   if (GetterMethod)
2614*0fca6ea1SDimitry Andric     CheckObjCMethodOverrides(GetterMethod, CurrentClass, SemaObjC::RTC_Unknown);
26150b57cec5SDimitry Andric   if (SetterMethod)
2616*0fca6ea1SDimitry Andric     CheckObjCMethodOverrides(SetterMethod, CurrentClass, SemaObjC::RTC_Unknown);
26170b57cec5SDimitry Andric }
26180b57cec5SDimitry Andric 
2619*0fca6ea1SDimitry Andric void SemaObjC::CheckObjCPropertyAttributes(Decl *PDecl, SourceLocation Loc,
26200b57cec5SDimitry Andric                                            unsigned &Attributes,
26210b57cec5SDimitry Andric                                            bool propertyInPrimaryClass) {
26220b57cec5SDimitry Andric   // FIXME: Improve the reported location.
26230b57cec5SDimitry Andric   if (!PDecl || PDecl->isInvalidDecl())
26240b57cec5SDimitry Andric     return;
26250b57cec5SDimitry Andric 
26265ffd83dbSDimitry Andric   if ((Attributes & ObjCPropertyAttribute::kind_readonly) &&
26275ffd83dbSDimitry Andric       (Attributes & ObjCPropertyAttribute::kind_readwrite))
26280b57cec5SDimitry Andric     Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
26290b57cec5SDimitry Andric     << "readonly" << "readwrite";
26300b57cec5SDimitry Andric 
26310b57cec5SDimitry Andric   ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
26320b57cec5SDimitry Andric   QualType PropertyTy = PropertyDecl->getType();
26330b57cec5SDimitry Andric 
26340b57cec5SDimitry Andric   // Check for copy or retain on non-object types.
26355ffd83dbSDimitry Andric   if ((Attributes &
26365ffd83dbSDimitry Andric        (ObjCPropertyAttribute::kind_weak | ObjCPropertyAttribute::kind_copy |
26375ffd83dbSDimitry Andric         ObjCPropertyAttribute::kind_retain |
26385ffd83dbSDimitry Andric         ObjCPropertyAttribute::kind_strong)) &&
26390b57cec5SDimitry Andric       !PropertyTy->isObjCRetainableType() &&
26400b57cec5SDimitry Andric       !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) {
26410b57cec5SDimitry Andric     Diag(Loc, diag::err_objc_property_requires_object)
26425ffd83dbSDimitry Andric         << (Attributes & ObjCPropertyAttribute::kind_weak
26435ffd83dbSDimitry Andric                 ? "weak"
26445ffd83dbSDimitry Andric                 : Attributes & ObjCPropertyAttribute::kind_copy
26455ffd83dbSDimitry Andric                       ? "copy"
26465ffd83dbSDimitry Andric                       : "retain (or strong)");
26475ffd83dbSDimitry Andric     Attributes &=
26485ffd83dbSDimitry Andric         ~(ObjCPropertyAttribute::kind_weak | ObjCPropertyAttribute::kind_copy |
26495ffd83dbSDimitry Andric           ObjCPropertyAttribute::kind_retain |
26505ffd83dbSDimitry Andric           ObjCPropertyAttribute::kind_strong);
26510b57cec5SDimitry Andric     PropertyDecl->setInvalidDecl();
26520b57cec5SDimitry Andric   }
26530b57cec5SDimitry Andric 
26540b57cec5SDimitry Andric   // Check for assign on object types.
26555ffd83dbSDimitry Andric   if ((Attributes & ObjCPropertyAttribute::kind_assign) &&
26565ffd83dbSDimitry Andric       !(Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) &&
26570b57cec5SDimitry Andric       PropertyTy->isObjCRetainableType() &&
26580b57cec5SDimitry Andric       !PropertyTy->isObjCARCImplicitlyUnretainedType()) {
26590b57cec5SDimitry Andric     Diag(Loc, diag::warn_objc_property_assign_on_object);
26600b57cec5SDimitry Andric   }
26610b57cec5SDimitry Andric 
26620b57cec5SDimitry Andric   // Check for more than one of { assign, copy, retain }.
26635ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_assign) {
26645ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_copy) {
26650b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
26660b57cec5SDimitry Andric         << "assign" << "copy";
26675ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_copy;
26680b57cec5SDimitry Andric     }
26695ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_retain) {
26700b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
26710b57cec5SDimitry Andric         << "assign" << "retain";
26725ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_retain;
26730b57cec5SDimitry Andric     }
26745ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_strong) {
26750b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
26760b57cec5SDimitry Andric         << "assign" << "strong";
26775ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_strong;
26780b57cec5SDimitry Andric     }
26790b57cec5SDimitry Andric     if (getLangOpts().ObjCAutoRefCount &&
26805ffd83dbSDimitry Andric         (Attributes & ObjCPropertyAttribute::kind_weak)) {
26810b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
26820b57cec5SDimitry Andric         << "assign" << "weak";
26835ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_weak;
26840b57cec5SDimitry Andric     }
26850b57cec5SDimitry Andric     if (PropertyDecl->hasAttr<IBOutletCollectionAttr>())
26860b57cec5SDimitry Andric       Diag(Loc, diag::warn_iboutletcollection_property_assign);
26875ffd83dbSDimitry Andric   } else if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) {
26885ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_copy) {
26890b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
26900b57cec5SDimitry Andric         << "unsafe_unretained" << "copy";
26915ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_copy;
26920b57cec5SDimitry Andric     }
26935ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_retain) {
26940b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
26950b57cec5SDimitry Andric         << "unsafe_unretained" << "retain";
26965ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_retain;
26970b57cec5SDimitry Andric     }
26985ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_strong) {
26990b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
27000b57cec5SDimitry Andric         << "unsafe_unretained" << "strong";
27015ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_strong;
27020b57cec5SDimitry Andric     }
27030b57cec5SDimitry Andric     if (getLangOpts().ObjCAutoRefCount &&
27045ffd83dbSDimitry Andric         (Attributes & ObjCPropertyAttribute::kind_weak)) {
27050b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
27060b57cec5SDimitry Andric         << "unsafe_unretained" << "weak";
27075ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_weak;
27080b57cec5SDimitry Andric     }
27095ffd83dbSDimitry Andric   } else if (Attributes & ObjCPropertyAttribute::kind_copy) {
27105ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_retain) {
27110b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
27120b57cec5SDimitry Andric         << "copy" << "retain";
27135ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_retain;
27140b57cec5SDimitry Andric     }
27155ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_strong) {
27160b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
27170b57cec5SDimitry Andric         << "copy" << "strong";
27185ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_strong;
27190b57cec5SDimitry Andric     }
27205ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_weak) {
27210b57cec5SDimitry Andric       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
27220b57cec5SDimitry Andric         << "copy" << "weak";
27235ffd83dbSDimitry Andric       Attributes &= ~ObjCPropertyAttribute::kind_weak;
27240b57cec5SDimitry Andric     }
27255ffd83dbSDimitry Andric   } else if ((Attributes & ObjCPropertyAttribute::kind_retain) &&
27265ffd83dbSDimitry Andric              (Attributes & ObjCPropertyAttribute::kind_weak)) {
27275ffd83dbSDimitry Andric     Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "retain"
27285ffd83dbSDimitry Andric                                                                << "weak";
27295ffd83dbSDimitry Andric     Attributes &= ~ObjCPropertyAttribute::kind_retain;
27305ffd83dbSDimitry Andric   } else if ((Attributes & ObjCPropertyAttribute::kind_strong) &&
27315ffd83dbSDimitry Andric              (Attributes & ObjCPropertyAttribute::kind_weak)) {
27325ffd83dbSDimitry Andric     Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "strong"
27335ffd83dbSDimitry Andric                                                                << "weak";
27345ffd83dbSDimitry Andric     Attributes &= ~ObjCPropertyAttribute::kind_weak;
27350b57cec5SDimitry Andric   }
27360b57cec5SDimitry Andric 
27375ffd83dbSDimitry Andric   if (Attributes & ObjCPropertyAttribute::kind_weak) {
27380b57cec5SDimitry Andric     // 'weak' and 'nonnull' are mutually exclusive.
2739bdd1243dSDimitry Andric     if (auto nullability = PropertyTy->getNullability()) {
27400b57cec5SDimitry Andric       if (*nullability == NullabilityKind::NonNull)
27410b57cec5SDimitry Andric         Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
27420b57cec5SDimitry Andric           << "nonnull" << "weak";
27430b57cec5SDimitry Andric     }
27440b57cec5SDimitry Andric   }
27450b57cec5SDimitry Andric 
27465ffd83dbSDimitry Andric   if ((Attributes & ObjCPropertyAttribute::kind_atomic) &&
27475ffd83dbSDimitry Andric       (Attributes & ObjCPropertyAttribute::kind_nonatomic)) {
27485ffd83dbSDimitry Andric     Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "atomic"
27495ffd83dbSDimitry Andric                                                                << "nonatomic";
27505ffd83dbSDimitry Andric     Attributes &= ~ObjCPropertyAttribute::kind_atomic;
27510b57cec5SDimitry Andric   }
27520b57cec5SDimitry Andric 
27530b57cec5SDimitry Andric   // Warn if user supplied no assignment attribute, property is
27540b57cec5SDimitry Andric   // readwrite, and this is an object type.
27550b57cec5SDimitry Andric   if (!getOwnershipRule(Attributes) && PropertyTy->isObjCRetainableType()) {
27565ffd83dbSDimitry Andric     if (Attributes & ObjCPropertyAttribute::kind_readonly) {
27570b57cec5SDimitry Andric       // do nothing
27580b57cec5SDimitry Andric     } else if (getLangOpts().ObjCAutoRefCount) {
27590b57cec5SDimitry Andric       // With arc, @property definitions should default to strong when
27600b57cec5SDimitry Andric       // not specified.
27615ffd83dbSDimitry Andric       PropertyDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
27620b57cec5SDimitry Andric     } else if (PropertyTy->isObjCObjectPointerType()) {
27635ffd83dbSDimitry Andric       bool isAnyClassTy = (PropertyTy->isObjCClassType() ||
27640b57cec5SDimitry Andric                            PropertyTy->isObjCQualifiedClassType());
27650b57cec5SDimitry Andric       // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
27660b57cec5SDimitry Andric       // issue any warning.
27670b57cec5SDimitry Andric       if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC)
27680b57cec5SDimitry Andric         ;
27690b57cec5SDimitry Andric       else if (propertyInPrimaryClass) {
27700b57cec5SDimitry Andric         // Don't issue warning on property with no life time in class
27710b57cec5SDimitry Andric         // extension as it is inherited from property in primary class.
27720b57cec5SDimitry Andric         // Skip this warning in gc-only mode.
27730b57cec5SDimitry Andric         if (getLangOpts().getGC() != LangOptions::GCOnly)
27740b57cec5SDimitry Andric           Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
27750b57cec5SDimitry Andric 
27760b57cec5SDimitry Andric         // If non-gc code warn that this is likely inappropriate.
27770b57cec5SDimitry Andric         if (getLangOpts().getGC() == LangOptions::NonGC)
27780b57cec5SDimitry Andric           Diag(Loc, diag::warn_objc_property_default_assign_on_object);
27790b57cec5SDimitry Andric       }
27800b57cec5SDimitry Andric     }
27810b57cec5SDimitry Andric 
27820b57cec5SDimitry Andric     // FIXME: Implement warning dependent on NSCopying being
27835f757f3fSDimitry Andric     // implemented.
27840b57cec5SDimitry Andric   }
27850b57cec5SDimitry Andric 
27865ffd83dbSDimitry Andric   if (!(Attributes & ObjCPropertyAttribute::kind_copy) &&
27875ffd83dbSDimitry Andric       !(Attributes & ObjCPropertyAttribute::kind_readonly) &&
27885ffd83dbSDimitry Andric       getLangOpts().getGC() == LangOptions::GCOnly &&
27895ffd83dbSDimitry Andric       PropertyTy->isBlockPointerType())
27900b57cec5SDimitry Andric     Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
27915ffd83dbSDimitry Andric   else if ((Attributes & ObjCPropertyAttribute::kind_retain) &&
27925ffd83dbSDimitry Andric            !(Attributes & ObjCPropertyAttribute::kind_readonly) &&
27935ffd83dbSDimitry Andric            !(Attributes & ObjCPropertyAttribute::kind_strong) &&
27940b57cec5SDimitry Andric            PropertyTy->isBlockPointerType())
27950b57cec5SDimitry Andric     Diag(Loc, diag::warn_objc_property_retain_of_block);
27960b57cec5SDimitry Andric 
27975ffd83dbSDimitry Andric   if ((Attributes & ObjCPropertyAttribute::kind_readonly) &&
27985ffd83dbSDimitry Andric       (Attributes & ObjCPropertyAttribute::kind_setter))
27990b57cec5SDimitry Andric     Diag(Loc, diag::warn_objc_readonly_property_has_setter);
28000b57cec5SDimitry Andric }
2801