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