blob: f5b8f4483e1f585d4516696a10666e9dc4c6911d [file] [log] [blame]
Ted Kremenek9d64c152010-03-12 00:38:38 +00001//===--- 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