1 //===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements semantic analysis for Objective C @property and
11 // @synthesize declarations.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "clang/Sema/SemaInternal.h"
16 #include "clang/AST/ASTMutationListener.h"
17 #include "clang/AST/DeclObjC.h"
18 #include "clang/AST/ExprCXX.h"
19 #include "clang/AST/ExprObjC.h"
20 #include "clang/Basic/SourceManager.h"
21 #include "clang/Lex/Lexer.h"
22 #include "clang/Lex/Preprocessor.h"
23 #include "clang/Sema/Initialization.h"
24 #include "llvm/ADT/DenseSet.h"
25 #include "llvm/ADT/SmallString.h"
26
27 using namespace clang;
28
29 //===----------------------------------------------------------------------===//
30 // Grammar actions.
31 //===----------------------------------------------------------------------===//
32
33 /// getImpliedARCOwnership - Given a set of property attributes and a
34 /// type, infer an expected lifetime. The type's ownership qualification
35 /// is not considered.
36 ///
37 /// Returns OCL_None if the attributes as stated do not imply an ownership.
38 /// Never returns OCL_Autoreleasing.
getImpliedARCOwnership(ObjCPropertyDecl::PropertyAttributeKind attrs,QualType type)39 static Qualifiers::ObjCLifetime getImpliedARCOwnership(
40 ObjCPropertyDecl::PropertyAttributeKind attrs,
41 QualType type) {
42 // retain, strong, copy, weak, and unsafe_unretained are only legal
43 // on properties of retainable pointer type.
44 if (attrs & (ObjCPropertyDecl::OBJC_PR_retain |
45 ObjCPropertyDecl::OBJC_PR_strong |
46 ObjCPropertyDecl::OBJC_PR_copy)) {
47 return Qualifiers::OCL_Strong;
48 } else if (attrs & ObjCPropertyDecl::OBJC_PR_weak) {
49 return Qualifiers::OCL_Weak;
50 } else if (attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) {
51 return Qualifiers::OCL_ExplicitNone;
52 }
53
54 // assign can appear on other types, so we have to check the
55 // property type.
56 if (attrs & ObjCPropertyDecl::OBJC_PR_assign &&
57 type->isObjCRetainableType()) {
58 return Qualifiers::OCL_ExplicitNone;
59 }
60
61 return Qualifiers::OCL_None;
62 }
63
64 /// Check the internal consistency of a property declaration.
checkARCPropertyDecl(Sema & S,ObjCPropertyDecl * property)65 static void checkARCPropertyDecl(Sema &S, ObjCPropertyDecl *property) {
66 if (property->isInvalidDecl()) return;
67
68 ObjCPropertyDecl::PropertyAttributeKind propertyKind
69 = property->getPropertyAttributes();
70 Qualifiers::ObjCLifetime propertyLifetime
71 = property->getType().getObjCLifetime();
72
73 // Nothing to do if we don't have a lifetime.
74 if (propertyLifetime == Qualifiers::OCL_None) return;
75
76 Qualifiers::ObjCLifetime expectedLifetime
77 = getImpliedARCOwnership(propertyKind, property->getType());
78 if (!expectedLifetime) {
79 // We have a lifetime qualifier but no dominating property
80 // attribute. That's okay, but restore reasonable invariants by
81 // setting the property attribute according to the lifetime
82 // qualifier.
83 ObjCPropertyDecl::PropertyAttributeKind attr;
84 if (propertyLifetime == Qualifiers::OCL_Strong) {
85 attr = ObjCPropertyDecl::OBJC_PR_strong;
86 } else if (propertyLifetime == Qualifiers::OCL_Weak) {
87 attr = ObjCPropertyDecl::OBJC_PR_weak;
88 } else {
89 assert(propertyLifetime == Qualifiers::OCL_ExplicitNone);
90 attr = ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
91 }
92 property->setPropertyAttributes(attr);
93 return;
94 }
95
96 if (propertyLifetime == expectedLifetime) return;
97
98 property->setInvalidDecl();
99 S.Diag(property->getLocation(),
100 diag::err_arc_inconsistent_property_ownership)
101 << property->getDeclName()
102 << expectedLifetime
103 << propertyLifetime;
104 }
105
deduceWeakPropertyFromType(Sema & S,QualType T)106 static unsigned deduceWeakPropertyFromType(Sema &S, QualType T) {
107 if ((S.getLangOpts().getGC() != LangOptions::NonGC &&
108 T.isObjCGCWeak()) ||
109 (S.getLangOpts().ObjCAutoRefCount &&
110 T.getObjCLifetime() == Qualifiers::OCL_Weak))
111 return ObjCDeclSpec::DQ_PR_weak;
112 return 0;
113 }
114
115 /// \brief Check this Objective-C property against a property declared in the
116 /// given protocol.
117 static void
CheckPropertyAgainstProtocol(Sema & S,ObjCPropertyDecl * Prop,ObjCProtocolDecl * Proto,llvm::SmallPtrSet<ObjCProtocolDecl *,16> & Known)118 CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop,
119 ObjCProtocolDecl *Proto,
120 llvm::SmallPtrSet<ObjCProtocolDecl *, 16> &Known) {
121 // Have we seen this protocol before?
122 if (!Known.insert(Proto))
123 return;
124
125 // Look for a property with the same name.
126 DeclContext::lookup_result R = Proto->lookup(Prop->getDeclName());
127 for (unsigned I = 0, N = R.size(); I != N; ++I) {
128 if (ObjCPropertyDecl *ProtoProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
129 S.DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier());
130 return;
131 }
132 }
133
134 // Check this property against any protocols we inherit.
135 for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
136 PEnd = Proto->protocol_end();
137 P != PEnd; ++P) {
138 CheckPropertyAgainstProtocol(S, Prop, *P, Known);
139 }
140 }
141
ActOnProperty(Scope * S,SourceLocation AtLoc,SourceLocation LParenLoc,FieldDeclarator & FD,ObjCDeclSpec & ODS,Selector GetterSel,Selector SetterSel,bool * isOverridingProperty,tok::ObjCKeywordKind MethodImplKind,DeclContext * lexicalDC)142 Decl *Sema::ActOnProperty(Scope *S, SourceLocation AtLoc,
143 SourceLocation LParenLoc,
144 FieldDeclarator &FD,
145 ObjCDeclSpec &ODS,
146 Selector GetterSel,
147 Selector SetterSel,
148 bool *isOverridingProperty,
149 tok::ObjCKeywordKind MethodImplKind,
150 DeclContext *lexicalDC) {
151 unsigned Attributes = ODS.getPropertyAttributes();
152 TypeSourceInfo *TSI = GetTypeForDeclarator(FD.D, S);
153 QualType T = TSI->getType();
154 Attributes |= deduceWeakPropertyFromType(*this, T);
155
156 bool isReadWrite = ((Attributes & ObjCDeclSpec::DQ_PR_readwrite) ||
157 // default is readwrite!
158 !(Attributes & ObjCDeclSpec::DQ_PR_readonly));
159 // property is defaulted to 'assign' if it is readwrite and is
160 // not retain or copy
161 bool isAssign = ((Attributes & ObjCDeclSpec::DQ_PR_assign) ||
162 (isReadWrite &&
163 !(Attributes & ObjCDeclSpec::DQ_PR_retain) &&
164 !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
165 !(Attributes & ObjCDeclSpec::DQ_PR_copy) &&
166 !(Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) &&
167 !(Attributes & ObjCDeclSpec::DQ_PR_weak)));
168
169 // Proceed with constructing the ObjCPropertyDecls.
170 ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(CurContext);
171 ObjCPropertyDecl *Res = 0;
172 if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
173 if (CDecl->IsClassExtension()) {
174 Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
175 FD, GetterSel, SetterSel,
176 isAssign, isReadWrite,
177 Attributes,
178 ODS.getPropertyAttributes(),
179 isOverridingProperty, TSI,
180 MethodImplKind);
181 if (!Res)
182 return 0;
183 }
184 }
185
186 if (!Res) {
187 Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
188 GetterSel, SetterSel, isAssign, isReadWrite,
189 Attributes, ODS.getPropertyAttributes(),
190 TSI, MethodImplKind);
191 if (lexicalDC)
192 Res->setLexicalDeclContext(lexicalDC);
193 }
194
195 // Validate the attributes on the @property.
196 CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
197 (isa<ObjCInterfaceDecl>(ClassDecl) ||
198 isa<ObjCProtocolDecl>(ClassDecl)));
199
200 if (getLangOpts().ObjCAutoRefCount)
201 checkARCPropertyDecl(*this, Res);
202
203 llvm::SmallPtrSet<ObjCProtocolDecl *, 16> KnownProtos;
204 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
205 // For a class, compare the property against a property in our superclass.
206 bool FoundInSuper = false;
207 if (ObjCInterfaceDecl *Super = IFace->getSuperClass()) {
208 DeclContext::lookup_result R = Super->lookup(Res->getDeclName());
209 for (unsigned I = 0, N = R.size(); I != N; ++I) {
210 if (ObjCPropertyDecl *SuperProp = dyn_cast<ObjCPropertyDecl>(R[I])) {
211 DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier());
212 FoundInSuper = true;
213 break;
214 }
215 }
216 }
217
218 if (FoundInSuper) {
219 // Also compare the property against a property in our protocols.
220 for (ObjCInterfaceDecl::protocol_iterator P = IFace->protocol_begin(),
221 PEnd = IFace->protocol_end();
222 P != PEnd; ++P) {
223 CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
224 }
225 } else {
226 // Slower path: look in all protocols we referenced.
227 for (ObjCInterfaceDecl::all_protocol_iterator
228 P = IFace->all_referenced_protocol_begin(),
229 PEnd = IFace->all_referenced_protocol_end();
230 P != PEnd; ++P) {
231 CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
232 }
233 }
234 } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
235 for (ObjCCategoryDecl::protocol_iterator P = Cat->protocol_begin(),
236 PEnd = Cat->protocol_end();
237 P != PEnd; ++P) {
238 CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
239 }
240 } else {
241 ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
242 for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
243 PEnd = Proto->protocol_end();
244 P != PEnd; ++P) {
245 CheckPropertyAgainstProtocol(*this, Res, *P, KnownProtos);
246 }
247 }
248
249 ActOnDocumentableDecl(Res);
250 return Res;
251 }
252
253 static ObjCPropertyDecl::PropertyAttributeKind
makePropertyAttributesAsWritten(unsigned Attributes)254 makePropertyAttributesAsWritten(unsigned Attributes) {
255 unsigned attributesAsWritten = 0;
256 if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
257 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readonly;
258 if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
259 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_readwrite;
260 if (Attributes & ObjCDeclSpec::DQ_PR_getter)
261 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_getter;
262 if (Attributes & ObjCDeclSpec::DQ_PR_setter)
263 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_setter;
264 if (Attributes & ObjCDeclSpec::DQ_PR_assign)
265 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_assign;
266 if (Attributes & ObjCDeclSpec::DQ_PR_retain)
267 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_retain;
268 if (Attributes & ObjCDeclSpec::DQ_PR_strong)
269 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_strong;
270 if (Attributes & ObjCDeclSpec::DQ_PR_weak)
271 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_weak;
272 if (Attributes & ObjCDeclSpec::DQ_PR_copy)
273 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_copy;
274 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
275 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_unsafe_unretained;
276 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
277 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_nonatomic;
278 if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
279 attributesAsWritten |= ObjCPropertyDecl::OBJC_PR_atomic;
280
281 return (ObjCPropertyDecl::PropertyAttributeKind)attributesAsWritten;
282 }
283
LocPropertyAttribute(ASTContext & Context,const char * attrName,SourceLocation LParenLoc,SourceLocation & Loc)284 static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
285 SourceLocation LParenLoc, SourceLocation &Loc) {
286 if (LParenLoc.isMacroID())
287 return false;
288
289 SourceManager &SM = Context.getSourceManager();
290 std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(LParenLoc);
291 // Try to load the file buffer.
292 bool invalidTemp = false;
293 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
294 if (invalidTemp)
295 return false;
296 const char *tokenBegin = file.data() + locInfo.second;
297
298 // Lex from the start of the given location.
299 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
300 Context.getLangOpts(),
301 file.begin(), tokenBegin, file.end());
302 Token Tok;
303 do {
304 lexer.LexFromRawLexer(Tok);
305 if (Tok.is(tok::raw_identifier) &&
306 StringRef(Tok.getRawIdentifierData(), Tok.getLength()) == attrName) {
307 Loc = Tok.getLocation();
308 return true;
309 }
310 } while (Tok.isNot(tok::r_paren));
311 return false;
312
313 }
314
getOwnershipRule(unsigned attr)315 static unsigned getOwnershipRule(unsigned attr) {
316 return attr & (ObjCPropertyDecl::OBJC_PR_assign |
317 ObjCPropertyDecl::OBJC_PR_retain |
318 ObjCPropertyDecl::OBJC_PR_copy |
319 ObjCPropertyDecl::OBJC_PR_weak |
320 ObjCPropertyDecl::OBJC_PR_strong |
321 ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
322 }
323
324 ObjCPropertyDecl *
HandlePropertyInClassExtension(Scope * S,SourceLocation AtLoc,SourceLocation LParenLoc,FieldDeclarator & FD,Selector GetterSel,Selector SetterSel,const bool isAssign,const bool isReadWrite,const unsigned Attributes,const unsigned AttributesAsWritten,bool * isOverridingProperty,TypeSourceInfo * T,tok::ObjCKeywordKind MethodImplKind)325 Sema::HandlePropertyInClassExtension(Scope *S,
326 SourceLocation AtLoc,
327 SourceLocation LParenLoc,
328 FieldDeclarator &FD,
329 Selector GetterSel, Selector SetterSel,
330 const bool isAssign,
331 const bool isReadWrite,
332 const unsigned Attributes,
333 const unsigned AttributesAsWritten,
334 bool *isOverridingProperty,
335 TypeSourceInfo *T,
336 tok::ObjCKeywordKind MethodImplKind) {
337 ObjCCategoryDecl *CDecl = cast<ObjCCategoryDecl>(CurContext);
338 // Diagnose if this property is already in continuation class.
339 DeclContext *DC = CurContext;
340 IdentifierInfo *PropertyId = FD.D.getIdentifier();
341 ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
342
343 if (CCPrimary) {
344 // Check for duplicate declaration of this property in current and
345 // other class extensions.
346 for (ObjCInterfaceDecl::known_extensions_iterator
347 Ext = CCPrimary->known_extensions_begin(),
348 ExtEnd = CCPrimary->known_extensions_end();
349 Ext != ExtEnd; ++Ext) {
350 if (ObjCPropertyDecl *prevDecl
351 = ObjCPropertyDecl::findPropertyDecl(*Ext, PropertyId)) {
352 Diag(AtLoc, diag::err_duplicate_property);
353 Diag(prevDecl->getLocation(), diag::note_property_declare);
354 return 0;
355 }
356 }
357 }
358
359 // Create a new ObjCPropertyDecl with the DeclContext being
360 // the class extension.
361 // FIXME. We should really be using CreatePropertyDecl for this.
362 ObjCPropertyDecl *PDecl =
363 ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(),
364 PropertyId, AtLoc, LParenLoc, T);
365 PDecl->setPropertyAttributesAsWritten(
366 makePropertyAttributesAsWritten(AttributesAsWritten));
367 if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
368 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
369 if (Attributes & ObjCDeclSpec::DQ_PR_readwrite)
370 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
371 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
372 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
373 if (Attributes & ObjCDeclSpec::DQ_PR_atomic)
374 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
375 // Set setter/getter selector name. Needed later.
376 PDecl->setGetterName(GetterSel);
377 PDecl->setSetterName(SetterSel);
378 ProcessDeclAttributes(S, PDecl, FD.D);
379 DC->addDecl(PDecl);
380
381 // We need to look in the @interface to see if the @property was
382 // already declared.
383 if (!CCPrimary) {
384 Diag(CDecl->getLocation(), diag::err_continuation_class);
385 *isOverridingProperty = true;
386 return 0;
387 }
388
389 // Find the property in continuation class's primary class only.
390 ObjCPropertyDecl *PIDecl =
391 CCPrimary->FindPropertyVisibleInPrimaryClass(PropertyId);
392
393 if (!PIDecl) {
394 // No matching property found in the primary class. Just fall thru
395 // and add property to continuation class's primary class.
396 ObjCPropertyDecl *PrimaryPDecl =
397 CreatePropertyDecl(S, CCPrimary, AtLoc, LParenLoc,
398 FD, GetterSel, SetterSel, isAssign, isReadWrite,
399 Attributes,AttributesAsWritten, T, MethodImplKind, DC);
400
401 // A case of continuation class adding a new property in the class. This
402 // is not what it was meant for. However, gcc supports it and so should we.
403 // Make sure setter/getters are declared here.
404 ProcessPropertyDecl(PrimaryPDecl, CCPrimary, /* redeclaredProperty = */ 0,
405 /* lexicalDC = */ CDecl);
406 PDecl->setGetterMethodDecl(PrimaryPDecl->getGetterMethodDecl());
407 PDecl->setSetterMethodDecl(PrimaryPDecl->getSetterMethodDecl());
408 if (ASTMutationListener *L = Context.getASTMutationListener())
409 L->AddedObjCPropertyInClassExtension(PrimaryPDecl, /*OrigProp=*/0, CDecl);
410 return PrimaryPDecl;
411 }
412 if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
413 bool IncompatibleObjC = false;
414 QualType ConvertedType;
415 // Relax the strict type matching for property type in continuation class.
416 // Allow property object type of continuation class to be different as long
417 // as it narrows the object type in its primary class property. Note that
418 // this conversion is safe only because the wider type is for a 'readonly'
419 // property in primary class and 'narrowed' type for a 'readwrite' property
420 // in continuation class.
421 if (!isa<ObjCObjectPointerType>(PIDecl->getType()) ||
422 !isa<ObjCObjectPointerType>(PDecl->getType()) ||
423 (!isObjCPointerConversion(PDecl->getType(), PIDecl->getType(),
424 ConvertedType, IncompatibleObjC))
425 || IncompatibleObjC) {
426 Diag(AtLoc,
427 diag::err_type_mismatch_continuation_class) << PDecl->getType();
428 Diag(PIDecl->getLocation(), diag::note_property_declare);
429 return 0;
430 }
431 }
432
433 // The property 'PIDecl's readonly attribute will be over-ridden
434 // with continuation class's readwrite property attribute!
435 unsigned PIkind = PIDecl->getPropertyAttributesAsWritten();
436 if (isReadWrite && (PIkind & ObjCPropertyDecl::OBJC_PR_readonly)) {
437 PIkind |= deduceWeakPropertyFromType(*this, PIDecl->getType());
438 unsigned ClassExtensionMemoryModel = getOwnershipRule(Attributes);
439 unsigned PrimaryClassMemoryModel = getOwnershipRule(PIkind);
440 if (PrimaryClassMemoryModel && ClassExtensionMemoryModel &&
441 (PrimaryClassMemoryModel != ClassExtensionMemoryModel)) {
442 Diag(AtLoc, diag::warn_property_attr_mismatch);
443 Diag(PIDecl->getLocation(), diag::note_property_declare);
444 }
445 DeclContext *DC = cast<DeclContext>(CCPrimary);
446 if (!ObjCPropertyDecl::findPropertyDecl(DC,
447 PIDecl->getDeclName().getAsIdentifierInfo())) {
448 // Protocol is not in the primary class. Must build one for it.
449 ObjCDeclSpec ProtocolPropertyODS;
450 // FIXME. Assuming that ObjCDeclSpec::ObjCPropertyAttributeKind
451 // and ObjCPropertyDecl::PropertyAttributeKind have identical
452 // values. Should consolidate both into one enum type.
453 ProtocolPropertyODS.
454 setPropertyAttributes((ObjCDeclSpec::ObjCPropertyAttributeKind)
455 PIkind);
456 // Must re-establish the context from class extension to primary
457 // class context.
458 ContextRAII SavedContext(*this, CCPrimary);
459
460 Decl *ProtocolPtrTy =
461 ActOnProperty(S, AtLoc, LParenLoc, FD, ProtocolPropertyODS,
462 PIDecl->getGetterName(),
463 PIDecl->getSetterName(),
464 isOverridingProperty,
465 MethodImplKind,
466 /* lexicalDC = */ CDecl);
467 PIDecl = cast<ObjCPropertyDecl>(ProtocolPtrTy);
468 }
469 PIDecl->makeitReadWriteAttribute();
470 if (Attributes & ObjCDeclSpec::DQ_PR_retain)
471 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
472 if (Attributes & ObjCDeclSpec::DQ_PR_strong)
473 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
474 if (Attributes & ObjCDeclSpec::DQ_PR_copy)
475 PIDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
476 PIDecl->setSetterName(SetterSel);
477 } else {
478 // Tailor the diagnostics for the common case where a readwrite
479 // property is declared both in the @interface and the continuation.
480 // This is a common error where the user often intended the original
481 // declaration to be readonly.
482 unsigned diag =
483 (Attributes & ObjCDeclSpec::DQ_PR_readwrite) &&
484 (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite)
485 ? diag::err_use_continuation_class_redeclaration_readwrite
486 : diag::err_use_continuation_class;
487 Diag(AtLoc, diag)
488 << CCPrimary->getDeclName();
489 Diag(PIDecl->getLocation(), diag::note_property_declare);
490 return 0;
491 }
492 *isOverridingProperty = true;
493 // Make sure setter decl is synthesized, and added to primary class's list.
494 ProcessPropertyDecl(PIDecl, CCPrimary, PDecl, CDecl);
495 PDecl->setGetterMethodDecl(PIDecl->getGetterMethodDecl());
496 PDecl->setSetterMethodDecl(PIDecl->getSetterMethodDecl());
497 if (ASTMutationListener *L = Context.getASTMutationListener())
498 L->AddedObjCPropertyInClassExtension(PDecl, PIDecl, CDecl);
499 return PDecl;
500 }
501
CreatePropertyDecl(Scope * S,ObjCContainerDecl * CDecl,SourceLocation AtLoc,SourceLocation LParenLoc,FieldDeclarator & FD,Selector GetterSel,Selector SetterSel,const bool isAssign,const bool isReadWrite,const unsigned Attributes,const unsigned AttributesAsWritten,TypeSourceInfo * TInfo,tok::ObjCKeywordKind MethodImplKind,DeclContext * lexicalDC)502 ObjCPropertyDecl *Sema::CreatePropertyDecl(Scope *S,
503 ObjCContainerDecl *CDecl,
504 SourceLocation AtLoc,
505 SourceLocation LParenLoc,
506 FieldDeclarator &FD,
507 Selector GetterSel,
508 Selector SetterSel,
509 const bool isAssign,
510 const bool isReadWrite,
511 const unsigned Attributes,
512 const unsigned AttributesAsWritten,
513 TypeSourceInfo *TInfo,
514 tok::ObjCKeywordKind MethodImplKind,
515 DeclContext *lexicalDC){
516 IdentifierInfo *PropertyId = FD.D.getIdentifier();
517 QualType T = TInfo->getType();
518
519 // Issue a warning if property is 'assign' as default and its object, which is
520 // gc'able conforms to NSCopying protocol
521 if (getLangOpts().getGC() != LangOptions::NonGC &&
522 isAssign && !(Attributes & ObjCDeclSpec::DQ_PR_assign))
523 if (const ObjCObjectPointerType *ObjPtrTy =
524 T->getAs<ObjCObjectPointerType>()) {
525 ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
526 if (IDecl)
527 if (ObjCProtocolDecl* PNSCopying =
528 LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
529 if (IDecl->ClassImplementsProtocol(PNSCopying, true))
530 Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
531 }
532
533 if (T->isObjCObjectType()) {
534 SourceLocation StarLoc = TInfo->getTypeLoc().getLocEnd();
535 StarLoc = PP.getLocForEndOfToken(StarLoc);
536 Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
537 << FixItHint::CreateInsertion(StarLoc, "*");
538 T = Context.getObjCObjectPointerType(T);
539 SourceLocation TLoc = TInfo->getTypeLoc().getLocStart();
540 TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
541 }
542
543 DeclContext *DC = cast<DeclContext>(CDecl);
544 ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
545 FD.D.getIdentifierLoc(),
546 PropertyId, AtLoc, LParenLoc, TInfo);
547
548 if (ObjCPropertyDecl *prevDecl =
549 ObjCPropertyDecl::findPropertyDecl(DC, PropertyId)) {
550 Diag(PDecl->getLocation(), diag::err_duplicate_property);
551 Diag(prevDecl->getLocation(), diag::note_property_declare);
552 PDecl->setInvalidDecl();
553 }
554 else {
555 DC->addDecl(PDecl);
556 if (lexicalDC)
557 PDecl->setLexicalDeclContext(lexicalDC);
558 }
559
560 if (T->isArrayType() || T->isFunctionType()) {
561 Diag(AtLoc, diag::err_property_type) << T;
562 PDecl->setInvalidDecl();
563 }
564
565 ProcessDeclAttributes(S, PDecl, FD.D);
566
567 // Regardless of setter/getter attribute, we save the default getter/setter
568 // selector names in anticipation of declaration of setter/getter methods.
569 PDecl->setGetterName(GetterSel);
570 PDecl->setSetterName(SetterSel);
571 PDecl->setPropertyAttributesAsWritten(
572 makePropertyAttributesAsWritten(AttributesAsWritten));
573
574 if (Attributes & ObjCDeclSpec::DQ_PR_readonly)
575 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readonly);
576
577 if (Attributes & ObjCDeclSpec::DQ_PR_getter)
578 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_getter);
579
580 if (Attributes & ObjCDeclSpec::DQ_PR_setter)
581 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_setter);
582
583 if (isReadWrite)
584 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_readwrite);
585
586 if (Attributes & ObjCDeclSpec::DQ_PR_retain)
587 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_retain);
588
589 if (Attributes & ObjCDeclSpec::DQ_PR_strong)
590 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
591
592 if (Attributes & ObjCDeclSpec::DQ_PR_weak)
593 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak);
594
595 if (Attributes & ObjCDeclSpec::DQ_PR_copy)
596 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_copy);
597
598 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
599 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
600
601 if (isAssign)
602 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
603
604 // In the semantic attributes, one of nonatomic or atomic is always set.
605 if (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)
606 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_nonatomic);
607 else
608 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_atomic);
609
610 // 'unsafe_unretained' is alias for 'assign'.
611 if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained)
612 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_assign);
613 if (isAssign)
614 PDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_unsafe_unretained);
615
616 if (MethodImplKind == tok::objc_required)
617 PDecl->setPropertyImplementation(ObjCPropertyDecl::Required);
618 else if (MethodImplKind == tok::objc_optional)
619 PDecl->setPropertyImplementation(ObjCPropertyDecl::Optional);
620
621 return PDecl;
622 }
623
checkARCPropertyImpl(Sema & S,SourceLocation propertyImplLoc,ObjCPropertyDecl * property,ObjCIvarDecl * ivar)624 static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
625 ObjCPropertyDecl *property,
626 ObjCIvarDecl *ivar) {
627 if (property->isInvalidDecl() || ivar->isInvalidDecl()) return;
628
629 QualType ivarType = ivar->getType();
630 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
631
632 // The lifetime implied by the property's attributes.
633 Qualifiers::ObjCLifetime propertyLifetime =
634 getImpliedARCOwnership(property->getPropertyAttributes(),
635 property->getType());
636
637 // We're fine if they match.
638 if (propertyLifetime == ivarLifetime) return;
639
640 // These aren't valid lifetimes for object ivars; don't diagnose twice.
641 if (ivarLifetime == Qualifiers::OCL_None ||
642 ivarLifetime == Qualifiers::OCL_Autoreleasing)
643 return;
644
645 // If the ivar is private, and it's implicitly __unsafe_unretained
646 // becaues of its type, then pretend it was actually implicitly
647 // __strong. This is only sound because we're processing the
648 // property implementation before parsing any method bodies.
649 if (ivarLifetime == Qualifiers::OCL_ExplicitNone &&
650 propertyLifetime == Qualifiers::OCL_Strong &&
651 ivar->getAccessControl() == ObjCIvarDecl::Private) {
652 SplitQualType split = ivarType.split();
653 if (split.Quals.hasObjCLifetime()) {
654 assert(ivarType->isObjCARCImplicitlyUnretainedType());
655 split.Quals.setObjCLifetime(Qualifiers::OCL_Strong);
656 ivarType = S.Context.getQualifiedType(split);
657 ivar->setType(ivarType);
658 return;
659 }
660 }
661
662 switch (propertyLifetime) {
663 case Qualifiers::OCL_Strong:
664 S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership)
665 << property->getDeclName()
666 << ivar->getDeclName()
667 << ivarLifetime;
668 break;
669
670 case Qualifiers::OCL_Weak:
671 S.Diag(ivar->getLocation(), diag::error_weak_property)
672 << property->getDeclName()
673 << ivar->getDeclName();
674 break;
675
676 case Qualifiers::OCL_ExplicitNone:
677 S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership)
678 << property->getDeclName()
679 << ivar->getDeclName()
680 << ((property->getPropertyAttributesAsWritten()
681 & ObjCPropertyDecl::OBJC_PR_assign) != 0);
682 break;
683
684 case Qualifiers::OCL_Autoreleasing:
685 llvm_unreachable("properties cannot be autoreleasing");
686
687 case Qualifiers::OCL_None:
688 // Any other property should be ignored.
689 return;
690 }
691
692 S.Diag(property->getLocation(), diag::note_property_declare);
693 if (propertyImplLoc.isValid())
694 S.Diag(propertyImplLoc, diag::note_property_synthesize);
695 }
696
697 /// setImpliedPropertyAttributeForReadOnlyProperty -
698 /// This routine evaludates life-time attributes for a 'readonly'
699 /// property with no known lifetime of its own, using backing
700 /// 'ivar's attribute, if any. If no backing 'ivar', property's
701 /// life-time is assumed 'strong'.
setImpliedPropertyAttributeForReadOnlyProperty(ObjCPropertyDecl * property,ObjCIvarDecl * ivar)702 static void setImpliedPropertyAttributeForReadOnlyProperty(
703 ObjCPropertyDecl *property, ObjCIvarDecl *ivar) {
704 Qualifiers::ObjCLifetime propertyLifetime =
705 getImpliedARCOwnership(property->getPropertyAttributes(),
706 property->getType());
707 if (propertyLifetime != Qualifiers::OCL_None)
708 return;
709
710 if (!ivar) {
711 // if no backing ivar, make property 'strong'.
712 property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
713 return;
714 }
715 // property assumes owenership of backing ivar.
716 QualType ivarType = ivar->getType();
717 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
718 if (ivarLifetime == Qualifiers::OCL_Strong)
719 property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
720 else if (ivarLifetime == Qualifiers::OCL_Weak)
721 property->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_weak);
722 return;
723 }
724
725 /// DiagnosePropertyMismatchDeclInProtocols - diagnose properties declared
726 /// in inherited protocols with mismatched types. Since any of them can
727 /// be candidate for synthesis.
728 static void
DiagnosePropertyMismatchDeclInProtocols(Sema & S,SourceLocation AtLoc,ObjCInterfaceDecl * ClassDecl,ObjCPropertyDecl * Property)729 DiagnosePropertyMismatchDeclInProtocols(Sema &S, SourceLocation AtLoc,
730 ObjCInterfaceDecl *ClassDecl,
731 ObjCPropertyDecl *Property) {
732 ObjCInterfaceDecl::ProtocolPropertyMap PropMap;
733 for (ObjCInterfaceDecl::all_protocol_iterator
734 PI = ClassDecl->all_referenced_protocol_begin(),
735 E = ClassDecl->all_referenced_protocol_end(); PI != E; ++PI) {
736 if (const ObjCProtocolDecl *PDecl = (*PI)->getDefinition())
737 PDecl->collectInheritedProtocolProperties(Property, PropMap);
738 }
739 if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass())
740 while (SDecl) {
741 for (ObjCInterfaceDecl::all_protocol_iterator
742 PI = SDecl->all_referenced_protocol_begin(),
743 E = SDecl->all_referenced_protocol_end(); PI != E; ++PI) {
744 if (const ObjCProtocolDecl *PDecl = (*PI)->getDefinition())
745 PDecl->collectInheritedProtocolProperties(Property, PropMap);
746 }
747 SDecl = SDecl->getSuperClass();
748 }
749
750 if (PropMap.empty())
751 return;
752
753 QualType RHSType = S.Context.getCanonicalType(Property->getType());
754 bool FirsTime = true;
755 for (ObjCInterfaceDecl::ProtocolPropertyMap::iterator
756 I = PropMap.begin(), E = PropMap.end(); I != E; I++) {
757 ObjCPropertyDecl *Prop = I->second;
758 QualType LHSType = S.Context.getCanonicalType(Prop->getType());
759 if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) {
760 bool IncompatibleObjC = false;
761 QualType ConvertedType;
762 if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC)
763 || IncompatibleObjC) {
764 if (FirsTime) {
765 S.Diag(Property->getLocation(), diag::warn_protocol_property_mismatch)
766 << Property->getType();
767 FirsTime = false;
768 }
769 S.Diag(Prop->getLocation(), diag::note_protocol_property_declare)
770 << Prop->getType();
771 }
772 }
773 }
774 if (!FirsTime && AtLoc.isValid())
775 S.Diag(AtLoc, diag::note_property_synthesize);
776 }
777
778 /// DiagnoseClassAndClassExtPropertyMismatch - diagnose inconsistant property
779 /// attribute declared in primary class and attributes overridden in any of its
780 /// class extensions.
781 static void
DiagnoseClassAndClassExtPropertyMismatch(Sema & S,ObjCInterfaceDecl * ClassDecl,ObjCPropertyDecl * property)782 DiagnoseClassAndClassExtPropertyMismatch(Sema &S, ObjCInterfaceDecl *ClassDecl,
783 ObjCPropertyDecl *property) {
784 unsigned Attributes = property->getPropertyAttributesAsWritten();
785 bool warn = (Attributes & ObjCDeclSpec::DQ_PR_readonly);
786 for (ObjCInterfaceDecl::known_extensions_iterator
787 Ext = ClassDecl->known_extensions_begin(),
788 ExtEnd = ClassDecl->known_extensions_end();
789 Ext != ExtEnd; ++Ext) {
790 ObjCPropertyDecl *ClassExtProperty = 0;
791 DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
792 for (unsigned I = 0, N = R.size(); I != N; ++I) {
793 ClassExtProperty = dyn_cast<ObjCPropertyDecl>(R[0]);
794 if (ClassExtProperty)
795 break;
796 }
797
798 if (ClassExtProperty) {
799 warn = false;
800 unsigned classExtPropertyAttr =
801 ClassExtProperty->getPropertyAttributesAsWritten();
802 // We are issuing the warning that we postponed because class extensions
803 // can override readonly->readwrite and 'setter' attributes originally
804 // placed on class's property declaration now make sense in the overridden
805 // property.
806 if (Attributes & ObjCDeclSpec::DQ_PR_readonly) {
807 if (!classExtPropertyAttr ||
808 (classExtPropertyAttr &
809 (ObjCDeclSpec::DQ_PR_readwrite|
810 ObjCDeclSpec::DQ_PR_assign |
811 ObjCDeclSpec::DQ_PR_unsafe_unretained |
812 ObjCDeclSpec::DQ_PR_copy |
813 ObjCDeclSpec::DQ_PR_retain |
814 ObjCDeclSpec::DQ_PR_strong)))
815 continue;
816 warn = true;
817 break;
818 }
819 }
820 }
821 if (warn) {
822 unsigned setterAttrs = (ObjCDeclSpec::DQ_PR_assign |
823 ObjCDeclSpec::DQ_PR_unsafe_unretained |
824 ObjCDeclSpec::DQ_PR_copy |
825 ObjCDeclSpec::DQ_PR_retain |
826 ObjCDeclSpec::DQ_PR_strong);
827 if (Attributes & setterAttrs) {
828 const char * which =
829 (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
830 "assign" :
831 (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
832 "unsafe_unretained" :
833 (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
834 "copy" :
835 (Attributes & ObjCDeclSpec::DQ_PR_retain) ?
836 "retain" : "strong";
837
838 S.Diag(property->getLocation(),
839 diag::warn_objc_property_attr_mutually_exclusive)
840 << "readonly" << which;
841 }
842 }
843
844
845 }
846
847 /// ActOnPropertyImplDecl - This routine performs semantic checks and
848 /// builds the AST node for a property implementation declaration; declared
849 /// as \@synthesize or \@dynamic.
850 ///
ActOnPropertyImplDecl(Scope * S,SourceLocation AtLoc,SourceLocation PropertyLoc,bool Synthesize,IdentifierInfo * PropertyId,IdentifierInfo * PropertyIvar,SourceLocation PropertyIvarLoc)851 Decl *Sema::ActOnPropertyImplDecl(Scope *S,
852 SourceLocation AtLoc,
853 SourceLocation PropertyLoc,
854 bool Synthesize,
855 IdentifierInfo *PropertyId,
856 IdentifierInfo *PropertyIvar,
857 SourceLocation PropertyIvarLoc) {
858 ObjCContainerDecl *ClassImpDecl =
859 dyn_cast<ObjCContainerDecl>(CurContext);
860 // Make sure we have a context for the property implementation declaration.
861 if (!ClassImpDecl) {
862 Diag(AtLoc, diag::error_missing_property_context);
863 return 0;
864 }
865 if (PropertyIvarLoc.isInvalid())
866 PropertyIvarLoc = PropertyLoc;
867 SourceLocation PropertyDiagLoc = PropertyLoc;
868 if (PropertyDiagLoc.isInvalid())
869 PropertyDiagLoc = ClassImpDecl->getLocStart();
870 ObjCPropertyDecl *property = 0;
871 ObjCInterfaceDecl* IDecl = 0;
872 // Find the class or category class where this property must have
873 // a declaration.
874 ObjCImplementationDecl *IC = 0;
875 ObjCCategoryImplDecl* CatImplClass = 0;
876 if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
877 IDecl = IC->getClassInterface();
878 // We always synthesize an interface for an implementation
879 // without an interface decl. So, IDecl is always non-zero.
880 assert(IDecl &&
881 "ActOnPropertyImplDecl - @implementation without @interface");
882
883 // Look for this property declaration in the @implementation's @interface
884 property = IDecl->FindPropertyDeclaration(PropertyId);
885 if (!property) {
886 Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName();
887 return 0;
888 }
889 unsigned PIkind = property->getPropertyAttributesAsWritten();
890 if ((PIkind & (ObjCPropertyDecl::OBJC_PR_atomic |
891 ObjCPropertyDecl::OBJC_PR_nonatomic) ) == 0) {
892 if (AtLoc.isValid())
893 Diag(AtLoc, diag::warn_implicit_atomic_property);
894 else
895 Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
896 Diag(property->getLocation(), diag::note_property_declare);
897 }
898
899 if (const ObjCCategoryDecl *CD =
900 dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
901 if (!CD->IsClassExtension()) {
902 Diag(PropertyLoc, diag::error_category_property) << CD->getDeclName();
903 Diag(property->getLocation(), diag::note_property_declare);
904 return 0;
905 }
906 }
907 if (Synthesize&&
908 (PIkind & ObjCPropertyDecl::OBJC_PR_readonly) &&
909 property->hasAttr<IBOutletAttr>() &&
910 !AtLoc.isValid()) {
911 bool ReadWriteProperty = false;
912 // Search into the class extensions and see if 'readonly property is
913 // redeclared 'readwrite', then no warning is to be issued.
914 for (ObjCInterfaceDecl::known_extensions_iterator
915 Ext = IDecl->known_extensions_begin(),
916 ExtEnd = IDecl->known_extensions_end(); Ext != ExtEnd; ++Ext) {
917 DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
918 if (!R.empty())
919 if (ObjCPropertyDecl *ExtProp = dyn_cast<ObjCPropertyDecl>(R[0])) {
920 PIkind = ExtProp->getPropertyAttributesAsWritten();
921 if (PIkind & ObjCPropertyDecl::OBJC_PR_readwrite) {
922 ReadWriteProperty = true;
923 break;
924 }
925 }
926 }
927
928 if (!ReadWriteProperty) {
929 Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
930 << property->getName();
931 SourceLocation readonlyLoc;
932 if (LocPropertyAttribute(Context, "readonly",
933 property->getLParenLoc(), readonlyLoc)) {
934 SourceLocation endLoc =
935 readonlyLoc.getLocWithOffset(strlen("readonly")-1);
936 SourceRange ReadonlySourceRange(readonlyLoc, endLoc);
937 Diag(property->getLocation(),
938 diag::note_auto_readonly_iboutlet_fixup_suggest) <<
939 FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
940 }
941 }
942 }
943 if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext()))
944 DiagnosePropertyMismatchDeclInProtocols(*this, AtLoc, IDecl, property);
945
946 DiagnoseClassAndClassExtPropertyMismatch(*this, IDecl, property);
947
948 } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
949 if (Synthesize) {
950 Diag(AtLoc, diag::error_synthesize_category_decl);
951 return 0;
952 }
953 IDecl = CatImplClass->getClassInterface();
954 if (!IDecl) {
955 Diag(AtLoc, diag::error_missing_property_interface);
956 return 0;
957 }
958 ObjCCategoryDecl *Category =
959 IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
960
961 // If category for this implementation not found, it is an error which
962 // has already been reported eralier.
963 if (!Category)
964 return 0;
965 // Look for this property declaration in @implementation's category
966 property = Category->FindPropertyDeclaration(PropertyId);
967 if (!property) {
968 Diag(PropertyLoc, diag::error_bad_category_property_decl)
969 << Category->getDeclName();
970 return 0;
971 }
972 } else {
973 Diag(AtLoc, diag::error_bad_property_context);
974 return 0;
975 }
976 ObjCIvarDecl *Ivar = 0;
977 bool CompleteTypeErr = false;
978 bool compat = true;
979 // Check that we have a valid, previously declared ivar for @synthesize
980 if (Synthesize) {
981 // @synthesize
982 if (!PropertyIvar)
983 PropertyIvar = PropertyId;
984 // Check that this is a previously declared 'ivar' in 'IDecl' interface
985 ObjCInterfaceDecl *ClassDeclared;
986 Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
987 QualType PropType = property->getType();
988 QualType PropertyIvarType = PropType.getNonReferenceType();
989
990 if (RequireCompleteType(PropertyDiagLoc, PropertyIvarType,
991 diag::err_incomplete_synthesized_property,
992 property->getDeclName())) {
993 Diag(property->getLocation(), diag::note_property_declare);
994 CompleteTypeErr = true;
995 }
996
997 if (getLangOpts().ObjCAutoRefCount &&
998 (property->getPropertyAttributesAsWritten() &
999 ObjCPropertyDecl::OBJC_PR_readonly) &&
1000 PropertyIvarType->isObjCRetainableType()) {
1001 setImpliedPropertyAttributeForReadOnlyProperty(property, Ivar);
1002 }
1003
1004 ObjCPropertyDecl::PropertyAttributeKind kind
1005 = property->getPropertyAttributes();
1006
1007 // Add GC __weak to the ivar type if the property is weak.
1008 if ((kind & ObjCPropertyDecl::OBJC_PR_weak) &&
1009 getLangOpts().getGC() != LangOptions::NonGC) {
1010 assert(!getLangOpts().ObjCAutoRefCount);
1011 if (PropertyIvarType.isObjCGCStrong()) {
1012 Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
1013 Diag(property->getLocation(), diag::note_property_declare);
1014 } else {
1015 PropertyIvarType =
1016 Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
1017 }
1018 }
1019 if (AtLoc.isInvalid()) {
1020 // Check when default synthesizing a property that there is
1021 // an ivar matching property name and issue warning; since this
1022 // is the most common case of not using an ivar used for backing
1023 // property in non-default synthesis case.
1024 ObjCInterfaceDecl *ClassDeclared=0;
1025 ObjCIvarDecl *originalIvar =
1026 IDecl->lookupInstanceVariable(property->getIdentifier(),
1027 ClassDeclared);
1028 if (originalIvar) {
1029 Diag(PropertyDiagLoc,
1030 diag::warn_autosynthesis_property_ivar_match)
1031 << PropertyId << (Ivar == 0) << PropertyIvar
1032 << originalIvar->getIdentifier();
1033 Diag(property->getLocation(), diag::note_property_declare);
1034 Diag(originalIvar->getLocation(), diag::note_ivar_decl);
1035 }
1036 }
1037
1038 if (!Ivar) {
1039 // In ARC, give the ivar a lifetime qualifier based on the
1040 // property attributes.
1041 if (getLangOpts().ObjCAutoRefCount &&
1042 !PropertyIvarType.getObjCLifetime() &&
1043 PropertyIvarType->isObjCRetainableType()) {
1044
1045 // It's an error if we have to do this and the user didn't
1046 // explicitly write an ownership attribute on the property.
1047 if (!property->hasWrittenStorageAttribute() &&
1048 !(kind & ObjCPropertyDecl::OBJC_PR_strong)) {
1049 Diag(PropertyDiagLoc,
1050 diag::err_arc_objc_property_default_assign_on_object);
1051 Diag(property->getLocation(), diag::note_property_declare);
1052 } else {
1053 Qualifiers::ObjCLifetime lifetime =
1054 getImpliedARCOwnership(kind, PropertyIvarType);
1055 assert(lifetime && "no lifetime for property?");
1056 if (lifetime == Qualifiers::OCL_Weak) {
1057 bool err = false;
1058 if (const ObjCObjectPointerType *ObjT =
1059 PropertyIvarType->getAs<ObjCObjectPointerType>()) {
1060 const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
1061 if (ObjI && ObjI->isArcWeakrefUnavailable()) {
1062 Diag(property->getLocation(),
1063 diag::err_arc_weak_unavailable_property) << PropertyIvarType;
1064 Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
1065 << ClassImpDecl->getName();
1066 err = true;
1067 }
1068 }
1069 if (!err && !getLangOpts().ObjCARCWeak) {
1070 Diag(PropertyDiagLoc, diag::err_arc_weak_no_runtime);
1071 Diag(property->getLocation(), diag::note_property_declare);
1072 }
1073 }
1074
1075 Qualifiers qs;
1076 qs.addObjCLifetime(lifetime);
1077 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
1078 }
1079 }
1080
1081 if (kind & ObjCPropertyDecl::OBJC_PR_weak &&
1082 !getLangOpts().ObjCAutoRefCount &&
1083 getLangOpts().getGC() == LangOptions::NonGC) {
1084 Diag(PropertyDiagLoc, diag::error_synthesize_weak_non_arc_or_gc);
1085 Diag(property->getLocation(), diag::note_property_declare);
1086 }
1087
1088 Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
1089 PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
1090 PropertyIvarType, /*Dinfo=*/0,
1091 ObjCIvarDecl::Private,
1092 (Expr *)0, true);
1093 if (RequireNonAbstractType(PropertyIvarLoc,
1094 PropertyIvarType,
1095 diag::err_abstract_type_in_decl,
1096 AbstractSynthesizedIvarType)) {
1097 Diag(property->getLocation(), diag::note_property_declare);
1098 Ivar->setInvalidDecl();
1099 } else if (CompleteTypeErr)
1100 Ivar->setInvalidDecl();
1101 ClassImpDecl->addDecl(Ivar);
1102 IDecl->makeDeclVisibleInContext(Ivar);
1103
1104 if (getLangOpts().ObjCRuntime.isFragile())
1105 Diag(PropertyDiagLoc, diag::error_missing_property_ivar_decl)
1106 << PropertyId;
1107 // Note! I deliberately want it to fall thru so, we have a
1108 // a property implementation and to avoid future warnings.
1109 } else if (getLangOpts().ObjCRuntime.isNonFragile() &&
1110 !declaresSameEntity(ClassDeclared, IDecl)) {
1111 Diag(PropertyDiagLoc, diag::error_ivar_in_superclass_use)
1112 << property->getDeclName() << Ivar->getDeclName()
1113 << ClassDeclared->getDeclName();
1114 Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
1115 << Ivar << Ivar->getName();
1116 // Note! I deliberately want it to fall thru so more errors are caught.
1117 }
1118 property->setPropertyIvarDecl(Ivar);
1119
1120 QualType IvarType = Context.getCanonicalType(Ivar->getType());
1121
1122 // Check that type of property and its ivar are type compatible.
1123 if (!Context.hasSameType(PropertyIvarType, IvarType)) {
1124 if (isa<ObjCObjectPointerType>(PropertyIvarType)
1125 && isa<ObjCObjectPointerType>(IvarType))
1126 compat =
1127 Context.canAssignObjCInterfaces(
1128 PropertyIvarType->getAs<ObjCObjectPointerType>(),
1129 IvarType->getAs<ObjCObjectPointerType>());
1130 else {
1131 compat = (CheckAssignmentConstraints(PropertyIvarLoc, PropertyIvarType,
1132 IvarType)
1133 == Compatible);
1134 }
1135 if (!compat) {
1136 Diag(PropertyDiagLoc, diag::error_property_ivar_type)
1137 << property->getDeclName() << PropType
1138 << Ivar->getDeclName() << IvarType;
1139 Diag(Ivar->getLocation(), diag::note_ivar_decl);
1140 // Note! I deliberately want it to fall thru so, we have a
1141 // a property implementation and to avoid future warnings.
1142 }
1143 else {
1144 // FIXME! Rules for properties are somewhat different that those
1145 // for assignments. Use a new routine to consolidate all cases;
1146 // specifically for property redeclarations as well as for ivars.
1147 QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
1148 QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
1149 if (lhsType != rhsType &&
1150 lhsType->isArithmeticType()) {
1151 Diag(PropertyDiagLoc, diag::error_property_ivar_type)
1152 << property->getDeclName() << PropType
1153 << Ivar->getDeclName() << IvarType;
1154 Diag(Ivar->getLocation(), diag::note_ivar_decl);
1155 // Fall thru - see previous comment
1156 }
1157 }
1158 // __weak is explicit. So it works on Canonical type.
1159 if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
1160 getLangOpts().getGC() != LangOptions::NonGC)) {
1161 Diag(PropertyDiagLoc, diag::error_weak_property)
1162 << property->getDeclName() << Ivar->getDeclName();
1163 Diag(Ivar->getLocation(), diag::note_ivar_decl);
1164 // Fall thru - see previous comment
1165 }
1166 // Fall thru - see previous comment
1167 if ((property->getType()->isObjCObjectPointerType() ||
1168 PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
1169 getLangOpts().getGC() != LangOptions::NonGC) {
1170 Diag(PropertyDiagLoc, diag::error_strong_property)
1171 << property->getDeclName() << Ivar->getDeclName();
1172 // Fall thru - see previous comment
1173 }
1174 }
1175 if (getLangOpts().ObjCAutoRefCount)
1176 checkARCPropertyImpl(*this, PropertyLoc, property, Ivar);
1177 } else if (PropertyIvar)
1178 // @dynamic
1179 Diag(PropertyDiagLoc, diag::error_dynamic_property_ivar_decl);
1180
1181 assert (property && "ActOnPropertyImplDecl - property declaration missing");
1182 ObjCPropertyImplDecl *PIDecl =
1183 ObjCPropertyImplDecl::Create(Context, CurContext, AtLoc, PropertyLoc,
1184 property,
1185 (Synthesize ?
1186 ObjCPropertyImplDecl::Synthesize
1187 : ObjCPropertyImplDecl::Dynamic),
1188 Ivar, PropertyIvarLoc);
1189
1190 if (CompleteTypeErr || !compat)
1191 PIDecl->setInvalidDecl();
1192
1193 if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
1194 getterMethod->createImplicitParams(Context, IDecl);
1195 if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
1196 Ivar->getType()->isRecordType()) {
1197 // For Objective-C++, need to synthesize the AST for the IVAR object to be
1198 // returned by the getter as it must conform to C++'s copy-return rules.
1199 // FIXME. Eventually we want to do this for Objective-C as well.
1200 SynthesizedFunctionScope Scope(*this, getterMethod);
1201 ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
1202 DeclRefExpr *SelfExpr =
1203 new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
1204 VK_RValue, PropertyDiagLoc);
1205 MarkDeclRefReferenced(SelfExpr);
1206 Expr *IvarRefExpr =
1207 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
1208 Ivar->getLocation(),
1209 SelfExpr, true, true);
1210 ExprResult Res =
1211 PerformCopyInitialization(InitializedEntity::InitializeResult(
1212 PropertyDiagLoc,
1213 getterMethod->getResultType(),
1214 /*NRVO=*/false),
1215 PropertyDiagLoc,
1216 Owned(IvarRefExpr));
1217 if (!Res.isInvalid()) {
1218 Expr *ResExpr = Res.takeAs<Expr>();
1219 if (ResExpr)
1220 ResExpr = MaybeCreateExprWithCleanups(ResExpr);
1221 PIDecl->setGetterCXXConstructor(ResExpr);
1222 }
1223 }
1224 if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
1225 !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
1226 Diag(getterMethod->getLocation(),
1227 diag::warn_property_getter_owning_mismatch);
1228 Diag(property->getLocation(), diag::note_property_declare);
1229 }
1230 if (getLangOpts().ObjCAutoRefCount && Synthesize)
1231 switch (getterMethod->getMethodFamily()) {
1232 case OMF_retain:
1233 case OMF_retainCount:
1234 case OMF_release:
1235 case OMF_autorelease:
1236 Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def)
1237 << 1 << getterMethod->getSelector();
1238 break;
1239 default:
1240 break;
1241 }
1242 }
1243 if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
1244 setterMethod->createImplicitParams(Context, IDecl);
1245 if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
1246 Ivar->getType()->isRecordType()) {
1247 // FIXME. Eventually we want to do this for Objective-C as well.
1248 SynthesizedFunctionScope Scope(*this, setterMethod);
1249 ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
1250 DeclRefExpr *SelfExpr =
1251 new (Context) DeclRefExpr(SelfDecl, false, SelfDecl->getType(),
1252 VK_RValue, PropertyDiagLoc);
1253 MarkDeclRefReferenced(SelfExpr);
1254 Expr *lhs =
1255 new (Context) ObjCIvarRefExpr(Ivar, Ivar->getType(), PropertyDiagLoc,
1256 Ivar->getLocation(),
1257 SelfExpr, true, true);
1258 ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
1259 ParmVarDecl *Param = (*P);
1260 QualType T = Param->getType().getNonReferenceType();
1261 DeclRefExpr *rhs = new (Context) DeclRefExpr(Param, false, T,
1262 VK_LValue, PropertyDiagLoc);
1263 MarkDeclRefReferenced(rhs);
1264 ExprResult Res = BuildBinOp(S, PropertyDiagLoc,
1265 BO_Assign, lhs, rhs);
1266 if (property->getPropertyAttributes() &
1267 ObjCPropertyDecl::OBJC_PR_atomic) {
1268 Expr *callExpr = Res.takeAs<Expr>();
1269 if (const CXXOperatorCallExpr *CXXCE =
1270 dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
1271 if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
1272 if (!FuncDecl->isTrivial())
1273 if (property->getType()->isReferenceType()) {
1274 Diag(PropertyDiagLoc,
1275 diag::err_atomic_property_nontrivial_assign_op)
1276 << property->getType();
1277 Diag(FuncDecl->getLocStart(),
1278 diag::note_callee_decl) << FuncDecl;
1279 }
1280 }
1281 PIDecl->setSetterCXXAssignment(Res.takeAs<Expr>());
1282 }
1283 }
1284
1285 if (IC) {
1286 if (Synthesize)
1287 if (ObjCPropertyImplDecl *PPIDecl =
1288 IC->FindPropertyImplIvarDecl(PropertyIvar)) {
1289 Diag(PropertyLoc, diag::error_duplicate_ivar_use)
1290 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
1291 << PropertyIvar;
1292 Diag(PPIDecl->getLocation(), diag::note_previous_use);
1293 }
1294
1295 if (ObjCPropertyImplDecl *PPIDecl
1296 = IC->FindPropertyImplDecl(PropertyId)) {
1297 Diag(PropertyLoc, diag::error_property_implemented) << PropertyId;
1298 Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
1299 return 0;
1300 }
1301 IC->addPropertyImplementation(PIDecl);
1302 if (getLangOpts().ObjCDefaultSynthProperties &&
1303 getLangOpts().ObjCRuntime.isNonFragile() &&
1304 !IDecl->isObjCRequiresPropertyDefs()) {
1305 // Diagnose if an ivar was lazily synthesdized due to a previous
1306 // use and if 1) property is @dynamic or 2) property is synthesized
1307 // but it requires an ivar of different name.
1308 ObjCInterfaceDecl *ClassDeclared=0;
1309 ObjCIvarDecl *Ivar = 0;
1310 if (!Synthesize)
1311 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
1312 else {
1313 if (PropertyIvar && PropertyIvar != PropertyId)
1314 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
1315 }
1316 // Issue diagnostics only if Ivar belongs to current class.
1317 if (Ivar && Ivar->getSynthesize() &&
1318 declaresSameEntity(IC->getClassInterface(), ClassDeclared)) {
1319 Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
1320 << PropertyId;
1321 Ivar->setInvalidDecl();
1322 }
1323 }
1324 } else {
1325 if (Synthesize)
1326 if (ObjCPropertyImplDecl *PPIDecl =
1327 CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
1328 Diag(PropertyDiagLoc, diag::error_duplicate_ivar_use)
1329 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
1330 << PropertyIvar;
1331 Diag(PPIDecl->getLocation(), diag::note_previous_use);
1332 }
1333
1334 if (ObjCPropertyImplDecl *PPIDecl =
1335 CatImplClass->FindPropertyImplDecl(PropertyId)) {
1336 Diag(PropertyDiagLoc, diag::error_property_implemented) << PropertyId;
1337 Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
1338 return 0;
1339 }
1340 CatImplClass->addPropertyImplementation(PIDecl);
1341 }
1342
1343 return PIDecl;
1344 }
1345
1346 //===----------------------------------------------------------------------===//
1347 // Helper methods.
1348 //===----------------------------------------------------------------------===//
1349
1350 /// DiagnosePropertyMismatch - Compares two properties for their
1351 /// attributes and types and warns on a variety of inconsistencies.
1352 ///
1353 void
DiagnosePropertyMismatch(ObjCPropertyDecl * Property,ObjCPropertyDecl * SuperProperty,const IdentifierInfo * inheritedName)1354 Sema::DiagnosePropertyMismatch(ObjCPropertyDecl *Property,
1355 ObjCPropertyDecl *SuperProperty,
1356 const IdentifierInfo *inheritedName) {
1357 ObjCPropertyDecl::PropertyAttributeKind CAttr =
1358 Property->getPropertyAttributes();
1359 ObjCPropertyDecl::PropertyAttributeKind SAttr =
1360 SuperProperty->getPropertyAttributes();
1361 if ((CAttr & ObjCPropertyDecl::OBJC_PR_readonly)
1362 && (SAttr & ObjCPropertyDecl::OBJC_PR_readwrite))
1363 Diag(Property->getLocation(), diag::warn_readonly_property)
1364 << Property->getDeclName() << inheritedName;
1365 if ((CAttr & ObjCPropertyDecl::OBJC_PR_copy)
1366 != (SAttr & ObjCPropertyDecl::OBJC_PR_copy))
1367 Diag(Property->getLocation(), diag::warn_property_attribute)
1368 << Property->getDeclName() << "copy" << inheritedName;
1369 else if (!(SAttr & ObjCPropertyDecl::OBJC_PR_readonly)){
1370 unsigned CAttrRetain =
1371 (CAttr &
1372 (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
1373 unsigned SAttrRetain =
1374 (SAttr &
1375 (ObjCPropertyDecl::OBJC_PR_retain | ObjCPropertyDecl::OBJC_PR_strong));
1376 bool CStrong = (CAttrRetain != 0);
1377 bool SStrong = (SAttrRetain != 0);
1378 if (CStrong != SStrong)
1379 Diag(Property->getLocation(), diag::warn_property_attribute)
1380 << Property->getDeclName() << "retain (or strong)" << inheritedName;
1381 }
1382
1383 if ((CAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)
1384 != (SAttr & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
1385 Diag(Property->getLocation(), diag::warn_property_attribute)
1386 << Property->getDeclName() << "atomic" << inheritedName;
1387 Diag(SuperProperty->getLocation(), diag::note_property_declare);
1388 }
1389 if (Property->getSetterName() != SuperProperty->getSetterName()) {
1390 Diag(Property->getLocation(), diag::warn_property_attribute)
1391 << Property->getDeclName() << "setter" << inheritedName;
1392 Diag(SuperProperty->getLocation(), diag::note_property_declare);
1393 }
1394 if (Property->getGetterName() != SuperProperty->getGetterName()) {
1395 Diag(Property->getLocation(), diag::warn_property_attribute)
1396 << Property->getDeclName() << "getter" << inheritedName;
1397 Diag(SuperProperty->getLocation(), diag::note_property_declare);
1398 }
1399
1400 QualType LHSType =
1401 Context.getCanonicalType(SuperProperty->getType());
1402 QualType RHSType =
1403 Context.getCanonicalType(Property->getType());
1404
1405 if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) {
1406 // Do cases not handled in above.
1407 // FIXME. For future support of covariant property types, revisit this.
1408 bool IncompatibleObjC = false;
1409 QualType ConvertedType;
1410 if (!isObjCPointerConversion(RHSType, LHSType,
1411 ConvertedType, IncompatibleObjC) ||
1412 IncompatibleObjC) {
1413 Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
1414 << Property->getType() << SuperProperty->getType() << inheritedName;
1415 Diag(SuperProperty->getLocation(), diag::note_property_declare);
1416 }
1417 }
1418 }
1419
DiagnosePropertyAccessorMismatch(ObjCPropertyDecl * property,ObjCMethodDecl * GetterMethod,SourceLocation Loc)1420 bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property,
1421 ObjCMethodDecl *GetterMethod,
1422 SourceLocation Loc) {
1423 if (!GetterMethod)
1424 return false;
1425 QualType GetterType = GetterMethod->getResultType().getNonReferenceType();
1426 QualType PropertyIvarType = property->getType().getNonReferenceType();
1427 bool compat = Context.hasSameType(PropertyIvarType, GetterType);
1428 if (!compat) {
1429 if (isa<ObjCObjectPointerType>(PropertyIvarType) &&
1430 isa<ObjCObjectPointerType>(GetterType))
1431 compat =
1432 Context.canAssignObjCInterfaces(
1433 GetterType->getAs<ObjCObjectPointerType>(),
1434 PropertyIvarType->getAs<ObjCObjectPointerType>());
1435 else if (CheckAssignmentConstraints(Loc, GetterType, PropertyIvarType)
1436 != Compatible) {
1437 Diag(Loc, diag::error_property_accessor_type)
1438 << property->getDeclName() << PropertyIvarType
1439 << GetterMethod->getSelector() << GetterType;
1440 Diag(GetterMethod->getLocation(), diag::note_declared_at);
1441 return true;
1442 } else {
1443 compat = true;
1444 QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
1445 QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType();
1446 if (lhsType != rhsType && lhsType->isArithmeticType())
1447 compat = false;
1448 }
1449 }
1450
1451 if (!compat) {
1452 Diag(Loc, diag::warn_accessor_property_type_mismatch)
1453 << property->getDeclName()
1454 << GetterMethod->getSelector();
1455 Diag(GetterMethod->getLocation(), diag::note_declared_at);
1456 return true;
1457 }
1458
1459 return false;
1460 }
1461
1462 /// CollectImmediateProperties - This routine collects all properties in
1463 /// the class and its conforming protocols; but not those in its super class.
CollectImmediateProperties(ObjCContainerDecl * CDecl,ObjCContainerDecl::PropertyMap & PropMap,ObjCContainerDecl::PropertyMap & SuperPropMap)1464 void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
1465 ObjCContainerDecl::PropertyMap &PropMap,
1466 ObjCContainerDecl::PropertyMap &SuperPropMap) {
1467 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
1468 for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(),
1469 E = IDecl->prop_end(); P != E; ++P) {
1470 ObjCPropertyDecl *Prop = *P;
1471 PropMap[Prop->getIdentifier()] = Prop;
1472 }
1473 // scan through class's protocols.
1474 for (ObjCInterfaceDecl::all_protocol_iterator
1475 PI = IDecl->all_referenced_protocol_begin(),
1476 E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
1477 CollectImmediateProperties((*PI), PropMap, SuperPropMap);
1478 }
1479 if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
1480 if (!CATDecl->IsClassExtension())
1481 for (ObjCContainerDecl::prop_iterator P = CATDecl->prop_begin(),
1482 E = CATDecl->prop_end(); P != E; ++P) {
1483 ObjCPropertyDecl *Prop = *P;
1484 PropMap[Prop->getIdentifier()] = Prop;
1485 }
1486 // scan through class's protocols.
1487 for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
1488 E = CATDecl->protocol_end(); PI != E; ++PI)
1489 CollectImmediateProperties((*PI), PropMap, SuperPropMap);
1490 }
1491 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
1492 for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(),
1493 E = PDecl->prop_end(); P != E; ++P) {
1494 ObjCPropertyDecl *Prop = *P;
1495 ObjCPropertyDecl *PropertyFromSuper = SuperPropMap[Prop->getIdentifier()];
1496 // Exclude property for protocols which conform to class's super-class,
1497 // as super-class has to implement the property.
1498 if (!PropertyFromSuper ||
1499 PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) {
1500 ObjCPropertyDecl *&PropEntry = PropMap[Prop->getIdentifier()];
1501 if (!PropEntry)
1502 PropEntry = Prop;
1503 }
1504 }
1505 // scan through protocol's protocols.
1506 for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(),
1507 E = PDecl->protocol_end(); PI != E; ++PI)
1508 CollectImmediateProperties((*PI), PropMap, SuperPropMap);
1509 }
1510 }
1511
1512 /// CollectSuperClassPropertyImplementations - This routine collects list of
1513 /// properties to be implemented in super class(s) and also coming from their
1514 /// conforming protocols.
CollectSuperClassPropertyImplementations(ObjCInterfaceDecl * CDecl,ObjCInterfaceDecl::PropertyMap & PropMap)1515 static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
1516 ObjCInterfaceDecl::PropertyMap &PropMap) {
1517 if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
1518 ObjCInterfaceDecl::PropertyDeclOrder PO;
1519 while (SDecl) {
1520 SDecl->collectPropertiesToImplement(PropMap, PO);
1521 SDecl = SDecl->getSuperClass();
1522 }
1523 }
1524 }
1525
1526 /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
1527 /// an ivar synthesized for 'Method' and 'Method' is a property accessor
1528 /// declared in class 'IFace'.
1529 bool
IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl * IFace,ObjCMethodDecl * Method,ObjCIvarDecl * IV)1530 Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
1531 ObjCMethodDecl *Method, ObjCIvarDecl *IV) {
1532 if (!IV->getSynthesize())
1533 return false;
1534 ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(),
1535 Method->isInstanceMethod());
1536 if (!IMD || !IMD->isPropertyAccessor())
1537 return false;
1538
1539 // look up a property declaration whose one of its accessors is implemented
1540 // by this method.
1541 for (ObjCContainerDecl::prop_iterator P = IFace->prop_begin(),
1542 E = IFace->prop_end(); P != E; ++P) {
1543 ObjCPropertyDecl *property = *P;
1544 if ((property->getGetterName() == IMD->getSelector() ||
1545 property->getSetterName() == IMD->getSelector()) &&
1546 (property->getPropertyIvarDecl() == IV))
1547 return true;
1548 }
1549 return false;
1550 }
1551
1552
1553 /// \brief Default synthesizes all properties which must be synthesized
1554 /// in class's \@implementation.
DefaultSynthesizeProperties(Scope * S,ObjCImplDecl * IMPDecl,ObjCInterfaceDecl * IDecl)1555 void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
1556 ObjCInterfaceDecl *IDecl) {
1557
1558 ObjCInterfaceDecl::PropertyMap PropMap;
1559 ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder;
1560 IDecl->collectPropertiesToImplement(PropMap, PropertyOrder);
1561 if (PropMap.empty())
1562 return;
1563 ObjCInterfaceDecl::PropertyMap SuperPropMap;
1564 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
1565
1566 for (unsigned i = 0, e = PropertyOrder.size(); i != e; i++) {
1567 ObjCPropertyDecl *Prop = PropertyOrder[i];
1568 // Is there a matching property synthesize/dynamic?
1569 if (Prop->isInvalidDecl() ||
1570 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional)
1571 continue;
1572 // Property may have been synthesized by user.
1573 if (IMPDecl->FindPropertyImplDecl(Prop->getIdentifier()))
1574 continue;
1575 if (IMPDecl->getInstanceMethod(Prop->getGetterName())) {
1576 if (Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readonly)
1577 continue;
1578 if (IMPDecl->getInstanceMethod(Prop->getSetterName()))
1579 continue;
1580 }
1581 // If property to be implemented in the super class, ignore.
1582 if (SuperPropMap[Prop->getIdentifier()]) {
1583 ObjCPropertyDecl *PropInSuperClass = SuperPropMap[Prop->getIdentifier()];
1584 if ((Prop->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_readwrite) &&
1585 (PropInSuperClass->getPropertyAttributes() &
1586 ObjCPropertyDecl::OBJC_PR_readonly) &&
1587 !IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
1588 !IDecl->HasUserDeclaredSetterMethod(Prop)) {
1589 Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
1590 << Prop->getIdentifier()->getName();
1591 Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
1592 }
1593 continue;
1594 }
1595 if (ObjCPropertyImplDecl *PID =
1596 IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
1597 if (PID->getPropertyDecl() != Prop) {
1598 Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
1599 << Prop->getIdentifier()->getName();
1600 if (!PID->getLocation().isInvalid())
1601 Diag(PID->getLocation(), diag::note_property_synthesize);
1602 }
1603 continue;
1604 }
1605 if (isa<ObjCProtocolDecl>(Prop->getDeclContext())) {
1606 // We won't auto-synthesize properties declared in protocols.
1607 Diag(IMPDecl->getLocation(),
1608 diag::warn_auto_synthesizing_protocol_property);
1609 Diag(Prop->getLocation(), diag::note_property_declare);
1610 continue;
1611 }
1612
1613 // We use invalid SourceLocations for the synthesized ivars since they
1614 // aren't really synthesized at a particular location; they just exist.
1615 // Saying that they are located at the @implementation isn't really going
1616 // to help users.
1617 ObjCPropertyImplDecl *PIDecl = dyn_cast_or_null<ObjCPropertyImplDecl>(
1618 ActOnPropertyImplDecl(S, SourceLocation(), SourceLocation(),
1619 true,
1620 /* property = */ Prop->getIdentifier(),
1621 /* ivar = */ Prop->getDefaultSynthIvarName(Context),
1622 Prop->getLocation()));
1623 if (PIDecl) {
1624 Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis);
1625 Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
1626 }
1627 }
1628 }
1629
DefaultSynthesizeProperties(Scope * S,Decl * D)1630 void Sema::DefaultSynthesizeProperties(Scope *S, Decl *D) {
1631 if (!LangOpts.ObjCDefaultSynthProperties || LangOpts.ObjCRuntime.isFragile())
1632 return;
1633 ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D);
1634 if (!IC)
1635 return;
1636 if (ObjCInterfaceDecl* IDecl = IC->getClassInterface())
1637 if (!IDecl->isObjCRequiresPropertyDefs())
1638 DefaultSynthesizeProperties(S, IC, IDecl);
1639 }
1640
DiagnoseUnimplementedProperties(Scope * S,ObjCImplDecl * IMPDecl,ObjCContainerDecl * CDecl)1641 void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl,
1642 ObjCContainerDecl *CDecl) {
1643 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
1644 ObjCInterfaceDecl *IDecl;
1645 // Gather properties which need not be implemented in this class
1646 // or category.
1647 if (!(IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)))
1648 if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
1649 // For categories, no need to implement properties declared in
1650 // its primary class (and its super classes) if property is
1651 // declared in one of those containers.
1652 if ((IDecl = C->getClassInterface())) {
1653 ObjCInterfaceDecl::PropertyDeclOrder PO;
1654 IDecl->collectPropertiesToImplement(NoNeedToImplPropMap, PO);
1655 }
1656 }
1657 if (IDecl)
1658 CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
1659
1660 ObjCContainerDecl::PropertyMap PropMap;
1661 CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap);
1662 if (PropMap.empty())
1663 return;
1664
1665 llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
1666 for (ObjCImplDecl::propimpl_iterator
1667 I = IMPDecl->propimpl_begin(),
1668 EI = IMPDecl->propimpl_end(); I != EI; ++I)
1669 PropImplMap.insert(I->getPropertyDecl());
1670
1671 SelectorSet InsMap;
1672 // Collect property accessors implemented in current implementation.
1673 for (ObjCImplementationDecl::instmeth_iterator
1674 I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I)
1675 InsMap.insert((*I)->getSelector());
1676
1677 ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
1678 ObjCInterfaceDecl *PrimaryClass = 0;
1679 if (C && !C->IsClassExtension())
1680 if ((PrimaryClass = C->getClassInterface()))
1681 // Report unimplemented properties in the category as well.
1682 if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) {
1683 // When reporting on missing setter/getters, do not report when
1684 // setter/getter is implemented in category's primary class
1685 // implementation.
1686 for (ObjCImplementationDecl::instmeth_iterator
1687 I = IMP->instmeth_begin(), E = IMP->instmeth_end(); I!=E; ++I)
1688 InsMap.insert((*I)->getSelector());
1689 }
1690
1691 for (ObjCContainerDecl::PropertyMap::iterator
1692 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
1693 ObjCPropertyDecl *Prop = P->second;
1694 // Is there a matching propery synthesize/dynamic?
1695 if (Prop->isInvalidDecl() ||
1696 Prop->getPropertyImplementation() == ObjCPropertyDecl::Optional ||
1697 PropImplMap.count(Prop) ||
1698 Prop->getAvailability() == AR_Unavailable)
1699 continue;
1700 // When reporting on missing property getter implementation in
1701 // categories, do not report when they are declared in primary class,
1702 // class's protocol, or one of it super classes. This is because,
1703 // the class is going to implement them.
1704 if (!InsMap.count(Prop->getGetterName()) &&
1705 (PrimaryClass == 0 ||
1706 !PrimaryClass->lookupPropertyAccessor(Prop->getGetterName(), C))) {
1707 Diag(IMPDecl->getLocation(),
1708 isa<ObjCCategoryDecl>(CDecl) ?
1709 diag::warn_setter_getter_impl_required_in_category :
1710 diag::warn_setter_getter_impl_required)
1711 << Prop->getDeclName() << Prop->getGetterName();
1712 Diag(Prop->getLocation(),
1713 diag::note_property_declare);
1714 if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCRuntime.isNonFragile())
1715 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
1716 if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
1717 Diag(RID->getLocation(), diag::note_suppressed_class_declare);
1718
1719 }
1720 // When reporting on missing property setter implementation in
1721 // categories, do not report when they are declared in primary class,
1722 // class's protocol, or one of it super classes. This is because,
1723 // the class is going to implement them.
1724 if (!Prop->isReadOnly() && !InsMap.count(Prop->getSetterName()) &&
1725 (PrimaryClass == 0 ||
1726 !PrimaryClass->lookupPropertyAccessor(Prop->getSetterName(), C))) {
1727 Diag(IMPDecl->getLocation(),
1728 isa<ObjCCategoryDecl>(CDecl) ?
1729 diag::warn_setter_getter_impl_required_in_category :
1730 diag::warn_setter_getter_impl_required)
1731 << Prop->getDeclName() << Prop->getSetterName();
1732 Diag(Prop->getLocation(),
1733 diag::note_property_declare);
1734 if (LangOpts.ObjCDefaultSynthProperties && LangOpts.ObjCRuntime.isNonFragile())
1735 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
1736 if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
1737 Diag(RID->getLocation(), diag::note_suppressed_class_declare);
1738 }
1739 }
1740 }
1741
1742 void
AtomicPropertySetterGetterRules(ObjCImplDecl * IMPDecl,ObjCContainerDecl * IDecl)1743 Sema::AtomicPropertySetterGetterRules (ObjCImplDecl* IMPDecl,
1744 ObjCContainerDecl* IDecl) {
1745 // Rules apply in non-GC mode only
1746 if (getLangOpts().getGC() != LangOptions::NonGC)
1747 return;
1748 for (ObjCContainerDecl::prop_iterator I = IDecl->prop_begin(),
1749 E = IDecl->prop_end();
1750 I != E; ++I) {
1751 ObjCPropertyDecl *Property = *I;
1752 ObjCMethodDecl *GetterMethod = 0;
1753 ObjCMethodDecl *SetterMethod = 0;
1754 bool LookedUpGetterSetter = false;
1755
1756 unsigned Attributes = Property->getPropertyAttributes();
1757 unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten();
1758
1759 if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic) &&
1760 !(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_nonatomic)) {
1761 GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
1762 SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
1763 LookedUpGetterSetter = true;
1764 if (GetterMethod) {
1765 Diag(GetterMethod->getLocation(),
1766 diag::warn_default_atomic_custom_getter_setter)
1767 << Property->getIdentifier() << 0;
1768 Diag(Property->getLocation(), diag::note_property_declare);
1769 }
1770 if (SetterMethod) {
1771 Diag(SetterMethod->getLocation(),
1772 diag::warn_default_atomic_custom_getter_setter)
1773 << Property->getIdentifier() << 1;
1774 Diag(Property->getLocation(), diag::note_property_declare);
1775 }
1776 }
1777
1778 // We only care about readwrite atomic property.
1779 if ((Attributes & ObjCPropertyDecl::OBJC_PR_nonatomic) ||
1780 !(Attributes & ObjCPropertyDecl::OBJC_PR_readwrite))
1781 continue;
1782 if (const ObjCPropertyImplDecl *PIDecl
1783 = IMPDecl->FindPropertyImplDecl(Property->getIdentifier())) {
1784 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
1785 continue;
1786 if (!LookedUpGetterSetter) {
1787 GetterMethod = IMPDecl->getInstanceMethod(Property->getGetterName());
1788 SetterMethod = IMPDecl->getInstanceMethod(Property->getSetterName());
1789 LookedUpGetterSetter = true;
1790 }
1791 if ((GetterMethod && !SetterMethod) || (!GetterMethod && SetterMethod)) {
1792 SourceLocation MethodLoc =
1793 (GetterMethod ? GetterMethod->getLocation()
1794 : SetterMethod->getLocation());
1795 Diag(MethodLoc, diag::warn_atomic_property_rule)
1796 << Property->getIdentifier() << (GetterMethod != 0)
1797 << (SetterMethod != 0);
1798 // fixit stuff.
1799 if (!AttributesAsWritten) {
1800 if (Property->getLParenLoc().isValid()) {
1801 // @property () ... case.
1802 SourceRange PropSourceRange(Property->getAtLoc(),
1803 Property->getLParenLoc());
1804 Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
1805 FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic");
1806 }
1807 else {
1808 //@property id etc.
1809 SourceLocation endLoc =
1810 Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
1811 endLoc = endLoc.getLocWithOffset(-1);
1812 SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
1813 Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
1814 FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic) ");
1815 }
1816 }
1817 else if (!(AttributesAsWritten & ObjCPropertyDecl::OBJC_PR_atomic)) {
1818 // @property () ... case.
1819 SourceLocation endLoc = Property->getLParenLoc();
1820 SourceRange PropSourceRange(Property->getAtLoc(), endLoc);
1821 Diag(Property->getLocation(), diag::note_atomic_property_fixup_suggest) <<
1822 FixItHint::CreateReplacement(PropSourceRange, "@property (nonatomic, ");
1823 }
1824 else
1825 Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
1826 Diag(Property->getLocation(), diag::note_property_declare);
1827 }
1828 }
1829 }
1830 }
1831
DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl * D)1832 void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D) {
1833 if (getLangOpts().getGC() == LangOptions::GCOnly)
1834 return;
1835
1836 for (ObjCImplementationDecl::propimpl_iterator
1837 i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) {
1838 ObjCPropertyImplDecl *PID = *i;
1839 if (PID->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
1840 continue;
1841
1842 const ObjCPropertyDecl *PD = PID->getPropertyDecl();
1843 if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
1844 !D->getInstanceMethod(PD->getGetterName())) {
1845 ObjCMethodDecl *method = PD->getGetterMethodDecl();
1846 if (!method)
1847 continue;
1848 ObjCMethodFamily family = method->getMethodFamily();
1849 if (family == OMF_alloc || family == OMF_copy ||
1850 family == OMF_mutableCopy || family == OMF_new) {
1851 if (getLangOpts().ObjCAutoRefCount)
1852 Diag(PID->getLocation(), diag::err_ownin_getter_rule);
1853 else
1854 Diag(PID->getLocation(), diag::warn_owning_getter_rule);
1855 Diag(PD->getLocation(), diag::note_property_declare);
1856 }
1857 }
1858 }
1859 }
1860
1861 /// AddPropertyAttrs - Propagates attributes from a property to the
1862 /// implicitly-declared getter or setter for that property.
AddPropertyAttrs(Sema & S,ObjCMethodDecl * PropertyMethod,ObjCPropertyDecl * Property)1863 static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
1864 ObjCPropertyDecl *Property) {
1865 // Should we just clone all attributes over?
1866 for (Decl::attr_iterator A = Property->attr_begin(),
1867 AEnd = Property->attr_end();
1868 A != AEnd; ++A) {
1869 if (isa<DeprecatedAttr>(*A) ||
1870 isa<UnavailableAttr>(*A) ||
1871 isa<AvailabilityAttr>(*A))
1872 PropertyMethod->addAttr((*A)->clone(S.Context));
1873 }
1874 }
1875
1876 /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
1877 /// have the property type and issue diagnostics if they don't.
1878 /// Also synthesize a getter/setter method if none exist (and update the
1879 /// appropriate lookup tables. FIXME: Should reconsider if adding synthesized
1880 /// methods is the "right" thing to do.
ProcessPropertyDecl(ObjCPropertyDecl * property,ObjCContainerDecl * CD,ObjCPropertyDecl * redeclaredProperty,ObjCContainerDecl * lexicalDC)1881 void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
1882 ObjCContainerDecl *CD,
1883 ObjCPropertyDecl *redeclaredProperty,
1884 ObjCContainerDecl *lexicalDC) {
1885
1886 ObjCMethodDecl *GetterMethod, *SetterMethod;
1887
1888 GetterMethod = CD->getInstanceMethod(property->getGetterName());
1889 SetterMethod = CD->getInstanceMethod(property->getSetterName());
1890 DiagnosePropertyAccessorMismatch(property, GetterMethod,
1891 property->getLocation());
1892
1893 if (SetterMethod) {
1894 ObjCPropertyDecl::PropertyAttributeKind CAttr =
1895 property->getPropertyAttributes();
1896 if ((!(CAttr & ObjCPropertyDecl::OBJC_PR_readonly)) &&
1897 Context.getCanonicalType(SetterMethod->getResultType()) !=
1898 Context.VoidTy)
1899 Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
1900 if (SetterMethod->param_size() != 1 ||
1901 !Context.hasSameUnqualifiedType(
1902 (*SetterMethod->param_begin())->getType().getNonReferenceType(),
1903 property->getType().getNonReferenceType())) {
1904 Diag(property->getLocation(),
1905 diag::warn_accessor_property_type_mismatch)
1906 << property->getDeclName()
1907 << SetterMethod->getSelector();
1908 Diag(SetterMethod->getLocation(), diag::note_declared_at);
1909 }
1910 }
1911
1912 // Synthesize getter/setter methods if none exist.
1913 // Find the default getter and if one not found, add one.
1914 // FIXME: The synthesized property we set here is misleading. We almost always
1915 // synthesize these methods unless the user explicitly provided prototypes
1916 // (which is odd, but allowed). Sema should be typechecking that the
1917 // declarations jive in that situation (which it is not currently).
1918 if (!GetterMethod) {
1919 // No instance method of same name as property getter name was found.
1920 // Declare a getter method and add it to the list of methods
1921 // for this class.
1922 SourceLocation Loc = redeclaredProperty ?
1923 redeclaredProperty->getLocation() :
1924 property->getLocation();
1925
1926 GetterMethod = ObjCMethodDecl::Create(Context, Loc, Loc,
1927 property->getGetterName(),
1928 property->getType(), 0, CD, /*isInstance=*/true,
1929 /*isVariadic=*/false, /*isPropertyAccessor=*/true,
1930 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
1931 (property->getPropertyImplementation() ==
1932 ObjCPropertyDecl::Optional) ?
1933 ObjCMethodDecl::Optional :
1934 ObjCMethodDecl::Required);
1935 CD->addDecl(GetterMethod);
1936
1937 AddPropertyAttrs(*this, GetterMethod, property);
1938
1939 // FIXME: Eventually this shouldn't be needed, as the lexical context
1940 // and the real context should be the same.
1941 if (lexicalDC)
1942 GetterMethod->setLexicalDeclContext(lexicalDC);
1943 if (property->hasAttr<NSReturnsNotRetainedAttr>())
1944 GetterMethod->addAttr(
1945 ::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
1946
1947 if (getLangOpts().ObjCAutoRefCount)
1948 CheckARCMethodDecl(GetterMethod);
1949 } else
1950 // A user declared getter will be synthesize when @synthesize of
1951 // the property with the same name is seen in the @implementation
1952 GetterMethod->setPropertyAccessor(true);
1953 property->setGetterMethodDecl(GetterMethod);
1954
1955 // Skip setter if property is read-only.
1956 if (!property->isReadOnly()) {
1957 // Find the default setter and if one not found, add one.
1958 if (!SetterMethod) {
1959 // No instance method of same name as property setter name was found.
1960 // Declare a setter method and add it to the list of methods
1961 // for this class.
1962 SourceLocation Loc = redeclaredProperty ?
1963 redeclaredProperty->getLocation() :
1964 property->getLocation();
1965
1966 SetterMethod =
1967 ObjCMethodDecl::Create(Context, Loc, Loc,
1968 property->getSetterName(), Context.VoidTy, 0,
1969 CD, /*isInstance=*/true, /*isVariadic=*/false,
1970 /*isPropertyAccessor=*/true,
1971 /*isImplicitlyDeclared=*/true,
1972 /*isDefined=*/false,
1973 (property->getPropertyImplementation() ==
1974 ObjCPropertyDecl::Optional) ?
1975 ObjCMethodDecl::Optional :
1976 ObjCMethodDecl::Required);
1977
1978 // Invent the arguments for the setter. We don't bother making a
1979 // nice name for the argument.
1980 ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
1981 Loc, Loc,
1982 property->getIdentifier(),
1983 property->getType().getUnqualifiedType(),
1984 /*TInfo=*/0,
1985 SC_None,
1986 0);
1987 SetterMethod->setMethodParams(Context, Argument, None);
1988
1989 AddPropertyAttrs(*this, SetterMethod, property);
1990
1991 CD->addDecl(SetterMethod);
1992 // FIXME: Eventually this shouldn't be needed, as the lexical context
1993 // and the real context should be the same.
1994 if (lexicalDC)
1995 SetterMethod->setLexicalDeclContext(lexicalDC);
1996
1997 // It's possible for the user to have set a very odd custom
1998 // setter selector that causes it to have a method family.
1999 if (getLangOpts().ObjCAutoRefCount)
2000 CheckARCMethodDecl(SetterMethod);
2001 } else
2002 // A user declared setter will be synthesize when @synthesize of
2003 // the property with the same name is seen in the @implementation
2004 SetterMethod->setPropertyAccessor(true);
2005 property->setSetterMethodDecl(SetterMethod);
2006 }
2007 // Add any synthesized methods to the global pool. This allows us to
2008 // handle the following, which is supported by GCC (and part of the design).
2009 //
2010 // @interface Foo
2011 // @property double bar;
2012 // @end
2013 //
2014 // void thisIsUnfortunate() {
2015 // id foo;
2016 // double bar = [foo bar];
2017 // }
2018 //
2019 if (GetterMethod)
2020 AddInstanceMethodToGlobalPool(GetterMethod);
2021 if (SetterMethod)
2022 AddInstanceMethodToGlobalPool(SetterMethod);
2023
2024 ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD);
2025 if (!CurrentClass) {
2026 if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CD))
2027 CurrentClass = Cat->getClassInterface();
2028 else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(CD))
2029 CurrentClass = Impl->getClassInterface();
2030 }
2031 if (GetterMethod)
2032 CheckObjCMethodOverrides(GetterMethod, CurrentClass, Sema::RTC_Unknown);
2033 if (SetterMethod)
2034 CheckObjCMethodOverrides(SetterMethod, CurrentClass, Sema::RTC_Unknown);
2035 }
2036
CheckObjCPropertyAttributes(Decl * PDecl,SourceLocation Loc,unsigned & Attributes,bool propertyInPrimaryClass)2037 void Sema::CheckObjCPropertyAttributes(Decl *PDecl,
2038 SourceLocation Loc,
2039 unsigned &Attributes,
2040 bool propertyInPrimaryClass) {
2041 // FIXME: Improve the reported location.
2042 if (!PDecl || PDecl->isInvalidDecl())
2043 return;
2044
2045 ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
2046 QualType PropertyTy = PropertyDecl->getType();
2047
2048 if (getLangOpts().ObjCAutoRefCount &&
2049 (Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
2050 PropertyTy->isObjCRetainableType()) {
2051 // 'readonly' property with no obvious lifetime.
2052 // its life time will be determined by its backing ivar.
2053 unsigned rel = (ObjCDeclSpec::DQ_PR_unsafe_unretained |
2054 ObjCDeclSpec::DQ_PR_copy |
2055 ObjCDeclSpec::DQ_PR_retain |
2056 ObjCDeclSpec::DQ_PR_strong |
2057 ObjCDeclSpec::DQ_PR_weak |
2058 ObjCDeclSpec::DQ_PR_assign);
2059 if ((Attributes & rel) == 0)
2060 return;
2061 }
2062
2063 if (propertyInPrimaryClass) {
2064 // we postpone most property diagnosis until class's implementation
2065 // because, its readonly attribute may be overridden in its class
2066 // extensions making other attributes, which make no sense, to make sense.
2067 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
2068 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
2069 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2070 << "readonly" << "readwrite";
2071 }
2072 // readonly and readwrite/assign/retain/copy conflict.
2073 else if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
2074 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
2075 ObjCDeclSpec::DQ_PR_assign |
2076 ObjCDeclSpec::DQ_PR_unsafe_unretained |
2077 ObjCDeclSpec::DQ_PR_copy |
2078 ObjCDeclSpec::DQ_PR_retain |
2079 ObjCDeclSpec::DQ_PR_strong))) {
2080 const char * which = (Attributes & ObjCDeclSpec::DQ_PR_readwrite) ?
2081 "readwrite" :
2082 (Attributes & ObjCDeclSpec::DQ_PR_assign) ?
2083 "assign" :
2084 (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) ?
2085 "unsafe_unretained" :
2086 (Attributes & ObjCDeclSpec::DQ_PR_copy) ?
2087 "copy" : "retain";
2088
2089 Diag(Loc, (Attributes & (ObjCDeclSpec::DQ_PR_readwrite)) ?
2090 diag::err_objc_property_attr_mutually_exclusive :
2091 diag::warn_objc_property_attr_mutually_exclusive)
2092 << "readonly" << which;
2093 }
2094
2095 // Check for copy or retain on non-object types.
2096 if ((Attributes & (ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
2097 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong)) &&
2098 !PropertyTy->isObjCRetainableType() &&
2099 !PropertyDecl->getAttr<ObjCNSObjectAttr>()) {
2100 Diag(Loc, diag::err_objc_property_requires_object)
2101 << (Attributes & ObjCDeclSpec::DQ_PR_weak ? "weak" :
2102 Attributes & ObjCDeclSpec::DQ_PR_copy ? "copy" : "retain (or strong)");
2103 Attributes &= ~(ObjCDeclSpec::DQ_PR_weak | ObjCDeclSpec::DQ_PR_copy |
2104 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong);
2105 PropertyDecl->setInvalidDecl();
2106 }
2107
2108 // Check for more than one of { assign, copy, retain }.
2109 if (Attributes & ObjCDeclSpec::DQ_PR_assign) {
2110 if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
2111 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2112 << "assign" << "copy";
2113 Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
2114 }
2115 if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
2116 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2117 << "assign" << "retain";
2118 Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
2119 }
2120 if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
2121 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2122 << "assign" << "strong";
2123 Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
2124 }
2125 if (getLangOpts().ObjCAutoRefCount &&
2126 (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
2127 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2128 << "assign" << "weak";
2129 Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
2130 }
2131 if (PropertyDecl->getAttr<IBOutletCollectionAttr>())
2132 Diag(Loc, diag::warn_iboutletcollection_property_assign);
2133 } else if (Attributes & ObjCDeclSpec::DQ_PR_unsafe_unretained) {
2134 if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
2135 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2136 << "unsafe_unretained" << "copy";
2137 Attributes &= ~ObjCDeclSpec::DQ_PR_copy;
2138 }
2139 if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
2140 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2141 << "unsafe_unretained" << "retain";
2142 Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
2143 }
2144 if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
2145 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2146 << "unsafe_unretained" << "strong";
2147 Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
2148 }
2149 if (getLangOpts().ObjCAutoRefCount &&
2150 (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
2151 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2152 << "unsafe_unretained" << "weak";
2153 Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
2154 }
2155 } else if (Attributes & ObjCDeclSpec::DQ_PR_copy) {
2156 if (Attributes & ObjCDeclSpec::DQ_PR_retain) {
2157 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2158 << "copy" << "retain";
2159 Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
2160 }
2161 if (Attributes & ObjCDeclSpec::DQ_PR_strong) {
2162 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2163 << "copy" << "strong";
2164 Attributes &= ~ObjCDeclSpec::DQ_PR_strong;
2165 }
2166 if (Attributes & ObjCDeclSpec::DQ_PR_weak) {
2167 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2168 << "copy" << "weak";
2169 Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
2170 }
2171 }
2172 else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) &&
2173 (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
2174 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2175 << "retain" << "weak";
2176 Attributes &= ~ObjCDeclSpec::DQ_PR_retain;
2177 }
2178 else if ((Attributes & ObjCDeclSpec::DQ_PR_strong) &&
2179 (Attributes & ObjCDeclSpec::DQ_PR_weak)) {
2180 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2181 << "strong" << "weak";
2182 Attributes &= ~ObjCDeclSpec::DQ_PR_weak;
2183 }
2184
2185 if ((Attributes & ObjCDeclSpec::DQ_PR_atomic) &&
2186 (Attributes & ObjCDeclSpec::DQ_PR_nonatomic)) {
2187 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2188 << "atomic" << "nonatomic";
2189 Attributes &= ~ObjCDeclSpec::DQ_PR_atomic;
2190 }
2191
2192 // Warn if user supplied no assignment attribute, property is
2193 // readwrite, and this is an object type.
2194 if (!(Attributes & (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_copy |
2195 ObjCDeclSpec::DQ_PR_unsafe_unretained |
2196 ObjCDeclSpec::DQ_PR_retain | ObjCDeclSpec::DQ_PR_strong |
2197 ObjCDeclSpec::DQ_PR_weak)) &&
2198 PropertyTy->isObjCObjectPointerType()) {
2199 if (getLangOpts().ObjCAutoRefCount)
2200 // With arc, @property definitions should default to (strong) when
2201 // not specified; including when property is 'readonly'.
2202 PropertyDecl->setPropertyAttributes(ObjCPropertyDecl::OBJC_PR_strong);
2203 else if (!(Attributes & ObjCDeclSpec::DQ_PR_readonly)) {
2204 bool isAnyClassTy =
2205 (PropertyTy->isObjCClassType() ||
2206 PropertyTy->isObjCQualifiedClassType());
2207 // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
2208 // issue any warning.
2209 if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC)
2210 ;
2211 else if (propertyInPrimaryClass) {
2212 // Don't issue warning on property with no life time in class
2213 // extension as it is inherited from property in primary class.
2214 // Skip this warning in gc-only mode.
2215 if (getLangOpts().getGC() != LangOptions::GCOnly)
2216 Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
2217
2218 // If non-gc code warn that this is likely inappropriate.
2219 if (getLangOpts().getGC() == LangOptions::NonGC)
2220 Diag(Loc, diag::warn_objc_property_default_assign_on_object);
2221 }
2222 }
2223
2224 // FIXME: Implement warning dependent on NSCopying being
2225 // implemented. See also:
2226 // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
2227 // (please trim this list while you are at it).
2228 }
2229
2230 if (!(Attributes & ObjCDeclSpec::DQ_PR_copy)
2231 &&!(Attributes & ObjCDeclSpec::DQ_PR_readonly)
2232 && getLangOpts().getGC() == LangOptions::GCOnly
2233 && PropertyTy->isBlockPointerType())
2234 Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
2235 else if ((Attributes & ObjCDeclSpec::DQ_PR_retain) &&
2236 !(Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
2237 !(Attributes & ObjCDeclSpec::DQ_PR_strong) &&
2238 PropertyTy->isBlockPointerType())
2239 Diag(Loc, diag::warn_objc_property_retain_of_block);
2240
2241 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
2242 (Attributes & ObjCDeclSpec::DQ_PR_setter))
2243 Diag(Loc, diag::warn_objc_readonly_property_has_setter);
2244
2245 }
2246