SemaObjCProperty.cpp revision 527eec86ce96695a7198073e574bf4a184848d24
1//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10//  This file implements semantic analysis for Objective C @property and
11//  @synthesize declarations.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Sema/SemaInternal.h"
16#include "clang/Sema/Initialization.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/ExprObjC.h"
19#include "llvm/ADT/DenseSet.h"
20
21using namespace clang;
22
23//===----------------------------------------------------------------------===//
24// Grammar actions.
25//===----------------------------------------------------------------------===//
26
27/// Check the internal consistency of a property declaration.
28static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
29  if (property->isInvalidDecl()) return;
30
31  ObjCPropertyDecl::PropertyAttributeKind propertyKind
32    = property->getPropertyAttributes();
33  Qualifiers::ObjCLifetime propertyLifetime
34    = property->getType().getObjCLifetime();
35
36  // Nothing to do if we don't have a lifetime.
37  if (propertyLifetime == Qualifiers::OCL_None) return;
38
39  Qualifiers::ObjCLifetime expectedLifetime;
40  unsigned selector;
41
42  // Strong properties should have either strong or no lifetime.
43  if (propertyKind & (ObjCPropertyDecl::OBJC_PR_retain |
44                      ObjCPropertyDecl::OBJC_PR_strong |
45                      ObjCPropertyDecl::OBJC_PR_copy)) {
46    expectedLifetime = Qualifiers::OCL_Strong;
47    selector = 0;
48  } else if (propertyKind & ObjCPropertyDecl::OBJC_PR_weak) {
49    expectedLifetime = Qualifiers::OCL_Weak;
50    selector = 1;
51  } else if (propertyKind & (ObjCPropertyDecl::OBJC_PR_assign |
52                             ObjCPropertyDecl::OBJC_PR_unsafe_unretained) &&
53             property->getType()->isObjCRetainableType()) {
54    expectedLifetime = Qualifiers::OCL_ExplicitNone;
55    selector = 2;
56  } else {
57    // We have a lifetime qualifier but no dominating property
58    // attribute.  That's okay.
59    return;
60  }
61
62  if (propertyLifetime == expectedLifetime) return;
63
64  property->setInvalidDecl();
65  S.Diag(property->getLocation(),
66         diag::err_arc_inconsistent_property_ownership)
67    << property->getDeclName()
68    << selector
69    << propertyLifetime;
70}
71
72Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
73                          FieldDeclarator &FD,
74                          ObjCDeclSpec &ODS,
75                          Selector GetterSel,
76                          Selector SetterSel,
77                          Decl *ClassCategory,
78                          bool *isOverridingProperty,
79                          tok::ObjCKeywordKind MethodImplKind,
80                          DeclContext *lexicalDC) {
81  unsigned Attributes = ODS.getPropertyAttributes();
82  TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
83  QualType T = TSI->getType();
84  if ((getLangOptions().getGCMode() != LangOptions::NonGC &&
85       T.isObjCGCWeak()) ||
86      (getLangOptions().ObjCAutoRefCount &&
87       T.getObjCLifetime() == Qualifiers::OCL_Weak))
88    Attributes |= ObjCDeclSpec::DQ_PR_weak;
89
90  bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
91                      // default is readwrite!
92                      !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
93  // property is defaulted to 'assign' if it is readwrite and is
94  // not retain or copy
95  bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
96                   (isReadWrite &&
97                    !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
98                    !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
99                    !(Attributes & ObjCDeclSpec::DQ_PR_copy) &&
100                    !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) &&
101                    !(Attributes & ObjCDeclSpec::DQ_PR_weak)));
102
103  // Proceed with constructing the ObjCPropertDecls.
104  ObjCContainerDecl *ClassDecl =
105    cast<ObjCContainerDecl>(ClassCategory);
106
107  if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
108    if (CDecl->IsClassExtension()) {
109      Decl *Res = HandlePropertyInClassExtension(S, CDecl, AtLoc,
110                                           FD, GetterSel, SetterSel,
111                                           isAssign, isReadWrite,
112                                           Attributes,
113                                           isOverridingProperty, TSI,
114                                           MethodImplKind);
115      if (Res) {
116        CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
117        if (getLangOptions().ObjCAutoRefCount)
118          checkARCPropertyDecl(*this, cast<ObjCPropertyDecl>(Res));
119      }
120      return Res;
121    }
122
123  ObjCPropertyDecl *Res = CreatePropertyDecl(S, ClassDecl, AtLoc, FD,
124                                             GetterSel, SetterSel,
125                                             isAssign, isReadWrite,
126                                             Attributes, TSI, MethodImplKind);
127  if (lexicalDC)
128    Res->setLexicalDeclContext(lexicalDC);
129
130  // Validate the attributes on the @property.
131  CheckObjCPropertyAttributes(Res, AtLoc, Attributes);
132
133  if (getLangOptions().ObjCAutoRefCount)
134    checkARCPropertyDecl(*this, Res);
135
136  return Res;
137}
138
139Decl *
140Sema::HandlePropertyInClassExtension(Scope *S, ObjCCategoryDecl *CDecl,
141                                     SourceLocation AtLoc, FieldDeclarator &FD,
142                                     Selector GetterSel, Selector SetterSel,
143                                     const bool isAssign,
144                                     const bool isReadWrite,
145                                     const unsigned Attributes,
146                                     bool *isOverridingProperty,
147                                     TypeSourceInfo *T,
148                                     tok::ObjCKeywordKind MethodImplKind) {
149
150  // Diagnose if this property is already in continuation class.
151  DeclContext *DC = cast<DeclContext>(CDecl);
152  IdentifierInfo *PropertyId = FD.D.getIdentifier();
153  ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
154
155  if (CCPrimary)
156    // Check for duplicate declaration of this property in current and
157    // other class extensions.
158    for (const ObjCCategoryDecl *ClsExtDecl =
159         CCPrimary->getFirstClassExtension();
160         ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) {
161      if (ObjCPropertyDecl *prevDecl =
162          ObjCPropertyDecl::findPropertyDecl(ClsExtDecl, PropertyId)) {
163        Diag(AtLoc, diag::err_duplicate_property);
164        Diag(prevDecl->getLocation(), diag::note_property_declare);
165        return 0;
166      }
167    }
168
169  // Create a new ObjCPropertyDecl with the DeclContext being
170  // the class extension.
171  // FIXME. We should really be using CreatePropertyDecl for this.
172  ObjCPropertyDecl *PDecl =
173    ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
174                             PropertyId, AtLoc, T);
175  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
176    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
177  if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
178    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
179  // Set setter/getter selector name. Needed later.
180  PDecl->setGetterName(GetterSel);
181  PDecl->setSetterName(SetterSel);
182  ProcessDeclAttributes(S, PDecl, FD.D);
183  DC->addDecl(PDecl);
184
185  // We need to look in the @interface to see if the @property was
186  // already declared.
187  if (!CCPrimary) {
188    Diag(CDecl->getLocation(), diag::err_continuation_class);
189    *isOverridingProperty = true;
190    return 0;
191  }
192
193  // Find the property in continuation class's primary class only.
194  ObjCPropertyDecl *PIDecl =
195    CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
196
197  if (!PIDecl) {
198    // No matching property found in the primary class. Just fall thru
199    // and add property to continuation class's primary class.
200    ObjCPropertyDecl *PDecl =
201      CreatePropertyDecl(S, CCPrimary, AtLoc,
202                         FD, GetterSel, SetterSel, isAssign, isReadWrite,
203                         Attributes, T, MethodImplKind, DC);
204
205    // A case of continuation class adding a new property in the class. This
206    // is not what it was meant for. However, gcc supports it and so should we.
207    // Make sure setter/getters are declared here.
208    ProcessPropertyDecl(PDecl, CCPrimary, /* redeclaredProperty = */ 0,
209                        /* lexicalDC = */ CDecl);
210    return PDecl;
211  }
212
213  // The property 'PIDecl's readonly attribute will be over-ridden
214  // with continuation class's readwrite property attribute!
215  unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
216  if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
217    unsigned retainCopyNonatomic =
218    (ObjCPropertyDecl::OBJC_PR_retain |
219     ObjCPropertyDecl::OBJC_PR_strong |
220     ObjCPropertyDecl::OBJC_PR_copy |
221     ObjCPropertyDecl::OBJC_PR_nonatomic);
222    if ((Attributes & retainCopyNonatomic) !=
223        (PIkind & retainCopyNonatomic)) {
224      Diag(AtLoc, diag::warn_property_attr_mismatch);
225      Diag(PIDecl->getLocation(), diag::note_property_declare);
226    }
227    DeclContext *DC = cast<DeclContext>(CCPrimary);
228    if (!ObjCPropertyDecl::findPropertyDecl(DC,
229                                 PIDecl->getDeclName().getAsIdentifierInfo())) {
230      // Protocol is not in the primary class. Must build one for it.
231      ObjCDeclSpec ProtocolPropertyODS;
232      // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
233      // and ObjCPropertyDecl::PropertyAttributeKind have identical
234      // values.  Should consolidate both into one enum type.
235      ProtocolPropertyODS.
236      setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
237                            PIkind);
238
239      Decl *ProtocolPtrTy =
240        ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS,
241                      PIDecl->getGetterName(),
242                      PIDecl->getSetterName(),
243                      CCPrimary, isOverridingProperty,
244                      MethodImplKind,
245                      /* lexicalDC = */ CDecl);
246      PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
247    }
248    PIDecl->makeitReadWriteAttribute();
249    if (Attributes & ObjCDeclSpec::DQ_PR_retain)
250      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
251    if (Attributes & ObjCDeclSpec::DQ_PR_strong)
252      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
253    if (Attributes & ObjCDeclSpec::DQ_PR_copy)
254      PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
255    PIDecl->setSetterName(SetterSel);
256  } else {
257    // Tailor the diagnostics for the common case where a readwrite
258    // property is declared both in the @interface and the continuation.
259    // This is a common error where the user often intended the original
260    // declaration to be readonly.
261    unsigned diag =
262      (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
263      (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite)
264      ? diag::err_use_continuation_class_redeclaration_readwrite
265      : diag::err_use_continuation_class;
266    Diag(AtLoc, diag)
267      << CCPrimary->getDeclName();
268    Diag(PIDecl->getLocation(), diag::note_property_declare);
269  }
270  *isOverridingProperty = true;
271  // Make sure setter decl is synthesized, and added to primary class's list.
272  ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);
273  return 0;
274}
275
276ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
277                                           ObjCContainerDecl *CDecl,
278                                           SourceLocation AtLoc,
279                                           FieldDeclarator &FD,
280                                           Selector GetterSel,
281                                           Selector SetterSel,
282                                           const bool isAssign,
283                                           const bool isReadWrite,
284                                           const unsigned Attributes,
285                                           TypeSourceInfo *TInfo,
286                                           tok::ObjCKeywordKind MethodImplKind,
287                                           DeclContext *lexicalDC){
288  IdentifierInfo *PropertyId = FD.D.getIdentifier();
289  QualType T = TInfo->getType();
290
291  // Issue a warning if property is 'assign' as default and its object, which is
292  // gc'able conforms to NSCopying protocol
293  if (getLangOptions().getGCMode() != LangOptions::NonGC &&
294      isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
295    if (const ObjCObjectPointerType *ObjPtrTy =
296          T->getAs<ObjCObjectPointerType>()) {
297      ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
298      if (IDecl)
299        if (ObjCProtocolDecl* PNSCopying =
300            LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
301          if (IDecl->ClassImplementsProtocol(PNSCopying, true))
302            Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
303    }
304  if (T->isObjCObjectType())
305    Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object);
306
307  DeclContext *DC = cast<DeclContext>(CDecl);
308  ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
309                                                     FD.D.getIdentifierLoc(),
310                                                     PropertyId, AtLoc, TInfo);
311
312  if (ObjCPropertyDecl *prevDecl =
313        ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
314    Diag(PDecl->getLocation(), diag::err_duplicate_property);
315    Diag(prevDecl->getLocation(), diag::note_property_declare);
316    PDecl->setInvalidDecl();
317  }
318  else {
319    DC->addDecl(PDecl);
320    if (lexicalDC)
321      PDecl->setLexicalDeclContext(lexicalDC);
322  }
323
324  if (T->isArrayType() || T->isFunctionType()) {
325    Diag(AtLoc, diag::err_property_type) << T;
326    PDecl->setInvalidDecl();
327  }
328
329  ProcessDeclAttributes(S, PDecl, FD.D);
330
331  // Regardless of setter/getter attribute, we save the default getter/setter
332  // selector names in anticipation of declaration of setter/getter methods.
333  PDecl->setGetterName(GetterSel);
334  PDecl->setSetterName(SetterSel);
335
336  unsigned attributesAsWritten = 0;
337  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
338    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly;
339  if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
340    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite;
341  if (Attributes & ObjCDeclSpec::DQ_PR_getter)
342    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter;
343  if (Attributes & ObjCDeclSpec::DQ_PR_setter)
344    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter;
345  if (Attributes & ObjCDeclSpec::DQ_PR_assign)
346    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign;
347  if (Attributes & ObjCDeclSpec::DQ_PR_retain)
348    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain;
349  if (Attributes & ObjCDeclSpec::DQ_PR_strong)
350    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong;
351  if (Attributes & ObjCDeclSpec::DQ_PR_weak)
352    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak;
353  if (Attributes & ObjCDeclSpec::DQ_PR_copy)
354    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy;
355  if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
356    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
357  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
358    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic;
359  if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
360    attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic;
361
362  PDecl->setPropertyAttributesAsWritten(
363                  (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten);
364
365  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
366    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
367
368  if (Attributes & ObjCDeclSpec::DQ_PR_getter)
369    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
370
371  if (Attributes & ObjCDeclSpec::DQ_PR_setter)
372    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
373
374  if (isReadWrite)
375    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
376
377  if (Attributes & ObjCDeclSpec::DQ_PR_retain)
378    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
379
380  if (Attributes & ObjCDeclSpec::DQ_PR_strong)
381    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
382
383  if (Attributes & ObjCDeclSpec::DQ_PR_weak)
384    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak);
385
386  if (Attributes & ObjCDeclSpec::DQ_PR_copy)
387    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
388
389  if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
390    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
391
392  if (isAssign)
393    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
394
395  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
396    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
397  else if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
398    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
399
400  // 'unsafe_unretained' is alias for 'assign'.
401  if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
402    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
403  if (isAssign)
404    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
405
406  if (MethodImplKind == tok::objc_required)
407    PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
408  else if (MethodImplKind == tok::objc_optional)
409    PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
410
411  return PDecl;
412}
413
414static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
415                                 ObjCPropertyDecl *property,
416                                 ObjCIvarDecl *ivar) {
417  if (property->isInvalidDecl() || ivar->isInvalidDecl()) return;
418
419  QualType propertyType = property->getType();
420  Qualifiers::ObjCLifetime propertyLifetime = propertyType.getObjCLifetime();
421  ObjCPropertyDecl::PropertyAttributeKind propertyKind
422    = property->getPropertyAttributes();
423
424  QualType ivarType = ivar->getType();
425  Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
426
427  // Case 1: strong properties.
428  if (propertyLifetime == Qualifiers::OCL_Strong ||
429      (propertyKind & (ObjCPropertyDecl::OBJC_PR_retain |
430                       ObjCPropertyDecl::OBJC_PR_strong |
431                       ObjCPropertyDecl::OBJC_PR_copy))) {
432    switch (ivarLifetime) {
433    case Qualifiers::OCL_Strong:
434      // Okay.
435      return;
436
437    case Qualifiers::OCL_None:
438    case Qualifiers::OCL_Autoreleasing:
439      // These aren't valid lifetimes for object ivars;  don't diagnose twice.
440      return;
441
442    case Qualifiers::OCL_ExplicitNone:
443    case Qualifiers::OCL_Weak:
444      S.Diag(propertyImplLoc, diag::err_arc_strong_property_ownership)
445        << property->getDeclName()
446        << ivar->getDeclName()
447        << ivarLifetime;
448      break;
449    }
450
451  // Case 2: weak properties.
452  } else if (propertyLifetime == Qualifiers::OCL_Weak ||
453             (propertyKind & ObjCPropertyDecl::OBJC_PR_weak)) {
454    switch (ivarLifetime) {
455    case Qualifiers::OCL_Weak:
456      // Okay.
457      return;
458
459    case Qualifiers::OCL_None:
460    case Qualifiers::OCL_Autoreleasing:
461      // These aren't valid lifetimes for object ivars;  don't diagnose twice.
462      return;
463
464    case Qualifiers::OCL_ExplicitNone:
465    case Qualifiers::OCL_Strong:
466      S.Diag(propertyImplLoc, diag::error_weak_property)
467        << property->getDeclName()
468        << ivar->getDeclName();
469      break;
470    }
471
472  // Case 3: assign properties.
473  } else if ((propertyKind & ObjCPropertyDecl::OBJC_PR_assign) &&
474             propertyType->isObjCRetainableType()) {
475    switch (ivarLifetime) {
476    case Qualifiers::OCL_ExplicitNone:
477      // Okay.
478      return;
479
480    case Qualifiers::OCL_None:
481    case Qualifiers::OCL_Autoreleasing:
482      // These aren't valid lifetimes for object ivars;  don't diagnose twice.
483      return;
484
485    case Qualifiers::OCL_Weak:
486    case Qualifiers::OCL_Strong:
487      S.Diag(propertyImplLoc, diag::err_arc_assign_property_ownership)
488        << property->getDeclName()
489        << ivar->getDeclName();
490      break;
491    }
492
493  // Any other property should be ignored.
494  } else {
495    return;
496  }
497
498  S.Diag(property->getLocation(), diag::note_property_declare);
499}
500
501
502/// ActOnPropertyImplDecl - This routine performs semantic checks and
503/// builds the AST node for a property implementation declaration; declared
504/// as @synthesize or @dynamic.
505///
506Decl *Sema::ActOnPropertyImplDecl(Scope *S,
507                                  SourceLocation AtLoc,
508                                  SourceLocation PropertyLoc,
509                                  bool Synthesize,
510                                  Decl *ClassCatImpDecl,
511                                  IdentifierInfo *PropertyId,
512                                  IdentifierInfo *PropertyIvar,
513                                  SourceLocation PropertyIvarLoc) {
514  ObjCContainerDecl *ClassImpDecl =
515    cast_or_null<ObjCContainerDecl>(ClassCatImpDecl);
516  // Make sure we have a context for the property implementation declaration.
517  if (!ClassImpDecl) {
518    Diag(AtLoc, diag::error_missing_property_context);
519    return 0;
520  }
521  ObjCPropertyDecl *property = 0;
522  ObjCInterfaceDecl* IDecl = 0;
523  // Find the class or category class where this property must have
524  // a declaration.
525  ObjCImplementationDecl *IC = 0;
526  ObjCCategoryImplDecl* CatImplClass = 0;
527  if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
528    IDecl = IC->getClassInterface();
529    // We always synthesize an interface for an implementation
530    // without an interface decl. So, IDecl is always non-zero.
531    assert(IDecl &&
532           "ActOnPropertyImplDecl - @implementation without @interface");
533
534    // Look for this property declaration in the @implementation's @interface
535    property = IDecl->FindPropertyDeclaration(PropertyId);
536    if (!property) {
537      Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
538      return 0;
539    }
540    unsigned PIkind = property->getPropertyAttributesAsWritten();
541    if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic |
542                   ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) {
543      if (AtLoc.isValid())
544        Diag(AtLoc, diag::warn_implicit_atomic_property);
545      else
546        Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
547      Diag(property->getLocation(), diag::note_property_declare);
548    }
549
550    if (const ObjCCategoryDecl *CD =
551        dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
552      if (!CD->IsClassExtension()) {
553        Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
554        Diag(property->getLocation(), diag::note_property_declare);
555        return 0;
556      }
557    }
558    if ((IC->meth_begin() != IC->meth_end()) && AtLoc.isValid()) {
559      if (getLangOptions().ObjCAutoRefCount)
560        Diag(AtLoc, diag::error_property_after_method_impl);
561      else
562        Diag(AtLoc, diag::warn_property_after_method_impl);
563      ObjCMethodDecl *method = *(IC->meth_begin());
564      Diag(method->getLocation(), diag::note_method_declared_at);
565    }
566  } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
567    if (Synthesize) {
568      Diag(AtLoc, diag::error_synthesize_category_decl);
569      return 0;
570    }
571    IDecl = CatImplClass->getClassInterface();
572    if (!IDecl) {
573      Diag(AtLoc, diag::error_missing_property_interface);
574      return 0;
575    }
576    ObjCCategoryDecl *Category =
577    IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
578
579    // If category for this implementation not found, it is an error which
580    // has already been reported eralier.
581    if (!Category)
582      return 0;
583    // Look for this property declaration in @implementation's category
584    property = Category->FindPropertyDeclaration(PropertyId);
585    if (!property) {
586      Diag(PropertyLoc, diag::error_bad_category_property_decl)
587      << Category->getDeclName();
588      return 0;
589    }
590  } else {
591    Diag(AtLoc, diag::error_bad_property_context);
592    return 0;
593  }
594  ObjCIvarDecl *Ivar = 0;
595  // Check that we have a valid, previously declared ivar for @synthesize
596  if (Synthesize) {
597    if (getLangOptions().ObjCAutoRefCount &&
598        !property->hasWrittenStorageAttribute() &&
599        property->getType()->isObjCRetainableType()) {
600      Diag(PropertyLoc, diag::err_arc_objc_property_default_assign_on_object);
601      Diag(property->getLocation(), diag::note_property_declare);
602    }
603
604    // @synthesize
605    if (!PropertyIvar)
606      PropertyIvar = PropertyId;
607    ObjCPropertyDecl::PropertyAttributeKind kind
608      = property->getPropertyAttributes();
609    QualType PropType = Context.getCanonicalType(property->getType());
610    QualType PropertyIvarType = PropType;
611    if (PropType->isReferenceType())
612      PropertyIvarType = cast<ReferenceType>(PropType)->getPointeeType();
613    // Check that this is a previously declared 'ivar' in 'IDecl' interface
614    ObjCInterfaceDecl *ClassDeclared;
615    Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
616    if (!Ivar) {
617      // In ARC, give the ivar a lifetime qualifier based on its
618      // property attributes.
619      if (getLangOptions().ObjCAutoRefCount &&
620          !PropertyIvarType.getObjCLifetime()) {
621
622        // retain/copy have retaining lifetime.
623        if (kind & (ObjCPropertyDecl::OBJC_PR_retain |
624                    ObjCPropertyDecl::OBJC_PR_strong |
625                    ObjCPropertyDecl::OBJC_PR_copy)) {
626          Qualifiers qs;
627          qs.addObjCLifetime(Qualifiers::OCL_Strong);
628          PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
629        }
630        else if (kind & ObjCPropertyDecl::OBJC_PR_weak) {
631          if (!getLangOptions().ObjCRuntimeHasWeak) {
632            Diag(PropertyLoc, diag::err_arc_weak_no_runtime);
633            Diag(property->getLocation(), diag::note_property_declare);
634          }
635          Qualifiers qs;
636          qs.addObjCLifetime(Qualifiers::OCL_Weak);
637          PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
638        }
639        else if (kind & ObjCPropertyDecl::OBJC_PR_assign &&
640                 PropertyIvarType->isObjCRetainableType()) {
641            // assume that an 'assign' property synthesizes __unsafe_unretained
642            // ivar
643            Qualifiers qs;
644            qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone);
645            PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
646        }
647      }
648
649      if (kind & ObjCPropertyDecl::OBJC_PR_weak &&
650          !getLangOptions().ObjCAutoRefCount &&
651          getLangOptions().getGCMode() == LangOptions::NonGC) {
652        Diag(PropertyLoc, diag::error_synthesize_weak_non_arc_or_gc);
653        Diag(property->getLocation(), diag::note_property_declare);
654      }
655
656      Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
657                                  PropertyLoc, PropertyLoc, PropertyIvar,
658                                  PropertyIvarType, /*Dinfo=*/0,
659                                  ObjCIvarDecl::Private,
660                                  (Expr *)0, true);
661      ClassImpDecl->addDecl(Ivar);
662      IDecl->makeDeclVisibleInContext(Ivar, false);
663      property->setPropertyIvarDecl(Ivar);
664
665      if (!getLangOptions().ObjCNonFragileABI)
666        Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId;
667      // Note! I deliberately want it to fall thru so, we have a
668      // a property implementation and to avoid future warnings.
669    } else if (getLangOptions().ObjCNonFragileABI &&
670               ClassDeclared != IDecl) {
671      Diag(PropertyLoc, diag::error_ivar_in_superclass_use)
672      << property->getDeclName() << Ivar->getDeclName()
673      << ClassDeclared->getDeclName();
674      Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
675      << Ivar << Ivar->getName();
676      // Note! I deliberately want it to fall thru so more errors are caught.
677    }
678    QualType IvarType = Context.getCanonicalType(Ivar->getType());
679
680    // Check that type of property and its ivar are type compatible.
681    if (PropertyIvarType != IvarType) {
682      bool compat = false;
683      if (isa<ObjCObjectPointerType>(PropertyIvarType)
684          && isa<ObjCObjectPointerType>(IvarType))
685        compat =
686          Context.canAssignObjCInterfaces(
687                                  PropertyIvarType->getAs<ObjCObjectPointerType>(),
688                                  IvarType->getAs<ObjCObjectPointerType>());
689      else {
690        SourceLocation Loc = PropertyIvarLoc;
691        if (Loc.isInvalid())
692          Loc = PropertyLoc;
693        compat = (CheckAssignmentConstraints(Loc, PropertyIvarType, IvarType)
694                    == Compatible);
695      }
696      if (!compat) {
697        Diag(PropertyLoc, diag::error_property_ivar_type)
698          << property->getDeclName() << PropType
699          << Ivar->getDeclName() << IvarType;
700        Diag(Ivar->getLocation(), diag::note_ivar_decl);
701        // Note! I deliberately want it to fall thru so, we have a
702        // a property implementation and to avoid future warnings.
703      }
704
705      // FIXME! Rules for properties are somewhat different that those
706      // for assignments. Use a new routine to consolidate all cases;
707      // specifically for property redeclarations as well as for ivars.
708      QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
709      QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
710      if (lhsType != rhsType &&
711          lhsType->isArithmeticType()) {
712        Diag(PropertyLoc, diag::error_property_ivar_type)
713          << property->getDeclName() << PropType
714          << Ivar->getDeclName() << IvarType;
715        Diag(Ivar->getLocation(), diag::note_ivar_decl);
716        // Fall thru - see previous comment
717      }
718      // __weak is explicit. So it works on Canonical type.
719      if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
720           getLangOptions().getGCMode() != LangOptions::NonGC)) {
721        Diag(PropertyLoc, diag::error_weak_property)
722        << property->getDeclName() << Ivar->getDeclName();
723        // Fall thru - see previous comment
724      }
725      // Fall thru - see previous comment
726      if ((property->getType()->isObjCObjectPointerType() ||
727           PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
728          getLangOptions().getGCMode() != LangOptions::NonGC) {
729        Diag(PropertyLoc, diag::error_strong_property)
730        << property->getDeclName() << Ivar->getDeclName();
731        // Fall thru - see previous comment
732      }
733    }
734    if (getLangOptions().ObjCAutoRefCount)
735      checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
736  } else if (PropertyIvar)
737    // @dynamic
738    Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
739
740  assert (property && "ActOnPropertyImplDecl - property declaration missing");
741  ObjCPropertyImplDecl *PIDecl =
742  ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
743                               property,
744                               (Synthesize ?
745                                ObjCPropertyImplDecl::Synthesize
746                                : ObjCPropertyImplDecl::Dynamic),
747                               Ivar, PropertyIvarLoc);
748  if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
749    getterMethod->createImplicitParams(Context, IDecl);
750    if (getLangOptions().CPlusPlus && Synthesize &&
751        Ivar->getType()->isRecordType()) {
752      // For Objective-C++, need to synthesize the AST for the IVAR object to be
753      // returned by the getter as it must conform to C++'s copy-return rules.
754      // FIXME. Eventually we want to do this for Objective-C as well.
755      ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
756      DeclRefExpr *SelfExpr =
757        new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(),
758                                  VK_RValue, SourceLocation());
759      Expr *IvarRefExpr =
760        new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
761                                      SelfExpr, true, true);
762      ExprResult Res =
763        PerformCopyInitialization(InitializedEntity::InitializeResult(
764                                    SourceLocation(),
765                                    getterMethod->getResultType(),
766                                    /*NRVO=*/false),
767                                  SourceLocation(),
768                                  Owned(IvarRefExpr));
769      if (!Res.isInvalid()) {
770        Expr *ResExpr = Res.takeAs<Expr>();
771        if (ResExpr)
772          ResExpr = MaybeCreateExprWithCleanups(ResExpr);
773        PIDecl->setGetterCXXConstructor(ResExpr);
774      }
775    }
776    if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
777        !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
778      Diag(getterMethod->getLocation(),
779           diag::warn_property_getter_owning_mismatch);
780      Diag(property->getLocation(), diag::note_property_declare);
781    }
782  }
783  if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
784    setterMethod->createImplicitParams(Context, IDecl);
785    if (getLangOptions().CPlusPlus && Synthesize
786        && Ivar->getType()->isRecordType()) {
787      // FIXME. Eventually we want to do this for Objective-C as well.
788      ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
789      DeclRefExpr *SelfExpr =
790        new (Context) DeclRefExpr(SelfDecl, SelfDecl->getType(),
791                                  VK_RValue, SourceLocation());
792      Expr *lhs =
793        new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), AtLoc,
794                                      SelfExpr, true, true);
795      ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
796      ParmVarDecl *Param = (*P);
797      QualType T = Param->getType();
798      if (T->isReferenceType())
799        T = T->getAs<ReferenceType>()->getPointeeType();
800      Expr *rhs = new (Context) DeclRefExpr(Param, T,
801                                            VK_LValue, SourceLocation());
802      ExprResult Res = BuildBinOp(S, lhs->getLocEnd(),
803                                  BO_Assign, lhs, rhs);
804      PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
805    }
806  }
807
808  if (IC) {
809    if (Synthesize)
810      if (ObjCPropertyImplDecl *PPIDecl =
811          IC->FindPropertyImplIvarDecl(PropertyIvar)) {
812        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
813        << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
814        << PropertyIvar;
815        Diag(PPIDecl->getLocation(), diag::note_previous_use);
816      }
817
818    if (ObjCPropertyImplDecl *PPIDecl
819        = IC->FindPropertyImplDecl(PropertyId)) {
820      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
821      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
822      return 0;
823    }
824    IC->addPropertyImplementation(PIDecl);
825    if (getLangOptions().ObjCDefaultSynthProperties &&
826        getLangOptions().ObjCNonFragileABI2) {
827      // Diagnose if an ivar was lazily synthesdized due to a previous
828      // use and if 1) property is @dynamic or 2) property is synthesized
829      // but it requires an ivar of different name.
830      ObjCInterfaceDecl *ClassDeclared=0;
831      ObjCIvarDecl *Ivar = 0;
832      if (!Synthesize)
833        Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
834      else {
835        if (PropertyIvar && PropertyIvar != PropertyId)
836          Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
837      }
838      // Issue diagnostics only if Ivar belongs to current class.
839      if (Ivar && Ivar->getSynthesize() &&
840          IC->getClassInterface() == ClassDeclared) {
841        Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
842        << PropertyId;
843        Ivar->setInvalidDecl();
844      }
845    }
846  } else {
847    if (Synthesize)
848      if (ObjCPropertyImplDecl *PPIDecl =
849          CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
850        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
851        << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
852        << PropertyIvar;
853        Diag(PPIDecl->getLocation(), diag::note_previous_use);
854      }
855
856    if (ObjCPropertyImplDecl *PPIDecl =
857        CatImplClass->FindPropertyImplDecl(PropertyId)) {
858      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
859      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
860      return 0;
861    }
862    CatImplClass->addPropertyImplementation(PIDecl);
863  }
864
865  return PIDecl;
866}
867
868//===----------------------------------------------------------------------===//
869// Helper methods.
870//===----------------------------------------------------------------------===//
871
872/// DiagnosePropertyMismatch - Compares two properties for their
873/// attributes and types and warns on a variety of inconsistencies.
874///
875void
876Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
877                               ObjCPropertyDecl *SuperProperty,
878                               const IdentifierInfo *inheritedName) {
879  ObjCPropertyDecl::PropertyAttributeKind CAttr =
880  Property->getPropertyAttributes();
881  ObjCPropertyDecl::PropertyAttributeKind SAttr =
882  SuperProperty->getPropertyAttributes();
883  if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
884      && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
885    Diag(Property->getLocation(), diag::warn_readonly_property)
886      << Property->getDeclName() << inheritedName;
887  if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
888      != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
889    Diag(Property->getLocation(), diag::warn_property_attribute)
890      << Property->getDeclName() << "copy" << inheritedName;
891  else {
892    unsigned CAttrRetain =
893      (CAttr &
894       (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
895    unsigned SAttrRetain =
896      (SAttr &
897       (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
898    bool CStrong = (CAttrRetain != 0);
899    bool SStrong = (SAttrRetain != 0);
900    if (CStrong != SStrong)
901      Diag(Property->getLocation(), diag::warn_property_attribute)
902        << Property->getDeclName() << "retain (or strong)" << inheritedName;
903  }
904
905  if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
906      != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic))
907    Diag(Property->getLocation(), diag::warn_property_attribute)
908      << Property->getDeclName() << "atomic" << inheritedName;
909  if (Property->getSetterName() != SuperProperty->getSetterName())
910    Diag(Property->getLocation(), diag::warn_property_attribute)
911      << Property->getDeclName() << "setter" << inheritedName;
912  if (Property->getGetterName() != SuperProperty->getGetterName())
913    Diag(Property->getLocation(), diag::warn_property_attribute)
914      << Property->getDeclName() << "getter" << inheritedName;
915
916  QualType LHSType =
917    Context.getCanonicalType(SuperProperty->getType());
918  QualType RHSType =
919    Context.getCanonicalType(Property->getType());
920
921  if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) {
922    // Do cases not handled in above.
923    // FIXME. For future support of covariant property types, revisit this.
924    bool IncompatibleObjC = false;
925    QualType ConvertedType;
926    if (!isObjCPointerConversion(RHSType, LHSType,
927                                 ConvertedType, IncompatibleObjC) ||
928        IncompatibleObjC)
929        Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
930        << Property->getType() << SuperProperty->getType() << inheritedName;
931  }
932}
933
934bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
935                                            ObjCMethodDecl *GetterMethod,
936                                            SourceLocation Loc) {
937  if (GetterMethod &&
938      GetterMethod->getResultType() != property->getType()) {
939    AssignConvertType result = Incompatible;
940    if (property->getType()->isObjCObjectPointerType())
941      result = CheckAssignmentConstraints(Loc, GetterMethod->getResultType(),
942                                          property->getType());
943    if (result != Compatible) {
944      Diag(Loc, diag::warn_accessor_property_type_mismatch)
945      << property->getDeclName()
946      << GetterMethod->getSelector();
947      Diag(GetterMethod->getLocation(), diag::note_declared_at);
948      return true;
949    }
950  }
951  return false;
952}
953
954/// ComparePropertiesInBaseAndSuper - This routine compares property
955/// declarations in base and its super class, if any, and issues
956/// diagnostics in a variety of inconsistent situations.
957///
958void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
959  ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
960  if (!SDecl)
961    return;
962  // FIXME: O(N^2)
963  for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(),
964       E = SDecl->prop_end(); S != E; ++S) {
965    ObjCPropertyDecl *SuperPDecl = (*S);
966    // Does property in super class has declaration in current class?
967    for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(),
968         E = IDecl->prop_end(); I != E; ++I) {
969      ObjCPropertyDecl *PDecl = (*I);
970      if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
971          DiagnosePropertyMismatch(PDecl, SuperPDecl,
972                                   SDecl->getIdentifier());
973    }
974  }
975}
976
977/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
978/// of properties declared in a protocol and compares their attribute against
979/// the same property declared in the class or category.
980void
981Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
982                                          ObjCProtocolDecl *PDecl) {
983  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
984  if (!IDecl) {
985    // Category
986    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
987    assert (CatDecl && "MatchOneProtocolPropertiesInClass");
988    if (!CatDecl->IsClassExtension())
989      for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
990           E = PDecl->prop_end(); P != E; ++P) {
991        ObjCPropertyDecl *Pr = (*P);
992        ObjCCategoryDecl::prop_iterator CP, CE;
993        // Is this property already in  category's list of properties?
994        for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP!=CE; ++CP)
995          if ((*CP)->getIdentifier() == Pr->getIdentifier())
996            break;
997        if (CP != CE)
998          // Property protocol already exist in class. Diagnose any mismatch.
999          DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
1000      }
1001    return;
1002  }
1003  for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
1004       E = PDecl->prop_end(); P != E; ++P) {
1005    ObjCPropertyDecl *Pr = (*P);
1006    ObjCInterfaceDecl::prop_iterator CP, CE;
1007    // Is this property already in  class's list of properties?
1008    for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP)
1009      if ((*CP)->getIdentifier() == Pr->getIdentifier())
1010        break;
1011    if (CP != CE)
1012      // Property protocol already exist in class. Diagnose any mismatch.
1013      DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
1014    }
1015}
1016
1017/// CompareProperties - This routine compares properties
1018/// declared in 'ClassOrProtocol' objects (which can be a class or an
1019/// inherited protocol with the list of properties for class/category 'CDecl'
1020///
1021void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) {
1022  Decl *ClassDecl = ClassOrProtocol;
1023  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
1024
1025  if (!IDecl) {
1026    // Category
1027    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
1028    assert (CatDecl && "CompareProperties");
1029    if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
1030      for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
1031           E = MDecl->protocol_end(); P != E; ++P)
1032      // Match properties of category with those of protocol (*P)
1033      MatchOneProtocolPropertiesInClass(CatDecl, *P);
1034
1035      // Go thru the list of protocols for this category and recursively match
1036      // their properties with those in the category.
1037      for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
1038           E = CatDecl->protocol_end(); P != E; ++P)
1039        CompareProperties(CatDecl, *P);
1040    } else {
1041      ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
1042      for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
1043           E = MD->protocol_end(); P != E; ++P)
1044        MatchOneProtocolPropertiesInClass(CatDecl, *P);
1045    }
1046    return;
1047  }
1048
1049  if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
1050    for (ObjCInterfaceDecl::all_protocol_iterator
1051          P = MDecl->all_referenced_protocol_begin(),
1052          E = MDecl->all_referenced_protocol_end(); P != E; ++P)
1053      // Match properties of class IDecl with those of protocol (*P).
1054      MatchOneProtocolPropertiesInClass(IDecl, *P);
1055
1056    // Go thru the list of protocols for this class and recursively match
1057    // their properties with those declared in the class.
1058    for (ObjCInterfaceDecl::all_protocol_iterator
1059          P = IDecl->all_referenced_protocol_begin(),
1060          E = IDecl->all_referenced_protocol_end(); P != E; ++P)
1061      CompareProperties(IDecl, *P);
1062  } else {
1063    ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
1064    for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
1065         E = MD->protocol_end(); P != E; ++P)
1066      MatchOneProtocolPropertiesInClass(IDecl, *P);
1067  }
1068}
1069
1070/// isPropertyReadonly - Return true if property is readonly, by searching
1071/// for the property in the class and in its categories and implementations
1072///
1073bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
1074                              ObjCInterfaceDecl *IDecl) {
1075  // by far the most common case.
1076  if (!PDecl->isReadOnly())
1077    return false;
1078  // Even if property is ready only, if interface has a user defined setter,
1079  // it is not considered read only.
1080  if (IDecl->getInstanceMethod(PDecl->getSetterName()))
1081    return false;
1082
1083  // Main class has the property as 'readonly'. Must search
1084  // through the category list to see if the property's
1085  // attribute has been over-ridden to 'readwrite'.
1086  for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
1087       Category; Category = Category->getNextClassCategory()) {
1088    // Even if property is ready only, if a category has a user defined setter,
1089    // it is not considered read only.
1090    if (Category->getInstanceMethod(PDecl->getSetterName()))
1091      return false;
1092    ObjCPropertyDecl *P =
1093      Category->FindPropertyDeclaration(PDecl->getIdentifier());
1094    if (P && !P->isReadOnly())
1095      return false;
1096  }
1097
1098  // Also, check for definition of a setter method in the implementation if
1099  // all else failed.
1100  if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) {
1101    if (ObjCImplementationDecl *IMD =
1102        dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) {
1103      if (IMD->getInstanceMethod(PDecl->getSetterName()))
1104        return false;
1105    } else if (ObjCCategoryImplDecl *CIMD =
1106               dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
1107      if (CIMD->getInstanceMethod(PDecl->getSetterName()))
1108        return false;
1109    }
1110  }
1111  // Lastly, look through the implementation (if one is in scope).
1112  if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation())
1113    if (ImpDecl->getInstanceMethod(PDecl->getSetterName()))
1114      return false;
1115  // If all fails, look at the super class.
1116  if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass())
1117    return isPropertyReadonly(PDecl, SIDecl);
1118  return true;
1119}
1120
1121/// CollectImmediateProperties - This routine collects all properties in
1122/// the class and its conforming protocols; but not those it its super class.
1123void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
1124            llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
1125            llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap) {
1126  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
1127    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
1128         E = IDecl->prop_end(); P != E; ++P) {
1129      ObjCPropertyDecl *Prop = (*P);
1130      PropMap[Prop->getIdentifier()] = Prop;
1131    }
1132    // scan through class's protocols.
1133    for (ObjCInterfaceDecl::all_protocol_iterator
1134         PI = IDecl->all_referenced_protocol_begin(),
1135         E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
1136        CollectImmediateProperties((*PI), PropMap, SuperPropMap);
1137  }
1138  if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
1139    if (!CATDecl->IsClassExtension())
1140      for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
1141           E = CATDecl->prop_end(); P != E; ++P) {
1142        ObjCPropertyDecl *Prop = (*P);
1143        PropMap[Prop->getIdentifier()] = Prop;
1144      }
1145    // scan through class's protocols.
1146    for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
1147         E = CATDecl->protocol_end(); PI != E; ++PI)
1148      CollectImmediateProperties((*PI), PropMap, SuperPropMap);
1149  }
1150  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
1151    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
1152         E = PDecl->prop_end(); P != E; ++P) {
1153      ObjCPropertyDecl *Prop = (*P);
1154      ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()];
1155      // Exclude property for protocols which conform to class's super-class,
1156      // as super-class has to implement the property.
1157      if (!PropertyFromSuper || PropertyFromSuper != Prop) {
1158        ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
1159        if (!PropEntry)
1160          PropEntry = Prop;
1161      }
1162    }
1163    // scan through protocol's protocols.
1164    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
1165         E = PDecl->protocol_end(); PI != E; ++PI)
1166      CollectImmediateProperties((*PI), PropMap, SuperPropMap);
1167  }
1168}
1169
1170/// CollectClassPropertyImplementations - This routine collects list of
1171/// properties to be implemented in the class. This includes, class's
1172/// and its conforming protocols' properties.
1173static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl,
1174                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
1175  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
1176    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
1177         E = IDecl->prop_end(); P != E; ++P) {
1178      ObjCPropertyDecl *Prop = (*P);
1179      PropMap[Prop->getIdentifier()] = Prop;
1180    }
1181    for (ObjCInterfaceDecl::all_protocol_iterator
1182         PI = IDecl->all_referenced_protocol_begin(),
1183         E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
1184      CollectClassPropertyImplementations((*PI), PropMap);
1185  }
1186  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
1187    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
1188         E = PDecl->prop_end(); P != E; ++P) {
1189      ObjCPropertyDecl *Prop = (*P);
1190      PropMap[Prop->getIdentifier()] = Prop;
1191    }
1192    // scan through protocol's protocols.
1193    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
1194         E = PDecl->protocol_end(); PI != E; ++PI)
1195      CollectClassPropertyImplementations((*PI), PropMap);
1196  }
1197}
1198
1199/// CollectSuperClassPropertyImplementations - This routine collects list of
1200/// properties to be implemented in super class(s) and also coming from their
1201/// conforming protocols.
1202static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
1203                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
1204  if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
1205    while (SDecl) {
1206      CollectClassPropertyImplementations(SDecl, PropMap);
1207      SDecl = SDecl->getSuperClass();
1208    }
1209  }
1210}
1211
1212/// LookupPropertyDecl - Looks up a property in the current class and all
1213/// its protocols.
1214ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
1215                                     IdentifierInfo *II) {
1216  if (const ObjCInterfaceDecl *IDecl =
1217        dyn_cast<ObjCInterfaceDecl>(CDecl)) {
1218    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
1219         E = IDecl->prop_end(); P != E; ++P) {
1220      ObjCPropertyDecl *Prop = (*P);
1221      if (Prop->getIdentifier() == II)
1222        return Prop;
1223    }
1224    // scan through class's protocols.
1225    for (ObjCInterfaceDecl::all_protocol_iterator
1226         PI = IDecl->all_referenced_protocol_begin(),
1227         E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) {
1228      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
1229      if (Prop)
1230        return Prop;
1231    }
1232  }
1233  else if (const ObjCProtocolDecl *PDecl =
1234            dyn_cast<ObjCProtocolDecl>(CDecl)) {
1235    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
1236         E = PDecl->prop_end(); P != E; ++P) {
1237      ObjCPropertyDecl *Prop = (*P);
1238      if (Prop->getIdentifier() == II)
1239        return Prop;
1240    }
1241    // scan through protocol's protocols.
1242    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
1243         E = PDecl->protocol_end(); PI != E; ++PI) {
1244      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
1245      if (Prop)
1246        return Prop;
1247    }
1248  }
1249  return 0;
1250}
1251
1252/// DefaultSynthesizeProperties - This routine default synthesizes all
1253/// properties which must be synthesized in class's @implementation.
1254void Sema::DefaultSynthesizeProperties (Scope *S, ObjCImplDecl* IMPDecl,
1255                                        ObjCInterfaceDecl *IDecl) {
1256
1257  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
1258  CollectClassPropertyImplementations(IDecl, PropMap);
1259  if (PropMap.empty())
1260    return;
1261  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap;
1262  CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
1263
1264  for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
1265       P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
1266    ObjCPropertyDecl *Prop = P->second;
1267    // If property to be implemented in the super class, ignore.
1268    if (SuperPropMap[Prop->getIdentifier()])
1269      continue;
1270    // Is there a matching propery synthesize/dynamic?
1271    if (Prop->isInvalidDecl() ||
1272        Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
1273        IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier()))
1274      continue;
1275    // Property may have been synthesized by user.
1276    if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
1277      continue;
1278    if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
1279      if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
1280        continue;
1281      if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
1282        continue;
1283    }
1284
1285
1286    // We use invalid SourceLocations for the synthesized ivars since they
1287    // aren't really synthesized at a particular location; they just exist.
1288    // Saying that they are located at the @implementation isn't really going
1289    // to help users.
1290    ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(),
1291                          true,IMPDecl,
1292                          Prop->getIdentifier(), Prop->getIdentifier(),
1293                          SourceLocation());
1294  }
1295}
1296
1297void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
1298                                      ObjCContainerDecl *CDecl,
1299                                      const llvm::DenseSet<Selector>& InsMap) {
1300  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> SuperPropMap;
1301  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl))
1302    CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
1303
1304  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
1305  CollectImmediateProperties(CDecl, PropMap, SuperPropMap);
1306  if (PropMap.empty())
1307    return;
1308
1309  llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
1310  for (ObjCImplDecl::propimpl_iterator
1311       I = IMPDecl->propimpl_begin(),
1312       EI = IMPDecl->propimpl_end(); I != EI; ++I)
1313    PropImplMap.insert((*I)->getPropertyDecl());
1314
1315  for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
1316       P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
1317    ObjCPropertyDecl *Prop = P->second;
1318    // Is there a matching propery synthesize/dynamic?
1319    if (Prop->isInvalidDecl() ||
1320        Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
1321        PropImplMap.count(Prop) || Prop->hasAttr<UnavailableAttr>())
1322      continue;
1323    if (!InsMap.count(Prop->getGetterName())) {
1324      Diag(Prop->getLocation(),
1325           isa<ObjCCategoryDecl>(CDecl) ?
1326            diag::warn_setter_getter_impl_required_in_category :
1327            diag::warn_setter_getter_impl_required)
1328      << Prop->getDeclName() << Prop->getGetterName();
1329      Diag(IMPDecl->getLocation(),
1330           diag::note_property_impl_required);
1331    }
1332
1333    if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
1334      Diag(Prop->getLocation(),
1335           isa<ObjCCategoryDecl>(CDecl) ?
1336           diag::warn_setter_getter_impl_required_in_category :
1337           diag::warn_setter_getter_impl_required)
1338      << Prop->getDeclName() << Prop->getSetterName();
1339      Diag(IMPDecl->getLocation(),
1340           diag::note_property_impl_required);
1341    }
1342  }
1343}
1344
1345void
1346Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
1347                                       ObjCContainerDecl* IDecl) {
1348  // Rules apply in non-GC mode only
1349  if (getLangOptions().getGCMode() != LangOptions::NonGC)
1350    return;
1351  for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
1352       E = IDecl->prop_end();
1353       I != E; ++I) {
1354    ObjCPropertyDecl *Property = (*I);
1355    ObjCMethodDecl *GetterMethod = 0;
1356    ObjCMethodDecl *SetterMethod = 0;
1357    bool LookedUpGetterSetter = false;
1358
1359    unsigned Attributes = Property->getPropertyAttributes();
1360    unsigned AttributesAsWrittern = Property->getPropertyAttributesAsWritten();
1361
1362    if (!(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_atomic) &&
1363        !(AttributesAsWrittern & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
1364      GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
1365      SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
1366      LookedUpGetterSetter = true;
1367      if (GetterMethod) {
1368        Diag(GetterMethod->getLocation(),
1369             diag::warn_default_atomic_custom_getter_setter)
1370          << Property->getIdentifier() << 0;
1371        Diag(Property->getLocation(), diag::note_property_declare);
1372      }
1373      if (SetterMethod) {
1374        Diag(SetterMethod->getLocation(),
1375             diag::warn_default_atomic_custom_getter_setter)
1376          << Property->getIdentifier() << 1;
1377        Diag(Property->getLocation(), diag::note_property_declare);
1378      }
1379    }
1380
1381    // We only care about readwrite atomic property.
1382    if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
1383        !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
1384      continue;
1385    if (const ObjCPropertyImplDecl *PIDecl
1386         = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
1387      if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
1388        continue;
1389      if (!LookedUpGetterSetter) {
1390        GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
1391        SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
1392        LookedUpGetterSetter = true;
1393      }
1394      if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
1395        SourceLocation MethodLoc =
1396          (GetterMethod ? GetterMethod->getLocation()
1397                        : SetterMethod->getLocation());
1398        Diag(MethodLoc, diag::warn_atomic_property_rule)
1399          << Property->getIdentifier();
1400        Diag(Property->getLocation(), diag::note_property_declare);
1401      }
1402    }
1403  }
1404}
1405
1406void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) {
1407  if (getLangOptions().getGCMode() == LangOptions::GCOnly)
1408    return;
1409
1410  for (ObjCImplementationDecl::propimpl_iterator
1411         i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) {
1412    ObjCPropertyImplDecl *PID = *i;
1413    if (PID->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
1414      continue;
1415
1416    const ObjCPropertyDecl *PD = PID->getPropertyDecl();
1417    if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
1418        !D->getInstanceMethod(PD->getGetterName())) {
1419      ObjCMethodDecl *method = PD->getGetterMethodDecl();
1420      if (!method)
1421        continue;
1422      ObjCMethodFamily family = method->getMethodFamily();
1423      if (family == OMF_alloc || family == OMF_copy ||
1424          family == OMF_mutableCopy || family == OMF_new) {
1425        if (getLangOptions().ObjCAutoRefCount)
1426          Diag(PID->getLocation(), diag::err_ownin_getter_rule);
1427        else
1428          Diag(PID->getLocation(), diag::warn_ownin_getter_rule);
1429        Diag(PD->getLocation(), diag::note_property_declare);
1430      }
1431    }
1432  }
1433}
1434
1435/// AddPropertyAttrs - Propagates attributes from a property to the
1436/// implicitly-declared getter or setter for that property.
1437static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
1438                             ObjCPropertyDecl *Property) {
1439  // Should we just clone all attributes over?
1440  for (Decl::attr_iterator A = Property->attr_begin(),
1441                        AEnd = Property->attr_end();
1442       A != AEnd; ++A) {
1443    if (isa<DeprecatedAttr>(*A) ||
1444        isa<UnavailableAttr>(*A) ||
1445        isa<AvailabilityAttr>(*A))
1446      PropertyMethod->addAttr((*A)->clone(S.Context));
1447  }
1448}
1449
1450/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
1451/// have the property type and issue diagnostics if they don't.
1452/// Also synthesize a getter/setter method if none exist (and update the
1453/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
1454/// methods is the "right" thing to do.
1455void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
1456                               ObjCContainerDecl *CD,
1457                               ObjCPropertyDecl *redeclaredProperty,
1458                               ObjCContainerDecl *lexicalDC) {
1459
1460  ObjCMethodDecl *GetterMethod, *SetterMethod;
1461
1462  GetterMethod = CD->getInstanceMethod(property->getGetterName());
1463  SetterMethod = CD->getInstanceMethod(property->getSetterName());
1464  DiagnosePropertyAccessorMismatch(property, GetterMethod,
1465                                   property->getLocation());
1466
1467  if (SetterMethod) {
1468    ObjCPropertyDecl::PropertyAttributeKind CAttr =
1469      property->getPropertyAttributes();
1470    if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
1471        Context.getCanonicalType(SetterMethod->getResultType()) !=
1472          Context.VoidTy)
1473      Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
1474    if (SetterMethod->param_size() != 1 ||
1475        ((*SetterMethod->param_begin())->getType() != property->getType())) {
1476      Diag(property->getLocation(),
1477           diag::warn_accessor_property_type_mismatch)
1478        << property->getDeclName()
1479        << SetterMethod->getSelector();
1480      Diag(SetterMethod->getLocation(), diag::note_declared_at);
1481    }
1482  }
1483
1484  // Synthesize getter/setter methods if none exist.
1485  // Find the default getter and if one not found, add one.
1486  // FIXME: The synthesized property we set here is misleading. We almost always
1487  // synthesize these methods unless the user explicitly provided prototypes
1488  // (which is odd, but allowed). Sema should be typechecking that the
1489  // declarations jive in that situation (which it is not currently).
1490  if (!GetterMethod) {
1491    // No instance method of same name as property getter name was found.
1492    // Declare a getter method and add it to the list of methods
1493    // for this class.
1494    SourceLocation Loc = redeclaredProperty ?
1495      redeclaredProperty->getLocation() :
1496      property->getLocation();
1497
1498    GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
1499                             property->getGetterName(),
1500                             property->getType(), 0, CD, true, false, true,
1501                             false,
1502                             (property->getPropertyImplementation() ==
1503                              ObjCPropertyDecl::Optional) ?
1504                             ObjCMethodDecl::Optional :
1505                             ObjCMethodDecl::Required);
1506    CD->addDecl(GetterMethod);
1507
1508    AddPropertyAttrs(*this, GetterMethod, property);
1509
1510    // FIXME: Eventually this shouldn't be needed, as the lexical context
1511    // and the real context should be the same.
1512    if (lexicalDC)
1513      GetterMethod->setLexicalDeclContext(lexicalDC);
1514    if (property->hasAttr<NSReturnsNotRetainedAttr>())
1515      GetterMethod->addAttr(
1516        ::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
1517  } else
1518    // A user declared getter will be synthesize when @synthesize of
1519    // the property with the same name is seen in the @implementation
1520    GetterMethod->setSynthesized(true);
1521  property->setGetterMethodDecl(GetterMethod);
1522
1523  // Skip setter if property is read-only.
1524  if (!property->isReadOnly()) {
1525    // Find the default setter and if one not found, add one.
1526    if (!SetterMethod) {
1527      // No instance method of same name as property setter name was found.
1528      // Declare a setter method and add it to the list of methods
1529      // for this class.
1530      SourceLocation Loc = redeclaredProperty ?
1531        redeclaredProperty->getLocation() :
1532        property->getLocation();
1533
1534      SetterMethod =
1535        ObjCMethodDecl::Create(Context, Loc, Loc,
1536                               property->getSetterName(), Context.VoidTy, 0,
1537                               CD, true, false, true, false,
1538                               (property->getPropertyImplementation() ==
1539                                ObjCPropertyDecl::Optional) ?
1540                                ObjCMethodDecl::Optional :
1541                                ObjCMethodDecl::Required);
1542
1543      // Invent the arguments for the setter. We don't bother making a
1544      // nice name for the argument.
1545      ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
1546                                                  Loc, Loc,
1547                                                  property->getIdentifier(),
1548                                    property->getType().getUnqualifiedType(),
1549                                                  /*TInfo=*/0,
1550                                                  SC_None,
1551                                                  SC_None,
1552                                                  0);
1553      SetterMethod->setMethodParams(Context, &Argument, 1, 1);
1554
1555      AddPropertyAttrs(*this, SetterMethod, property);
1556
1557      CD->addDecl(SetterMethod);
1558      // FIXME: Eventually this shouldn't be needed, as the lexical context
1559      // and the real context should be the same.
1560      if (lexicalDC)
1561        SetterMethod->setLexicalDeclContext(lexicalDC);
1562    } else
1563      // A user declared setter will be synthesize when @synthesize of
1564      // the property with the same name is seen in the @implementation
1565      SetterMethod->setSynthesized(true);
1566    property->setSetterMethodDecl(SetterMethod);
1567  }
1568  // Add any synthesized methods to the global pool. This allows us to
1569  // handle the following, which is supported by GCC (and part of the design).
1570  //
1571  // @interface Foo
1572  // @property double bar;
1573  // @end
1574  //
1575  // void thisIsUnfortunate() {
1576  //   id foo;
1577  //   double bar = [foo bar];
1578  // }
1579  //
1580  if (GetterMethod)
1581    AddInstanceMethodToGlobalPool(GetterMethod);
1582  if (SetterMethod)
1583    AddInstanceMethodToGlobalPool(SetterMethod);
1584}
1585
1586void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
1587                                       SourceLocation Loc,
1588                                       unsigned &Attributes) {
1589  // FIXME: Improve the reported location.
1590  if (!PDecl || PDecl->isInvalidDecl())
1591    return;
1592
1593  ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
1594  QualType PropertyTy = PropertyDecl->getType();
1595
1596  // readonly and readwrite/assign/retain/copy conflict.
1597  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
1598      (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
1599                     ObjCDeclSpec::DQ_PR_assign |
1600                     ObjCDeclSpec::DQ_PR_unsafe_unretained |
1601                     ObjCDeclSpec::DQ_PR_copy |
1602                     ObjCDeclSpec::DQ_PR_retain |
1603                     ObjCDeclSpec::DQ_PR_strong))) {
1604    const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
1605                          "readwrite" :
1606                         (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
1607                          "assign" :
1608                         (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
1609                          "unsafe_unretained" :
1610                         (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
1611                          "copy" : "retain";
1612
1613    Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
1614                 diag::err_objc_property_attr_mutually_exclusive :
1615                 diag::warn_objc_property_attr_mutually_exclusive)
1616      << "readonly" << which;
1617  }
1618
1619  // Check for copy or retain on non-object types.
1620  if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
1621                    ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) &&
1622      !PropertyTy->isObjCRetainableType() &&
1623      !PropertyDecl->getAttr<ObjCNSObjectAttr>()) {
1624    Diag(Loc, diag::err_objc_property_requires_object)
1625      << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" :
1626          Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)");
1627    Attributes &= ~(ObjCDeclSpec::DQ_PR_weak   | ObjCDeclSpec::DQ_PR_copy |
1628                    ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong);
1629  }
1630
1631  // Check for more than one of { assign, copy, retain }.
1632  if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
1633    if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
1634      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1635        << "assign" << "copy";
1636      Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
1637    }
1638    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
1639      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1640        << "assign" << "retain";
1641      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
1642    }
1643    if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
1644      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1645        << "assign" << "strong";
1646      Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
1647    }
1648    if (getLangOptions().ObjCAutoRefCount  &&
1649        (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
1650      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1651        << "assign" << "weak";
1652      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
1653    }
1654  } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) {
1655    if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
1656      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1657        << "unsafe_unretained" << "copy";
1658      Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
1659    }
1660    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
1661      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1662        << "unsafe_unretained" << "retain";
1663      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
1664    }
1665    if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
1666      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1667        << "unsafe_unretained" << "strong";
1668      Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
1669    }
1670    if (getLangOptions().ObjCAutoRefCount  &&
1671        (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
1672      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1673        << "unsafe_unretained" << "weak";
1674      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
1675    }
1676  } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
1677    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
1678      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1679        << "copy" << "retain";
1680      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
1681    }
1682    if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
1683      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1684        << "copy" << "strong";
1685      Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
1686    }
1687    if (Attributes & ObjCDeclSpec::DQ_PR_weak) {
1688      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1689        << "copy" << "weak";
1690      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
1691    }
1692  }
1693  else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) &&
1694           (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
1695      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1696        << "retain" << "weak";
1697      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
1698  }
1699  else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) &&
1700           (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
1701      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
1702        << "strong" << "weak";
1703      Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
1704  }
1705
1706  // Warn if user supplied no assignment attribute, property is
1707  // readwrite, and this is an object type.
1708  if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
1709                      ObjCDeclSpec::DQ_PR_unsafe_unretained |
1710                      ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong |
1711                      ObjCDeclSpec::DQ_PR_weak)) &&
1712      !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
1713      PropertyTy->isObjCObjectPointerType()) {
1714    // Skip this warning in gc-only mode.
1715    if (getLangOptions().getGCMode() != LangOptions::GCOnly)
1716      Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
1717
1718    // If non-gc code warn that this is likely inappropriate.
1719    if (getLangOptions().getGCMode() == LangOptions::NonGC)
1720      Diag(Loc, diag::warn_objc_property_default_assign_on_object);
1721
1722    // FIXME: Implement warning dependent on NSCopying being
1723    // implemented. See also:
1724    // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
1725    // (please trim this list while you are at it).
1726  }
1727
1728  if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)
1729      &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly)
1730      && getLangOptions().getGCMode() == LangOptions::GCOnly
1731      && PropertyTy->isBlockPointerType())
1732    Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
1733}
1734