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