xref: /minix3/external/bsd/llvm/dist/clang/lib/Sema/SemaObjCProperty.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc //  This file implements semantic analysis for Objective C @property and
11f4a2713aSLionel Sambuc //  @synthesize declarations.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "clang/Sema/SemaInternal.h"
16f4a2713aSLionel Sambuc #include "clang/AST/ASTMutationListener.h"
17f4a2713aSLionel Sambuc #include "clang/AST/DeclObjC.h"
18f4a2713aSLionel Sambuc #include "clang/AST/ExprCXX.h"
19f4a2713aSLionel Sambuc #include "clang/AST/ExprObjC.h"
20f4a2713aSLionel Sambuc #include "clang/Basic/SourceManager.h"
21f4a2713aSLionel Sambuc #include "clang/Lex/Lexer.h"
22f4a2713aSLionel Sambuc #include "clang/Sema/Initialization.h"
23f4a2713aSLionel Sambuc #include "llvm/ADT/DenseSet.h"
24f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
25f4a2713aSLionel Sambuc 
26f4a2713aSLionel Sambuc using namespace clang;
27f4a2713aSLionel Sambuc 
28f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
29f4a2713aSLionel Sambuc // Grammar actions.
30f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
31f4a2713aSLionel Sambuc 
32f4a2713aSLionel Sambuc /// getImpliedARCOwnership - Given a set of property attributes and a
33f4a2713aSLionel Sambuc /// type, infer an expected lifetime.  The type's ownership qualification
34f4a2713aSLionel Sambuc /// is not considered.
35f4a2713aSLionel Sambuc ///
36f4a2713aSLionel Sambuc /// Returns OCL_None if the attributes as stated do not imply an ownership.
37f4a2713aSLionel Sambuc /// Never returns OCL_Autoreleasing.
getImpliedARCOwnership(ObjCPropertyDecl::PropertyAttributeKind attrs,QualType type)38f4a2713aSLionel Sambuc static Qualifiers::ObjCLifetime getImpliedARCOwnership(
39f4a2713aSLionel Sambuc                                ObjCPropertyDecl::PropertyAttributeKind attrs,
40f4a2713aSLionel Sambuc                                                 QualType type) {
41f4a2713aSLionel Sambuc   // retain, strong, copy, weak, and unsafe_unretained are only legal
42f4a2713aSLionel Sambuc   // on properties of retainable pointer type.
43f4a2713aSLionel Sambuc   if (attrs & (ObjCPropertyDecl::OBJC_PR_retain |
44f4a2713aSLionel Sambuc                ObjCPropertyDecl::OBJC_PR_strong |
45f4a2713aSLionel Sambuc                ObjCPropertyDecl::OBJC_PR_copy)) {
46f4a2713aSLionel Sambuc     return Qualifiers::OCL_Strong;
47f4a2713aSLionel Sambuc   } else if (attrs & ObjCPropertyDecl::OBJC_PR_weak) {
48f4a2713aSLionel Sambuc     return Qualifiers::OCL_Weak;
49f4a2713aSLionel Sambuc   } else if (attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) {
50f4a2713aSLionel Sambuc     return Qualifiers::OCL_ExplicitNone;
51f4a2713aSLionel Sambuc   }
52f4a2713aSLionel Sambuc 
53f4a2713aSLionel Sambuc   // assign can appear on other types, so we have to check the
54f4a2713aSLionel Sambuc   // property type.
55f4a2713aSLionel Sambuc   if (attrs & ObjCPropertyDecl::OBJC_PR_assign &&
56f4a2713aSLionel Sambuc       type->isObjCRetainableType()) {
57f4a2713aSLionel Sambuc     return Qualifiers::OCL_ExplicitNone;
58f4a2713aSLionel Sambuc   }
59f4a2713aSLionel Sambuc 
60f4a2713aSLionel Sambuc   return Qualifiers::OCL_None;
61f4a2713aSLionel Sambuc }
62f4a2713aSLionel Sambuc 
63f4a2713aSLionel Sambuc /// Check the internal consistency of a property declaration.
checkARCPropertyDecl(Sema & S,ObjCPropertyDecl * property)64f4a2713aSLionel Sambuc static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
65f4a2713aSLionel Sambuc   if (property->isInvalidDecl()) return;
66f4a2713aSLionel Sambuc 
67f4a2713aSLionel Sambuc   ObjCPropertyDecl::PropertyAttributeKind propertyKind
68f4a2713aSLionel Sambuc     = property->getPropertyAttributes();
69f4a2713aSLionel Sambuc   Qualifiers::ObjCLifetime propertyLifetime
70f4a2713aSLionel Sambuc     = property->getType().getObjCLifetime();
71f4a2713aSLionel Sambuc 
72f4a2713aSLionel Sambuc   // Nothing to do if we don't have a lifetime.
73f4a2713aSLionel Sambuc   if (propertyLifetime == Qualifiers::OCL_None) return;
74f4a2713aSLionel Sambuc 
75f4a2713aSLionel Sambuc   Qualifiers::ObjCLifetime expectedLifetime
76f4a2713aSLionel Sambuc     = getImpliedARCOwnership(propertyKind, property->getType());
77f4a2713aSLionel Sambuc   if (!expectedLifetime) {
78f4a2713aSLionel Sambuc     // We have a lifetime qualifier but no dominating property
79f4a2713aSLionel Sambuc     // attribute.  That's okay, but restore reasonable invariants by
80f4a2713aSLionel Sambuc     // setting the property attribute according to the lifetime
81f4a2713aSLionel Sambuc     // qualifier.
82f4a2713aSLionel Sambuc     ObjCPropertyDecl::PropertyAttributeKind attr;
83f4a2713aSLionel Sambuc     if (propertyLifetime == Qualifiers::OCL_Strong) {
84f4a2713aSLionel Sambuc       attr = ObjCPropertyDecl::OBJC_PR_strong;
85f4a2713aSLionel Sambuc     } else if (propertyLifetime == Qualifiers::OCL_Weak) {
86f4a2713aSLionel Sambuc       attr = ObjCPropertyDecl::OBJC_PR_weak;
87f4a2713aSLionel Sambuc     } else {
88f4a2713aSLionel Sambuc       assert(propertyLifetime == Qualifiers::OCL_ExplicitNone);
89f4a2713aSLionel Sambuc       attr = ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
90f4a2713aSLionel Sambuc     }
91f4a2713aSLionel Sambuc     property->setPropertyAttributes(attr);
92f4a2713aSLionel Sambuc     return;
93f4a2713aSLionel Sambuc   }
94f4a2713aSLionel Sambuc 
95f4a2713aSLionel Sambuc   if (propertyLifetime == expectedLifetime) return;
96f4a2713aSLionel Sambuc 
97f4a2713aSLionel Sambuc   property->setInvalidDecl();
98f4a2713aSLionel Sambuc   S.Diag(property->getLocation(),
99f4a2713aSLionel Sambuc          diag::err_arc_inconsistent_property_ownership)
100f4a2713aSLionel Sambuc     << property->getDeclName()
101f4a2713aSLionel Sambuc     << expectedLifetime
102f4a2713aSLionel Sambuc     << propertyLifetime;
103f4a2713aSLionel Sambuc }
104f4a2713aSLionel Sambuc 
deduceWeakPropertyFromType(Sema & S,QualType T)105f4a2713aSLionel Sambuc static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) {
106f4a2713aSLionel Sambuc   if ((S.getLangOpts().getGC() != LangOptions::NonGC &&
107f4a2713aSLionel Sambuc        T.isObjCGCWeak()) ||
108f4a2713aSLionel Sambuc       (S.getLangOpts().ObjCAutoRefCount &&
109f4a2713aSLionel Sambuc        T.getObjCLifetime() == Qualifiers::OCL_Weak))
110f4a2713aSLionel Sambuc     return ObjCDeclSpec::DQ_PR_weak;
111f4a2713aSLionel Sambuc   return 0;
112f4a2713aSLionel Sambuc }
113f4a2713aSLionel Sambuc 
114f4a2713aSLionel Sambuc /// \brief Check this Objective-C property against a property declared in the
115f4a2713aSLionel Sambuc /// given protocol.
116f4a2713aSLionel Sambuc static void
CheckPropertyAgainstProtocol(Sema & S,ObjCPropertyDecl * Prop,ObjCProtocolDecl * Proto,llvm::SmallPtrSetImpl<ObjCProtocolDecl * > & Known)117f4a2713aSLionel Sambuc CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
118f4a2713aSLionel Sambuc                              ObjCProtocolDecl *Proto,
119*0a6a1f1dSLionel Sambuc                              llvm::SmallPtrSetImpl<ObjCProtocolDecl *> &Known) {
120f4a2713aSLionel Sambuc   // Have we seen this protocol before?
121*0a6a1f1dSLionel Sambuc   if (!Known.insert(Proto).second)
122f4a2713aSLionel Sambuc     return;
123f4a2713aSLionel Sambuc 
124f4a2713aSLionel Sambuc   // Look for a property with the same name.
125f4a2713aSLionel Sambuc   DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName());
126f4a2713aSLionel Sambuc   for (unsigned I = 0, N = R.size(); I != N; ++I) {
127f4a2713aSLionel Sambuc     if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
128f4a2713aSLionel Sambuc       S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(), true);
129f4a2713aSLionel Sambuc       return;
130f4a2713aSLionel Sambuc     }
131f4a2713aSLionel Sambuc   }
132f4a2713aSLionel Sambuc 
133f4a2713aSLionel Sambuc   // Check this property against any protocols we inherit.
134*0a6a1f1dSLionel Sambuc   for (auto *P : Proto->protocols())
135*0a6a1f1dSLionel Sambuc     CheckPropertyAgainstProtocol(S, Prop, P, Known);
136f4a2713aSLionel Sambuc }
137f4a2713aSLionel Sambuc 
ActOnProperty(Scope * S,SourceLocation AtLoc,SourceLocation LParenLoc,FieldDeclarator & FD,ObjCDeclSpec & ODS,Selector GetterSel,Selector SetterSel,bool * isOverridingProperty,tok::ObjCKeywordKind MethodImplKind,DeclContext * lexicalDC)138f4a2713aSLionel Sambuc Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
139f4a2713aSLionel Sambuc                           SourceLocation LParenLoc,
140f4a2713aSLionel Sambuc                           FieldDeclarator &FD,
141f4a2713aSLionel Sambuc                           ObjCDeclSpec &ODS,
142f4a2713aSLionel Sambuc                           Selector GetterSel,
143f4a2713aSLionel Sambuc                           Selector SetterSel,
144f4a2713aSLionel Sambuc                           bool *isOverridingProperty,
145f4a2713aSLionel Sambuc                           tok::ObjCKeywordKind MethodImplKind,
146f4a2713aSLionel Sambuc                           DeclContext *lexicalDC) {
147f4a2713aSLionel Sambuc   unsigned Attributes = ODS.getPropertyAttributes();
148f4a2713aSLionel Sambuc   TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
149f4a2713aSLionel Sambuc   QualType T = TSI->getType();
150f4a2713aSLionel Sambuc   Attributes |= deduceWeakPropertyFromType(*this, T);
151f4a2713aSLionel Sambuc 
152f4a2713aSLionel Sambuc   bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
153f4a2713aSLionel Sambuc                       // default is readwrite!
154f4a2713aSLionel Sambuc                       !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
155f4a2713aSLionel Sambuc   // property is defaulted to 'assign' if it is readwrite and is
156f4a2713aSLionel Sambuc   // not retain or copy
157f4a2713aSLionel Sambuc   bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
158f4a2713aSLionel Sambuc                    (isReadWrite &&
159f4a2713aSLionel Sambuc                     !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
160f4a2713aSLionel Sambuc                     !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
161f4a2713aSLionel Sambuc                     !(Attributes & ObjCDeclSpec::DQ_PR_copy) &&
162f4a2713aSLionel Sambuc                     !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) &&
163f4a2713aSLionel Sambuc                     !(Attributes & ObjCDeclSpec::DQ_PR_weak)));
164f4a2713aSLionel Sambuc 
165f4a2713aSLionel Sambuc   // Proceed with constructing the ObjCPropertyDecls.
166f4a2713aSLionel Sambuc   ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
167*0a6a1f1dSLionel Sambuc   ObjCPropertyDecl *Res = nullptr;
168f4a2713aSLionel Sambuc   if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
169f4a2713aSLionel Sambuc     if (CDecl->IsClassExtension()) {
170f4a2713aSLionel Sambuc       Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
171f4a2713aSLionel Sambuc                                            FD, GetterSel, SetterSel,
172f4a2713aSLionel Sambuc                                            isAssign, isReadWrite,
173f4a2713aSLionel Sambuc                                            Attributes,
174f4a2713aSLionel Sambuc                                            ODS.getPropertyAttributes(),
175f4a2713aSLionel Sambuc                                            isOverridingProperty, TSI,
176f4a2713aSLionel Sambuc                                            MethodImplKind);
177f4a2713aSLionel Sambuc       if (!Res)
178*0a6a1f1dSLionel Sambuc         return nullptr;
179f4a2713aSLionel Sambuc     }
180f4a2713aSLionel Sambuc   }
181f4a2713aSLionel Sambuc 
182f4a2713aSLionel Sambuc   if (!Res) {
183f4a2713aSLionel Sambuc     Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
184f4a2713aSLionel Sambuc                              GetterSel, SetterSel, isAssign, isReadWrite,
185f4a2713aSLionel Sambuc                              Attributes, ODS.getPropertyAttributes(),
186f4a2713aSLionel Sambuc                              TSI, MethodImplKind);
187f4a2713aSLionel Sambuc     if (lexicalDC)
188f4a2713aSLionel Sambuc       Res->setLexicalDeclContext(lexicalDC);
189f4a2713aSLionel Sambuc   }
190f4a2713aSLionel Sambuc 
191f4a2713aSLionel Sambuc   // Validate the attributes on the @property.
192f4a2713aSLionel Sambuc   CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
193f4a2713aSLionel Sambuc                               (isa<ObjCInterfaceDecl>(ClassDecl) ||
194f4a2713aSLionel Sambuc                                isa<ObjCProtocolDecl>(ClassDecl)));
195f4a2713aSLionel Sambuc 
196f4a2713aSLionel Sambuc   if (getLangOpts().ObjCAutoRefCount)
197f4a2713aSLionel Sambuc     checkARCPropertyDecl(*this, Res);
198f4a2713aSLionel Sambuc 
199f4a2713aSLionel Sambuc   llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos;
200f4a2713aSLionel Sambuc   if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
201f4a2713aSLionel Sambuc     // For a class, compare the property against a property in our superclass.
202f4a2713aSLionel Sambuc     bool FoundInSuper = false;
203*0a6a1f1dSLionel Sambuc     ObjCInterfaceDecl *CurrentInterfaceDecl = IFace;
204*0a6a1f1dSLionel Sambuc     while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) {
205f4a2713aSLionel Sambuc       DeclContext::lookup_result R = Super->lookup(Res->getDeclName());
206f4a2713aSLionel Sambuc       for (unsigned I = 0, N = R.size(); I != N; ++I) {
207f4a2713aSLionel Sambuc         if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
208f4a2713aSLionel Sambuc           DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
209f4a2713aSLionel Sambuc           FoundInSuper = true;
210f4a2713aSLionel Sambuc           break;
211f4a2713aSLionel Sambuc         }
212f4a2713aSLionel Sambuc       }
213*0a6a1f1dSLionel Sambuc       if (FoundInSuper)
214*0a6a1f1dSLionel Sambuc         break;
215*0a6a1f1dSLionel Sambuc       else
216*0a6a1f1dSLionel Sambuc         CurrentInterfaceDecl = Super;
217f4a2713aSLionel Sambuc     }
218f4a2713aSLionel Sambuc 
219f4a2713aSLionel Sambuc     if (FoundInSuper) {
220f4a2713aSLionel Sambuc       // Also compare the property against a property in our protocols.
221*0a6a1f1dSLionel Sambuc       for (auto *P : CurrentInterfaceDecl->protocols()) {
222*0a6a1f1dSLionel Sambuc         CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
223f4a2713aSLionel Sambuc       }
224f4a2713aSLionel Sambuc     } else {
225f4a2713aSLionel Sambuc       // Slower path: look in all protocols we referenced.
226*0a6a1f1dSLionel Sambuc       for (auto *P : IFace->all_referenced_protocols()) {
227*0a6a1f1dSLionel Sambuc         CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
228f4a2713aSLionel Sambuc       }
229f4a2713aSLionel Sambuc     }
230f4a2713aSLionel Sambuc   } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
231*0a6a1f1dSLionel Sambuc     for (auto *P : Cat->protocols())
232*0a6a1f1dSLionel Sambuc       CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
233f4a2713aSLionel Sambuc   } else {
234f4a2713aSLionel Sambuc     ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
235*0a6a1f1dSLionel Sambuc     for (auto *P : Proto->protocols())
236*0a6a1f1dSLionel Sambuc       CheckPropertyAgainstProtocol(*this, Res, P, KnownProtos);
237f4a2713aSLionel Sambuc   }
238f4a2713aSLionel Sambuc 
239f4a2713aSLionel Sambuc   ActOnDocumentableDecl(Res);
240f4a2713aSLionel Sambuc   return Res;
241f4a2713aSLionel Sambuc }
242f4a2713aSLionel Sambuc 
243f4a2713aSLionel Sambuc static ObjCPropertyDecl::PropertyAttributeKind
makePropertyAttributesAsWritten(unsigned Attributes)244f4a2713aSLionel Sambuc makePropertyAttributesAsWritten(unsigned Attributes) {
245f4a2713aSLionel Sambuc   unsigned attributesAsWritten = 0;
246f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
247f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly;
248f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
249f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite;
250f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_getter)
251f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter;
252f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_setter)
253f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter;
254f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_assign)
255f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign;
256f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_retain)
257f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain;
258f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_strong)
259f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong;
260f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_weak)
261f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak;
262f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_copy)
263f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy;
264f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
265f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
266f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
267f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic;
268f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
269f4a2713aSLionel Sambuc     attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic;
270f4a2713aSLionel Sambuc 
271f4a2713aSLionel Sambuc   return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten;
272f4a2713aSLionel Sambuc }
273f4a2713aSLionel Sambuc 
LocPropertyAttribute(ASTContext & Context,const char * attrName,SourceLocation LParenLoc,SourceLocation & Loc)274f4a2713aSLionel Sambuc static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
275f4a2713aSLionel Sambuc                                  SourceLocation LParenLoc, SourceLocation &Loc) {
276f4a2713aSLionel Sambuc   if (LParenLoc.isMacroID())
277f4a2713aSLionel Sambuc     return false;
278f4a2713aSLionel Sambuc 
279f4a2713aSLionel Sambuc   SourceManager &SM = Context.getSourceManager();
280f4a2713aSLionel Sambuc   std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(LParenLoc);
281f4a2713aSLionel Sambuc   // Try to load the file buffer.
282f4a2713aSLionel Sambuc   bool invalidTemp = false;
283f4a2713aSLionel Sambuc   StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
284f4a2713aSLionel Sambuc   if (invalidTemp)
285f4a2713aSLionel Sambuc     return false;
286f4a2713aSLionel Sambuc   const char *tokenBegin = file.data() + locInfo.second;
287f4a2713aSLionel Sambuc 
288f4a2713aSLionel Sambuc   // Lex from the start of the given location.
289f4a2713aSLionel Sambuc   Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
290f4a2713aSLionel Sambuc               Context.getLangOpts(),
291f4a2713aSLionel Sambuc               file.begin(), tokenBegin, file.end());
292f4a2713aSLionel Sambuc   Token Tok;
293f4a2713aSLionel Sambuc   do {
294f4a2713aSLionel Sambuc     lexer.LexFromRawLexer(Tok);
295*0a6a1f1dSLionel Sambuc     if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) {
296f4a2713aSLionel Sambuc       Loc = Tok.getLocation();
297f4a2713aSLionel Sambuc       return true;
298f4a2713aSLionel Sambuc     }
299f4a2713aSLionel Sambuc   } while (Tok.isNot(tok::r_paren));
300f4a2713aSLionel Sambuc   return false;
301f4a2713aSLionel Sambuc 
302f4a2713aSLionel Sambuc }
303f4a2713aSLionel Sambuc 
getOwnershipRule(unsigned attr)304f4a2713aSLionel Sambuc static unsigned getOwnershipRule(unsigned attr) {
305f4a2713aSLionel Sambuc   return attr & (ObjCPropertyDecl::OBJC_PR_assign |
306f4a2713aSLionel Sambuc                  ObjCPropertyDecl::OBJC_PR_retain |
307f4a2713aSLionel Sambuc                  ObjCPropertyDecl::OBJC_PR_copy   |
308f4a2713aSLionel Sambuc                  ObjCPropertyDecl::OBJC_PR_weak   |
309f4a2713aSLionel Sambuc                  ObjCPropertyDecl::OBJC_PR_strong |
310f4a2713aSLionel Sambuc                  ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
311f4a2713aSLionel Sambuc }
312f4a2713aSLionel Sambuc 
313f4a2713aSLionel Sambuc ObjCPropertyDecl *
HandlePropertyInClassExtension(Scope * S,SourceLocation AtLoc,SourceLocation LParenLoc,FieldDeclarator & FD,Selector GetterSel,Selector SetterSel,const bool isAssign,const bool isReadWrite,const unsigned Attributes,const unsigned AttributesAsWritten,bool * isOverridingProperty,TypeSourceInfo * T,tok::ObjCKeywordKind MethodImplKind)314f4a2713aSLionel Sambuc Sema::HandlePropertyInClassExtension(Scope *S,
315f4a2713aSLionel Sambuc                                      SourceLocation AtLoc,
316f4a2713aSLionel Sambuc                                      SourceLocation LParenLoc,
317f4a2713aSLionel Sambuc                                      FieldDeclarator &FD,
318f4a2713aSLionel Sambuc                                      Selector GetterSel, Selector SetterSel,
319f4a2713aSLionel Sambuc                                      const bool isAssign,
320f4a2713aSLionel Sambuc                                      const bool isReadWrite,
321f4a2713aSLionel Sambuc                                      const unsigned Attributes,
322f4a2713aSLionel Sambuc                                      const unsigned AttributesAsWritten,
323f4a2713aSLionel Sambuc                                      bool *isOverridingProperty,
324f4a2713aSLionel Sambuc                                      TypeSourceInfo *T,
325f4a2713aSLionel Sambuc                                      tok::ObjCKeywordKind MethodImplKind) {
326f4a2713aSLionel Sambuc   ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext);
327f4a2713aSLionel Sambuc   // Diagnose if this property is already in continuation class.
328f4a2713aSLionel Sambuc   DeclContext *DC = CurContext;
329f4a2713aSLionel Sambuc   IdentifierInfo *PropertyId = FD.D.getIdentifier();
330f4a2713aSLionel Sambuc   ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
331f4a2713aSLionel Sambuc 
332f4a2713aSLionel Sambuc   if (CCPrimary) {
333f4a2713aSLionel Sambuc     // Check for duplicate declaration of this property in current and
334f4a2713aSLionel Sambuc     // other class extensions.
335*0a6a1f1dSLionel Sambuc     for (const auto *Ext : CCPrimary->known_extensions()) {
336f4a2713aSLionel Sambuc       if (ObjCPropertyDecl *prevDecl
337*0a6a1f1dSLionel Sambuc             = ObjCPropertyDecl::findPropertyDecl(Ext, PropertyId)) {
338f4a2713aSLionel Sambuc         Diag(AtLoc, diag::err_duplicate_property);
339f4a2713aSLionel Sambuc         Diag(prevDecl->getLocation(), diag::note_property_declare);
340*0a6a1f1dSLionel Sambuc         return nullptr;
341f4a2713aSLionel Sambuc       }
342f4a2713aSLionel Sambuc     }
343f4a2713aSLionel Sambuc   }
344f4a2713aSLionel Sambuc 
345f4a2713aSLionel Sambuc   // Create a new ObjCPropertyDecl with the DeclContext being
346f4a2713aSLionel Sambuc   // the class extension.
347f4a2713aSLionel Sambuc   // FIXME. We should really be using CreatePropertyDecl for this.
348f4a2713aSLionel Sambuc   ObjCPropertyDecl *PDecl =
349f4a2713aSLionel Sambuc     ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
350f4a2713aSLionel Sambuc                              PropertyId, AtLoc, LParenLoc, T);
351f4a2713aSLionel Sambuc   PDecl->setPropertyAttributesAsWritten(
352f4a2713aSLionel Sambuc                           makePropertyAttributesAsWritten(AttributesAsWritten));
353f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
354f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
355f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
356f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
357f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
358f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
359f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
360f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
361f4a2713aSLionel Sambuc   // Set setter/getter selector name. Needed later.
362f4a2713aSLionel Sambuc   PDecl->setGetterName(GetterSel);
363f4a2713aSLionel Sambuc   PDecl->setSetterName(SetterSel);
364f4a2713aSLionel Sambuc   ProcessDeclAttributes(S, PDecl, FD.D);
365f4a2713aSLionel Sambuc   DC->addDecl(PDecl);
366f4a2713aSLionel Sambuc 
367f4a2713aSLionel Sambuc   // We need to look in the @interface to see if the @property was
368f4a2713aSLionel Sambuc   // already declared.
369f4a2713aSLionel Sambuc   if (!CCPrimary) {
370f4a2713aSLionel Sambuc     Diag(CDecl->getLocation(), diag::err_continuation_class);
371f4a2713aSLionel Sambuc     *isOverridingProperty = true;
372*0a6a1f1dSLionel Sambuc     return nullptr;
373f4a2713aSLionel Sambuc   }
374f4a2713aSLionel Sambuc 
375f4a2713aSLionel Sambuc   // Find the property in continuation class's primary class only.
376f4a2713aSLionel Sambuc   ObjCPropertyDecl *PIDecl =
377f4a2713aSLionel Sambuc     CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
378f4a2713aSLionel Sambuc 
379f4a2713aSLionel Sambuc   if (!PIDecl) {
380f4a2713aSLionel Sambuc     // No matching property found in the primary class. Just fall thru
381f4a2713aSLionel Sambuc     // and add property to continuation class's primary class.
382f4a2713aSLionel Sambuc     ObjCPropertyDecl *PrimaryPDecl =
383f4a2713aSLionel Sambuc       CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,
384f4a2713aSLionel Sambuc                          FD, GetterSel, SetterSel, isAssign, isReadWrite,
385f4a2713aSLionel Sambuc                          Attributes,AttributesAsWritten, T, MethodImplKind, DC);
386f4a2713aSLionel Sambuc 
387f4a2713aSLionel Sambuc     // A case of continuation class adding a new property in the class. This
388f4a2713aSLionel Sambuc     // is not what it was meant for. However, gcc supports it and so should we.
389f4a2713aSLionel Sambuc     // Make sure setter/getters are declared here.
390*0a6a1f1dSLionel Sambuc     ProcessPropertyDecl(PrimaryPDecl, CCPrimary,
391*0a6a1f1dSLionel Sambuc                         /* redeclaredProperty = */ nullptr,
392f4a2713aSLionel Sambuc                         /* lexicalDC = */ CDecl);
393f4a2713aSLionel Sambuc     PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());
394f4a2713aSLionel Sambuc     PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());
395f4a2713aSLionel Sambuc     if (ASTMutationListener *L = Context.getASTMutationListener())
396*0a6a1f1dSLionel Sambuc       L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/nullptr,
397*0a6a1f1dSLionel Sambuc                                            CDecl);
398f4a2713aSLionel Sambuc     return PrimaryPDecl;
399f4a2713aSLionel Sambuc   }
400f4a2713aSLionel Sambuc   if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
401f4a2713aSLionel Sambuc     bool IncompatibleObjC = false;
402f4a2713aSLionel Sambuc     QualType ConvertedType;
403f4a2713aSLionel Sambuc     // Relax the strict type matching for property type in continuation class.
404f4a2713aSLionel Sambuc     // Allow property object type of continuation class to be different as long
405f4a2713aSLionel Sambuc     // as it narrows the object type in its primary class property. Note that
406f4a2713aSLionel Sambuc     // this conversion is safe only because the wider type is for a 'readonly'
407f4a2713aSLionel Sambuc     // property in primary class and 'narrowed' type for a 'readwrite' property
408f4a2713aSLionel Sambuc     // in continuation class.
409f4a2713aSLionel Sambuc     if (!isa<ObjCObjectPointerType>(PIDecl->getType()) ||
410f4a2713aSLionel Sambuc         !isa<ObjCObjectPointerType>(PDecl->getType()) ||
411f4a2713aSLionel Sambuc         (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(),
412f4a2713aSLionel Sambuc                                   ConvertedType, IncompatibleObjC))
413f4a2713aSLionel Sambuc         || IncompatibleObjC) {
414f4a2713aSLionel Sambuc       Diag(AtLoc,
415f4a2713aSLionel Sambuc           diag::err_type_mismatch_continuation_class) << PDecl->getType();
416f4a2713aSLionel Sambuc       Diag(PIDecl->getLocation(), diag::note_property_declare);
417*0a6a1f1dSLionel Sambuc       return nullptr;
418f4a2713aSLionel Sambuc     }
419f4a2713aSLionel Sambuc   }
420f4a2713aSLionel Sambuc 
421f4a2713aSLionel Sambuc   // The property 'PIDecl's readonly attribute will be over-ridden
422f4a2713aSLionel Sambuc   // with continuation class's readwrite property attribute!
423f4a2713aSLionel Sambuc   unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
424f4a2713aSLionel Sambuc   if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
425f4a2713aSLionel Sambuc     PIkind &= ~ObjCPropertyDecl::OBJC_PR_readonly;
426f4a2713aSLionel Sambuc     PIkind |= ObjCPropertyDecl::OBJC_PR_readwrite;
427f4a2713aSLionel Sambuc     PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType());
428f4a2713aSLionel Sambuc     unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
429f4a2713aSLionel Sambuc     unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
430f4a2713aSLionel Sambuc     if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&
431f4a2713aSLionel Sambuc         (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {
432f4a2713aSLionel Sambuc       Diag(AtLoc, diag::warn_property_attr_mismatch);
433f4a2713aSLionel Sambuc       Diag(PIDecl->getLocation(), diag::note_property_declare);
434f4a2713aSLionel Sambuc     }
435f4a2713aSLionel Sambuc     else if (getLangOpts().ObjCAutoRefCount) {
436f4a2713aSLionel Sambuc       QualType PrimaryPropertyQT =
437f4a2713aSLionel Sambuc         Context.getCanonicalType(PIDecl->getType()).getUnqualifiedType();
438f4a2713aSLionel Sambuc       if (isa<ObjCObjectPointerType>(PrimaryPropertyQT)) {
439f4a2713aSLionel Sambuc         bool PropertyIsWeak = ((PIkind & ObjCPropertyDecl::OBJC_PR_weak) != 0);
440f4a2713aSLionel Sambuc         Qualifiers::ObjCLifetime PrimaryPropertyLifeTime =
441f4a2713aSLionel Sambuc           PrimaryPropertyQT.getObjCLifetime();
442f4a2713aSLionel Sambuc         if (PrimaryPropertyLifeTime == Qualifiers::OCL_None &&
443f4a2713aSLionel Sambuc             (Attributes & ObjCDeclSpec::DQ_PR_weak) &&
444f4a2713aSLionel Sambuc             !PropertyIsWeak) {
445f4a2713aSLionel Sambuc               Diag(AtLoc, diag::warn_property_implicitly_mismatched);
446f4a2713aSLionel Sambuc               Diag(PIDecl->getLocation(), diag::note_property_declare);
447f4a2713aSLionel Sambuc             }
448f4a2713aSLionel Sambuc         }
449f4a2713aSLionel Sambuc     }
450f4a2713aSLionel Sambuc 
451f4a2713aSLionel Sambuc     DeclContext *DC = cast<DeclContext>(CCPrimary);
452f4a2713aSLionel Sambuc     if (!ObjCPropertyDecl::findPropertyDecl(DC,
453f4a2713aSLionel Sambuc                                  PIDecl->getDeclName().getAsIdentifierInfo())) {
454*0a6a1f1dSLionel Sambuc       // In mrr mode, 'readwrite' property must have an explicit
455*0a6a1f1dSLionel Sambuc       // memory attribute. If none specified, select the default (assign).
456*0a6a1f1dSLionel Sambuc       if (!getLangOpts().ObjCAutoRefCount) {
457*0a6a1f1dSLionel Sambuc         if (!(PIkind & (ObjCDeclSpec::DQ_PR_assign |
458*0a6a1f1dSLionel Sambuc                         ObjCDeclSpec::DQ_PR_retain |
459*0a6a1f1dSLionel Sambuc                         ObjCDeclSpec::DQ_PR_strong |
460*0a6a1f1dSLionel Sambuc                         ObjCDeclSpec::DQ_PR_copy |
461*0a6a1f1dSLionel Sambuc                         ObjCDeclSpec::DQ_PR_unsafe_unretained |
462*0a6a1f1dSLionel Sambuc                         ObjCDeclSpec::DQ_PR_weak)))
463*0a6a1f1dSLionel Sambuc           PIkind |= ObjCPropertyDecl::OBJC_PR_assign;
464*0a6a1f1dSLionel Sambuc       }
465*0a6a1f1dSLionel Sambuc 
466f4a2713aSLionel Sambuc       // Protocol is not in the primary class. Must build one for it.
467f4a2713aSLionel Sambuc       ObjCDeclSpec ProtocolPropertyODS;
468f4a2713aSLionel Sambuc       // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
469f4a2713aSLionel Sambuc       // and ObjCPropertyDecl::PropertyAttributeKind have identical
470f4a2713aSLionel Sambuc       // values.  Should consolidate both into one enum type.
471f4a2713aSLionel Sambuc       ProtocolPropertyODS.
472f4a2713aSLionel Sambuc       setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
473f4a2713aSLionel Sambuc                             PIkind);
474f4a2713aSLionel Sambuc       // Must re-establish the context from class extension to primary
475f4a2713aSLionel Sambuc       // class context.
476f4a2713aSLionel Sambuc       ContextRAII SavedContext(*this, CCPrimary);
477f4a2713aSLionel Sambuc 
478f4a2713aSLionel Sambuc       Decl *ProtocolPtrTy =
479f4a2713aSLionel Sambuc         ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS,
480f4a2713aSLionel Sambuc                       PIDecl->getGetterName(),
481f4a2713aSLionel Sambuc                       PIDecl->getSetterName(),
482f4a2713aSLionel Sambuc                       isOverridingProperty,
483f4a2713aSLionel Sambuc                       MethodImplKind,
484f4a2713aSLionel Sambuc                       /* lexicalDC = */ CDecl);
485f4a2713aSLionel Sambuc       PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
486f4a2713aSLionel Sambuc     }
487f4a2713aSLionel Sambuc     PIDecl->makeitReadWriteAttribute();
488f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_retain)
489f4a2713aSLionel Sambuc       PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
490f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_strong)
491f4a2713aSLionel Sambuc       PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
492f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_copy)
493f4a2713aSLionel Sambuc       PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
494f4a2713aSLionel Sambuc     PIDecl->setSetterName(SetterSel);
495f4a2713aSLionel Sambuc   } else {
496f4a2713aSLionel Sambuc     // Tailor the diagnostics for the common case where a readwrite
497f4a2713aSLionel Sambuc     // property is declared both in the @interface and the continuation.
498f4a2713aSLionel Sambuc     // This is a common error where the user often intended the original
499f4a2713aSLionel Sambuc     // declaration to be readonly.
500f4a2713aSLionel Sambuc     unsigned diag =
501f4a2713aSLionel Sambuc       (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
502f4a2713aSLionel Sambuc       (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite)
503f4a2713aSLionel Sambuc       ? diag::err_use_continuation_class_redeclaration_readwrite
504f4a2713aSLionel Sambuc       : diag::err_use_continuation_class;
505f4a2713aSLionel Sambuc     Diag(AtLoc, diag)
506f4a2713aSLionel Sambuc       << CCPrimary->getDeclName();
507f4a2713aSLionel Sambuc     Diag(PIDecl->getLocation(), diag::note_property_declare);
508*0a6a1f1dSLionel Sambuc     return nullptr;
509f4a2713aSLionel Sambuc   }
510f4a2713aSLionel Sambuc   *isOverridingProperty = true;
511f4a2713aSLionel Sambuc   // Make sure setter decl is synthesized, and added to primary class's list.
512f4a2713aSLionel Sambuc   ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);
513f4a2713aSLionel Sambuc   PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl());
514f4a2713aSLionel Sambuc   PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl());
515f4a2713aSLionel Sambuc   if (ASTMutationListener *L = Context.getASTMutationListener())
516f4a2713aSLionel Sambuc     L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl);
517f4a2713aSLionel Sambuc   return PDecl;
518f4a2713aSLionel Sambuc }
519f4a2713aSLionel Sambuc 
CreatePropertyDecl(Scope * S,ObjCContainerDecl * CDecl,SourceLocation AtLoc,SourceLocation LParenLoc,FieldDeclarator & FD,Selector GetterSel,Selector SetterSel,const bool isAssign,const bool isReadWrite,const unsigned Attributes,const unsigned AttributesAsWritten,TypeSourceInfo * TInfo,tok::ObjCKeywordKind MethodImplKind,DeclContext * lexicalDC)520f4a2713aSLionel Sambuc ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
521f4a2713aSLionel Sambuc                                            ObjCContainerDecl *CDecl,
522f4a2713aSLionel Sambuc                                            SourceLocation AtLoc,
523f4a2713aSLionel Sambuc                                            SourceLocation LParenLoc,
524f4a2713aSLionel Sambuc                                            FieldDeclarator &FD,
525f4a2713aSLionel Sambuc                                            Selector GetterSel,
526f4a2713aSLionel Sambuc                                            Selector SetterSel,
527f4a2713aSLionel Sambuc                                            const bool isAssign,
528f4a2713aSLionel Sambuc                                            const bool isReadWrite,
529f4a2713aSLionel Sambuc                                            const unsigned Attributes,
530f4a2713aSLionel Sambuc                                            const unsigned AttributesAsWritten,
531f4a2713aSLionel Sambuc                                            TypeSourceInfo *TInfo,
532f4a2713aSLionel Sambuc                                            tok::ObjCKeywordKind MethodImplKind,
533f4a2713aSLionel Sambuc                                            DeclContext *lexicalDC){
534f4a2713aSLionel Sambuc   IdentifierInfo *PropertyId = FD.D.getIdentifier();
535f4a2713aSLionel Sambuc   QualType T = TInfo->getType();
536f4a2713aSLionel Sambuc 
537f4a2713aSLionel Sambuc   // Issue a warning if property is 'assign' as default and its object, which is
538f4a2713aSLionel Sambuc   // gc'able conforms to NSCopying protocol
539f4a2713aSLionel Sambuc   if (getLangOpts().getGC() != LangOptions::NonGC &&
540f4a2713aSLionel Sambuc       isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
541f4a2713aSLionel Sambuc     if (const ObjCObjectPointerType *ObjPtrTy =
542f4a2713aSLionel Sambuc           T->getAs<ObjCObjectPointerType>()) {
543f4a2713aSLionel Sambuc       ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
544f4a2713aSLionel Sambuc       if (IDecl)
545f4a2713aSLionel Sambuc         if (ObjCProtocolDecl* PNSCopying =
546f4a2713aSLionel Sambuc             LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
547f4a2713aSLionel Sambuc           if (IDecl->ClassImplementsProtocol(PNSCopying, true))
548f4a2713aSLionel Sambuc             Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
549f4a2713aSLionel Sambuc     }
550f4a2713aSLionel Sambuc 
551f4a2713aSLionel Sambuc   if (T->isObjCObjectType()) {
552f4a2713aSLionel Sambuc     SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd();
553*0a6a1f1dSLionel Sambuc     StarLoc = getLocForEndOfToken(StarLoc);
554f4a2713aSLionel Sambuc     Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
555f4a2713aSLionel Sambuc       << FixItHint::CreateInsertion(StarLoc, "*");
556f4a2713aSLionel Sambuc     T = Context.getObjCObjectPointerType(T);
557f4a2713aSLionel Sambuc     SourceLocation TLoc = TInfo->getTypeLoc().getLocStart();
558f4a2713aSLionel Sambuc     TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
559f4a2713aSLionel Sambuc   }
560f4a2713aSLionel Sambuc 
561f4a2713aSLionel Sambuc   DeclContext *DC = cast<DeclContext>(CDecl);
562f4a2713aSLionel Sambuc   ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
563f4a2713aSLionel Sambuc                                                      FD.D.getIdentifierLoc(),
564f4a2713aSLionel Sambuc                                                      PropertyId, AtLoc, LParenLoc, TInfo);
565f4a2713aSLionel Sambuc 
566f4a2713aSLionel Sambuc   if (ObjCPropertyDecl *prevDecl =
567f4a2713aSLionel Sambuc         ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
568f4a2713aSLionel Sambuc     Diag(PDecl->getLocation(), diag::err_duplicate_property);
569f4a2713aSLionel Sambuc     Diag(prevDecl->getLocation(), diag::note_property_declare);
570f4a2713aSLionel Sambuc     PDecl->setInvalidDecl();
571f4a2713aSLionel Sambuc   }
572f4a2713aSLionel Sambuc   else {
573f4a2713aSLionel Sambuc     DC->addDecl(PDecl);
574f4a2713aSLionel Sambuc     if (lexicalDC)
575f4a2713aSLionel Sambuc       PDecl->setLexicalDeclContext(lexicalDC);
576f4a2713aSLionel Sambuc   }
577f4a2713aSLionel Sambuc 
578f4a2713aSLionel Sambuc   if (T->isArrayType() || T->isFunctionType()) {
579f4a2713aSLionel Sambuc     Diag(AtLoc, diag::err_property_type) << T;
580f4a2713aSLionel Sambuc     PDecl->setInvalidDecl();
581f4a2713aSLionel Sambuc   }
582f4a2713aSLionel Sambuc 
583f4a2713aSLionel Sambuc   ProcessDeclAttributes(S, PDecl, FD.D);
584f4a2713aSLionel Sambuc 
585f4a2713aSLionel Sambuc   // Regardless of setter/getter attribute, we save the default getter/setter
586f4a2713aSLionel Sambuc   // selector names in anticipation of declaration of setter/getter methods.
587f4a2713aSLionel Sambuc   PDecl->setGetterName(GetterSel);
588f4a2713aSLionel Sambuc   PDecl->setSetterName(SetterSel);
589f4a2713aSLionel Sambuc   PDecl->setPropertyAttributesAsWritten(
590f4a2713aSLionel Sambuc                           makePropertyAttributesAsWritten(AttributesAsWritten));
591f4a2713aSLionel Sambuc 
592f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
593f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
594f4a2713aSLionel Sambuc 
595f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_getter)
596f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
597f4a2713aSLionel Sambuc 
598f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_setter)
599f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
600f4a2713aSLionel Sambuc 
601f4a2713aSLionel Sambuc   if (isReadWrite)
602f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
603f4a2713aSLionel Sambuc 
604f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_retain)
605f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
606f4a2713aSLionel Sambuc 
607f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_strong)
608f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
609f4a2713aSLionel Sambuc 
610f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_weak)
611f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak);
612f4a2713aSLionel Sambuc 
613f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_copy)
614f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
615f4a2713aSLionel Sambuc 
616f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
617f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
618f4a2713aSLionel Sambuc 
619f4a2713aSLionel Sambuc   if (isAssign)
620f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
621f4a2713aSLionel Sambuc 
622f4a2713aSLionel Sambuc   // In the semantic attributes, one of nonatomic or atomic is always set.
623f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
624f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
625f4a2713aSLionel Sambuc   else
626f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
627f4a2713aSLionel Sambuc 
628f4a2713aSLionel Sambuc   // 'unsafe_unretained' is alias for 'assign'.
629f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
630f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
631f4a2713aSLionel Sambuc   if (isAssign)
632f4a2713aSLionel Sambuc     PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
633f4a2713aSLionel Sambuc 
634f4a2713aSLionel Sambuc   if (MethodImplKind == tok::objc_required)
635f4a2713aSLionel Sambuc     PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
636f4a2713aSLionel Sambuc   else if (MethodImplKind == tok::objc_optional)
637f4a2713aSLionel Sambuc     PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
638f4a2713aSLionel Sambuc 
639f4a2713aSLionel Sambuc   return PDecl;
640f4a2713aSLionel Sambuc }
641f4a2713aSLionel Sambuc 
checkARCPropertyImpl(Sema & S,SourceLocation propertyImplLoc,ObjCPropertyDecl * property,ObjCIvarDecl * ivar)642f4a2713aSLionel Sambuc static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
643f4a2713aSLionel Sambuc                                  ObjCPropertyDecl *property,
644f4a2713aSLionel Sambuc                                  ObjCIvarDecl *ivar) {
645f4a2713aSLionel Sambuc   if (property->isInvalidDecl() || ivar->isInvalidDecl()) return;
646f4a2713aSLionel Sambuc 
647f4a2713aSLionel Sambuc   QualType ivarType = ivar->getType();
648f4a2713aSLionel Sambuc   Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
649f4a2713aSLionel Sambuc 
650f4a2713aSLionel Sambuc   // The lifetime implied by the property's attributes.
651f4a2713aSLionel Sambuc   Qualifiers::ObjCLifetime propertyLifetime =
652f4a2713aSLionel Sambuc     getImpliedARCOwnership(property->getPropertyAttributes(),
653f4a2713aSLionel Sambuc                            property->getType());
654f4a2713aSLionel Sambuc 
655f4a2713aSLionel Sambuc   // We're fine if they match.
656f4a2713aSLionel Sambuc   if (propertyLifetime == ivarLifetime) return;
657f4a2713aSLionel Sambuc 
658f4a2713aSLionel Sambuc   // These aren't valid lifetimes for object ivars;  don't diagnose twice.
659f4a2713aSLionel Sambuc   if (ivarLifetime == Qualifiers::OCL_None ||
660f4a2713aSLionel Sambuc       ivarLifetime == Qualifiers::OCL_Autoreleasing)
661f4a2713aSLionel Sambuc     return;
662f4a2713aSLionel Sambuc 
663f4a2713aSLionel Sambuc   // If the ivar is private, and it's implicitly __unsafe_unretained
664f4a2713aSLionel Sambuc   // becaues of its type, then pretend it was actually implicitly
665f4a2713aSLionel Sambuc   // __strong.  This is only sound because we're processing the
666f4a2713aSLionel Sambuc   // property implementation before parsing any method bodies.
667f4a2713aSLionel Sambuc   if (ivarLifetime == Qualifiers::OCL_ExplicitNone &&
668f4a2713aSLionel Sambuc       propertyLifetime == Qualifiers::OCL_Strong &&
669f4a2713aSLionel Sambuc       ivar->getAccessControl() == ObjCIvarDecl::Private) {
670f4a2713aSLionel Sambuc     SplitQualType split = ivarType.split();
671f4a2713aSLionel Sambuc     if (split.Quals.hasObjCLifetime()) {
672f4a2713aSLionel Sambuc       assert(ivarType->isObjCARCImplicitlyUnretainedType());
673f4a2713aSLionel Sambuc       split.Quals.setObjCLifetime(Qualifiers::OCL_Strong);
674f4a2713aSLionel Sambuc       ivarType = S.Context.getQualifiedType(split);
675f4a2713aSLionel Sambuc       ivar->setType(ivarType);
676f4a2713aSLionel Sambuc       return;
677f4a2713aSLionel Sambuc     }
678f4a2713aSLionel Sambuc   }
679f4a2713aSLionel Sambuc 
680f4a2713aSLionel Sambuc   switch (propertyLifetime) {
681f4a2713aSLionel Sambuc   case Qualifiers::OCL_Strong:
682f4a2713aSLionel Sambuc     S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership)
683f4a2713aSLionel Sambuc       << property->getDeclName()
684f4a2713aSLionel Sambuc       << ivar->getDeclName()
685f4a2713aSLionel Sambuc       << ivarLifetime;
686f4a2713aSLionel Sambuc     break;
687f4a2713aSLionel Sambuc 
688f4a2713aSLionel Sambuc   case Qualifiers::OCL_Weak:
689f4a2713aSLionel Sambuc     S.Diag(ivar->getLocation(), diag::error_weak_property)
690f4a2713aSLionel Sambuc       << property->getDeclName()
691f4a2713aSLionel Sambuc       << ivar->getDeclName();
692f4a2713aSLionel Sambuc     break;
693f4a2713aSLionel Sambuc 
694f4a2713aSLionel Sambuc   case Qualifiers::OCL_ExplicitNone:
695f4a2713aSLionel Sambuc     S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership)
696f4a2713aSLionel Sambuc       << property->getDeclName()
697f4a2713aSLionel Sambuc       << ivar->getDeclName()
698f4a2713aSLionel Sambuc       << ((property->getPropertyAttributesAsWritten()
699f4a2713aSLionel Sambuc            & ObjCPropertyDecl::OBJC_PR_assign) != 0);
700f4a2713aSLionel Sambuc     break;
701f4a2713aSLionel Sambuc 
702f4a2713aSLionel Sambuc   case Qualifiers::OCL_Autoreleasing:
703f4a2713aSLionel Sambuc     llvm_unreachable("properties cannot be autoreleasing");
704f4a2713aSLionel Sambuc 
705f4a2713aSLionel Sambuc   case Qualifiers::OCL_None:
706f4a2713aSLionel Sambuc     // Any other property should be ignored.
707f4a2713aSLionel Sambuc     return;
708f4a2713aSLionel Sambuc   }
709f4a2713aSLionel Sambuc 
710f4a2713aSLionel Sambuc   S.Diag(property->getLocation(), diag::note_property_declare);
711f4a2713aSLionel Sambuc   if (propertyImplLoc.isValid())
712f4a2713aSLionel Sambuc     S.Diag(propertyImplLoc, diag::note_property_synthesize);
713f4a2713aSLionel Sambuc }
714f4a2713aSLionel Sambuc 
715f4a2713aSLionel Sambuc /// setImpliedPropertyAttributeForReadOnlyProperty -
716f4a2713aSLionel Sambuc /// This routine evaludates life-time attributes for a 'readonly'
717f4a2713aSLionel Sambuc /// property with no known lifetime of its own, using backing
718f4a2713aSLionel Sambuc /// 'ivar's attribute, if any. If no backing 'ivar', property's
719f4a2713aSLionel Sambuc /// life-time is assumed 'strong'.
setImpliedPropertyAttributeForReadOnlyProperty(ObjCPropertyDecl * property,ObjCIvarDecl * ivar)720f4a2713aSLionel Sambuc static void setImpliedPropertyAttributeForReadOnlyProperty(
721f4a2713aSLionel Sambuc               ObjCPropertyDecl *property, ObjCIvarDecl *ivar) {
722f4a2713aSLionel Sambuc   Qualifiers::ObjCLifetime propertyLifetime =
723f4a2713aSLionel Sambuc     getImpliedARCOwnership(property->getPropertyAttributes(),
724f4a2713aSLionel Sambuc                            property->getType());
725f4a2713aSLionel Sambuc   if (propertyLifetime != Qualifiers::OCL_None)
726f4a2713aSLionel Sambuc     return;
727f4a2713aSLionel Sambuc 
728f4a2713aSLionel Sambuc   if (!ivar) {
729f4a2713aSLionel Sambuc     // if no backing ivar, make property 'strong'.
730f4a2713aSLionel Sambuc     property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
731f4a2713aSLionel Sambuc     return;
732f4a2713aSLionel Sambuc   }
733f4a2713aSLionel Sambuc   // property assumes owenership of backing ivar.
734f4a2713aSLionel Sambuc   QualType ivarType = ivar->getType();
735f4a2713aSLionel Sambuc   Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
736f4a2713aSLionel Sambuc   if (ivarLifetime == Qualifiers::OCL_Strong)
737f4a2713aSLionel Sambuc     property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
738f4a2713aSLionel Sambuc   else if (ivarLifetime == Qualifiers::OCL_Weak)
739f4a2713aSLionel Sambuc     property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak);
740f4a2713aSLionel Sambuc   return;
741f4a2713aSLionel Sambuc }
742f4a2713aSLionel Sambuc 
743f4a2713aSLionel Sambuc /// DiagnosePropertyMismatchDeclInProtocols - diagnose properties declared
744f4a2713aSLionel Sambuc /// in inherited protocols with mismatched types. Since any of them can
745f4a2713aSLionel Sambuc /// be candidate for synthesis.
746f4a2713aSLionel Sambuc static void
DiagnosePropertyMismatchDeclInProtocols(Sema & S,SourceLocation AtLoc,ObjCInterfaceDecl * ClassDecl,ObjCPropertyDecl * Property)747f4a2713aSLionel Sambuc DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc,
748f4a2713aSLionel Sambuc                                         ObjCInterfaceDecl *ClassDecl,
749f4a2713aSLionel Sambuc                                         ObjCPropertyDecl *Property) {
750f4a2713aSLionel Sambuc   ObjCInterfaceDecl::ProtocolPropertyMap PropMap;
751*0a6a1f1dSLionel Sambuc   for (const auto *PI : ClassDecl->all_referenced_protocols()) {
752*0a6a1f1dSLionel Sambuc     if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
753f4a2713aSLionel Sambuc       PDecl->collectInheritedProtocolProperties(Property, PropMap);
754f4a2713aSLionel Sambuc   }
755f4a2713aSLionel Sambuc   if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass())
756f4a2713aSLionel Sambuc     while (SDecl) {
757*0a6a1f1dSLionel Sambuc       for (const auto *PI : SDecl->all_referenced_protocols()) {
758*0a6a1f1dSLionel Sambuc         if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
759f4a2713aSLionel Sambuc           PDecl->collectInheritedProtocolProperties(Property, PropMap);
760f4a2713aSLionel Sambuc       }
761f4a2713aSLionel Sambuc       SDecl = SDecl->getSuperClass();
762f4a2713aSLionel Sambuc     }
763f4a2713aSLionel Sambuc 
764f4a2713aSLionel Sambuc   if (PropMap.empty())
765f4a2713aSLionel Sambuc     return;
766f4a2713aSLionel Sambuc 
767f4a2713aSLionel Sambuc   QualType RHSType = S.Context.getCanonicalType(Property->getType());
768f4a2713aSLionel Sambuc   bool FirsTime = true;
769f4a2713aSLionel Sambuc   for (ObjCInterfaceDecl::ProtocolPropertyMap::iterator
770f4a2713aSLionel Sambuc        I = PropMap.begin(), E = PropMap.end(); I != E; I++) {
771f4a2713aSLionel Sambuc     ObjCPropertyDecl *Prop = I->second;
772f4a2713aSLionel Sambuc     QualType LHSType = S.Context.getCanonicalType(Prop->getType());
773f4a2713aSLionel Sambuc     if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) {
774f4a2713aSLionel Sambuc       bool IncompatibleObjC = false;
775f4a2713aSLionel Sambuc       QualType ConvertedType;
776f4a2713aSLionel Sambuc       if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC)
777f4a2713aSLionel Sambuc           || IncompatibleObjC) {
778f4a2713aSLionel Sambuc         if (FirsTime) {
779f4a2713aSLionel Sambuc           S.Diag(Property->getLocation(), diag::warn_protocol_property_mismatch)
780f4a2713aSLionel Sambuc             << Property->getType();
781f4a2713aSLionel Sambuc           FirsTime = false;
782f4a2713aSLionel Sambuc         }
783f4a2713aSLionel Sambuc         S.Diag(Prop->getLocation(), diag::note_protocol_property_declare)
784f4a2713aSLionel Sambuc           << Prop->getType();
785f4a2713aSLionel Sambuc       }
786f4a2713aSLionel Sambuc     }
787f4a2713aSLionel Sambuc   }
788f4a2713aSLionel Sambuc   if (!FirsTime && AtLoc.isValid())
789f4a2713aSLionel Sambuc     S.Diag(AtLoc, diag::note_property_synthesize);
790f4a2713aSLionel Sambuc }
791f4a2713aSLionel Sambuc 
792f4a2713aSLionel Sambuc /// ActOnPropertyImplDecl - This routine performs semantic checks and
793f4a2713aSLionel Sambuc /// builds the AST node for a property implementation declaration; declared
794f4a2713aSLionel Sambuc /// as \@synthesize or \@dynamic.
795f4a2713aSLionel Sambuc ///
ActOnPropertyImplDecl(Scope * S,SourceLocation AtLoc,SourceLocation PropertyLoc,bool Synthesize,IdentifierInfo * PropertyId,IdentifierInfo * PropertyIvar,SourceLocation PropertyIvarLoc)796f4a2713aSLionel Sambuc Decl *Sema::ActOnPropertyImplDecl(Scope *S,
797f4a2713aSLionel Sambuc                                   SourceLocation AtLoc,
798f4a2713aSLionel Sambuc                                   SourceLocation PropertyLoc,
799f4a2713aSLionel Sambuc                                   bool Synthesize,
800f4a2713aSLionel Sambuc                                   IdentifierInfo *PropertyId,
801f4a2713aSLionel Sambuc                                   IdentifierInfo *PropertyIvar,
802f4a2713aSLionel Sambuc                                   SourceLocation PropertyIvarLoc) {
803f4a2713aSLionel Sambuc   ObjCContainerDecl *ClassImpDecl =
804f4a2713aSLionel Sambuc     dyn_cast<ObjCContainerDecl>(CurContext);
805f4a2713aSLionel Sambuc   // Make sure we have a context for the property implementation declaration.
806f4a2713aSLionel Sambuc   if (!ClassImpDecl) {
807f4a2713aSLionel Sambuc     Diag(AtLoc, diag::error_missing_property_context);
808*0a6a1f1dSLionel Sambuc     return nullptr;
809f4a2713aSLionel Sambuc   }
810f4a2713aSLionel Sambuc   if (PropertyIvarLoc.isInvalid())
811f4a2713aSLionel Sambuc     PropertyIvarLoc = PropertyLoc;
812f4a2713aSLionel Sambuc   SourceLocation PropertyDiagLoc = PropertyLoc;
813f4a2713aSLionel Sambuc   if (PropertyDiagLoc.isInvalid())
814f4a2713aSLionel Sambuc     PropertyDiagLoc = ClassImpDecl->getLocStart();
815*0a6a1f1dSLionel Sambuc   ObjCPropertyDecl *property = nullptr;
816*0a6a1f1dSLionel Sambuc   ObjCInterfaceDecl *IDecl = nullptr;
817f4a2713aSLionel Sambuc   // Find the class or category class where this property must have
818f4a2713aSLionel Sambuc   // a declaration.
819*0a6a1f1dSLionel Sambuc   ObjCImplementationDecl *IC = nullptr;
820*0a6a1f1dSLionel Sambuc   ObjCCategoryImplDecl *CatImplClass = nullptr;
821f4a2713aSLionel Sambuc   if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
822f4a2713aSLionel Sambuc     IDecl = IC->getClassInterface();
823f4a2713aSLionel Sambuc     // We always synthesize an interface for an implementation
824f4a2713aSLionel Sambuc     // without an interface decl. So, IDecl is always non-zero.
825f4a2713aSLionel Sambuc     assert(IDecl &&
826f4a2713aSLionel Sambuc            "ActOnPropertyImplDecl - @implementation without @interface");
827f4a2713aSLionel Sambuc 
828f4a2713aSLionel Sambuc     // Look for this property declaration in the @implementation's @interface
829f4a2713aSLionel Sambuc     property = IDecl->FindPropertyDeclaration(PropertyId);
830f4a2713aSLionel Sambuc     if (!property) {
831f4a2713aSLionel Sambuc       Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
832*0a6a1f1dSLionel Sambuc       return nullptr;
833f4a2713aSLionel Sambuc     }
834f4a2713aSLionel Sambuc     unsigned PIkind = property->getPropertyAttributesAsWritten();
835f4a2713aSLionel Sambuc     if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic |
836f4a2713aSLionel Sambuc                    ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) {
837f4a2713aSLionel Sambuc       if (AtLoc.isValid())
838f4a2713aSLionel Sambuc         Diag(AtLoc, diag::warn_implicit_atomic_property);
839f4a2713aSLionel Sambuc       else
840f4a2713aSLionel Sambuc         Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
841f4a2713aSLionel Sambuc       Diag(property->getLocation(), diag::note_property_declare);
842f4a2713aSLionel Sambuc     }
843f4a2713aSLionel Sambuc 
844f4a2713aSLionel Sambuc     if (const ObjCCategoryDecl *CD =
845f4a2713aSLionel Sambuc         dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
846f4a2713aSLionel Sambuc       if (!CD->IsClassExtension()) {
847f4a2713aSLionel Sambuc         Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
848f4a2713aSLionel Sambuc         Diag(property->getLocation(), diag::note_property_declare);
849*0a6a1f1dSLionel Sambuc         return nullptr;
850f4a2713aSLionel Sambuc       }
851f4a2713aSLionel Sambuc     }
852f4a2713aSLionel Sambuc     if (Synthesize&&
853f4a2713aSLionel Sambuc         (PIkind & ObjCPropertyDecl::OBJC_PR_readonly) &&
854f4a2713aSLionel Sambuc         property->hasAttr<IBOutletAttr>() &&
855f4a2713aSLionel Sambuc         !AtLoc.isValid()) {
856f4a2713aSLionel Sambuc       bool ReadWriteProperty = false;
857f4a2713aSLionel Sambuc       // Search into the class extensions and see if 'readonly property is
858f4a2713aSLionel Sambuc       // redeclared 'readwrite', then no warning is to be issued.
859*0a6a1f1dSLionel Sambuc       for (auto *Ext : IDecl->known_extensions()) {
860f4a2713aSLionel Sambuc         DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
861f4a2713aSLionel Sambuc         if (!R.empty())
862f4a2713aSLionel Sambuc           if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) {
863f4a2713aSLionel Sambuc             PIkind = ExtProp->getPropertyAttributesAsWritten();
864f4a2713aSLionel Sambuc             if (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) {
865f4a2713aSLionel Sambuc               ReadWriteProperty = true;
866f4a2713aSLionel Sambuc               break;
867f4a2713aSLionel Sambuc             }
868f4a2713aSLionel Sambuc           }
869f4a2713aSLionel Sambuc       }
870f4a2713aSLionel Sambuc 
871f4a2713aSLionel Sambuc       if (!ReadWriteProperty) {
872f4a2713aSLionel Sambuc         Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
873*0a6a1f1dSLionel Sambuc             << property;
874f4a2713aSLionel Sambuc         SourceLocation readonlyLoc;
875f4a2713aSLionel Sambuc         if (LocPropertyAttribute(Context, "readonly",
876f4a2713aSLionel Sambuc                                  property->getLParenLoc(), readonlyLoc)) {
877f4a2713aSLionel Sambuc           SourceLocation endLoc =
878f4a2713aSLionel Sambuc             readonlyLoc.getLocWithOffset(strlen("readonly")-1);
879f4a2713aSLionel Sambuc           SourceRange ReadonlySourceRange(readonlyLoc, endLoc);
880f4a2713aSLionel Sambuc           Diag(property->getLocation(),
881f4a2713aSLionel Sambuc                diag::note_auto_readonly_iboutlet_fixup_suggest) <<
882f4a2713aSLionel Sambuc           FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
883f4a2713aSLionel Sambuc         }
884f4a2713aSLionel Sambuc       }
885f4a2713aSLionel Sambuc     }
886f4a2713aSLionel Sambuc     if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext()))
887f4a2713aSLionel Sambuc       DiagnosePropertyMismatchDeclInProtocols(*this, AtLoc, IDecl, property);
888f4a2713aSLionel Sambuc 
889f4a2713aSLionel Sambuc   } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
890f4a2713aSLionel Sambuc     if (Synthesize) {
891f4a2713aSLionel Sambuc       Diag(AtLoc, diag::error_synthesize_category_decl);
892*0a6a1f1dSLionel Sambuc       return nullptr;
893f4a2713aSLionel Sambuc     }
894f4a2713aSLionel Sambuc     IDecl = CatImplClass->getClassInterface();
895f4a2713aSLionel Sambuc     if (!IDecl) {
896f4a2713aSLionel Sambuc       Diag(AtLoc, diag::error_missing_property_interface);
897*0a6a1f1dSLionel Sambuc       return nullptr;
898f4a2713aSLionel Sambuc     }
899f4a2713aSLionel Sambuc     ObjCCategoryDecl *Category =
900f4a2713aSLionel Sambuc     IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
901f4a2713aSLionel Sambuc 
902f4a2713aSLionel Sambuc     // If category for this implementation not found, it is an error which
903f4a2713aSLionel Sambuc     // has already been reported eralier.
904f4a2713aSLionel Sambuc     if (!Category)
905*0a6a1f1dSLionel Sambuc       return nullptr;
906f4a2713aSLionel Sambuc     // Look for this property declaration in @implementation's category
907f4a2713aSLionel Sambuc     property = Category->FindPropertyDeclaration(PropertyId);
908f4a2713aSLionel Sambuc     if (!property) {
909f4a2713aSLionel Sambuc       Diag(PropertyLoc, diag::error_bad_category_property_decl)
910f4a2713aSLionel Sambuc       << Category->getDeclName();
911*0a6a1f1dSLionel Sambuc       return nullptr;
912f4a2713aSLionel Sambuc     }
913f4a2713aSLionel Sambuc   } else {
914f4a2713aSLionel Sambuc     Diag(AtLoc, diag::error_bad_property_context);
915*0a6a1f1dSLionel Sambuc     return nullptr;
916f4a2713aSLionel Sambuc   }
917*0a6a1f1dSLionel Sambuc   ObjCIvarDecl *Ivar = nullptr;
918f4a2713aSLionel Sambuc   bool CompleteTypeErr = false;
919f4a2713aSLionel Sambuc   bool compat = true;
920f4a2713aSLionel Sambuc   // Check that we have a valid, previously declared ivar for @synthesize
921f4a2713aSLionel Sambuc   if (Synthesize) {
922f4a2713aSLionel Sambuc     // @synthesize
923f4a2713aSLionel Sambuc     if (!PropertyIvar)
924f4a2713aSLionel Sambuc       PropertyIvar = PropertyId;
925f4a2713aSLionel Sambuc     // Check that this is a previously declared 'ivar' in 'IDecl' interface
926f4a2713aSLionel Sambuc     ObjCInterfaceDecl *ClassDeclared;
927f4a2713aSLionel Sambuc     Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
928f4a2713aSLionel Sambuc     QualType PropType = property->getType();
929f4a2713aSLionel Sambuc     QualType PropertyIvarType = PropType.getNonReferenceType();
930f4a2713aSLionel Sambuc 
931f4a2713aSLionel Sambuc     if (RequireCompleteType(PropertyDiagLoc, PropertyIvarType,
932f4a2713aSLionel Sambuc                             diag::err_incomplete_synthesized_property,
933f4a2713aSLionel Sambuc                             property->getDeclName())) {
934f4a2713aSLionel Sambuc       Diag(property->getLocation(), diag::note_property_declare);
935f4a2713aSLionel Sambuc       CompleteTypeErr = true;
936f4a2713aSLionel Sambuc     }
937f4a2713aSLionel Sambuc 
938f4a2713aSLionel Sambuc     if (getLangOpts().ObjCAutoRefCount &&
939f4a2713aSLionel Sambuc         (property->getPropertyAttributesAsWritten() &
940f4a2713aSLionel Sambuc          ObjCPropertyDecl::OBJC_PR_readonly) &&
941f4a2713aSLionel Sambuc         PropertyIvarType->isObjCRetainableType()) {
942f4a2713aSLionel Sambuc       setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar);
943f4a2713aSLionel Sambuc     }
944f4a2713aSLionel Sambuc 
945f4a2713aSLionel Sambuc     ObjCPropertyDecl::PropertyAttributeKind kind
946f4a2713aSLionel Sambuc       = property->getPropertyAttributes();
947f4a2713aSLionel Sambuc 
948f4a2713aSLionel Sambuc     // Add GC __weak to the ivar type if the property is weak.
949f4a2713aSLionel Sambuc     if ((kind & ObjCPropertyDecl::OBJC_PR_weak) &&
950f4a2713aSLionel Sambuc         getLangOpts().getGC() != LangOptions::NonGC) {
951f4a2713aSLionel Sambuc       assert(!getLangOpts().ObjCAutoRefCount);
952f4a2713aSLionel Sambuc       if (PropertyIvarType.isObjCGCStrong()) {
953f4a2713aSLionel Sambuc         Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
954f4a2713aSLionel Sambuc         Diag(property->getLocation(), diag::note_property_declare);
955f4a2713aSLionel Sambuc       } else {
956f4a2713aSLionel Sambuc         PropertyIvarType =
957f4a2713aSLionel Sambuc           Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
958f4a2713aSLionel Sambuc       }
959f4a2713aSLionel Sambuc     }
960f4a2713aSLionel Sambuc     if (AtLoc.isInvalid()) {
961f4a2713aSLionel Sambuc       // Check when default synthesizing a property that there is
962f4a2713aSLionel Sambuc       // an ivar matching property name and issue warning; since this
963f4a2713aSLionel Sambuc       // is the most common case of not using an ivar used for backing
964f4a2713aSLionel Sambuc       // property in non-default synthesis case.
965*0a6a1f1dSLionel Sambuc       ObjCInterfaceDecl *ClassDeclared=nullptr;
966f4a2713aSLionel Sambuc       ObjCIvarDecl *originalIvar =
967f4a2713aSLionel Sambuc       IDecl->lookupInstanceVariable(property->getIdentifier(),
968f4a2713aSLionel Sambuc                                     ClassDeclared);
969f4a2713aSLionel Sambuc       if (originalIvar) {
970f4a2713aSLionel Sambuc         Diag(PropertyDiagLoc,
971f4a2713aSLionel Sambuc              diag::warn_autosynthesis_property_ivar_match)
972*0a6a1f1dSLionel Sambuc         << PropertyId << (Ivar == nullptr) << PropertyIvar
973f4a2713aSLionel Sambuc         << originalIvar->getIdentifier();
974f4a2713aSLionel Sambuc         Diag(property->getLocation(), diag::note_property_declare);
975f4a2713aSLionel Sambuc         Diag(originalIvar->getLocation(), diag::note_ivar_decl);
976f4a2713aSLionel Sambuc       }
977f4a2713aSLionel Sambuc     }
978f4a2713aSLionel Sambuc 
979f4a2713aSLionel Sambuc     if (!Ivar) {
980f4a2713aSLionel Sambuc       // In ARC, give the ivar a lifetime qualifier based on the
981f4a2713aSLionel Sambuc       // property attributes.
982f4a2713aSLionel Sambuc       if (getLangOpts().ObjCAutoRefCount &&
983f4a2713aSLionel Sambuc           !PropertyIvarType.getObjCLifetime() &&
984f4a2713aSLionel Sambuc           PropertyIvarType->isObjCRetainableType()) {
985f4a2713aSLionel Sambuc 
986f4a2713aSLionel Sambuc         // It's an error if we have to do this and the user didn't
987f4a2713aSLionel Sambuc         // explicitly write an ownership attribute on the property.
988f4a2713aSLionel Sambuc         if (!property->hasWrittenStorageAttribute() &&
989f4a2713aSLionel Sambuc             !(kind & ObjCPropertyDecl::OBJC_PR_strong)) {
990f4a2713aSLionel Sambuc           Diag(PropertyDiagLoc,
991f4a2713aSLionel Sambuc                diag::err_arc_objc_property_default_assign_on_object);
992f4a2713aSLionel Sambuc           Diag(property->getLocation(), diag::note_property_declare);
993f4a2713aSLionel Sambuc         } else {
994f4a2713aSLionel Sambuc           Qualifiers::ObjCLifetime lifetime =
995f4a2713aSLionel Sambuc             getImpliedARCOwnership(kind, PropertyIvarType);
996f4a2713aSLionel Sambuc           assert(lifetime && "no lifetime for property?");
997f4a2713aSLionel Sambuc           if (lifetime == Qualifiers::OCL_Weak) {
998f4a2713aSLionel Sambuc             bool err = false;
999f4a2713aSLionel Sambuc             if (const ObjCObjectPointerType *ObjT =
1000f4a2713aSLionel Sambuc                 PropertyIvarType->getAs<ObjCObjectPointerType>()) {
1001f4a2713aSLionel Sambuc               const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
1002f4a2713aSLionel Sambuc               if (ObjI && ObjI->isArcWeakrefUnavailable()) {
1003f4a2713aSLionel Sambuc                 Diag(property->getLocation(),
1004f4a2713aSLionel Sambuc                      diag::err_arc_weak_unavailable_property) << PropertyIvarType;
1005f4a2713aSLionel Sambuc                 Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
1006f4a2713aSLionel Sambuc                   << ClassImpDecl->getName();
1007f4a2713aSLionel Sambuc                 err = true;
1008f4a2713aSLionel Sambuc               }
1009f4a2713aSLionel Sambuc             }
1010f4a2713aSLionel Sambuc             if (!err && !getLangOpts().ObjCARCWeak) {
1011f4a2713aSLionel Sambuc               Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
1012f4a2713aSLionel Sambuc               Diag(property->getLocation(), diag::note_property_declare);
1013f4a2713aSLionel Sambuc             }
1014f4a2713aSLionel Sambuc           }
1015f4a2713aSLionel Sambuc 
1016f4a2713aSLionel Sambuc           Qualifiers qs;
1017f4a2713aSLionel Sambuc           qs.addObjCLifetime(lifetime);
1018f4a2713aSLionel Sambuc           PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
1019f4a2713aSLionel Sambuc         }
1020f4a2713aSLionel Sambuc       }
1021f4a2713aSLionel Sambuc 
1022f4a2713aSLionel Sambuc       if (kind & ObjCPropertyDecl::OBJC_PR_weak &&
1023f4a2713aSLionel Sambuc           !getLangOpts().ObjCAutoRefCount &&
1024f4a2713aSLionel Sambuc           getLangOpts().getGC() == LangOptions::NonGC) {
1025f4a2713aSLionel Sambuc         Diag(PropertyDiagLoc, diag::error_synthesize_weak_non_arc_or_gc);
1026f4a2713aSLionel Sambuc         Diag(property->getLocation(), diag::note_property_declare);
1027f4a2713aSLionel Sambuc       }
1028f4a2713aSLionel Sambuc 
1029f4a2713aSLionel Sambuc       Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
1030f4a2713aSLionel Sambuc                                   PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
1031*0a6a1f1dSLionel Sambuc                                   PropertyIvarType, /*Dinfo=*/nullptr,
1032f4a2713aSLionel Sambuc                                   ObjCIvarDecl::Private,
1033*0a6a1f1dSLionel Sambuc                                   (Expr *)nullptr, true);
1034f4a2713aSLionel Sambuc       if (RequireNonAbstractType(PropertyIvarLoc,
1035f4a2713aSLionel Sambuc                                  PropertyIvarType,
1036f4a2713aSLionel Sambuc                                  diag::err_abstract_type_in_decl,
1037f4a2713aSLionel Sambuc                                  AbstractSynthesizedIvarType)) {
1038f4a2713aSLionel Sambuc         Diag(property->getLocation(), diag::note_property_declare);
1039f4a2713aSLionel Sambuc         Ivar->setInvalidDecl();
1040f4a2713aSLionel Sambuc       } else if (CompleteTypeErr)
1041f4a2713aSLionel Sambuc           Ivar->setInvalidDecl();
1042f4a2713aSLionel Sambuc       ClassImpDecl->addDecl(Ivar);
1043f4a2713aSLionel Sambuc       IDecl->makeDeclVisibleInContext(Ivar);
1044f4a2713aSLionel Sambuc 
1045f4a2713aSLionel Sambuc       if (getLangOpts().ObjCRuntime.isFragile())
1046f4a2713aSLionel Sambuc         Diag(PropertyDiagLoc, diag::error_missing_property_ivar_decl)
1047f4a2713aSLionel Sambuc             << PropertyId;
1048f4a2713aSLionel Sambuc       // Note! I deliberately want it to fall thru so, we have a
1049f4a2713aSLionel Sambuc       // a property implementation and to avoid future warnings.
1050f4a2713aSLionel Sambuc     } else if (getLangOpts().ObjCRuntime.isNonFragile() &&
1051f4a2713aSLionel Sambuc                !declaresSameEntity(ClassDeclared, IDecl)) {
1052f4a2713aSLionel Sambuc       Diag(PropertyDiagLoc, diag::error_ivar_in_superclass_use)
1053f4a2713aSLionel Sambuc       << property->getDeclName() << Ivar->getDeclName()
1054f4a2713aSLionel Sambuc       << ClassDeclared->getDeclName();
1055f4a2713aSLionel Sambuc       Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
1056f4a2713aSLionel Sambuc       << Ivar << Ivar->getName();
1057f4a2713aSLionel Sambuc       // Note! I deliberately want it to fall thru so more errors are caught.
1058f4a2713aSLionel Sambuc     }
1059f4a2713aSLionel Sambuc     property->setPropertyIvarDecl(Ivar);
1060f4a2713aSLionel Sambuc 
1061f4a2713aSLionel Sambuc     QualType IvarType = Context.getCanonicalType(Ivar->getType());
1062f4a2713aSLionel Sambuc 
1063f4a2713aSLionel Sambuc     // Check that type of property and its ivar are type compatible.
1064f4a2713aSLionel Sambuc     if (!Context.hasSameType(PropertyIvarType, IvarType)) {
1065f4a2713aSLionel Sambuc       if (isa<ObjCObjectPointerType>(PropertyIvarType)
1066f4a2713aSLionel Sambuc           && isa<ObjCObjectPointerType>(IvarType))
1067f4a2713aSLionel Sambuc         compat =
1068f4a2713aSLionel Sambuc           Context.canAssignObjCInterfaces(
1069f4a2713aSLionel Sambuc                                   PropertyIvarType->getAs<ObjCObjectPointerType>(),
1070f4a2713aSLionel Sambuc                                   IvarType->getAs<ObjCObjectPointerType>());
1071f4a2713aSLionel Sambuc       else {
1072f4a2713aSLionel Sambuc         compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType,
1073f4a2713aSLionel Sambuc                                              IvarType)
1074f4a2713aSLionel Sambuc                     == Compatible);
1075f4a2713aSLionel Sambuc       }
1076f4a2713aSLionel Sambuc       if (!compat) {
1077f4a2713aSLionel Sambuc         Diag(PropertyDiagLoc, diag::error_property_ivar_type)
1078f4a2713aSLionel Sambuc           << property->getDeclName() << PropType
1079f4a2713aSLionel Sambuc           << Ivar->getDeclName() << IvarType;
1080f4a2713aSLionel Sambuc         Diag(Ivar->getLocation(), diag::note_ivar_decl);
1081f4a2713aSLionel Sambuc         // Note! I deliberately want it to fall thru so, we have a
1082f4a2713aSLionel Sambuc         // a property implementation and to avoid future warnings.
1083f4a2713aSLionel Sambuc       }
1084f4a2713aSLionel Sambuc       else {
1085f4a2713aSLionel Sambuc         // FIXME! Rules for properties are somewhat different that those
1086f4a2713aSLionel Sambuc         // for assignments. Use a new routine to consolidate all cases;
1087f4a2713aSLionel Sambuc         // specifically for property redeclarations as well as for ivars.
1088f4a2713aSLionel Sambuc         QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
1089f4a2713aSLionel Sambuc         QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
1090f4a2713aSLionel Sambuc         if (lhsType != rhsType &&
1091f4a2713aSLionel Sambuc             lhsType->isArithmeticType()) {
1092f4a2713aSLionel Sambuc           Diag(PropertyDiagLoc, diag::error_property_ivar_type)
1093f4a2713aSLionel Sambuc             << property->getDeclName() << PropType
1094f4a2713aSLionel Sambuc             << Ivar->getDeclName() << IvarType;
1095f4a2713aSLionel Sambuc           Diag(Ivar->getLocation(), diag::note_ivar_decl);
1096f4a2713aSLionel Sambuc           // Fall thru - see previous comment
1097f4a2713aSLionel Sambuc         }
1098f4a2713aSLionel Sambuc       }
1099f4a2713aSLionel Sambuc       // __weak is explicit. So it works on Canonical type.
1100f4a2713aSLionel Sambuc       if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
1101f4a2713aSLionel Sambuc            getLangOpts().getGC() != LangOptions::NonGC)) {
1102f4a2713aSLionel Sambuc         Diag(PropertyDiagLoc, diag::error_weak_property)
1103f4a2713aSLionel Sambuc         << property->getDeclName() << Ivar->getDeclName();
1104f4a2713aSLionel Sambuc         Diag(Ivar->getLocation(), diag::note_ivar_decl);
1105f4a2713aSLionel Sambuc         // Fall thru - see previous comment
1106f4a2713aSLionel Sambuc       }
1107f4a2713aSLionel Sambuc       // Fall thru - see previous comment
1108f4a2713aSLionel Sambuc       if ((property->getType()->isObjCObjectPointerType() ||
1109f4a2713aSLionel Sambuc            PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
1110f4a2713aSLionel Sambuc           getLangOpts().getGC() != LangOptions::NonGC) {
1111f4a2713aSLionel Sambuc         Diag(PropertyDiagLoc, diag::error_strong_property)
1112f4a2713aSLionel Sambuc         << property->getDeclName() << Ivar->getDeclName();
1113f4a2713aSLionel Sambuc         // Fall thru - see previous comment
1114f4a2713aSLionel Sambuc       }
1115f4a2713aSLionel Sambuc     }
1116f4a2713aSLionel Sambuc     if (getLangOpts().ObjCAutoRefCount)
1117f4a2713aSLionel Sambuc       checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
1118f4a2713aSLionel Sambuc   } else if (PropertyIvar)
1119f4a2713aSLionel Sambuc     // @dynamic
1120f4a2713aSLionel Sambuc     Diag(PropertyDiagLoc, diag::error_dynamic_property_ivar_decl);
1121f4a2713aSLionel Sambuc 
1122f4a2713aSLionel Sambuc   assert (property && "ActOnPropertyImplDecl - property declaration missing");
1123f4a2713aSLionel Sambuc   ObjCPropertyImplDecl *PIDecl =
1124f4a2713aSLionel Sambuc   ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
1125f4a2713aSLionel Sambuc                                property,
1126f4a2713aSLionel Sambuc                                (Synthesize ?
1127f4a2713aSLionel Sambuc                                 ObjCPropertyImplDecl::Synthesize
1128f4a2713aSLionel Sambuc                                 : ObjCPropertyImplDecl::Dynamic),
1129f4a2713aSLionel Sambuc                                Ivar, PropertyIvarLoc);
1130f4a2713aSLionel Sambuc 
1131f4a2713aSLionel Sambuc   if (CompleteTypeErr || !compat)
1132f4a2713aSLionel Sambuc     PIDecl->setInvalidDecl();
1133f4a2713aSLionel Sambuc 
1134f4a2713aSLionel Sambuc   if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
1135f4a2713aSLionel Sambuc     getterMethod->createImplicitParams(Context, IDecl);
1136f4a2713aSLionel Sambuc     if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
1137f4a2713aSLionel Sambuc         Ivar->getType()->isRecordType()) {
1138f4a2713aSLionel Sambuc       // For Objective-C++, need to synthesize the AST for the IVAR object to be
1139f4a2713aSLionel Sambuc       // returned by the getter as it must conform to C++'s copy-return rules.
1140f4a2713aSLionel Sambuc       // FIXME. Eventually we want to do this for Objective-C as well.
1141f4a2713aSLionel Sambuc       SynthesizedFunctionScope Scope(*this, getterMethod);
1142f4a2713aSLionel Sambuc       ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
1143f4a2713aSLionel Sambuc       DeclRefExpr *SelfExpr =
1144f4a2713aSLionel Sambuc         new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
1145*0a6a1f1dSLionel Sambuc                                   VK_LValue, PropertyDiagLoc);
1146f4a2713aSLionel Sambuc       MarkDeclRefReferenced(SelfExpr);
1147*0a6a1f1dSLionel Sambuc       Expr *LoadSelfExpr =
1148*0a6a1f1dSLionel Sambuc         ImplicitCastExpr::Create(Context, SelfDecl->getType(),
1149*0a6a1f1dSLionel Sambuc                                  CK_LValueToRValue, SelfExpr, nullptr,
1150*0a6a1f1dSLionel Sambuc                                  VK_RValue);
1151f4a2713aSLionel Sambuc       Expr *IvarRefExpr =
1152f4a2713aSLionel Sambuc         new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
1153f4a2713aSLionel Sambuc                                       Ivar->getLocation(),
1154*0a6a1f1dSLionel Sambuc                                       LoadSelfExpr, true, true);
1155*0a6a1f1dSLionel Sambuc       ExprResult Res = PerformCopyInitialization(
1156*0a6a1f1dSLionel Sambuc           InitializedEntity::InitializeResult(PropertyDiagLoc,
1157*0a6a1f1dSLionel Sambuc                                               getterMethod->getReturnType(),
1158f4a2713aSLionel Sambuc                                               /*NRVO=*/false),
1159*0a6a1f1dSLionel Sambuc           PropertyDiagLoc, IvarRefExpr);
1160f4a2713aSLionel Sambuc       if (!Res.isInvalid()) {
1161*0a6a1f1dSLionel Sambuc         Expr *ResExpr = Res.getAs<Expr>();
1162f4a2713aSLionel Sambuc         if (ResExpr)
1163f4a2713aSLionel Sambuc           ResExpr = MaybeCreateExprWithCleanups(ResExpr);
1164f4a2713aSLionel Sambuc         PIDecl->setGetterCXXConstructor(ResExpr);
1165f4a2713aSLionel Sambuc       }
1166f4a2713aSLionel Sambuc     }
1167f4a2713aSLionel Sambuc     if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
1168f4a2713aSLionel Sambuc         !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
1169f4a2713aSLionel Sambuc       Diag(getterMethod->getLocation(),
1170f4a2713aSLionel Sambuc            diag::warn_property_getter_owning_mismatch);
1171f4a2713aSLionel Sambuc       Diag(property->getLocation(), diag::note_property_declare);
1172f4a2713aSLionel Sambuc     }
1173f4a2713aSLionel Sambuc     if (getLangOpts().ObjCAutoRefCount && Synthesize)
1174f4a2713aSLionel Sambuc       switch (getterMethod->getMethodFamily()) {
1175f4a2713aSLionel Sambuc         case OMF_retain:
1176f4a2713aSLionel Sambuc         case OMF_retainCount:
1177f4a2713aSLionel Sambuc         case OMF_release:
1178f4a2713aSLionel Sambuc         case OMF_autorelease:
1179f4a2713aSLionel Sambuc           Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def)
1180f4a2713aSLionel Sambuc             << 1 << getterMethod->getSelector();
1181f4a2713aSLionel Sambuc           break;
1182f4a2713aSLionel Sambuc         default:
1183f4a2713aSLionel Sambuc           break;
1184f4a2713aSLionel Sambuc       }
1185f4a2713aSLionel Sambuc   }
1186f4a2713aSLionel Sambuc   if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
1187f4a2713aSLionel Sambuc     setterMethod->createImplicitParams(Context, IDecl);
1188f4a2713aSLionel Sambuc     if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
1189f4a2713aSLionel Sambuc         Ivar->getType()->isRecordType()) {
1190f4a2713aSLionel Sambuc       // FIXME. Eventually we want to do this for Objective-C as well.
1191f4a2713aSLionel Sambuc       SynthesizedFunctionScope Scope(*this, setterMethod);
1192f4a2713aSLionel Sambuc       ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
1193f4a2713aSLionel Sambuc       DeclRefExpr *SelfExpr =
1194f4a2713aSLionel Sambuc         new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
1195*0a6a1f1dSLionel Sambuc                                   VK_LValue, PropertyDiagLoc);
1196f4a2713aSLionel Sambuc       MarkDeclRefReferenced(SelfExpr);
1197*0a6a1f1dSLionel Sambuc       Expr *LoadSelfExpr =
1198*0a6a1f1dSLionel Sambuc         ImplicitCastExpr::Create(Context, SelfDecl->getType(),
1199*0a6a1f1dSLionel Sambuc                                  CK_LValueToRValue, SelfExpr, nullptr,
1200*0a6a1f1dSLionel Sambuc                                  VK_RValue);
1201f4a2713aSLionel Sambuc       Expr *lhs =
1202f4a2713aSLionel Sambuc         new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
1203f4a2713aSLionel Sambuc                                       Ivar->getLocation(),
1204*0a6a1f1dSLionel Sambuc                                       LoadSelfExpr, true, true);
1205f4a2713aSLionel Sambuc       ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
1206f4a2713aSLionel Sambuc       ParmVarDecl *Param = (*P);
1207f4a2713aSLionel Sambuc       QualType T = Param->getType().getNonReferenceType();
1208f4a2713aSLionel Sambuc       DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T,
1209f4a2713aSLionel Sambuc                                                    VK_LValue, PropertyDiagLoc);
1210f4a2713aSLionel Sambuc       MarkDeclRefReferenced(rhs);
1211f4a2713aSLionel Sambuc       ExprResult Res = BuildBinOp(S, PropertyDiagLoc,
1212f4a2713aSLionel Sambuc                                   BO_Assign, lhs, rhs);
1213f4a2713aSLionel Sambuc       if (property->getPropertyAttributes() &
1214f4a2713aSLionel Sambuc           ObjCPropertyDecl::OBJC_PR_atomic) {
1215*0a6a1f1dSLionel Sambuc         Expr *callExpr = Res.getAs<Expr>();
1216f4a2713aSLionel Sambuc         if (const CXXOperatorCallExpr *CXXCE =
1217f4a2713aSLionel Sambuc               dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
1218f4a2713aSLionel Sambuc           if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
1219f4a2713aSLionel Sambuc             if (!FuncDecl->isTrivial())
1220f4a2713aSLionel Sambuc               if (property->getType()->isReferenceType()) {
1221f4a2713aSLionel Sambuc                 Diag(PropertyDiagLoc,
1222f4a2713aSLionel Sambuc                      diag::err_atomic_property_nontrivial_assign_op)
1223f4a2713aSLionel Sambuc                     << property->getType();
1224f4a2713aSLionel Sambuc                 Diag(FuncDecl->getLocStart(),
1225f4a2713aSLionel Sambuc                      diag::note_callee_decl) << FuncDecl;
1226f4a2713aSLionel Sambuc               }
1227f4a2713aSLionel Sambuc       }
1228*0a6a1f1dSLionel Sambuc       PIDecl->setSetterCXXAssignment(Res.getAs<Expr>());
1229f4a2713aSLionel Sambuc     }
1230f4a2713aSLionel Sambuc   }
1231f4a2713aSLionel Sambuc 
1232f4a2713aSLionel Sambuc   if (IC) {
1233f4a2713aSLionel Sambuc     if (Synthesize)
1234f4a2713aSLionel Sambuc       if (ObjCPropertyImplDecl *PPIDecl =
1235f4a2713aSLionel Sambuc           IC->FindPropertyImplIvarDecl(PropertyIvar)) {
1236f4a2713aSLionel Sambuc         Diag(PropertyLoc, diag::error_duplicate_ivar_use)
1237f4a2713aSLionel Sambuc         << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
1238f4a2713aSLionel Sambuc         << PropertyIvar;
1239f4a2713aSLionel Sambuc         Diag(PPIDecl->getLocation(), diag::note_previous_use);
1240f4a2713aSLionel Sambuc       }
1241f4a2713aSLionel Sambuc 
1242f4a2713aSLionel Sambuc     if (ObjCPropertyImplDecl *PPIDecl
1243f4a2713aSLionel Sambuc         = IC->FindPropertyImplDecl(PropertyId)) {
1244f4a2713aSLionel Sambuc       Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
1245f4a2713aSLionel Sambuc       Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
1246*0a6a1f1dSLionel Sambuc       return nullptr;
1247f4a2713aSLionel Sambuc     }
1248f4a2713aSLionel Sambuc     IC->addPropertyImplementation(PIDecl);
1249f4a2713aSLionel Sambuc     if (getLangOpts().ObjCDefaultSynthProperties &&
1250f4a2713aSLionel Sambuc         getLangOpts().ObjCRuntime.isNonFragile() &&
1251f4a2713aSLionel Sambuc         !IDecl->isObjCRequiresPropertyDefs()) {
1252f4a2713aSLionel Sambuc       // Diagnose if an ivar was lazily synthesdized due to a previous
1253f4a2713aSLionel Sambuc       // use and if 1) property is @dynamic or 2) property is synthesized
1254f4a2713aSLionel Sambuc       // but it requires an ivar of different name.
1255*0a6a1f1dSLionel Sambuc       ObjCInterfaceDecl *ClassDeclared=nullptr;
1256*0a6a1f1dSLionel Sambuc       ObjCIvarDecl *Ivar = nullptr;
1257f4a2713aSLionel Sambuc       if (!Synthesize)
1258f4a2713aSLionel Sambuc         Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
1259f4a2713aSLionel Sambuc       else {
1260f4a2713aSLionel Sambuc         if (PropertyIvar && PropertyIvar != PropertyId)
1261f4a2713aSLionel Sambuc           Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
1262f4a2713aSLionel Sambuc       }
1263f4a2713aSLionel Sambuc       // Issue diagnostics only if Ivar belongs to current class.
1264f4a2713aSLionel Sambuc       if (Ivar && Ivar->getSynthesize() &&
1265f4a2713aSLionel Sambuc           declaresSameEntity(IC->getClassInterface(), ClassDeclared)) {
1266f4a2713aSLionel Sambuc         Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
1267f4a2713aSLionel Sambuc         << PropertyId;
1268f4a2713aSLionel Sambuc         Ivar->setInvalidDecl();
1269f4a2713aSLionel Sambuc       }
1270f4a2713aSLionel Sambuc     }
1271f4a2713aSLionel Sambuc   } else {
1272f4a2713aSLionel Sambuc     if (Synthesize)
1273f4a2713aSLionel Sambuc       if (ObjCPropertyImplDecl *PPIDecl =
1274f4a2713aSLionel Sambuc           CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
1275f4a2713aSLionel Sambuc         Diag(PropertyDiagLoc, diag::error_duplicate_ivar_use)
1276f4a2713aSLionel Sambuc         << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
1277f4a2713aSLionel Sambuc         << PropertyIvar;
1278f4a2713aSLionel Sambuc         Diag(PPIDecl->getLocation(), diag::note_previous_use);
1279f4a2713aSLionel Sambuc       }
1280f4a2713aSLionel Sambuc 
1281f4a2713aSLionel Sambuc     if (ObjCPropertyImplDecl *PPIDecl =
1282f4a2713aSLionel Sambuc         CatImplClass->FindPropertyImplDecl(PropertyId)) {
1283f4a2713aSLionel Sambuc       Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId;
1284f4a2713aSLionel Sambuc       Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
1285*0a6a1f1dSLionel Sambuc       return nullptr;
1286f4a2713aSLionel Sambuc     }
1287f4a2713aSLionel Sambuc     CatImplClass->addPropertyImplementation(PIDecl);
1288f4a2713aSLionel Sambuc   }
1289f4a2713aSLionel Sambuc 
1290f4a2713aSLionel Sambuc   return PIDecl;
1291f4a2713aSLionel Sambuc }
1292f4a2713aSLionel Sambuc 
1293f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1294f4a2713aSLionel Sambuc // Helper methods.
1295f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1296f4a2713aSLionel Sambuc 
1297f4a2713aSLionel Sambuc /// DiagnosePropertyMismatch - Compares two properties for their
1298f4a2713aSLionel Sambuc /// attributes and types and warns on a variety of inconsistencies.
1299f4a2713aSLionel Sambuc ///
1300f4a2713aSLionel Sambuc void
DiagnosePropertyMismatch(ObjCPropertyDecl * Property,ObjCPropertyDecl * SuperProperty,const IdentifierInfo * inheritedName,bool OverridingProtocolProperty)1301f4a2713aSLionel Sambuc Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
1302f4a2713aSLionel Sambuc                                ObjCPropertyDecl *SuperProperty,
1303f4a2713aSLionel Sambuc                                const IdentifierInfo *inheritedName,
1304f4a2713aSLionel Sambuc                                bool OverridingProtocolProperty) {
1305f4a2713aSLionel Sambuc   ObjCPropertyDecl::PropertyAttributeKind CAttr =
1306f4a2713aSLionel Sambuc     Property->getPropertyAttributes();
1307f4a2713aSLionel Sambuc   ObjCPropertyDecl::PropertyAttributeKind SAttr =
1308f4a2713aSLionel Sambuc     SuperProperty->getPropertyAttributes();
1309f4a2713aSLionel Sambuc 
1310f4a2713aSLionel Sambuc   // We allow readonly properties without an explicit ownership
1311f4a2713aSLionel Sambuc   // (assign/unsafe_unretained/weak/retain/strong/copy) in super class
1312f4a2713aSLionel Sambuc   // to be overridden by a property with any explicit ownership in the subclass.
1313f4a2713aSLionel Sambuc   if (!OverridingProtocolProperty &&
1314f4a2713aSLionel Sambuc       !getOwnershipRule(SAttr) && getOwnershipRule(CAttr))
1315f4a2713aSLionel Sambuc     ;
1316f4a2713aSLionel Sambuc   else {
1317f4a2713aSLionel Sambuc     if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
1318f4a2713aSLionel Sambuc         && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
1319f4a2713aSLionel Sambuc       Diag(Property->getLocation(), diag::warn_readonly_property)
1320f4a2713aSLionel Sambuc         << Property->getDeclName() << inheritedName;
1321f4a2713aSLionel Sambuc     if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
1322f4a2713aSLionel Sambuc         != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
1323f4a2713aSLionel Sambuc       Diag(Property->getLocation(), diag::warn_property_attribute)
1324f4a2713aSLionel Sambuc         << Property->getDeclName() << "copy" << inheritedName;
1325f4a2713aSLionel Sambuc     else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){
1326f4a2713aSLionel Sambuc       unsigned CAttrRetain =
1327f4a2713aSLionel Sambuc         (CAttr &
1328f4a2713aSLionel Sambuc          (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
1329f4a2713aSLionel Sambuc       unsigned SAttrRetain =
1330f4a2713aSLionel Sambuc         (SAttr &
1331f4a2713aSLionel Sambuc          (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
1332f4a2713aSLionel Sambuc       bool CStrong = (CAttrRetain != 0);
1333f4a2713aSLionel Sambuc       bool SStrong = (SAttrRetain != 0);
1334f4a2713aSLionel Sambuc       if (CStrong != SStrong)
1335f4a2713aSLionel Sambuc         Diag(Property->getLocation(), diag::warn_property_attribute)
1336f4a2713aSLionel Sambuc           << Property->getDeclName() << "retain (or strong)" << inheritedName;
1337f4a2713aSLionel Sambuc     }
1338f4a2713aSLionel Sambuc   }
1339f4a2713aSLionel Sambuc 
1340f4a2713aSLionel Sambuc   if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
1341f4a2713aSLionel Sambuc       != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
1342f4a2713aSLionel Sambuc     Diag(Property->getLocation(), diag::warn_property_attribute)
1343f4a2713aSLionel Sambuc       << Property->getDeclName() << "atomic" << inheritedName;
1344f4a2713aSLionel Sambuc     Diag(SuperProperty->getLocation(), diag::note_property_declare);
1345f4a2713aSLionel Sambuc   }
1346f4a2713aSLionel Sambuc   if (Property->getSetterName() != SuperProperty->getSetterName()) {
1347f4a2713aSLionel Sambuc     Diag(Property->getLocation(), diag::warn_property_attribute)
1348f4a2713aSLionel Sambuc       << Property->getDeclName() << "setter" << inheritedName;
1349f4a2713aSLionel Sambuc     Diag(SuperProperty->getLocation(), diag::note_property_declare);
1350f4a2713aSLionel Sambuc   }
1351f4a2713aSLionel Sambuc   if (Property->getGetterName() != SuperProperty->getGetterName()) {
1352f4a2713aSLionel Sambuc     Diag(Property->getLocation(), diag::warn_property_attribute)
1353f4a2713aSLionel Sambuc       << Property->getDeclName() << "getter" << inheritedName;
1354f4a2713aSLionel Sambuc     Diag(SuperProperty->getLocation(), diag::note_property_declare);
1355f4a2713aSLionel Sambuc   }
1356f4a2713aSLionel Sambuc 
1357f4a2713aSLionel Sambuc   QualType LHSType =
1358f4a2713aSLionel Sambuc     Context.getCanonicalType(SuperProperty->getType());
1359f4a2713aSLionel Sambuc   QualType RHSType =
1360f4a2713aSLionel Sambuc     Context.getCanonicalType(Property->getType());
1361f4a2713aSLionel Sambuc 
1362f4a2713aSLionel Sambuc   if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) {
1363f4a2713aSLionel Sambuc     // Do cases not handled in above.
1364f4a2713aSLionel Sambuc     // FIXME. For future support of covariant property types, revisit this.
1365f4a2713aSLionel Sambuc     bool IncompatibleObjC = false;
1366f4a2713aSLionel Sambuc     QualType ConvertedType;
1367f4a2713aSLionel Sambuc     if (!isObjCPointerConversion(RHSType, LHSType,
1368f4a2713aSLionel Sambuc                                  ConvertedType, IncompatibleObjC) ||
1369f4a2713aSLionel Sambuc         IncompatibleObjC) {
1370f4a2713aSLionel Sambuc         Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
1371f4a2713aSLionel Sambuc         << Property->getType() << SuperProperty->getType() << inheritedName;
1372f4a2713aSLionel Sambuc       Diag(SuperProperty->getLocation(), diag::note_property_declare);
1373f4a2713aSLionel Sambuc     }
1374f4a2713aSLionel Sambuc   }
1375f4a2713aSLionel Sambuc }
1376f4a2713aSLionel Sambuc 
DiagnosePropertyAccessorMismatch(ObjCPropertyDecl * property,ObjCMethodDecl * GetterMethod,SourceLocation Loc)1377f4a2713aSLionel Sambuc bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
1378f4a2713aSLionel Sambuc                                             ObjCMethodDecl *GetterMethod,
1379f4a2713aSLionel Sambuc                                             SourceLocation Loc) {
1380f4a2713aSLionel Sambuc   if (!GetterMethod)
1381f4a2713aSLionel Sambuc     return false;
1382*0a6a1f1dSLionel Sambuc   QualType GetterType = GetterMethod->getReturnType().getNonReferenceType();
1383f4a2713aSLionel Sambuc   QualType PropertyIvarType = property->getType().getNonReferenceType();
1384f4a2713aSLionel Sambuc   bool compat = Context.hasSameType(PropertyIvarType, GetterType);
1385f4a2713aSLionel Sambuc   if (!compat) {
1386f4a2713aSLionel Sambuc     if (isa<ObjCObjectPointerType>(PropertyIvarType) &&
1387f4a2713aSLionel Sambuc         isa<ObjCObjectPointerType>(GetterType))
1388f4a2713aSLionel Sambuc       compat =
1389f4a2713aSLionel Sambuc         Context.canAssignObjCInterfaces(
1390f4a2713aSLionel Sambuc                                       GetterType->getAs<ObjCObjectPointerType>(),
1391f4a2713aSLionel Sambuc                                       PropertyIvarType->getAs<ObjCObjectPointerType>());
1392f4a2713aSLionel Sambuc     else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType)
1393f4a2713aSLionel Sambuc               != Compatible) {
1394f4a2713aSLionel Sambuc           Diag(Loc, diag::error_property_accessor_type)
1395f4a2713aSLionel Sambuc             << property->getDeclName() << PropertyIvarType
1396f4a2713aSLionel Sambuc             << GetterMethod->getSelector() << GetterType;
1397f4a2713aSLionel Sambuc           Diag(GetterMethod->getLocation(), diag::note_declared_at);
1398f4a2713aSLionel Sambuc           return true;
1399f4a2713aSLionel Sambuc     } else {
1400f4a2713aSLionel Sambuc       compat = true;
1401f4a2713aSLionel Sambuc       QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
1402f4a2713aSLionel Sambuc       QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType();
1403f4a2713aSLionel Sambuc       if (lhsType != rhsType && lhsType->isArithmeticType())
1404f4a2713aSLionel Sambuc         compat = false;
1405f4a2713aSLionel Sambuc     }
1406f4a2713aSLionel Sambuc   }
1407f4a2713aSLionel Sambuc 
1408f4a2713aSLionel Sambuc   if (!compat) {
1409f4a2713aSLionel Sambuc     Diag(Loc, diag::warn_accessor_property_type_mismatch)
1410f4a2713aSLionel Sambuc     << property->getDeclName()
1411f4a2713aSLionel Sambuc     << GetterMethod->getSelector();
1412f4a2713aSLionel Sambuc     Diag(GetterMethod->getLocation(), diag::note_declared_at);
1413f4a2713aSLionel Sambuc     return true;
1414f4a2713aSLionel Sambuc   }
1415f4a2713aSLionel Sambuc 
1416f4a2713aSLionel Sambuc   return false;
1417f4a2713aSLionel Sambuc }
1418f4a2713aSLionel Sambuc 
1419f4a2713aSLionel Sambuc /// CollectImmediateProperties - This routine collects all properties in
1420f4a2713aSLionel Sambuc /// the class and its conforming protocols; but not those in its super class.
CollectImmediateProperties(ObjCContainerDecl * CDecl,ObjCContainerDecl::PropertyMap & PropMap,ObjCContainerDecl::PropertyMap & SuperPropMap,bool IncludeProtocols=true)1421*0a6a1f1dSLionel Sambuc static void CollectImmediateProperties(ObjCContainerDecl *CDecl,
1422f4a2713aSLionel Sambuc                                        ObjCContainerDecl::PropertyMap &PropMap,
1423*0a6a1f1dSLionel Sambuc                                        ObjCContainerDecl::PropertyMap &SuperPropMap,
1424*0a6a1f1dSLionel Sambuc                                        bool IncludeProtocols = true) {
1425*0a6a1f1dSLionel Sambuc 
1426f4a2713aSLionel Sambuc   if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
1427*0a6a1f1dSLionel Sambuc     for (auto *Prop : IDecl->properties())
1428f4a2713aSLionel Sambuc       PropMap[Prop->getIdentifier()] = Prop;
1429*0a6a1f1dSLionel Sambuc     if (IncludeProtocols) {
1430*0a6a1f1dSLionel Sambuc       // Scan through class's protocols.
1431*0a6a1f1dSLionel Sambuc       for (auto *PI : IDecl->all_referenced_protocols())
1432*0a6a1f1dSLionel Sambuc         CollectImmediateProperties(PI, PropMap, SuperPropMap);
1433f4a2713aSLionel Sambuc     }
1434f4a2713aSLionel Sambuc   }
1435f4a2713aSLionel Sambuc   if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
1436f4a2713aSLionel Sambuc     if (!CATDecl->IsClassExtension())
1437*0a6a1f1dSLionel Sambuc       for (auto *Prop : CATDecl->properties())
1438f4a2713aSLionel Sambuc         PropMap[Prop->getIdentifier()] = Prop;
1439*0a6a1f1dSLionel Sambuc     if (IncludeProtocols) {
1440*0a6a1f1dSLionel Sambuc       // Scan through class's protocols.
1441*0a6a1f1dSLionel Sambuc       for (auto *PI : CATDecl->protocols())
1442*0a6a1f1dSLionel Sambuc         CollectImmediateProperties(PI, PropMap, SuperPropMap);
1443f4a2713aSLionel Sambuc     }
1444f4a2713aSLionel Sambuc   }
1445f4a2713aSLionel Sambuc   else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
1446*0a6a1f1dSLionel Sambuc     for (auto *Prop : PDecl->properties()) {
1447f4a2713aSLionel Sambuc       ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()];
1448f4a2713aSLionel Sambuc       // Exclude property for protocols which conform to class's super-class,
1449f4a2713aSLionel Sambuc       // as super-class has to implement the property.
1450f4a2713aSLionel Sambuc       if (!PropertyFromSuper ||
1451f4a2713aSLionel Sambuc           PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) {
1452f4a2713aSLionel Sambuc         ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
1453f4a2713aSLionel Sambuc         if (!PropEntry)
1454f4a2713aSLionel Sambuc           PropEntry = Prop;
1455f4a2713aSLionel Sambuc       }
1456f4a2713aSLionel Sambuc     }
1457f4a2713aSLionel Sambuc     // scan through protocol's protocols.
1458*0a6a1f1dSLionel Sambuc     for (auto *PI : PDecl->protocols())
1459*0a6a1f1dSLionel Sambuc       CollectImmediateProperties(PI, PropMap, SuperPropMap);
1460f4a2713aSLionel Sambuc   }
1461f4a2713aSLionel Sambuc }
1462f4a2713aSLionel Sambuc 
1463f4a2713aSLionel Sambuc /// CollectSuperClassPropertyImplementations - This routine collects list of
1464f4a2713aSLionel Sambuc /// properties to be implemented in super class(s) and also coming from their
1465f4a2713aSLionel Sambuc /// conforming protocols.
CollectSuperClassPropertyImplementations(ObjCInterfaceDecl * CDecl,ObjCInterfaceDecl::PropertyMap & PropMap)1466f4a2713aSLionel Sambuc static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
1467f4a2713aSLionel Sambuc                                     ObjCInterfaceDecl::PropertyMap &PropMap) {
1468f4a2713aSLionel Sambuc   if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
1469f4a2713aSLionel Sambuc     ObjCInterfaceDecl::PropertyDeclOrder PO;
1470f4a2713aSLionel Sambuc     while (SDecl) {
1471f4a2713aSLionel Sambuc       SDecl->collectPropertiesToImplement(PropMap, PO);
1472f4a2713aSLionel Sambuc       SDecl = SDecl->getSuperClass();
1473f4a2713aSLionel Sambuc     }
1474f4a2713aSLionel Sambuc   }
1475f4a2713aSLionel Sambuc }
1476f4a2713aSLionel Sambuc 
1477f4a2713aSLionel Sambuc /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
1478f4a2713aSLionel Sambuc /// an ivar synthesized for 'Method' and 'Method' is a property accessor
1479f4a2713aSLionel Sambuc /// declared in class 'IFace'.
1480f4a2713aSLionel Sambuc bool
IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl * IFace,ObjCMethodDecl * Method,ObjCIvarDecl * IV)1481f4a2713aSLionel Sambuc Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
1482f4a2713aSLionel Sambuc                                      ObjCMethodDecl *Method, ObjCIvarDecl *IV) {
1483f4a2713aSLionel Sambuc   if (!IV->getSynthesize())
1484f4a2713aSLionel Sambuc     return false;
1485f4a2713aSLionel Sambuc   ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(),
1486f4a2713aSLionel Sambuc                                             Method->isInstanceMethod());
1487f4a2713aSLionel Sambuc   if (!IMD || !IMD->isPropertyAccessor())
1488f4a2713aSLionel Sambuc     return false;
1489f4a2713aSLionel Sambuc 
1490f4a2713aSLionel Sambuc   // look up a property declaration whose one of its accessors is implemented
1491f4a2713aSLionel Sambuc   // by this method.
1492*0a6a1f1dSLionel Sambuc   for (const auto *Property : IFace->properties()) {
1493*0a6a1f1dSLionel Sambuc     if ((Property->getGetterName() == IMD->getSelector() ||
1494*0a6a1f1dSLionel Sambuc          Property->getSetterName() == IMD->getSelector()) &&
1495*0a6a1f1dSLionel Sambuc         (Property->getPropertyIvarDecl() == IV))
1496f4a2713aSLionel Sambuc       return true;
1497f4a2713aSLionel Sambuc   }
1498f4a2713aSLionel Sambuc   return false;
1499f4a2713aSLionel Sambuc }
1500f4a2713aSLionel Sambuc 
SuperClassImplementsProperty(ObjCInterfaceDecl * IDecl,ObjCPropertyDecl * Prop)1501*0a6a1f1dSLionel Sambuc static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl,
1502*0a6a1f1dSLionel Sambuc                                          ObjCPropertyDecl *Prop) {
1503*0a6a1f1dSLionel Sambuc   bool SuperClassImplementsGetter = false;
1504*0a6a1f1dSLionel Sambuc   bool SuperClassImplementsSetter = false;
1505*0a6a1f1dSLionel Sambuc   if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
1506*0a6a1f1dSLionel Sambuc     SuperClassImplementsSetter = true;
1507*0a6a1f1dSLionel Sambuc 
1508*0a6a1f1dSLionel Sambuc   while (IDecl->getSuperClass()) {
1509*0a6a1f1dSLionel Sambuc     ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
1510*0a6a1f1dSLionel Sambuc     if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName()))
1511*0a6a1f1dSLionel Sambuc       SuperClassImplementsGetter = true;
1512*0a6a1f1dSLionel Sambuc 
1513*0a6a1f1dSLionel Sambuc     if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName()))
1514*0a6a1f1dSLionel Sambuc       SuperClassImplementsSetter = true;
1515*0a6a1f1dSLionel Sambuc     if (SuperClassImplementsGetter && SuperClassImplementsSetter)
1516*0a6a1f1dSLionel Sambuc       return true;
1517*0a6a1f1dSLionel Sambuc     IDecl = IDecl->getSuperClass();
1518*0a6a1f1dSLionel Sambuc   }
1519*0a6a1f1dSLionel Sambuc   return false;
1520*0a6a1f1dSLionel Sambuc }
1521f4a2713aSLionel Sambuc 
1522f4a2713aSLionel Sambuc /// \brief Default synthesizes all properties which must be synthesized
1523f4a2713aSLionel Sambuc /// in class's \@implementation.
DefaultSynthesizeProperties(Scope * S,ObjCImplDecl * IMPDecl,ObjCInterfaceDecl * IDecl)1524f4a2713aSLionel Sambuc void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
1525f4a2713aSLionel Sambuc                                        ObjCInterfaceDecl *IDecl) {
1526f4a2713aSLionel Sambuc 
1527f4a2713aSLionel Sambuc   ObjCInterfaceDecl::PropertyMap PropMap;
1528f4a2713aSLionel Sambuc   ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder;
1529f4a2713aSLionel Sambuc   IDecl->collectPropertiesToImplement(PropMap, PropertyOrder);
1530f4a2713aSLionel Sambuc   if (PropMap.empty())
1531f4a2713aSLionel Sambuc     return;
1532f4a2713aSLionel Sambuc   ObjCInterfaceDecl::PropertyMap SuperPropMap;
1533f4a2713aSLionel Sambuc   CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
1534f4a2713aSLionel Sambuc 
1535f4a2713aSLionel Sambuc   for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) {
1536f4a2713aSLionel Sambuc     ObjCPropertyDecl *Prop = PropertyOrder[i];
1537f4a2713aSLionel Sambuc     // Is there a matching property synthesize/dynamic?
1538f4a2713aSLionel Sambuc     if (Prop->isInvalidDecl() ||
1539f4a2713aSLionel Sambuc         Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional)
1540f4a2713aSLionel Sambuc       continue;
1541f4a2713aSLionel Sambuc     // Property may have been synthesized by user.
1542f4a2713aSLionel Sambuc     if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
1543f4a2713aSLionel Sambuc       continue;
1544f4a2713aSLionel Sambuc     if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
1545f4a2713aSLionel Sambuc       if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
1546f4a2713aSLionel Sambuc         continue;
1547f4a2713aSLionel Sambuc       if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
1548f4a2713aSLionel Sambuc         continue;
1549f4a2713aSLionel Sambuc     }
1550*0a6a1f1dSLionel Sambuc     if (ObjCPropertyImplDecl *PID =
1551*0a6a1f1dSLionel Sambuc         IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
1552*0a6a1f1dSLionel Sambuc       Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
1553*0a6a1f1dSLionel Sambuc         << Prop->getIdentifier();
1554*0a6a1f1dSLionel Sambuc       if (!PID->getLocation().isInvalid())
1555*0a6a1f1dSLionel Sambuc         Diag(PID->getLocation(), diag::note_property_synthesize);
1556*0a6a1f1dSLionel Sambuc       continue;
1557*0a6a1f1dSLionel Sambuc     }
1558f4a2713aSLionel Sambuc     ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()];
1559*0a6a1f1dSLionel Sambuc     if (ObjCProtocolDecl *Proto =
1560*0a6a1f1dSLionel Sambuc           dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) {
1561*0a6a1f1dSLionel Sambuc       // We won't auto-synthesize properties declared in protocols.
1562*0a6a1f1dSLionel Sambuc       // Suppress the warning if class's superclass implements property's
1563*0a6a1f1dSLionel Sambuc       // getter and implements property's setter (if readwrite property).
1564*0a6a1f1dSLionel Sambuc       // Or, if property is going to be implemented in its super class.
1565*0a6a1f1dSLionel Sambuc       if (!SuperClassImplementsProperty(IDecl, Prop) && !PropInSuperClass) {
1566*0a6a1f1dSLionel Sambuc         Diag(IMPDecl->getLocation(),
1567*0a6a1f1dSLionel Sambuc              diag::warn_auto_synthesizing_protocol_property)
1568*0a6a1f1dSLionel Sambuc           << Prop << Proto;
1569*0a6a1f1dSLionel Sambuc         Diag(Prop->getLocation(), diag::note_property_declare);
1570*0a6a1f1dSLionel Sambuc       }
1571*0a6a1f1dSLionel Sambuc       continue;
1572*0a6a1f1dSLionel Sambuc     }
1573*0a6a1f1dSLionel Sambuc     // If property to be implemented in the super class, ignore.
1574*0a6a1f1dSLionel Sambuc     if (PropInSuperClass) {
1575f4a2713aSLionel Sambuc       if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) &&
1576f4a2713aSLionel Sambuc           (PropInSuperClass->getPropertyAttributes() &
1577f4a2713aSLionel Sambuc            ObjCPropertyDecl::OBJC_PR_readonly) &&
1578f4a2713aSLionel Sambuc           !IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
1579f4a2713aSLionel Sambuc           !IDecl->HasUserDeclaredSetterMethod(Prop)) {
1580f4a2713aSLionel Sambuc         Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
1581*0a6a1f1dSLionel Sambuc         << Prop->getIdentifier();
1582f4a2713aSLionel Sambuc         Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
1583f4a2713aSLionel Sambuc       }
1584*0a6a1f1dSLionel Sambuc       else {
1585*0a6a1f1dSLionel Sambuc         Diag(Prop->getLocation(), diag::warn_autosynthesis_property_in_superclass)
1586*0a6a1f1dSLionel Sambuc         << Prop->getIdentifier();
1587*0a6a1f1dSLionel Sambuc         Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
1588*0a6a1f1dSLionel Sambuc         Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
1589f4a2713aSLionel Sambuc       }
1590f4a2713aSLionel Sambuc       continue;
1591f4a2713aSLionel Sambuc     }
1592f4a2713aSLionel Sambuc     // We use invalid SourceLocations for the synthesized ivars since they
1593f4a2713aSLionel Sambuc     // aren't really synthesized at a particular location; they just exist.
1594f4a2713aSLionel Sambuc     // Saying that they are located at the @implementation isn't really going
1595f4a2713aSLionel Sambuc     // to help users.
1596f4a2713aSLionel Sambuc     ObjCPropertyImplDecl *PIDecl = dyn_cast_or_null<ObjCPropertyImplDecl>(
1597f4a2713aSLionel Sambuc       ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(),
1598f4a2713aSLionel Sambuc                             true,
1599f4a2713aSLionel Sambuc                             /* property = */ Prop->getIdentifier(),
1600f4a2713aSLionel Sambuc                             /* ivar = */ Prop->getDefaultSynthIvarName(Context),
1601f4a2713aSLionel Sambuc                             Prop->getLocation()));
1602f4a2713aSLionel Sambuc     if (PIDecl) {
1603f4a2713aSLionel Sambuc       Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis);
1604f4a2713aSLionel Sambuc       Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
1605f4a2713aSLionel Sambuc     }
1606f4a2713aSLionel Sambuc   }
1607f4a2713aSLionel Sambuc }
1608f4a2713aSLionel Sambuc 
DefaultSynthesizeProperties(Scope * S,Decl * D)1609f4a2713aSLionel Sambuc void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) {
1610f4a2713aSLionel Sambuc   if (!LangOpts.ObjCDefaultSynthProperties || LangOpts.ObjCRuntime.isFragile())
1611f4a2713aSLionel Sambuc     return;
1612f4a2713aSLionel Sambuc   ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D);
1613f4a2713aSLionel Sambuc   if (!IC)
1614f4a2713aSLionel Sambuc     return;
1615f4a2713aSLionel Sambuc   if (ObjCInterfaceDecl* IDecl = IC->getClassInterface())
1616f4a2713aSLionel Sambuc     if (!IDecl->isObjCRequiresPropertyDefs())
1617f4a2713aSLionel Sambuc       DefaultSynthesizeProperties(S, IC, IDecl);
1618f4a2713aSLionel Sambuc }
1619f4a2713aSLionel Sambuc 
DiagnoseUnimplementedAccessor(Sema & S,ObjCInterfaceDecl * PrimaryClass,Selector Method,ObjCImplDecl * IMPDecl,ObjCContainerDecl * CDecl,ObjCCategoryDecl * C,ObjCPropertyDecl * Prop,Sema::SelectorSet & SMap)1620*0a6a1f1dSLionel Sambuc static void DiagnoseUnimplementedAccessor(Sema &S,
1621*0a6a1f1dSLionel Sambuc                                           ObjCInterfaceDecl *PrimaryClass,
1622*0a6a1f1dSLionel Sambuc                                           Selector Method,
1623*0a6a1f1dSLionel Sambuc                                           ObjCImplDecl* IMPDecl,
1624*0a6a1f1dSLionel Sambuc                                           ObjCContainerDecl *CDecl,
1625*0a6a1f1dSLionel Sambuc                                           ObjCCategoryDecl *C,
1626*0a6a1f1dSLionel Sambuc                                           ObjCPropertyDecl *Prop,
1627*0a6a1f1dSLionel Sambuc                                           Sema::SelectorSet &SMap) {
1628*0a6a1f1dSLionel Sambuc   // When reporting on missing property setter/getter implementation in
1629*0a6a1f1dSLionel Sambuc   // categories, do not report when they are declared in primary class,
1630*0a6a1f1dSLionel Sambuc   // class's protocol, or one of it super classes. This is because,
1631*0a6a1f1dSLionel Sambuc   // the class is going to implement them.
1632*0a6a1f1dSLionel Sambuc   if (!SMap.count(Method) &&
1633*0a6a1f1dSLionel Sambuc       (PrimaryClass == nullptr ||
1634*0a6a1f1dSLionel Sambuc        !PrimaryClass->lookupPropertyAccessor(Method, C))) {
1635*0a6a1f1dSLionel Sambuc         S.Diag(IMPDecl->getLocation(),
1636*0a6a1f1dSLionel Sambuc                isa<ObjCCategoryDecl>(CDecl) ?
1637*0a6a1f1dSLionel Sambuc                diag::warn_setter_getter_impl_required_in_category :
1638*0a6a1f1dSLionel Sambuc                diag::warn_setter_getter_impl_required)
1639*0a6a1f1dSLionel Sambuc             << Prop->getDeclName() << Method;
1640*0a6a1f1dSLionel Sambuc         S.Diag(Prop->getLocation(),
1641*0a6a1f1dSLionel Sambuc              diag::note_property_declare);
1642*0a6a1f1dSLionel Sambuc         if (S.LangOpts.ObjCDefaultSynthProperties &&
1643*0a6a1f1dSLionel Sambuc             S.LangOpts.ObjCRuntime.isNonFragile())
1644*0a6a1f1dSLionel Sambuc           if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
1645*0a6a1f1dSLionel Sambuc             if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
1646*0a6a1f1dSLionel Sambuc             S.Diag(RID->getLocation(), diag::note_suppressed_class_declare);
1647*0a6a1f1dSLionel Sambuc       }
1648*0a6a1f1dSLionel Sambuc }
1649*0a6a1f1dSLionel Sambuc 
DiagnoseUnimplementedProperties(Scope * S,ObjCImplDecl * IMPDecl,ObjCContainerDecl * CDecl,bool SynthesizeProperties)1650f4a2713aSLionel Sambuc void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
1651*0a6a1f1dSLionel Sambuc                                            ObjCContainerDecl *CDecl,
1652*0a6a1f1dSLionel Sambuc                                            bool SynthesizeProperties) {
1653*0a6a1f1dSLionel Sambuc   ObjCContainerDecl::PropertyMap PropMap;
1654*0a6a1f1dSLionel Sambuc   ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
1655*0a6a1f1dSLionel Sambuc 
1656*0a6a1f1dSLionel Sambuc   if (!SynthesizeProperties) {
1657f4a2713aSLionel Sambuc     ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
1658f4a2713aSLionel Sambuc     // Gather properties which need not be implemented in this class
1659f4a2713aSLionel Sambuc     // or category.
1660*0a6a1f1dSLionel Sambuc     if (!IDecl)
1661f4a2713aSLionel Sambuc       if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
1662f4a2713aSLionel Sambuc         // For categories, no need to implement properties declared in
1663f4a2713aSLionel Sambuc         // its primary class (and its super classes) if property is
1664f4a2713aSLionel Sambuc         // declared in one of those containers.
1665f4a2713aSLionel Sambuc         if ((IDecl = C->getClassInterface())) {
1666f4a2713aSLionel Sambuc           ObjCInterfaceDecl::PropertyDeclOrder PO;
1667f4a2713aSLionel Sambuc           IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO);
1668f4a2713aSLionel Sambuc         }
1669f4a2713aSLionel Sambuc       }
1670f4a2713aSLionel Sambuc     if (IDecl)
1671f4a2713aSLionel Sambuc       CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
1672f4a2713aSLionel Sambuc 
1673f4a2713aSLionel Sambuc     CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap);
1674*0a6a1f1dSLionel Sambuc   }
1675*0a6a1f1dSLionel Sambuc 
1676*0a6a1f1dSLionel Sambuc   // Scan the @interface to see if any of the protocols it adopts
1677*0a6a1f1dSLionel Sambuc   // require an explicit implementation, via attribute
1678*0a6a1f1dSLionel Sambuc   // 'objc_protocol_requires_explicit_implementation'.
1679*0a6a1f1dSLionel Sambuc   if (IDecl) {
1680*0a6a1f1dSLionel Sambuc     std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap;
1681*0a6a1f1dSLionel Sambuc 
1682*0a6a1f1dSLionel Sambuc     for (auto *PDecl : IDecl->all_referenced_protocols()) {
1683*0a6a1f1dSLionel Sambuc       if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
1684*0a6a1f1dSLionel Sambuc         continue;
1685*0a6a1f1dSLionel Sambuc       // Lazily construct a set of all the properties in the @interface
1686*0a6a1f1dSLionel Sambuc       // of the class, without looking at the superclass.  We cannot
1687*0a6a1f1dSLionel Sambuc       // use the call to CollectImmediateProperties() above as that
1688*0a6a1f1dSLionel Sambuc       // utilizes information from the super class's properties as well
1689*0a6a1f1dSLionel Sambuc       // as scans the adopted protocols.  This work only triggers for protocols
1690*0a6a1f1dSLionel Sambuc       // with the attribute, which is very rare, and only occurs when
1691*0a6a1f1dSLionel Sambuc       // analyzing the @implementation.
1692*0a6a1f1dSLionel Sambuc       if (!LazyMap) {
1693*0a6a1f1dSLionel Sambuc         ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
1694*0a6a1f1dSLionel Sambuc         LazyMap.reset(new ObjCContainerDecl::PropertyMap());
1695*0a6a1f1dSLionel Sambuc         CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap,
1696*0a6a1f1dSLionel Sambuc                                    /* IncludeProtocols */ false);
1697*0a6a1f1dSLionel Sambuc       }
1698*0a6a1f1dSLionel Sambuc       // Add the properties of 'PDecl' to the list of properties that
1699*0a6a1f1dSLionel Sambuc       // need to be implemented.
1700*0a6a1f1dSLionel Sambuc       for (auto *PropDecl : PDecl->properties()) {
1701*0a6a1f1dSLionel Sambuc         if ((*LazyMap)[PropDecl->getIdentifier()])
1702*0a6a1f1dSLionel Sambuc           continue;
1703*0a6a1f1dSLionel Sambuc         PropMap[PropDecl->getIdentifier()] = PropDecl;
1704*0a6a1f1dSLionel Sambuc       }
1705*0a6a1f1dSLionel Sambuc     }
1706*0a6a1f1dSLionel Sambuc   }
1707*0a6a1f1dSLionel Sambuc 
1708f4a2713aSLionel Sambuc   if (PropMap.empty())
1709f4a2713aSLionel Sambuc     return;
1710f4a2713aSLionel Sambuc 
1711f4a2713aSLionel Sambuc   llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
1712*0a6a1f1dSLionel Sambuc   for (const auto *I : IMPDecl->property_impls())
1713f4a2713aSLionel Sambuc     PropImplMap.insert(I->getPropertyDecl());
1714f4a2713aSLionel Sambuc 
1715f4a2713aSLionel Sambuc   SelectorSet InsMap;
1716f4a2713aSLionel Sambuc   // Collect property accessors implemented in current implementation.
1717*0a6a1f1dSLionel Sambuc   for (const auto *I : IMPDecl->instance_methods())
1718*0a6a1f1dSLionel Sambuc     InsMap.insert(I->getSelector());
1719f4a2713aSLionel Sambuc 
1720f4a2713aSLionel Sambuc   ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
1721*0a6a1f1dSLionel Sambuc   ObjCInterfaceDecl *PrimaryClass = nullptr;
1722f4a2713aSLionel Sambuc   if (C && !C->IsClassExtension())
1723f4a2713aSLionel Sambuc     if ((PrimaryClass = C->getClassInterface()))
1724f4a2713aSLionel Sambuc       // Report unimplemented properties in the category as well.
1725f4a2713aSLionel Sambuc       if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) {
1726f4a2713aSLionel Sambuc         // When reporting on missing setter/getters, do not report when
1727f4a2713aSLionel Sambuc         // setter/getter is implemented in category's primary class
1728f4a2713aSLionel Sambuc         // implementation.
1729*0a6a1f1dSLionel Sambuc         for (const auto *I : IMP->instance_methods())
1730*0a6a1f1dSLionel Sambuc           InsMap.insert(I->getSelector());
1731f4a2713aSLionel Sambuc       }
1732f4a2713aSLionel Sambuc 
1733f4a2713aSLionel Sambuc   for (ObjCContainerDecl::PropertyMap::iterator
1734f4a2713aSLionel Sambuc        P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
1735f4a2713aSLionel Sambuc     ObjCPropertyDecl *Prop = P->second;
1736f4a2713aSLionel Sambuc     // Is there a matching propery synthesize/dynamic?
1737f4a2713aSLionel Sambuc     if (Prop->isInvalidDecl() ||
1738f4a2713aSLionel Sambuc         Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
1739f4a2713aSLionel Sambuc         PropImplMap.count(Prop) ||
1740f4a2713aSLionel Sambuc         Prop->getAvailability() == AR_Unavailable)
1741f4a2713aSLionel Sambuc       continue;
1742f4a2713aSLionel Sambuc 
1743*0a6a1f1dSLionel Sambuc     // Diagnose unimplemented getters and setters.
1744*0a6a1f1dSLionel Sambuc     DiagnoseUnimplementedAccessor(*this,
1745*0a6a1f1dSLionel Sambuc           PrimaryClass, Prop->getGetterName(), IMPDecl, CDecl, C, Prop, InsMap);
1746*0a6a1f1dSLionel Sambuc     if (!Prop->isReadOnly())
1747*0a6a1f1dSLionel Sambuc       DiagnoseUnimplementedAccessor(*this,
1748*0a6a1f1dSLionel Sambuc                                     PrimaryClass, Prop->getSetterName(),
1749*0a6a1f1dSLionel Sambuc                                     IMPDecl, CDecl, C, Prop, InsMap);
1750f4a2713aSLionel Sambuc   }
1751f4a2713aSLionel Sambuc }
1752f4a2713aSLionel Sambuc 
1753f4a2713aSLionel Sambuc void
AtomicPropertySetterGetterRules(ObjCImplDecl * IMPDecl,ObjCContainerDecl * IDecl)1754f4a2713aSLionel Sambuc Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
1755f4a2713aSLionel Sambuc                                        ObjCContainerDecl* IDecl) {
1756f4a2713aSLionel Sambuc   // Rules apply in non-GC mode only
1757f4a2713aSLionel Sambuc   if (getLangOpts().getGC() != LangOptions::NonGC)
1758f4a2713aSLionel Sambuc     return;
1759*0a6a1f1dSLionel Sambuc   for (const auto *Property : IDecl->properties()) {
1760*0a6a1f1dSLionel Sambuc     ObjCMethodDecl *GetterMethod = nullptr;
1761*0a6a1f1dSLionel Sambuc     ObjCMethodDecl *SetterMethod = nullptr;
1762f4a2713aSLionel Sambuc     bool LookedUpGetterSetter = false;
1763f4a2713aSLionel Sambuc 
1764f4a2713aSLionel Sambuc     unsigned Attributes = Property->getPropertyAttributes();
1765f4a2713aSLionel Sambuc     unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten();
1766f4a2713aSLionel Sambuc 
1767f4a2713aSLionel Sambuc     if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic) &&
1768f4a2713aSLionel Sambuc         !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
1769f4a2713aSLionel Sambuc       GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
1770f4a2713aSLionel Sambuc       SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
1771f4a2713aSLionel Sambuc       LookedUpGetterSetter = true;
1772f4a2713aSLionel Sambuc       if (GetterMethod) {
1773f4a2713aSLionel Sambuc         Diag(GetterMethod->getLocation(),
1774f4a2713aSLionel Sambuc              diag::warn_default_atomic_custom_getter_setter)
1775f4a2713aSLionel Sambuc           << Property->getIdentifier() << 0;
1776f4a2713aSLionel Sambuc         Diag(Property->getLocation(), diag::note_property_declare);
1777f4a2713aSLionel Sambuc       }
1778f4a2713aSLionel Sambuc       if (SetterMethod) {
1779f4a2713aSLionel Sambuc         Diag(SetterMethod->getLocation(),
1780f4a2713aSLionel Sambuc              diag::warn_default_atomic_custom_getter_setter)
1781f4a2713aSLionel Sambuc           << Property->getIdentifier() << 1;
1782f4a2713aSLionel Sambuc         Diag(Property->getLocation(), diag::note_property_declare);
1783f4a2713aSLionel Sambuc       }
1784f4a2713aSLionel Sambuc     }
1785f4a2713aSLionel Sambuc 
1786f4a2713aSLionel Sambuc     // We only care about readwrite atomic property.
1787f4a2713aSLionel Sambuc     if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
1788f4a2713aSLionel Sambuc         !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
1789f4a2713aSLionel Sambuc       continue;
1790f4a2713aSLionel Sambuc     if (const ObjCPropertyImplDecl *PIDecl
1791f4a2713aSLionel Sambuc          = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
1792f4a2713aSLionel Sambuc       if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
1793f4a2713aSLionel Sambuc         continue;
1794f4a2713aSLionel Sambuc       if (!LookedUpGetterSetter) {
1795f4a2713aSLionel Sambuc         GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
1796f4a2713aSLionel Sambuc         SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
1797f4a2713aSLionel Sambuc       }
1798f4a2713aSLionel Sambuc       if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
1799f4a2713aSLionel Sambuc         SourceLocation MethodLoc =
1800f4a2713aSLionel Sambuc           (GetterMethod ? GetterMethod->getLocation()
1801f4a2713aSLionel Sambuc                         : SetterMethod->getLocation());
1802f4a2713aSLionel Sambuc         Diag(MethodLoc, diag::warn_atomic_property_rule)
1803*0a6a1f1dSLionel Sambuc           << Property->getIdentifier() << (GetterMethod != nullptr)
1804*0a6a1f1dSLionel Sambuc           << (SetterMethod != nullptr);
1805f4a2713aSLionel Sambuc         // fixit stuff.
1806f4a2713aSLionel Sambuc         if (!AttributesAsWritten) {
1807f4a2713aSLionel Sambuc           if (Property->getLParenLoc().isValid()) {
1808f4a2713aSLionel Sambuc             // @property () ... case.
1809f4a2713aSLionel Sambuc             SourceRange PropSourceRange(Property->getAtLoc(),
1810f4a2713aSLionel Sambuc                                         Property->getLParenLoc());
1811f4a2713aSLionel Sambuc             Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
1812f4a2713aSLionel Sambuc               FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic");
1813f4a2713aSLionel Sambuc           }
1814f4a2713aSLionel Sambuc           else {
1815f4a2713aSLionel Sambuc             //@property id etc.
1816f4a2713aSLionel Sambuc             SourceLocation endLoc =
1817f4a2713aSLionel Sambuc               Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
1818f4a2713aSLionel Sambuc             endLoc = endLoc.getLocWithOffset(-1);
1819f4a2713aSLionel Sambuc             SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
1820f4a2713aSLionel Sambuc             Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
1821f4a2713aSLionel Sambuc               FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) ");
1822f4a2713aSLionel Sambuc           }
1823f4a2713aSLionel Sambuc         }
1824f4a2713aSLionel Sambuc         else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
1825f4a2713aSLionel Sambuc           // @property () ... case.
1826f4a2713aSLionel Sambuc           SourceLocation endLoc = Property->getLParenLoc();
1827f4a2713aSLionel Sambuc           SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
1828f4a2713aSLionel Sambuc           Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
1829f4a2713aSLionel Sambuc            FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, ");
1830f4a2713aSLionel Sambuc         }
1831f4a2713aSLionel Sambuc         else
1832f4a2713aSLionel Sambuc           Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
1833f4a2713aSLionel Sambuc         Diag(Property->getLocation(), diag::note_property_declare);
1834f4a2713aSLionel Sambuc       }
1835f4a2713aSLionel Sambuc     }
1836f4a2713aSLionel Sambuc   }
1837f4a2713aSLionel Sambuc }
1838f4a2713aSLionel Sambuc 
DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl * D)1839f4a2713aSLionel Sambuc void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) {
1840f4a2713aSLionel Sambuc   if (getLangOpts().getGC() == LangOptions::GCOnly)
1841f4a2713aSLionel Sambuc     return;
1842f4a2713aSLionel Sambuc 
1843*0a6a1f1dSLionel Sambuc   for (const auto *PID : D->property_impls()) {
1844f4a2713aSLionel Sambuc     const ObjCPropertyDecl *PD = PID->getPropertyDecl();
1845f4a2713aSLionel Sambuc     if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
1846f4a2713aSLionel Sambuc         !D->getInstanceMethod(PD->getGetterName())) {
1847f4a2713aSLionel Sambuc       ObjCMethodDecl *method = PD->getGetterMethodDecl();
1848f4a2713aSLionel Sambuc       if (!method)
1849f4a2713aSLionel Sambuc         continue;
1850f4a2713aSLionel Sambuc       ObjCMethodFamily family = method->getMethodFamily();
1851f4a2713aSLionel Sambuc       if (family == OMF_alloc || family == OMF_copy ||
1852f4a2713aSLionel Sambuc           family == OMF_mutableCopy || family == OMF_new) {
1853f4a2713aSLionel Sambuc         if (getLangOpts().ObjCAutoRefCount)
1854*0a6a1f1dSLionel Sambuc           Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule);
1855f4a2713aSLionel Sambuc         else
1856*0a6a1f1dSLionel Sambuc           Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule);
1857f4a2713aSLionel Sambuc       }
1858f4a2713aSLionel Sambuc     }
1859f4a2713aSLionel Sambuc   }
1860f4a2713aSLionel Sambuc }
1861f4a2713aSLionel Sambuc 
DiagnoseMissingDesignatedInitOverrides(const ObjCImplementationDecl * ImplD,const ObjCInterfaceDecl * IFD)1862*0a6a1f1dSLionel Sambuc void Sema::DiagnoseMissingDesignatedInitOverrides(
1863*0a6a1f1dSLionel Sambuc                                             const ObjCImplementationDecl *ImplD,
1864*0a6a1f1dSLionel Sambuc                                             const ObjCInterfaceDecl *IFD) {
1865*0a6a1f1dSLionel Sambuc   assert(IFD->hasDesignatedInitializers());
1866*0a6a1f1dSLionel Sambuc   const ObjCInterfaceDecl *SuperD = IFD->getSuperClass();
1867*0a6a1f1dSLionel Sambuc   if (!SuperD)
1868*0a6a1f1dSLionel Sambuc     return;
1869*0a6a1f1dSLionel Sambuc 
1870*0a6a1f1dSLionel Sambuc   SelectorSet InitSelSet;
1871*0a6a1f1dSLionel Sambuc   for (const auto *I : ImplD->instance_methods())
1872*0a6a1f1dSLionel Sambuc     if (I->getMethodFamily() == OMF_init)
1873*0a6a1f1dSLionel Sambuc       InitSelSet.insert(I->getSelector());
1874*0a6a1f1dSLionel Sambuc 
1875*0a6a1f1dSLionel Sambuc   SmallVector<const ObjCMethodDecl *, 8> DesignatedInits;
1876*0a6a1f1dSLionel Sambuc   SuperD->getDesignatedInitializers(DesignatedInits);
1877*0a6a1f1dSLionel Sambuc   for (SmallVector<const ObjCMethodDecl *, 8>::iterator
1878*0a6a1f1dSLionel Sambuc          I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) {
1879*0a6a1f1dSLionel Sambuc     const ObjCMethodDecl *MD = *I;
1880*0a6a1f1dSLionel Sambuc     if (!InitSelSet.count(MD->getSelector())) {
1881*0a6a1f1dSLionel Sambuc       Diag(ImplD->getLocation(),
1882*0a6a1f1dSLionel Sambuc            diag::warn_objc_implementation_missing_designated_init_override)
1883*0a6a1f1dSLionel Sambuc         << MD->getSelector();
1884*0a6a1f1dSLionel Sambuc       Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
1885*0a6a1f1dSLionel Sambuc     }
1886*0a6a1f1dSLionel Sambuc   }
1887*0a6a1f1dSLionel Sambuc }
1888*0a6a1f1dSLionel Sambuc 
1889f4a2713aSLionel Sambuc /// AddPropertyAttrs - Propagates attributes from a property to the
1890f4a2713aSLionel Sambuc /// implicitly-declared getter or setter for that property.
AddPropertyAttrs(Sema & S,ObjCMethodDecl * PropertyMethod,ObjCPropertyDecl * Property)1891f4a2713aSLionel Sambuc static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
1892f4a2713aSLionel Sambuc                              ObjCPropertyDecl *Property) {
1893f4a2713aSLionel Sambuc   // Should we just clone all attributes over?
1894*0a6a1f1dSLionel Sambuc   for (const auto *A : Property->attrs()) {
1895*0a6a1f1dSLionel Sambuc     if (isa<DeprecatedAttr>(A) ||
1896*0a6a1f1dSLionel Sambuc         isa<UnavailableAttr>(A) ||
1897*0a6a1f1dSLionel Sambuc         isa<AvailabilityAttr>(A))
1898*0a6a1f1dSLionel Sambuc       PropertyMethod->addAttr(A->clone(S.Context));
1899f4a2713aSLionel Sambuc   }
1900f4a2713aSLionel Sambuc }
1901f4a2713aSLionel Sambuc 
1902f4a2713aSLionel Sambuc /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
1903f4a2713aSLionel Sambuc /// have the property type and issue diagnostics if they don't.
1904f4a2713aSLionel Sambuc /// Also synthesize a getter/setter method if none exist (and update the
1905f4a2713aSLionel Sambuc /// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
1906f4a2713aSLionel Sambuc /// methods is the "right" thing to do.
ProcessPropertyDecl(ObjCPropertyDecl * property,ObjCContainerDecl * CD,ObjCPropertyDecl * redeclaredProperty,ObjCContainerDecl * lexicalDC)1907f4a2713aSLionel Sambuc void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
1908f4a2713aSLionel Sambuc                                ObjCContainerDecl *CD,
1909f4a2713aSLionel Sambuc                                ObjCPropertyDecl *redeclaredProperty,
1910f4a2713aSLionel Sambuc                                ObjCContainerDecl *lexicalDC) {
1911f4a2713aSLionel Sambuc 
1912f4a2713aSLionel Sambuc   ObjCMethodDecl *GetterMethod, *SetterMethod;
1913f4a2713aSLionel Sambuc 
1914*0a6a1f1dSLionel Sambuc   if (CD->isInvalidDecl())
1915*0a6a1f1dSLionel Sambuc     return;
1916*0a6a1f1dSLionel Sambuc 
1917f4a2713aSLionel Sambuc   GetterMethod = CD->getInstanceMethod(property->getGetterName());
1918f4a2713aSLionel Sambuc   SetterMethod = CD->getInstanceMethod(property->getSetterName());
1919f4a2713aSLionel Sambuc   DiagnosePropertyAccessorMismatch(property, GetterMethod,
1920f4a2713aSLionel Sambuc                                    property->getLocation());
1921f4a2713aSLionel Sambuc 
1922f4a2713aSLionel Sambuc   if (SetterMethod) {
1923f4a2713aSLionel Sambuc     ObjCPropertyDecl::PropertyAttributeKind CAttr =
1924f4a2713aSLionel Sambuc       property->getPropertyAttributes();
1925f4a2713aSLionel Sambuc     if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
1926*0a6a1f1dSLionel Sambuc         Context.getCanonicalType(SetterMethod->getReturnType()) !=
1927f4a2713aSLionel Sambuc             Context.VoidTy)
1928f4a2713aSLionel Sambuc       Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
1929f4a2713aSLionel Sambuc     if (SetterMethod->param_size() != 1 ||
1930f4a2713aSLionel Sambuc         !Context.hasSameUnqualifiedType(
1931f4a2713aSLionel Sambuc           (*SetterMethod->param_begin())->getType().getNonReferenceType(),
1932f4a2713aSLionel Sambuc           property->getType().getNonReferenceType())) {
1933f4a2713aSLionel Sambuc       Diag(property->getLocation(),
1934f4a2713aSLionel Sambuc            diag::warn_accessor_property_type_mismatch)
1935f4a2713aSLionel Sambuc         << property->getDeclName()
1936f4a2713aSLionel Sambuc         << SetterMethod->getSelector();
1937f4a2713aSLionel Sambuc       Diag(SetterMethod->getLocation(), diag::note_declared_at);
1938f4a2713aSLionel Sambuc     }
1939f4a2713aSLionel Sambuc   }
1940f4a2713aSLionel Sambuc 
1941f4a2713aSLionel Sambuc   // Synthesize getter/setter methods if none exist.
1942f4a2713aSLionel Sambuc   // Find the default getter and if one not found, add one.
1943f4a2713aSLionel Sambuc   // FIXME: The synthesized property we set here is misleading. We almost always
1944f4a2713aSLionel Sambuc   // synthesize these methods unless the user explicitly provided prototypes
1945f4a2713aSLionel Sambuc   // (which is odd, but allowed). Sema should be typechecking that the
1946f4a2713aSLionel Sambuc   // declarations jive in that situation (which it is not currently).
1947f4a2713aSLionel Sambuc   if (!GetterMethod) {
1948f4a2713aSLionel Sambuc     // No instance method of same name as property getter name was found.
1949f4a2713aSLionel Sambuc     // Declare a getter method and add it to the list of methods
1950f4a2713aSLionel Sambuc     // for this class.
1951f4a2713aSLionel Sambuc     SourceLocation Loc = redeclaredProperty ?
1952f4a2713aSLionel Sambuc       redeclaredProperty->getLocation() :
1953f4a2713aSLionel Sambuc       property->getLocation();
1954f4a2713aSLionel Sambuc 
1955f4a2713aSLionel Sambuc     GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
1956f4a2713aSLionel Sambuc                              property->getGetterName(),
1957*0a6a1f1dSLionel Sambuc                              property->getType(), nullptr, CD,
1958*0a6a1f1dSLionel Sambuc                              /*isInstance=*/true, /*isVariadic=*/false,
1959*0a6a1f1dSLionel Sambuc                              /*isPropertyAccessor=*/true,
1960f4a2713aSLionel Sambuc                              /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1961f4a2713aSLionel Sambuc                              (property->getPropertyImplementation() ==
1962f4a2713aSLionel Sambuc                               ObjCPropertyDecl::Optional) ?
1963f4a2713aSLionel Sambuc                              ObjCMethodDecl::Optional :
1964f4a2713aSLionel Sambuc                              ObjCMethodDecl::Required);
1965f4a2713aSLionel Sambuc     CD->addDecl(GetterMethod);
1966f4a2713aSLionel Sambuc 
1967f4a2713aSLionel Sambuc     AddPropertyAttrs(*this, GetterMethod, property);
1968f4a2713aSLionel Sambuc 
1969f4a2713aSLionel Sambuc     // FIXME: Eventually this shouldn't be needed, as the lexical context
1970f4a2713aSLionel Sambuc     // and the real context should be the same.
1971f4a2713aSLionel Sambuc     if (lexicalDC)
1972f4a2713aSLionel Sambuc       GetterMethod->setLexicalDeclContext(lexicalDC);
1973f4a2713aSLionel Sambuc     if (property->hasAttr<NSReturnsNotRetainedAttr>())
1974*0a6a1f1dSLionel Sambuc       GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
1975*0a6a1f1dSLionel Sambuc                                                                      Loc));
1976f4a2713aSLionel Sambuc 
1977f4a2713aSLionel Sambuc     if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
1978f4a2713aSLionel Sambuc       GetterMethod->addAttr(
1979*0a6a1f1dSLionel Sambuc         ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
1980*0a6a1f1dSLionel Sambuc 
1981*0a6a1f1dSLionel Sambuc     if (const SectionAttr *SA = property->getAttr<SectionAttr>())
1982*0a6a1f1dSLionel Sambuc       GetterMethod->addAttr(
1983*0a6a1f1dSLionel Sambuc           SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
1984*0a6a1f1dSLionel Sambuc                                       SA->getName(), Loc));
1985f4a2713aSLionel Sambuc 
1986f4a2713aSLionel Sambuc     if (getLangOpts().ObjCAutoRefCount)
1987f4a2713aSLionel Sambuc       CheckARCMethodDecl(GetterMethod);
1988f4a2713aSLionel Sambuc   } else
1989f4a2713aSLionel Sambuc     // A user declared getter will be synthesize when @synthesize of
1990f4a2713aSLionel Sambuc     // the property with the same name is seen in the @implementation
1991f4a2713aSLionel Sambuc     GetterMethod->setPropertyAccessor(true);
1992f4a2713aSLionel Sambuc   property->setGetterMethodDecl(GetterMethod);
1993f4a2713aSLionel Sambuc 
1994f4a2713aSLionel Sambuc   // Skip setter if property is read-only.
1995f4a2713aSLionel Sambuc   if (!property->isReadOnly()) {
1996f4a2713aSLionel Sambuc     // Find the default setter and if one not found, add one.
1997f4a2713aSLionel Sambuc     if (!SetterMethod) {
1998f4a2713aSLionel Sambuc       // No instance method of same name as property setter name was found.
1999f4a2713aSLionel Sambuc       // Declare a setter method and add it to the list of methods
2000f4a2713aSLionel Sambuc       // for this class.
2001f4a2713aSLionel Sambuc       SourceLocation Loc = redeclaredProperty ?
2002f4a2713aSLionel Sambuc         redeclaredProperty->getLocation() :
2003f4a2713aSLionel Sambuc         property->getLocation();
2004f4a2713aSLionel Sambuc 
2005f4a2713aSLionel Sambuc       SetterMethod =
2006f4a2713aSLionel Sambuc         ObjCMethodDecl::Create(Context, Loc, Loc,
2007*0a6a1f1dSLionel Sambuc                                property->getSetterName(), Context.VoidTy,
2008*0a6a1f1dSLionel Sambuc                                nullptr, CD, /*isInstance=*/true,
2009*0a6a1f1dSLionel Sambuc                                /*isVariadic=*/false,
2010f4a2713aSLionel Sambuc                                /*isPropertyAccessor=*/true,
2011f4a2713aSLionel Sambuc                                /*isImplicitlyDeclared=*/true,
2012f4a2713aSLionel Sambuc                                /*isDefined=*/false,
2013f4a2713aSLionel Sambuc                                (property->getPropertyImplementation() ==
2014f4a2713aSLionel Sambuc                                 ObjCPropertyDecl::Optional) ?
2015f4a2713aSLionel Sambuc                                 ObjCMethodDecl::Optional :
2016f4a2713aSLionel Sambuc                                 ObjCMethodDecl::Required);
2017f4a2713aSLionel Sambuc 
2018f4a2713aSLionel Sambuc       // Invent the arguments for the setter. We don't bother making a
2019f4a2713aSLionel Sambuc       // nice name for the argument.
2020f4a2713aSLionel Sambuc       ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
2021f4a2713aSLionel Sambuc                                                   Loc, Loc,
2022f4a2713aSLionel Sambuc                                                   property->getIdentifier(),
2023f4a2713aSLionel Sambuc                                     property->getType().getUnqualifiedType(),
2024*0a6a1f1dSLionel Sambuc                                                   /*TInfo=*/nullptr,
2025f4a2713aSLionel Sambuc                                                   SC_None,
2026*0a6a1f1dSLionel Sambuc                                                   nullptr);
2027f4a2713aSLionel Sambuc       SetterMethod->setMethodParams(Context, Argument, None);
2028f4a2713aSLionel Sambuc 
2029f4a2713aSLionel Sambuc       AddPropertyAttrs(*this, SetterMethod, property);
2030f4a2713aSLionel Sambuc 
2031f4a2713aSLionel Sambuc       CD->addDecl(SetterMethod);
2032f4a2713aSLionel Sambuc       // FIXME: Eventually this shouldn't be needed, as the lexical context
2033f4a2713aSLionel Sambuc       // and the real context should be the same.
2034f4a2713aSLionel Sambuc       if (lexicalDC)
2035f4a2713aSLionel Sambuc         SetterMethod->setLexicalDeclContext(lexicalDC);
2036*0a6a1f1dSLionel Sambuc       if (const SectionAttr *SA = property->getAttr<SectionAttr>())
2037*0a6a1f1dSLionel Sambuc         SetterMethod->addAttr(
2038*0a6a1f1dSLionel Sambuc             SectionAttr::CreateImplicit(Context, SectionAttr::GNU_section,
2039*0a6a1f1dSLionel Sambuc                                         SA->getName(), Loc));
2040f4a2713aSLionel Sambuc       // It's possible for the user to have set a very odd custom
2041f4a2713aSLionel Sambuc       // setter selector that causes it to have a method family.
2042f4a2713aSLionel Sambuc       if (getLangOpts().ObjCAutoRefCount)
2043f4a2713aSLionel Sambuc         CheckARCMethodDecl(SetterMethod);
2044f4a2713aSLionel Sambuc     } else
2045f4a2713aSLionel Sambuc       // A user declared setter will be synthesize when @synthesize of
2046f4a2713aSLionel Sambuc       // the property with the same name is seen in the @implementation
2047f4a2713aSLionel Sambuc       SetterMethod->setPropertyAccessor(true);
2048f4a2713aSLionel Sambuc     property->setSetterMethodDecl(SetterMethod);
2049f4a2713aSLionel Sambuc   }
2050f4a2713aSLionel Sambuc   // Add any synthesized methods to the global pool. This allows us to
2051f4a2713aSLionel Sambuc   // handle the following, which is supported by GCC (and part of the design).
2052f4a2713aSLionel Sambuc   //
2053f4a2713aSLionel Sambuc   // @interface Foo
2054f4a2713aSLionel Sambuc   // @property double bar;
2055f4a2713aSLionel Sambuc   // @end
2056f4a2713aSLionel Sambuc   //
2057f4a2713aSLionel Sambuc   // void thisIsUnfortunate() {
2058f4a2713aSLionel Sambuc   //   id foo;
2059f4a2713aSLionel Sambuc   //   double bar = [foo bar];
2060f4a2713aSLionel Sambuc   // }
2061f4a2713aSLionel Sambuc   //
2062f4a2713aSLionel Sambuc   if (GetterMethod)
2063f4a2713aSLionel Sambuc     AddInstanceMethodToGlobalPool(GetterMethod);
2064f4a2713aSLionel Sambuc   if (SetterMethod)
2065f4a2713aSLionel Sambuc     AddInstanceMethodToGlobalPool(SetterMethod);
2066f4a2713aSLionel Sambuc 
2067f4a2713aSLionel Sambuc   ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD);
2068f4a2713aSLionel Sambuc   if (!CurrentClass) {
2069f4a2713aSLionel Sambuc     if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CD))
2070f4a2713aSLionel Sambuc       CurrentClass = Cat->getClassInterface();
2071f4a2713aSLionel Sambuc     else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(CD))
2072f4a2713aSLionel Sambuc       CurrentClass = Impl->getClassInterface();
2073f4a2713aSLionel Sambuc   }
2074f4a2713aSLionel Sambuc   if (GetterMethod)
2075f4a2713aSLionel Sambuc     CheckObjCMethodOverrides(GetterMethod, CurrentClass, Sema::RTC_Unknown);
2076f4a2713aSLionel Sambuc   if (SetterMethod)
2077f4a2713aSLionel Sambuc     CheckObjCMethodOverrides(SetterMethod, CurrentClass, Sema::RTC_Unknown);
2078f4a2713aSLionel Sambuc }
2079f4a2713aSLionel Sambuc 
CheckObjCPropertyAttributes(Decl * PDecl,SourceLocation Loc,unsigned & Attributes,bool propertyInPrimaryClass)2080f4a2713aSLionel Sambuc void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
2081f4a2713aSLionel Sambuc                                        SourceLocation Loc,
2082f4a2713aSLionel Sambuc                                        unsigned &Attributes,
2083f4a2713aSLionel Sambuc                                        bool propertyInPrimaryClass) {
2084f4a2713aSLionel Sambuc   // FIXME: Improve the reported location.
2085f4a2713aSLionel Sambuc   if (!PDecl || PDecl->isInvalidDecl())
2086f4a2713aSLionel Sambuc     return;
2087f4a2713aSLionel Sambuc 
2088f4a2713aSLionel Sambuc   if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
2089f4a2713aSLionel Sambuc       (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
2090f4a2713aSLionel Sambuc     Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2091f4a2713aSLionel Sambuc     << "readonly" << "readwrite";
2092f4a2713aSLionel Sambuc 
2093f4a2713aSLionel Sambuc   ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
2094f4a2713aSLionel Sambuc   QualType PropertyTy = PropertyDecl->getType();
2095f4a2713aSLionel Sambuc   unsigned PropertyOwnership = getOwnershipRule(Attributes);
2096f4a2713aSLionel Sambuc 
2097f4a2713aSLionel Sambuc   // 'readonly' property with no obvious lifetime.
2098f4a2713aSLionel Sambuc   // its life time will be determined by its backing ivar.
2099*0a6a1f1dSLionel Sambuc   if (getLangOpts().ObjCAutoRefCount &&
2100*0a6a1f1dSLionel Sambuc       Attributes & ObjCDeclSpec::DQ_PR_readonly &&
2101*0a6a1f1dSLionel Sambuc       PropertyTy->isObjCRetainableType() &&
2102*0a6a1f1dSLionel Sambuc       !PropertyOwnership)
2103f4a2713aSLionel Sambuc     return;
2104f4a2713aSLionel Sambuc 
2105f4a2713aSLionel Sambuc   // Check for copy or retain on non-object types.
2106f4a2713aSLionel Sambuc   if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
2107f4a2713aSLionel Sambuc                     ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) &&
2108f4a2713aSLionel Sambuc       !PropertyTy->isObjCRetainableType() &&
2109*0a6a1f1dSLionel Sambuc       !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) {
2110f4a2713aSLionel Sambuc     Diag(Loc, diag::err_objc_property_requires_object)
2111f4a2713aSLionel Sambuc       << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" :
2112f4a2713aSLionel Sambuc           Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)");
2113f4a2713aSLionel Sambuc     Attributes &= ~(ObjCDeclSpec::DQ_PR_weak   | ObjCDeclSpec::DQ_PR_copy |
2114f4a2713aSLionel Sambuc                     ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong);
2115f4a2713aSLionel Sambuc     PropertyDecl->setInvalidDecl();
2116f4a2713aSLionel Sambuc   }
2117f4a2713aSLionel Sambuc 
2118f4a2713aSLionel Sambuc   // Check for more than one of { assign, copy, retain }.
2119f4a2713aSLionel Sambuc   if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
2120f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
2121f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2122f4a2713aSLionel Sambuc         << "assign" << "copy";
2123f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
2124f4a2713aSLionel Sambuc     }
2125f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
2126f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2127f4a2713aSLionel Sambuc         << "assign" << "retain";
2128f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
2129f4a2713aSLionel Sambuc     }
2130f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
2131f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2132f4a2713aSLionel Sambuc         << "assign" << "strong";
2133f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
2134f4a2713aSLionel Sambuc     }
2135f4a2713aSLionel Sambuc     if (getLangOpts().ObjCAutoRefCount  &&
2136f4a2713aSLionel Sambuc         (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
2137f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2138f4a2713aSLionel Sambuc         << "assign" << "weak";
2139f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
2140f4a2713aSLionel Sambuc     }
2141*0a6a1f1dSLionel Sambuc     if (PropertyDecl->hasAttr<IBOutletCollectionAttr>())
2142f4a2713aSLionel Sambuc       Diag(Loc, diag::warn_iboutletcollection_property_assign);
2143f4a2713aSLionel Sambuc   } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) {
2144f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
2145f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2146f4a2713aSLionel Sambuc         << "unsafe_unretained" << "copy";
2147f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
2148f4a2713aSLionel Sambuc     }
2149f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
2150f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2151f4a2713aSLionel Sambuc         << "unsafe_unretained" << "retain";
2152f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
2153f4a2713aSLionel Sambuc     }
2154f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
2155f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2156f4a2713aSLionel Sambuc         << "unsafe_unretained" << "strong";
2157f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
2158f4a2713aSLionel Sambuc     }
2159f4a2713aSLionel Sambuc     if (getLangOpts().ObjCAutoRefCount  &&
2160f4a2713aSLionel Sambuc         (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
2161f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2162f4a2713aSLionel Sambuc         << "unsafe_unretained" << "weak";
2163f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
2164f4a2713aSLionel Sambuc     }
2165f4a2713aSLionel Sambuc   } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
2166f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
2167f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2168f4a2713aSLionel Sambuc         << "copy" << "retain";
2169f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
2170f4a2713aSLionel Sambuc     }
2171f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
2172f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2173f4a2713aSLionel Sambuc         << "copy" << "strong";
2174f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
2175f4a2713aSLionel Sambuc     }
2176f4a2713aSLionel Sambuc     if (Attributes & ObjCDeclSpec::DQ_PR_weak) {
2177f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2178f4a2713aSLionel Sambuc         << "copy" << "weak";
2179f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
2180f4a2713aSLionel Sambuc     }
2181f4a2713aSLionel Sambuc   }
2182f4a2713aSLionel Sambuc   else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) &&
2183f4a2713aSLionel Sambuc            (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
2184f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2185f4a2713aSLionel Sambuc         << "retain" << "weak";
2186f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
2187f4a2713aSLionel Sambuc   }
2188f4a2713aSLionel Sambuc   else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) &&
2189f4a2713aSLionel Sambuc            (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
2190f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2191f4a2713aSLionel Sambuc         << "strong" << "weak";
2192f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
2193f4a2713aSLionel Sambuc   }
2194f4a2713aSLionel Sambuc 
2195f4a2713aSLionel Sambuc   if ((Attributes & ObjCDeclSpec::DQ_PR_atomic) &&
2196f4a2713aSLionel Sambuc       (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) {
2197f4a2713aSLionel Sambuc       Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2198f4a2713aSLionel Sambuc         << "atomic" << "nonatomic";
2199f4a2713aSLionel Sambuc       Attributes &= ~ObjCDeclSpec::DQ_PR_atomic;
2200f4a2713aSLionel Sambuc   }
2201f4a2713aSLionel Sambuc 
2202f4a2713aSLionel Sambuc   // Warn if user supplied no assignment attribute, property is
2203f4a2713aSLionel Sambuc   // readwrite, and this is an object type.
2204f4a2713aSLionel Sambuc   if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
2205f4a2713aSLionel Sambuc                       ObjCDeclSpec::DQ_PR_unsafe_unretained |
2206f4a2713aSLionel Sambuc                       ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong |
2207f4a2713aSLionel Sambuc                       ObjCDeclSpec::DQ_PR_weak)) &&
2208f4a2713aSLionel Sambuc       PropertyTy->isObjCObjectPointerType()) {
2209f4a2713aSLionel Sambuc       if (getLangOpts().ObjCAutoRefCount)
2210f4a2713aSLionel Sambuc         // With arc,  @property definitions should default to (strong) when
2211f4a2713aSLionel Sambuc         // not specified; including when property is 'readonly'.
2212f4a2713aSLionel Sambuc         PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
2213f4a2713aSLionel Sambuc       else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) {
2214f4a2713aSLionel Sambuc         bool isAnyClassTy =
2215f4a2713aSLionel Sambuc           (PropertyTy->isObjCClassType() ||
2216f4a2713aSLionel Sambuc            PropertyTy->isObjCQualifiedClassType());
2217f4a2713aSLionel Sambuc         // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
2218f4a2713aSLionel Sambuc         // issue any warning.
2219f4a2713aSLionel Sambuc         if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC)
2220f4a2713aSLionel Sambuc           ;
2221f4a2713aSLionel Sambuc         else if (propertyInPrimaryClass) {
2222f4a2713aSLionel Sambuc           // Don't issue warning on property with no life time in class
2223f4a2713aSLionel Sambuc           // extension as it is inherited from property in primary class.
2224f4a2713aSLionel Sambuc           // Skip this warning in gc-only mode.
2225f4a2713aSLionel Sambuc           if (getLangOpts().getGC() != LangOptions::GCOnly)
2226f4a2713aSLionel Sambuc             Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
2227f4a2713aSLionel Sambuc 
2228f4a2713aSLionel Sambuc           // If non-gc code warn that this is likely inappropriate.
2229f4a2713aSLionel Sambuc           if (getLangOpts().getGC() == LangOptions::NonGC)
2230f4a2713aSLionel Sambuc             Diag(Loc, diag::warn_objc_property_default_assign_on_object);
2231f4a2713aSLionel Sambuc         }
2232f4a2713aSLionel Sambuc       }
2233f4a2713aSLionel Sambuc 
2234f4a2713aSLionel Sambuc     // FIXME: Implement warning dependent on NSCopying being
2235f4a2713aSLionel Sambuc     // implemented. See also:
2236f4a2713aSLionel Sambuc     // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
2237f4a2713aSLionel Sambuc     // (please trim this list while you are at it).
2238f4a2713aSLionel Sambuc   }
2239f4a2713aSLionel Sambuc 
2240f4a2713aSLionel Sambuc   if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)
2241f4a2713aSLionel Sambuc       &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly)
2242f4a2713aSLionel Sambuc       && getLangOpts().getGC() == LangOptions::GCOnly
2243f4a2713aSLionel Sambuc       && PropertyTy->isBlockPointerType())
2244f4a2713aSLionel Sambuc     Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
2245f4a2713aSLionel Sambuc   else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) &&
2246f4a2713aSLionel Sambuc            !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
2247f4a2713aSLionel Sambuc            !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
2248f4a2713aSLionel Sambuc            PropertyTy->isBlockPointerType())
2249f4a2713aSLionel Sambuc       Diag(Loc, diag::warn_objc_property_retain_of_block);
2250f4a2713aSLionel Sambuc 
2251f4a2713aSLionel Sambuc   if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
2252f4a2713aSLionel Sambuc       (Attributes & ObjCDeclSpec::DQ_PR_setter))
2253f4a2713aSLionel Sambuc     Diag(Loc, diag::warn_objc_readonly_property_has_setter);
2254f4a2713aSLionel Sambuc 
2255f4a2713aSLionel Sambuc }
2256