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