SemaObjCProperty.cpp revision 4e60bac843342293369d5ac8812e760e6723e736
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 "Sema.h"
16
17using namespace clang;
18
19/// DiagnosePropertyMismatch - Compares two properties for their
20/// attributes and types and warns on a variety of inconsistencies.
21///
22void
23Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
24                               ObjCPropertyDecl *SuperProperty,
25                               const IdentifierInfo *inheritedName) {
26  ObjCPropertyDecl::PropertyAttributeKind CAttr =
27  Property->getPropertyAttributes();
28  ObjCPropertyDecl::PropertyAttributeKind SAttr =
29  SuperProperty->getPropertyAttributes();
30  if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
31      && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
32    Diag(Property->getLocation(), diag::warn_readonly_property)
33      << Property->getDeclName() << inheritedName;
34  if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
35      != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
36    Diag(Property->getLocation(), diag::warn_property_attribute)
37      << Property->getDeclName() << "copy" << inheritedName;
38  else if ((CAttr & ObjCPropertyDecl::OBJC_PR_retain)
39           != (SAttr & ObjCPropertyDecl::OBJC_PR_retain))
40    Diag(Property->getLocation(), diag::warn_property_attribute)
41      << Property->getDeclName() << "retain" << inheritedName;
42
43  if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
44      != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic))
45    Diag(Property->getLocation(), diag::warn_property_attribute)
46      << Property->getDeclName() << "atomic" << inheritedName;
47  if (Property->getSetterName() != SuperProperty->getSetterName())
48    Diag(Property->getLocation(), diag::warn_property_attribute)
49      << Property->getDeclName() << "setter" << inheritedName;
50  if (Property->getGetterName() != SuperProperty->getGetterName())
51    Diag(Property->getLocation(), diag::warn_property_attribute)
52      << Property->getDeclName() << "getter" << inheritedName;
53
54  QualType LHSType =
55    Context.getCanonicalType(SuperProperty->getType());
56  QualType RHSType =
57    Context.getCanonicalType(Property->getType());
58
59  if (!Context.typesAreCompatible(LHSType, RHSType)) {
60    // FIXME: Incorporate this test with typesAreCompatible.
61    if (LHSType->isObjCQualifiedIdType() && RHSType->isObjCQualifiedIdType())
62      if (Context.ObjCQualifiedIdTypesAreCompatible(LHSType, RHSType, false))
63        return;
64    Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
65      << Property->getType() << SuperProperty->getType() << inheritedName;
66  }
67}
68
69bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
70                                            ObjCMethodDecl *GetterMethod,
71                                            SourceLocation Loc) {
72  if (GetterMethod &&
73      GetterMethod->getResultType() != property->getType()) {
74    AssignConvertType result = Incompatible;
75    if (property->getType()->isObjCObjectPointerType())
76      result = CheckAssignmentConstraints(GetterMethod->getResultType(),
77                                          property->getType());
78    if (result != Compatible) {
79      Diag(Loc, diag::warn_accessor_property_type_mismatch)
80      << property->getDeclName()
81      << GetterMethod->getSelector();
82      Diag(GetterMethod->getLocation(), diag::note_declared_at);
83      return true;
84    }
85  }
86  return false;
87}
88
89/// ComparePropertiesInBaseAndSuper - This routine compares property
90/// declarations in base and its super class, if any, and issues
91/// diagnostics in a variety of inconsistant situations.
92///
93void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) {
94  ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
95  if (!SDecl)
96    return;
97  // FIXME: O(N^2)
98  for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(),
99       E = SDecl->prop_end(); S != E; ++S) {
100    ObjCPropertyDecl *SuperPDecl = (*S);
101    // Does property in super class has declaration in current class?
102    for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(),
103         E = IDecl->prop_end(); I != E; ++I) {
104      ObjCPropertyDecl *PDecl = (*I);
105      if (SuperPDecl->getIdentifier() == PDecl->getIdentifier())
106          DiagnosePropertyMismatch(PDecl, SuperPDecl,
107                                   SDecl->getIdentifier());
108    }
109  }
110}
111
112/// MatchOneProtocolPropertiesInClass - This routine goes thru the list
113/// of properties declared in a protocol and compares their attribute against
114/// the same property declared in the class or category.
115void
116Sema::MatchOneProtocolPropertiesInClass(Decl *CDecl,
117                                          ObjCProtocolDecl *PDecl) {
118  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
119  if (!IDecl) {
120    // Category
121    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
122    assert (CatDecl && "MatchOneProtocolPropertiesInClass");
123    if (!CatDecl->IsClassExtension())
124      for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
125           E = PDecl->prop_end(); P != E; ++P) {
126        ObjCPropertyDecl *Pr = (*P);
127        ObjCCategoryDecl::prop_iterator CP, CE;
128        // Is this property already in  category's list of properties?
129        for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP)
130          if ((*CP)->getIdentifier() == Pr->getIdentifier())
131            break;
132        if (CP != CE)
133          // Property protocol already exist in class. Diagnose any mismatch.
134          DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
135      }
136    return;
137  }
138  for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
139       E = PDecl->prop_end(); P != E; ++P) {
140    ObjCPropertyDecl *Pr = (*P);
141    ObjCInterfaceDecl::prop_iterator CP, CE;
142    // Is this property already in  class's list of properties?
143    for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP)
144      if ((*CP)->getIdentifier() == Pr->getIdentifier())
145        break;
146    if (CP != CE)
147      // Property protocol already exist in class. Diagnose any mismatch.
148      DiagnosePropertyMismatch((*CP), Pr, PDecl->getIdentifier());
149    }
150}
151
152/// CompareProperties - This routine compares properties
153/// declared in 'ClassOrProtocol' objects (which can be a class or an
154/// inherited protocol with the list of properties for class/category 'CDecl'
155///
156void Sema::CompareProperties(Decl *CDecl,
157                             DeclPtrTy ClassOrProtocol) {
158  Decl *ClassDecl = ClassOrProtocol.getAs<Decl>();
159  ObjCInterfaceDecl *IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDecl);
160
161  if (!IDecl) {
162    // Category
163    ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl);
164    assert (CatDecl && "CompareProperties");
165    if (ObjCCategoryDecl *MDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
166      for (ObjCCategoryDecl::protocol_iterator P = MDecl->protocol_begin(),
167           E = MDecl->protocol_end(); P != E; ++P)
168      // Match properties of category with those of protocol (*P)
169      MatchOneProtocolPropertiesInClass(CatDecl, *P);
170
171      // Go thru the list of protocols for this category and recursively match
172      // their properties with those in the category.
173      for (ObjCCategoryDecl::protocol_iterator P = CatDecl->protocol_begin(),
174           E = CatDecl->protocol_end(); P != E; ++P)
175        CompareProperties(CatDecl, DeclPtrTy::make(*P));
176    } else {
177      ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
178      for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
179           E = MD->protocol_end(); P != E; ++P)
180        MatchOneProtocolPropertiesInClass(CatDecl, *P);
181    }
182    return;
183  }
184
185  if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
186    for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
187         E = MDecl->protocol_end(); P != E; ++P)
188      // Match properties of class IDecl with those of protocol (*P).
189      MatchOneProtocolPropertiesInClass(IDecl, *P);
190
191    // Go thru the list of protocols for this class and recursively match
192    // their properties with those declared in the class.
193    for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
194         E = IDecl->protocol_end(); P != E; ++P)
195      CompareProperties(IDecl, DeclPtrTy::make(*P));
196  } else {
197    ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
198    for (ObjCProtocolDecl::protocol_iterator P = MD->protocol_begin(),
199         E = MD->protocol_end(); P != E; ++P)
200      MatchOneProtocolPropertiesInClass(IDecl, *P);
201  }
202}
203
204/// isPropertyReadonly - Return true if property is readonly, by searching
205/// for the property in the class and in its categories and implementations
206///
207bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl,
208                              ObjCInterfaceDecl *IDecl) {
209  // by far the most common case.
210  if (!PDecl->isReadOnly())
211    return false;
212  // Even if property is ready only, if interface has a user defined setter,
213  // it is not considered read only.
214  if (IDecl->getInstanceMethod(PDecl->getSetterName()))
215    return false;
216
217  // Main class has the property as 'readonly'. Must search
218  // through the category list to see if the property's
219  // attribute has been over-ridden to 'readwrite'.
220  for (ObjCCategoryDecl *Category = IDecl->getCategoryList();
221       Category; Category = Category->getNextClassCategory()) {
222    // Even if property is ready only, if a category has a user defined setter,
223    // it is not considered read only.
224    if (Category->getInstanceMethod(PDecl->getSetterName()))
225      return false;
226    ObjCPropertyDecl *P =
227      Category->FindPropertyDeclaration(PDecl->getIdentifier());
228    if (P && !P->isReadOnly())
229      return false;
230  }
231
232  // Also, check for definition of a setter method in the implementation if
233  // all else failed.
234  if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) {
235    if (ObjCImplementationDecl *IMD =
236        dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) {
237      if (IMD->getInstanceMethod(PDecl->getSetterName()))
238        return false;
239    } else if (ObjCCategoryImplDecl *CIMD =
240               dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
241      if (CIMD->getInstanceMethod(PDecl->getSetterName()))
242        return false;
243    }
244  }
245  // Lastly, look through the implementation (if one is in scope).
246  if (ObjCImplementationDecl *ImpDecl = IDecl->getImplementation())
247    if (ImpDecl->getInstanceMethod(PDecl->getSetterName()))
248      return false;
249  // If all fails, look at the super class.
250  if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass())
251    return isPropertyReadonly(PDecl, SIDecl);
252  return true;
253}
254
255/// CollectImmediateProperties - This routine collects all properties in
256/// the class and its conforming protocols; but not those it its super class.
257void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
258                llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap) {
259  if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
260    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
261         E = IDecl->prop_end(); P != E; ++P) {
262      ObjCPropertyDecl *Prop = (*P);
263      PropMap[Prop->getIdentifier()] = Prop;
264    }
265    // scan through class's protocols.
266    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
267         E = IDecl->protocol_end(); PI != E; ++PI)
268      CollectImmediateProperties((*PI), PropMap);
269  }
270  if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
271    if (!CATDecl->IsClassExtension())
272      for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
273           E = CATDecl->prop_end(); P != E; ++P) {
274        ObjCPropertyDecl *Prop = (*P);
275        PropMap[Prop->getIdentifier()] = Prop;
276      }
277    // scan through class's protocols.
278    for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
279         E = CATDecl->protocol_end(); PI != E; ++PI)
280      CollectImmediateProperties((*PI), PropMap);
281  }
282  else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
283    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
284         E = PDecl->prop_end(); P != E; ++P) {
285      ObjCPropertyDecl *Prop = (*P);
286      ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
287      if (!PropEntry)
288        PropEntry = Prop;
289    }
290    // scan through protocol's protocols.
291    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
292         E = PDecl->protocol_end(); PI != E; ++PI)
293      CollectImmediateProperties((*PI), PropMap);
294  }
295}
296
297/// LookupPropertyDecl - Looks up a property in the current class and all
298/// its protocols.
299ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
300                                     IdentifierInfo *II) {
301  if (const ObjCInterfaceDecl *IDecl =
302        dyn_cast<ObjCInterfaceDecl>(CDecl)) {
303    for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
304         E = IDecl->prop_end(); P != E; ++P) {
305      ObjCPropertyDecl *Prop = (*P);
306      if (Prop->getIdentifier() == II)
307        return Prop;
308    }
309    // scan through class's protocols.
310    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
311         E = IDecl->protocol_end(); PI != E; ++PI) {
312      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
313      if (Prop)
314        return Prop;
315    }
316  }
317  else if (const ObjCProtocolDecl *PDecl =
318            dyn_cast<ObjCProtocolDecl>(CDecl)) {
319    for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
320         E = PDecl->prop_end(); P != E; ++P) {
321      ObjCPropertyDecl *Prop = (*P);
322      if (Prop->getIdentifier() == II)
323        return Prop;
324    }
325    // scan through protocol's protocols.
326    for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
327         E = PDecl->protocol_end(); PI != E; ++PI) {
328      ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
329      if (Prop)
330        return Prop;
331    }
332  }
333  return 0;
334}
335
336
337void Sema::DiagnoseUnimplementedProperties(ObjCImplDecl* IMPDecl,
338                                      ObjCContainerDecl *CDecl,
339                                      const llvm::DenseSet<Selector>& InsMap) {
340  llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*> PropMap;
341  CollectImmediateProperties(CDecl, PropMap);
342  if (PropMap.empty())
343    return;
344
345  llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
346  for (ObjCImplDecl::propimpl_iterator
347       I = IMPDecl->propimpl_begin(),
348       EI = IMPDecl->propimpl_end(); I != EI; ++I)
349    PropImplMap.insert((*I)->getPropertyDecl());
350
351  for (llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>::iterator
352       P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
353    ObjCPropertyDecl *Prop = P->second;
354    // Is there a matching propery synthesize/dynamic?
355    if (Prop->isInvalidDecl() ||
356        Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
357        PropImplMap.count(Prop))
358      continue;
359    if (LangOpts.ObjCNonFragileABI2) {
360      ActOnPropertyImplDecl(IMPDecl->getLocation(),
361                            SourceLocation(),
362                            true, DeclPtrTy::make(IMPDecl),
363                            Prop->getIdentifier(),
364                            Prop->getIdentifier());
365      continue;
366    }
367    if (!InsMap.count(Prop->getGetterName())) {
368      Diag(Prop->getLocation(),
369           isa<ObjCCategoryDecl>(CDecl) ?
370            diag::warn_setter_getter_impl_required_in_category :
371            diag::warn_setter_getter_impl_required)
372      << Prop->getDeclName() << Prop->getGetterName();
373      Diag(IMPDecl->getLocation(),
374           diag::note_property_impl_required);
375    }
376
377    if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName())) {
378      Diag(Prop->getLocation(),
379           isa<ObjCCategoryDecl>(CDecl) ?
380           diag::warn_setter_getter_impl_required_in_category :
381           diag::warn_setter_getter_impl_required)
382      << Prop->getDeclName() << Prop->getSetterName();
383      Diag(IMPDecl->getLocation(),
384           diag::note_property_impl_required);
385    }
386  }
387}
388
389void
390Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
391                                       ObjCContainerDecl* IDecl) {
392  // Rules apply in non-GC mode only
393  if (getLangOptions().getGCMode() != LangOptions::NonGC)
394    return;
395  for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
396       E = IDecl->prop_end();
397       I != E; ++I) {
398    ObjCPropertyDecl *Property = (*I);
399    unsigned Attributes = Property->getPropertyAttributes();
400    // We only care about readwrite atomic property.
401    if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
402        !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
403      continue;
404    if (const ObjCPropertyImplDecl *PIDecl
405         = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
406      if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
407        continue;
408      ObjCMethodDecl *GetterMethod =
409        IMPDecl->getInstanceMethod(Property->getGetterName());
410      ObjCMethodDecl *SetterMethod =
411        IMPDecl->getInstanceMethod(Property->getSetterName());
412      if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
413        SourceLocation MethodLoc =
414          (GetterMethod ? GetterMethod->getLocation()
415                        : SetterMethod->getLocation());
416        Diag(MethodLoc, diag::warn_atomic_property_rule)
417          << Property->getIdentifier();
418        Diag(Property->getLocation(), diag::note_property_declare);
419      }
420    }
421  }
422}
423
424/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
425/// have the property type and issue diagnostics if they don't.
426/// Also synthesize a getter/setter method if none exist (and update the
427/// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
428/// methods is the "right" thing to do.
429void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
430                               ObjCContainerDecl *CD) {
431  ObjCMethodDecl *GetterMethod, *SetterMethod;
432
433  GetterMethod = CD->getInstanceMethod(property->getGetterName());
434  SetterMethod = CD->getInstanceMethod(property->getSetterName());
435  DiagnosePropertyAccessorMismatch(property, GetterMethod,
436                                   property->getLocation());
437
438  if (SetterMethod) {
439    ObjCPropertyDecl::PropertyAttributeKind CAttr =
440      property->getPropertyAttributes();
441    if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
442        Context.getCanonicalType(SetterMethod->getResultType()) !=
443          Context.VoidTy)
444      Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
445    if (SetterMethod->param_size() != 1 ||
446        ((*SetterMethod->param_begin())->getType() != property->getType())) {
447      Diag(property->getLocation(),
448           diag::warn_accessor_property_type_mismatch)
449        << property->getDeclName()
450        << SetterMethod->getSelector();
451      Diag(SetterMethod->getLocation(), diag::note_declared_at);
452    }
453  }
454
455  // Synthesize getter/setter methods if none exist.
456  // Find the default getter and if one not found, add one.
457  // FIXME: The synthesized property we set here is misleading. We almost always
458  // synthesize these methods unless the user explicitly provided prototypes
459  // (which is odd, but allowed). Sema should be typechecking that the
460  // declarations jive in that situation (which it is not currently).
461  if (!GetterMethod) {
462    // No instance method of same name as property getter name was found.
463    // Declare a getter method and add it to the list of methods
464    // for this class.
465    GetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
466                             property->getLocation(), property->getGetterName(),
467                             property->getType(), 0, CD, true, false, true,
468                             (property->getPropertyImplementation() ==
469                              ObjCPropertyDecl::Optional) ?
470                             ObjCMethodDecl::Optional :
471                             ObjCMethodDecl::Required);
472    CD->addDecl(GetterMethod);
473  } else
474    // A user declared getter will be synthesize when @synthesize of
475    // the property with the same name is seen in the @implementation
476    GetterMethod->setSynthesized(true);
477  property->setGetterMethodDecl(GetterMethod);
478
479  // Skip setter if property is read-only.
480  if (!property->isReadOnly()) {
481    // Find the default setter and if one not found, add one.
482    if (!SetterMethod) {
483      // No instance method of same name as property setter name was found.
484      // Declare a setter method and add it to the list of methods
485      // for this class.
486      SetterMethod = ObjCMethodDecl::Create(Context, property->getLocation(),
487                               property->getLocation(),
488                               property->getSetterName(),
489                               Context.VoidTy, 0, CD, true, false, true,
490                               (property->getPropertyImplementation() ==
491                                ObjCPropertyDecl::Optional) ?
492                               ObjCMethodDecl::Optional :
493                               ObjCMethodDecl::Required);
494      // Invent the arguments for the setter. We don't bother making a
495      // nice name for the argument.
496      ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
497                                                  property->getLocation(),
498                                                  property->getIdentifier(),
499                                                  property->getType(),
500                                                  /*TInfo=*/0,
501                                                  VarDecl::None,
502                                                  0);
503      SetterMethod->setMethodParams(Context, &Argument, 1);
504      CD->addDecl(SetterMethod);
505    } else
506      // A user declared setter will be synthesize when @synthesize of
507      // the property with the same name is seen in the @implementation
508      SetterMethod->setSynthesized(true);
509    property->setSetterMethodDecl(SetterMethod);
510  }
511  // Add any synthesized methods to the global pool. This allows us to
512  // handle the following, which is supported by GCC (and part of the design).
513  //
514  // @interface Foo
515  // @property double bar;
516  // @end
517  //
518  // void thisIsUnfortunate() {
519  //   id foo;
520  //   double bar = [foo bar];
521  // }
522  //
523  if (GetterMethod)
524    AddInstanceMethodToGlobalPool(GetterMethod);
525  if (SetterMethod)
526    AddInstanceMethodToGlobalPool(SetterMethod);
527}
528
529void Sema::CheckObjCPropertyAttributes(QualType PropertyTy,
530                                       SourceLocation Loc,
531                                       unsigned &Attributes) {
532  // FIXME: Improve the reported location.
533
534  // readonly and readwrite/assign/retain/copy conflict.
535  if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
536      (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
537                     ObjCDeclSpec::DQ_PR_assign |
538                     ObjCDeclSpec::DQ_PR_copy |
539                     ObjCDeclSpec::DQ_PR_retain))) {
540    const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
541                          "readwrite" :
542                         (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
543                          "assign" :
544                         (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
545                          "copy" : "retain";
546
547    Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
548                 diag::err_objc_property_attr_mutually_exclusive :
549                 diag::warn_objc_property_attr_mutually_exclusive)
550      << "readonly" << which;
551  }
552
553  // Check for copy or retain on non-object types.
554  if ((Attributes & (ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain)) &&
555      !PropertyTy->isObjCObjectPointerType() &&
556      !PropertyTy->isBlockPointerType() &&
557      !Context.isObjCNSObjectType(PropertyTy)) {
558    Diag(Loc, diag::err_objc_property_requires_object)
559      << (Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain");
560    Attributes &= ~(ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain);
561  }
562
563  // Check for more than one of { assign, copy, retain }.
564  if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
565    if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
566      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
567        << "assign" << "copy";
568      Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
569    }
570    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
571      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
572        << "assign" << "retain";
573      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
574    }
575  } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
576    if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
577      Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
578        << "copy" << "retain";
579      Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
580    }
581  }
582
583  // Warn if user supplied no assignment attribute, property is
584  // readwrite, and this is an object type.
585  if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
586                      ObjCDeclSpec::DQ_PR_retain)) &&
587      !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
588      PropertyTy->isObjCObjectPointerType()) {
589    // Skip this warning in gc-only mode.
590    if (getLangOptions().getGCMode() != LangOptions::GCOnly)
591      Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
592
593    // If non-gc code warn that this is likely inappropriate.
594    if (getLangOptions().getGCMode() == LangOptions::NonGC)
595      Diag(Loc, diag::warn_objc_property_default_assign_on_object);
596
597    // FIXME: Implement warning dependent on NSCopying being
598    // implemented. See also:
599    // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
600    // (please trim this list while you are at it).
601  }
602
603  if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)
604      && getLangOptions().getGCMode() == LangOptions::GCOnly
605      && PropertyTy->isBlockPointerType())
606    Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
607}
608
609Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
610                                    FieldDeclarator &FD,
611                                    ObjCDeclSpec &ODS,
612                                    Selector GetterSel,
613                                    Selector SetterSel,
614                                    DeclPtrTy ClassCategory,
615                                    bool *isOverridingProperty,
616                                    tok::ObjCKeywordKind MethodImplKind) {
617  unsigned Attributes = ODS.getPropertyAttributes();
618  bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
619                      // default is readwrite!
620                      !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
621  // property is defaulted to 'assign' if it is readwrite and is
622  // not retain or copy
623  bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
624                   (isReadWrite &&
625                    !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
626                    !(Attributes & ObjCDeclSpec::DQ_PR_copy)));
627  QualType T = GetTypeForDeclarator(FD.D, S);
628  if (T->isReferenceType()) {
629    Diag(AtLoc, diag::error_reference_property);
630    return DeclPtrTy();
631  }
632  Decl *ClassDecl = ClassCategory.getAs<Decl>();
633  ObjCInterfaceDecl *CCPrimary = 0; // continuation class's primary class
634  // May modify Attributes.
635  CheckObjCPropertyAttributes(T, AtLoc, Attributes);
636  if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl))
637    if (CDecl->IsClassExtension()) {
638      // Diagnose if this property is already in continuation class.
639      DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
640      assert(DC && "ClassDecl is not a DeclContext");
641      DeclContext::lookup_result Found = DC->lookup(FD.D.getIdentifier());
642      if (Found.first != Found.second && isa<ObjCPropertyDecl>(*Found.first)) {
643        Diag(AtLoc, diag::err_duplicate_property);
644        Diag((*Found.first)->getLocation(), diag::note_property_declare);
645        return DeclPtrTy();
646      }
647      ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
648                                                         FD.D.getIdentifierLoc(),
649                                                         FD.D.getIdentifier(),
650                                                         AtLoc, T);
651      DC->addDecl(PDecl);
652
653      // This is a continuation class. property requires special
654      // handling.
655      if ((CCPrimary = CDecl->getClassInterface())) {
656        // Find the property in continuation class's primary class only.
657        IdentifierInfo *PropertyId = FD.D.getIdentifier();
658        if (ObjCPropertyDecl *PIDecl =
659              CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId)) {
660          // property 'PIDecl's readonly attribute will be over-ridden
661          // with continuation class's readwrite property attribute!
662          unsigned PIkind = PIDecl->getPropertyAttributes();
663          if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
664            unsigned retainCopyNonatomic =
665              (ObjCPropertyDecl::OBJC_PR_retain |
666               ObjCPropertyDecl::OBJC_PR_copy |
667               ObjCPropertyDecl::OBJC_PR_nonatomic);
668            if ((Attributes & retainCopyNonatomic) !=
669                (PIkind & retainCopyNonatomic)) {
670              Diag(AtLoc, diag::warn_property_attr_mismatch);
671              Diag(PIDecl->getLocation(), diag::note_property_declare);
672            }
673            DeclContext *DC = dyn_cast<DeclContext>(CCPrimary);
674            assert(DC && "ClassDecl is not a DeclContext");
675            DeclContext::lookup_result Found =
676              DC->lookup(PIDecl->getDeclName());
677            bool PropertyInPrimaryClass = false;
678            for (; Found.first != Found.second; ++Found.first)
679              if (isa<ObjCPropertyDecl>(*Found.first)) {
680                PropertyInPrimaryClass = true;
681                break;
682              }
683            if (!PropertyInPrimaryClass) {
684              // Protocol is not in the primary class. Must build one for it.
685              ObjCDeclSpec ProtocolPropertyODS;
686              // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind and
687              // ObjCPropertyDecl::PropertyAttributeKind have identical values.
688              // Should consolidate both into one enum type.
689              ProtocolPropertyODS.setPropertyAttributes(
690                (ObjCDeclSpec::ObjCPropertyAttributeKind)PIkind);
691              DeclPtrTy ProtocolPtrTy =
692                ActOnProperty(S, AtLoc, FD, ProtocolPropertyODS,
693                              PIDecl->getGetterName(),
694                              PIDecl->getSetterName(),
695                              DeclPtrTy::make(CCPrimary), isOverridingProperty,
696                              MethodImplKind);
697              PIDecl = ProtocolPtrTy.getAs<ObjCPropertyDecl>();
698            }
699            PIDecl->makeitReadWriteAttribute();
700            if (Attributes & ObjCDeclSpec::DQ_PR_retain)
701              PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
702            if (Attributes & ObjCDeclSpec::DQ_PR_copy)
703              PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
704            PIDecl->setSetterName(SetterSel);
705          } else {
706            Diag(AtLoc, diag::err_use_continuation_class)
707              << CCPrimary->getDeclName();
708            Diag(PIDecl->getLocation(), diag::note_property_declare);
709          }
710          *isOverridingProperty = true;
711          // Make sure setter decl is synthesized, and added to primary
712          // class's list.
713          ProcessPropertyDecl(PIDecl, CCPrimary);
714          return DeclPtrTy();
715        }
716
717        // No matching property found in the primary class. Just fall thru
718        // and add property to continuation class's primary class.
719        ClassDecl = CCPrimary;
720      } else {
721        Diag(CDecl->getLocation(), diag::err_continuation_class);
722        *isOverridingProperty = true;
723        return DeclPtrTy();
724      }
725    }
726
727  // Issue a warning if property is 'assign' as default and its object, which is
728  // gc'able conforms to NSCopying protocol
729  if (getLangOptions().getGCMode() != LangOptions::NonGC &&
730      isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
731      if (T->isObjCObjectPointerType()) {
732        QualType InterfaceTy = T->getPointeeType();
733        if (const ObjCInterfaceType *OIT =
734              InterfaceTy->getAs<ObjCInterfaceType>()) {
735        ObjCInterfaceDecl *IDecl = OIT->getDecl();
736        if (IDecl)
737          if (ObjCProtocolDecl* PNSCopying =
738                LookupProtocol(&Context.Idents.get("NSCopying")))
739            if (IDecl->ClassImplementsProtocol(PNSCopying, true))
740              Diag(AtLoc, diag::warn_implements_nscopying)
741                << FD.D.getIdentifier();
742        }
743      }
744  if (T->isObjCInterfaceType())
745    Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object);
746
747  DeclContext *DC = dyn_cast<DeclContext>(ClassDecl);
748  assert(DC && "ClassDecl is not a DeclContext");
749  ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
750                                                     FD.D.getIdentifierLoc(),
751                                                     FD.D.getIdentifier(),
752                                                     AtLoc, T);
753  DeclContext::lookup_result Found = DC->lookup(PDecl->getDeclName());
754  if (Found.first != Found.second && isa<ObjCPropertyDecl>(*Found.first)) {
755    Diag(PDecl->getLocation(), diag::err_duplicate_property);
756    Diag((*Found.first)->getLocation(), diag::note_property_declare);
757    PDecl->setInvalidDecl();
758  }
759  else
760    DC->addDecl(PDecl);
761
762  if (T->isArrayType() || T->isFunctionType()) {
763    Diag(AtLoc, diag::err_property_type) << T;
764    PDecl->setInvalidDecl();
765  }
766
767  ProcessDeclAttributes(S, PDecl, FD.D);
768
769  // Regardless of setter/getter attribute, we save the default getter/setter
770  // selector names in anticipation of declaration of setter/getter methods.
771  PDecl->setGetterName(GetterSel);
772  PDecl->setSetterName(SetterSel);
773
774  if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
775    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
776
777  if (Attributes & ObjCDeclSpec::DQ_PR_getter)
778    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
779
780  if (Attributes & ObjCDeclSpec::DQ_PR_setter)
781    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
782
783  if (isReadWrite)
784    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
785
786  if (Attributes & ObjCDeclSpec::DQ_PR_retain)
787    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
788
789  if (Attributes & ObjCDeclSpec::DQ_PR_copy)
790    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
791
792  if (isAssign)
793    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
794
795  if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
796    PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
797
798  if (MethodImplKind == tok::objc_required)
799    PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
800  else if (MethodImplKind == tok::objc_optional)
801    PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
802  // A case of continuation class adding a new property in the class. This
803  // is not what it was meant for. However, gcc supports it and so should we.
804  // Make sure setter/getters are declared here.
805  if (CCPrimary)
806    ProcessPropertyDecl(PDecl, CCPrimary);
807
808  return DeclPtrTy::make(PDecl);
809}
810
811ObjCIvarDecl*
812Sema::SynthesizeNewPropertyIvar(ObjCInterfaceDecl *IDecl,
813                                IdentifierInfo *NameII) {
814  ObjCIvarDecl *Ivar = 0;
815  ObjCPropertyDecl *Prop = LookupPropertyDecl(IDecl, NameII);
816  if (Prop && !Prop->isInvalidDecl()) {
817    DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl);
818    QualType PropType = Context.getCanonicalType(Prop->getType());
819    assert(EnclosingContext &&
820           "null DeclContext for synthesized ivar - SynthesizeNewPropertyIvar");
821    Ivar = ObjCIvarDecl::Create(Context, EnclosingContext,
822                                              Prop->getLocation(),
823                                              NameII, PropType, /*Dinfo=*/0,
824                                              ObjCIvarDecl::Public,
825                                              (Expr *)0);
826    Ivar->setLexicalDeclContext(IDecl);
827    IDecl->addDecl(Ivar);
828    Prop->setPropertyIvarDecl(Ivar);
829  }
830  return Ivar;
831}
832
833/// ActOnPropertyImplDecl - This routine performs semantic checks and
834/// builds the AST node for a property implementation declaration; declared
835/// as @synthesize or @dynamic.
836///
837Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc,
838                                            SourceLocation PropertyLoc,
839                                            bool Synthesize,
840                                            DeclPtrTy ClassCatImpDecl,
841                                            IdentifierInfo *PropertyId,
842                                            IdentifierInfo *PropertyIvar) {
843  Decl *ClassImpDecl = ClassCatImpDecl.getAs<Decl>();
844  // Make sure we have a context for the property implementation declaration.
845  if (!ClassImpDecl) {
846    Diag(AtLoc, diag::error_missing_property_context);
847    return DeclPtrTy();
848  }
849  ObjCPropertyDecl *property = 0;
850  ObjCInterfaceDecl* IDecl = 0;
851  // Find the class or category class where this property must have
852  // a declaration.
853  ObjCImplementationDecl *IC = 0;
854  ObjCCategoryImplDecl* CatImplClass = 0;
855  if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
856    IDecl = IC->getClassInterface();
857    // We always synthesize an interface for an implementation
858    // without an interface decl. So, IDecl is always non-zero.
859    assert(IDecl &&
860           "ActOnPropertyImplDecl - @implementation without @interface");
861
862    // Look for this property declaration in the @implementation's @interface
863    property = IDecl->FindPropertyDeclaration(PropertyId);
864    if (!property) {
865      Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
866      return DeclPtrTy();
867    }
868    if (const ObjCCategoryDecl *CD =
869        dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
870      if (!CD->IsClassExtension()) {
871        Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
872        Diag(property->getLocation(), diag::note_property_declare);
873        return DeclPtrTy();
874      }
875    }
876  } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
877    if (Synthesize) {
878      Diag(AtLoc, diag::error_synthesize_category_decl);
879      return DeclPtrTy();
880    }
881    IDecl = CatImplClass->getClassInterface();
882    if (!IDecl) {
883      Diag(AtLoc, diag::error_missing_property_interface);
884      return DeclPtrTy();
885    }
886    ObjCCategoryDecl *Category =
887      IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
888
889    // If category for this implementation not found, it is an error which
890    // has already been reported eralier.
891    if (!Category)
892      return DeclPtrTy();
893    // Look for this property declaration in @implementation's category
894    property = Category->FindPropertyDeclaration(PropertyId);
895    if (!property) {
896      Diag(PropertyLoc, diag::error_bad_category_property_decl)
897        << Category->getDeclName();
898      return DeclPtrTy();
899    }
900  } else {
901    Diag(AtLoc, diag::error_bad_property_context);
902    return DeclPtrTy();
903  }
904  ObjCIvarDecl *Ivar = 0;
905  // Check that we have a valid, previously declared ivar for @synthesize
906  if (Synthesize) {
907    // @synthesize
908    if (!PropertyIvar)
909      PropertyIvar = PropertyId;
910    QualType PropType = Context.getCanonicalType(property->getType());
911    // Check that this is a previously declared 'ivar' in 'IDecl' interface
912    ObjCInterfaceDecl *ClassDeclared;
913    Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
914    if (!Ivar) {
915      DeclContext *EnclosingContext = cast_or_null<DeclContext>(ClassImpDecl);
916      assert(EnclosingContext &&
917             "null DeclContext for synthesized ivar - ActOnPropertyImplDecl");
918      Ivar = ObjCIvarDecl::Create(Context, EnclosingContext, PropertyLoc,
919                                  PropertyIvar, PropType, /*Dinfo=*/0,
920                                  ObjCIvarDecl::Public,
921                                  (Expr *)0);
922      EnclosingContext->addDecl(Ivar);
923      IDecl->makeDeclVisibleInContext(Ivar, false);
924      property->setPropertyIvarDecl(Ivar);
925
926      if (!getLangOptions().ObjCNonFragileABI)
927        Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId;
928        // Note! I deliberately want it to fall thru so, we have a
929        // a property implementation and to avoid future warnings.
930    } else if (getLangOptions().ObjCNonFragileABI &&
931               ClassDeclared != IDecl) {
932      Diag(PropertyLoc, diag::error_ivar_in_superclass_use)
933        << property->getDeclName() << Ivar->getDeclName()
934        << ClassDeclared->getDeclName();
935      Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
936        << Ivar << Ivar->getNameAsCString();
937      // Note! I deliberately want it to fall thru so more errors are caught.
938    }
939    QualType IvarType = Context.getCanonicalType(Ivar->getType());
940
941    // Check that type of property and its ivar are type compatible.
942    if (PropType != IvarType) {
943      if (CheckAssignmentConstraints(PropType, IvarType) != Compatible) {
944        Diag(PropertyLoc, diag::error_property_ivar_type)
945          << property->getDeclName() << Ivar->getDeclName();
946        // Note! I deliberately want it to fall thru so, we have a
947        // a property implementation and to avoid future warnings.
948      }
949
950      // FIXME! Rules for properties are somewhat different that those
951      // for assignments. Use a new routine to consolidate all cases;
952      // specifically for property redeclarations as well as for ivars.
953      QualType lhsType =Context.getCanonicalType(PropType).getUnqualifiedType();
954      QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
955      if (lhsType != rhsType &&
956          lhsType->isArithmeticType()) {
957        Diag(PropertyLoc, diag::error_property_ivar_type)
958        << property->getDeclName() << Ivar->getDeclName();
959        // Fall thru - see previous comment
960      }
961      // __weak is explicit. So it works on Canonical type.
962      if (PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
963          getLangOptions().getGCMode() != LangOptions::NonGC) {
964        Diag(PropertyLoc, diag::error_weak_property)
965        << property->getDeclName() << Ivar->getDeclName();
966        // Fall thru - see previous comment
967      }
968      if ((property->getType()->isObjCObjectPointerType() ||
969           PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
970           getLangOptions().getGCMode() != LangOptions::NonGC) {
971        Diag(PropertyLoc, diag::error_strong_property)
972        << property->getDeclName() << Ivar->getDeclName();
973        // Fall thru - see previous comment
974      }
975    }
976  } else if (PropertyIvar)
977      // @dynamic
978      Diag(PropertyLoc, diag::error_dynamic_property_ivar_decl);
979  assert (property && "ActOnPropertyImplDecl - property declaration missing");
980  ObjCPropertyImplDecl *PIDecl =
981    ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
982                                 property,
983                                 (Synthesize ?
984                                  ObjCPropertyImplDecl::Synthesize
985                                  : ObjCPropertyImplDecl::Dynamic),
986                                 Ivar);
987  if (IC) {
988    if (Synthesize)
989      if (ObjCPropertyImplDecl *PPIDecl =
990          IC->FindPropertyImplIvarDecl(PropertyIvar)) {
991        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
992          << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
993          << PropertyIvar;
994        Diag(PPIDecl->getLocation(), diag::note_previous_use);
995      }
996
997    if (ObjCPropertyImplDecl *PPIDecl
998          = IC->FindPropertyImplDecl(PropertyId)) {
999      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
1000      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
1001      return DeclPtrTy();
1002    }
1003    IC->addPropertyImplementation(PIDecl);
1004  } else {
1005    if (Synthesize)
1006      if (ObjCPropertyImplDecl *PPIDecl =
1007          CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
1008        Diag(PropertyLoc, diag::error_duplicate_ivar_use)
1009          << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
1010          << PropertyIvar;
1011        Diag(PPIDecl->getLocation(), diag::note_previous_use);
1012      }
1013
1014    if (ObjCPropertyImplDecl *PPIDecl =
1015          CatImplClass->FindPropertyImplDecl(PropertyId)) {
1016      Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
1017      Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
1018      return DeclPtrTy();
1019    }
1020    CatImplClass->addPropertyImplementation(PIDecl);
1021  }
1022
1023  return DeclPtrTy::make(PIDecl);
1024}
1025
1026