1 //===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements semantic analysis for Objective C @property and
10 // @synthesize declarations.
12 //===----------------------------------------------------------------------===//
14 #include "clang/AST/ASTMutationListener.h"
15 #include "clang/AST/DeclObjC.h"
16 #include "clang/AST/ExprCXX.h"
17 #include "clang/AST/ExprObjC.h"
18 #include "clang/Basic/SourceManager.h"
19 #include "clang/Lex/Lexer.h"
20 #include "clang/Lex/Preprocessor.h"
21 #include "clang/Sema/Initialization.h"
22 #include "clang/Sema/SemaObjC.h"
23 #include "llvm/ADT/DenseSet.h"
25 using namespace clang
;
27 //===----------------------------------------------------------------------===//
29 //===----------------------------------------------------------------------===//
31 /// getImpliedARCOwnership - Given a set of property attributes and a
32 /// type, infer an expected lifetime. The type's ownership qualification
33 /// is not considered.
35 /// Returns OCL_None if the attributes as stated do not imply an ownership.
36 /// Never returns OCL_Autoreleasing.
37 static Qualifiers::ObjCLifetime
38 getImpliedARCOwnership(ObjCPropertyAttribute::Kind attrs
, QualType type
) {
39 // retain, strong, copy, weak, and unsafe_unretained are only legal
40 // on properties of retainable pointer type.
42 (ObjCPropertyAttribute::kind_retain
| ObjCPropertyAttribute::kind_strong
|
43 ObjCPropertyAttribute::kind_copy
)) {
44 return Qualifiers::OCL_Strong
;
45 } else if (attrs
& ObjCPropertyAttribute::kind_weak
) {
46 return Qualifiers::OCL_Weak
;
47 } else if (attrs
& ObjCPropertyAttribute::kind_unsafe_unretained
) {
48 return Qualifiers::OCL_ExplicitNone
;
51 // assign can appear on other types, so we have to check the
53 if (attrs
& ObjCPropertyAttribute::kind_assign
&&
54 type
->isObjCRetainableType()) {
55 return Qualifiers::OCL_ExplicitNone
;
58 return Qualifiers::OCL_None
;
61 /// Check the internal consistency of a property declaration with
62 /// an explicit ownership qualifier.
63 static void checkPropertyDeclWithOwnership(Sema
&S
,
64 ObjCPropertyDecl
*property
) {
65 if (property
->isInvalidDecl()) return;
67 ObjCPropertyAttribute::Kind propertyKind
= property
->getPropertyAttributes();
68 Qualifiers::ObjCLifetime propertyLifetime
69 = property
->getType().getObjCLifetime();
71 assert(propertyLifetime
!= Qualifiers::OCL_None
);
73 Qualifiers::ObjCLifetime expectedLifetime
74 = getImpliedARCOwnership(propertyKind
, property
->getType());
75 if (!expectedLifetime
) {
76 // We have a lifetime qualifier but no dominating property
77 // attribute. That's okay, but restore reasonable invariants by
78 // setting the property attribute according to the lifetime
80 ObjCPropertyAttribute::Kind attr
;
81 if (propertyLifetime
== Qualifiers::OCL_Strong
) {
82 attr
= ObjCPropertyAttribute::kind_strong
;
83 } else if (propertyLifetime
== Qualifiers::OCL_Weak
) {
84 attr
= ObjCPropertyAttribute::kind_weak
;
86 assert(propertyLifetime
== Qualifiers::OCL_ExplicitNone
);
87 attr
= ObjCPropertyAttribute::kind_unsafe_unretained
;
89 property
->setPropertyAttributes(attr
);
93 if (propertyLifetime
== expectedLifetime
) return;
95 property
->setInvalidDecl();
96 S
.Diag(property
->getLocation(),
97 diag::err_arc_inconsistent_property_ownership
)
98 << property
->getDeclName()
103 /// Check this Objective-C property against a property declared in the
106 CheckPropertyAgainstProtocol(Sema
&S
, ObjCPropertyDecl
*Prop
,
107 ObjCProtocolDecl
*Proto
,
108 llvm::SmallPtrSetImpl
<ObjCProtocolDecl
*> &Known
) {
109 // Have we seen this protocol before?
110 if (!Known
.insert(Proto
).second
)
113 // Look for a property with the same name.
114 if (ObjCPropertyDecl
*ProtoProp
= Proto
->getProperty(
115 Prop
->getIdentifier(), Prop
->isInstanceProperty())) {
116 S
.ObjC().DiagnosePropertyMismatch(Prop
, ProtoProp
, Proto
->getIdentifier(),
121 // Check this property against any protocols we inherit.
122 for (auto *P
: Proto
->protocols())
123 CheckPropertyAgainstProtocol(S
, Prop
, P
, Known
);
126 static unsigned deducePropertyOwnershipFromType(Sema
&S
, QualType T
) {
127 // In GC mode, just look for the __weak qualifier.
128 if (S
.getLangOpts().getGC() != LangOptions::NonGC
) {
129 if (T
.isObjCGCWeak())
130 return ObjCPropertyAttribute::kind_weak
;
132 // In ARC/MRC, look for an explicit ownership qualifier.
133 // For some reason, this only applies to __weak.
134 } else if (auto ownership
= T
.getObjCLifetime()) {
136 case Qualifiers::OCL_Weak
:
137 return ObjCPropertyAttribute::kind_weak
;
138 case Qualifiers::OCL_Strong
:
139 return ObjCPropertyAttribute::kind_strong
;
140 case Qualifiers::OCL_ExplicitNone
:
141 return ObjCPropertyAttribute::kind_unsafe_unretained
;
142 case Qualifiers::OCL_Autoreleasing
:
143 case Qualifiers::OCL_None
:
146 llvm_unreachable("bad qualifier");
152 static const unsigned OwnershipMask
=
153 (ObjCPropertyAttribute::kind_assign
| ObjCPropertyAttribute::kind_retain
|
154 ObjCPropertyAttribute::kind_copy
| ObjCPropertyAttribute::kind_weak
|
155 ObjCPropertyAttribute::kind_strong
|
156 ObjCPropertyAttribute::kind_unsafe_unretained
);
158 static unsigned getOwnershipRule(unsigned attr
) {
159 unsigned result
= attr
& OwnershipMask
;
161 // From an ownership perspective, assign and unsafe_unretained are
162 // identical; make sure one also implies the other.
163 if (result
& (ObjCPropertyAttribute::kind_assign
|
164 ObjCPropertyAttribute::kind_unsafe_unretained
)) {
165 result
|= ObjCPropertyAttribute::kind_assign
|
166 ObjCPropertyAttribute::kind_unsafe_unretained
;
172 Decl
*SemaObjC::ActOnProperty(Scope
*S
, SourceLocation AtLoc
,
173 SourceLocation LParenLoc
, FieldDeclarator
&FD
,
174 ObjCDeclSpec
&ODS
, Selector GetterSel
,
176 tok::ObjCKeywordKind MethodImplKind
,
177 DeclContext
*lexicalDC
) {
178 unsigned Attributes
= ODS
.getPropertyAttributes();
179 FD
.D
.setObjCWeakProperty((Attributes
& ObjCPropertyAttribute::kind_weak
) !=
181 TypeSourceInfo
*TSI
= SemaRef
.GetTypeForDeclarator(FD
.D
);
182 QualType T
= TSI
->getType();
183 if (!getOwnershipRule(Attributes
)) {
184 Attributes
|= deducePropertyOwnershipFromType(SemaRef
, T
);
186 bool isReadWrite
= ((Attributes
& ObjCPropertyAttribute::kind_readwrite
) ||
187 // default is readwrite!
188 !(Attributes
& ObjCPropertyAttribute::kind_readonly
));
190 // Proceed with constructing the ObjCPropertyDecls.
191 ObjCContainerDecl
*ClassDecl
= cast
<ObjCContainerDecl
>(SemaRef
.CurContext
);
192 ObjCPropertyDecl
*Res
= nullptr;
193 if (ObjCCategoryDecl
*CDecl
= dyn_cast
<ObjCCategoryDecl
>(ClassDecl
)) {
194 if (CDecl
->IsClassExtension()) {
195 Res
= HandlePropertyInClassExtension(S
, AtLoc
, LParenLoc
,
197 GetterSel
, ODS
.getGetterNameLoc(),
198 SetterSel
, ODS
.getSetterNameLoc(),
199 isReadWrite
, Attributes
,
200 ODS
.getPropertyAttributes(),
201 T
, TSI
, MethodImplKind
);
208 Res
= CreatePropertyDecl(S
, ClassDecl
, AtLoc
, LParenLoc
, FD
,
209 GetterSel
, ODS
.getGetterNameLoc(), SetterSel
,
210 ODS
.getSetterNameLoc(), isReadWrite
, Attributes
,
211 ODS
.getPropertyAttributes(), T
, TSI
,
214 Res
->setLexicalDeclContext(lexicalDC
);
217 // Validate the attributes on the @property.
218 CheckObjCPropertyAttributes(Res
, AtLoc
, Attributes
,
219 (isa
<ObjCInterfaceDecl
>(ClassDecl
) ||
220 isa
<ObjCProtocolDecl
>(ClassDecl
)));
222 // Check consistency if the type has explicit ownership qualification.
223 if (Res
->getType().getObjCLifetime())
224 checkPropertyDeclWithOwnership(SemaRef
, Res
);
226 llvm::SmallPtrSet
<ObjCProtocolDecl
*, 16> KnownProtos
;
227 if (ObjCInterfaceDecl
*IFace
= dyn_cast
<ObjCInterfaceDecl
>(ClassDecl
)) {
228 // For a class, compare the property against a property in our superclass.
229 bool FoundInSuper
= false;
230 ObjCInterfaceDecl
*CurrentInterfaceDecl
= IFace
;
231 while (ObjCInterfaceDecl
*Super
= CurrentInterfaceDecl
->getSuperClass()) {
232 if (ObjCPropertyDecl
*SuperProp
= Super
->getProperty(
233 Res
->getIdentifier(), Res
->isInstanceProperty())) {
234 DiagnosePropertyMismatch(Res
, SuperProp
, Super
->getIdentifier(), false);
238 CurrentInterfaceDecl
= Super
;
242 // Also compare the property against a property in our protocols.
243 for (auto *P
: CurrentInterfaceDecl
->protocols()) {
244 CheckPropertyAgainstProtocol(SemaRef
, Res
, P
, KnownProtos
);
247 // Slower path: look in all protocols we referenced.
248 for (auto *P
: IFace
->all_referenced_protocols()) {
249 CheckPropertyAgainstProtocol(SemaRef
, Res
, P
, KnownProtos
);
252 } else if (ObjCCategoryDecl
*Cat
= dyn_cast
<ObjCCategoryDecl
>(ClassDecl
)) {
253 // We don't check if class extension. Because properties in class extension
254 // are meant to override some of the attributes and checking has already done
255 // when property in class extension is constructed.
256 if (!Cat
->IsClassExtension())
257 for (auto *P
: Cat
->protocols())
258 CheckPropertyAgainstProtocol(SemaRef
, Res
, P
, KnownProtos
);
260 ObjCProtocolDecl
*Proto
= cast
<ObjCProtocolDecl
>(ClassDecl
);
261 for (auto *P
: Proto
->protocols())
262 CheckPropertyAgainstProtocol(SemaRef
, Res
, P
, KnownProtos
);
265 SemaRef
.ActOnDocumentableDecl(Res
);
269 static ObjCPropertyAttribute::Kind
270 makePropertyAttributesAsWritten(unsigned Attributes
) {
271 unsigned attributesAsWritten
= 0;
272 if (Attributes
& ObjCPropertyAttribute::kind_readonly
)
273 attributesAsWritten
|= ObjCPropertyAttribute::kind_readonly
;
274 if (Attributes
& ObjCPropertyAttribute::kind_readwrite
)
275 attributesAsWritten
|= ObjCPropertyAttribute::kind_readwrite
;
276 if (Attributes
& ObjCPropertyAttribute::kind_getter
)
277 attributesAsWritten
|= ObjCPropertyAttribute::kind_getter
;
278 if (Attributes
& ObjCPropertyAttribute::kind_setter
)
279 attributesAsWritten
|= ObjCPropertyAttribute::kind_setter
;
280 if (Attributes
& ObjCPropertyAttribute::kind_assign
)
281 attributesAsWritten
|= ObjCPropertyAttribute::kind_assign
;
282 if (Attributes
& ObjCPropertyAttribute::kind_retain
)
283 attributesAsWritten
|= ObjCPropertyAttribute::kind_retain
;
284 if (Attributes
& ObjCPropertyAttribute::kind_strong
)
285 attributesAsWritten
|= ObjCPropertyAttribute::kind_strong
;
286 if (Attributes
& ObjCPropertyAttribute::kind_weak
)
287 attributesAsWritten
|= ObjCPropertyAttribute::kind_weak
;
288 if (Attributes
& ObjCPropertyAttribute::kind_copy
)
289 attributesAsWritten
|= ObjCPropertyAttribute::kind_copy
;
290 if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
)
291 attributesAsWritten
|= ObjCPropertyAttribute::kind_unsafe_unretained
;
292 if (Attributes
& ObjCPropertyAttribute::kind_nonatomic
)
293 attributesAsWritten
|= ObjCPropertyAttribute::kind_nonatomic
;
294 if (Attributes
& ObjCPropertyAttribute::kind_atomic
)
295 attributesAsWritten
|= ObjCPropertyAttribute::kind_atomic
;
296 if (Attributes
& ObjCPropertyAttribute::kind_class
)
297 attributesAsWritten
|= ObjCPropertyAttribute::kind_class
;
298 if (Attributes
& ObjCPropertyAttribute::kind_direct
)
299 attributesAsWritten
|= ObjCPropertyAttribute::kind_direct
;
301 return (ObjCPropertyAttribute::Kind
)attributesAsWritten
;
304 static bool LocPropertyAttribute( ASTContext
&Context
, const char *attrName
,
305 SourceLocation LParenLoc
, SourceLocation
&Loc
) {
306 if (LParenLoc
.isMacroID())
309 SourceManager
&SM
= Context
.getSourceManager();
310 std::pair
<FileID
, unsigned> locInfo
= SM
.getDecomposedLoc(LParenLoc
);
311 // Try to load the file buffer.
312 bool invalidTemp
= false;
313 StringRef file
= SM
.getBufferData(locInfo
.first
, &invalidTemp
);
316 const char *tokenBegin
= file
.data() + locInfo
.second
;
318 // Lex from the start of the given location.
319 Lexer
lexer(SM
.getLocForStartOfFile(locInfo
.first
),
320 Context
.getLangOpts(),
321 file
.begin(), tokenBegin
, file
.end());
324 lexer
.LexFromRawLexer(Tok
);
325 if (Tok
.is(tok::raw_identifier
) && Tok
.getRawIdentifier() == attrName
) {
326 Loc
= Tok
.getLocation();
329 } while (Tok
.isNot(tok::r_paren
));
333 /// Check for a mismatch in the atomicity of the given properties.
334 static void checkAtomicPropertyMismatch(Sema
&S
,
335 ObjCPropertyDecl
*OldProperty
,
336 ObjCPropertyDecl
*NewProperty
,
337 bool PropagateAtomicity
) {
338 // If the atomicity of both matches, we're done.
339 bool OldIsAtomic
= (OldProperty
->getPropertyAttributes() &
340 ObjCPropertyAttribute::kind_nonatomic
) == 0;
341 bool NewIsAtomic
= (NewProperty
->getPropertyAttributes() &
342 ObjCPropertyAttribute::kind_nonatomic
) == 0;
343 if (OldIsAtomic
== NewIsAtomic
) return;
345 // Determine whether the given property is readonly and implicitly
347 auto isImplicitlyReadonlyAtomic
= [](ObjCPropertyDecl
*Property
) -> bool {
349 auto Attrs
= Property
->getPropertyAttributes();
350 if ((Attrs
& ObjCPropertyAttribute::kind_readonly
) == 0)
354 if (Attrs
& ObjCPropertyAttribute::kind_nonatomic
)
357 // Was 'atomic' specified directly?
358 if (Property
->getPropertyAttributesAsWritten() &
359 ObjCPropertyAttribute::kind_atomic
)
365 // If we're allowed to propagate atomicity, and the new property did
366 // not specify atomicity at all, propagate.
367 const unsigned AtomicityMask
= (ObjCPropertyAttribute::kind_atomic
|
368 ObjCPropertyAttribute::kind_nonatomic
);
369 if (PropagateAtomicity
&&
370 ((NewProperty
->getPropertyAttributesAsWritten() & AtomicityMask
) == 0)) {
371 unsigned Attrs
= NewProperty
->getPropertyAttributes();
372 Attrs
= Attrs
& ~AtomicityMask
;
374 Attrs
|= ObjCPropertyAttribute::kind_atomic
;
376 Attrs
|= ObjCPropertyAttribute::kind_nonatomic
;
378 NewProperty
->overwritePropertyAttributes(Attrs
);
382 // One of the properties is atomic; if it's a readonly property, and
383 // 'atomic' wasn't explicitly specified, we're okay.
384 if ((OldIsAtomic
&& isImplicitlyReadonlyAtomic(OldProperty
)) ||
385 (NewIsAtomic
&& isImplicitlyReadonlyAtomic(NewProperty
)))
388 // Diagnose the conflict.
389 const IdentifierInfo
*OldContextName
;
390 auto *OldDC
= OldProperty
->getDeclContext();
391 if (auto Category
= dyn_cast
<ObjCCategoryDecl
>(OldDC
))
392 OldContextName
= Category
->getClassInterface()->getIdentifier();
394 OldContextName
= cast
<ObjCContainerDecl
>(OldDC
)->getIdentifier();
396 S
.Diag(NewProperty
->getLocation(), diag::warn_property_attribute
)
397 << NewProperty
->getDeclName() << "atomic"
399 S
.Diag(OldProperty
->getLocation(), diag::note_property_declare
);
402 ObjCPropertyDecl
*SemaObjC::HandlePropertyInClassExtension(
403 Scope
*S
, SourceLocation AtLoc
, SourceLocation LParenLoc
,
404 FieldDeclarator
&FD
, Selector GetterSel
, SourceLocation GetterNameLoc
,
405 Selector SetterSel
, SourceLocation SetterNameLoc
, const bool isReadWrite
,
406 unsigned &Attributes
, const unsigned AttributesAsWritten
, QualType T
,
407 TypeSourceInfo
*TSI
, tok::ObjCKeywordKind MethodImplKind
) {
408 ObjCCategoryDecl
*CDecl
= cast
<ObjCCategoryDecl
>(SemaRef
.CurContext
);
409 // Diagnose if this property is already in continuation class.
410 DeclContext
*DC
= SemaRef
.CurContext
;
411 const IdentifierInfo
*PropertyId
= FD
.D
.getIdentifier();
412 ObjCInterfaceDecl
*CCPrimary
= CDecl
->getClassInterface();
414 // We need to look in the @interface to see if the @property was
417 Diag(CDecl
->getLocation(), diag::err_continuation_class
);
421 bool isClassProperty
=
422 (AttributesAsWritten
& ObjCPropertyAttribute::kind_class
) ||
423 (Attributes
& ObjCPropertyAttribute::kind_class
);
425 // Find the property in the extended class's primary class or
427 ObjCPropertyDecl
*PIDecl
= CCPrimary
->FindPropertyVisibleInPrimaryClass(
428 PropertyId
, ObjCPropertyDecl::getQueryKind(isClassProperty
));
430 // If we found a property in an extension, complain.
431 if (PIDecl
&& isa
<ObjCCategoryDecl
>(PIDecl
->getDeclContext())) {
432 Diag(AtLoc
, diag::err_duplicate_property
);
433 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
437 // Check for consistency with the previous declaration, if there is one.
439 // A readonly property declared in the primary class can be refined
440 // by adding a readwrite property within an extension.
441 // Anything else is an error.
442 if (!(PIDecl
->isReadOnly() && isReadWrite
)) {
443 // Tailor the diagnostics for the common case where a readwrite
444 // property is declared both in the @interface and the continuation.
445 // This is a common error where the user often intended the original
446 // declaration to be readonly.
448 (Attributes
& ObjCPropertyAttribute::kind_readwrite
) &&
449 (PIDecl
->getPropertyAttributesAsWritten() &
450 ObjCPropertyAttribute::kind_readwrite
)
451 ? diag::err_use_continuation_class_redeclaration_readwrite
452 : diag::err_use_continuation_class
;
454 << CCPrimary
->getDeclName();
455 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
459 // Check for consistency of getters.
460 if (PIDecl
->getGetterName() != GetterSel
) {
461 // If the getter was written explicitly, complain.
462 if (AttributesAsWritten
& ObjCPropertyAttribute::kind_getter
) {
463 Diag(AtLoc
, diag::warn_property_redecl_getter_mismatch
)
464 << PIDecl
->getGetterName() << GetterSel
;
465 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
468 // Always adopt the getter from the original declaration.
469 GetterSel
= PIDecl
->getGetterName();
470 Attributes
|= ObjCPropertyAttribute::kind_getter
;
473 // Check consistency of ownership.
474 unsigned ExistingOwnership
475 = getOwnershipRule(PIDecl
->getPropertyAttributes());
476 unsigned NewOwnership
= getOwnershipRule(Attributes
);
477 if (ExistingOwnership
&& NewOwnership
!= ExistingOwnership
) {
478 // If the ownership was written explicitly, complain.
479 if (getOwnershipRule(AttributesAsWritten
)) {
480 Diag(AtLoc
, diag::warn_property_attr_mismatch
);
481 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
484 // Take the ownership from the original property.
485 Attributes
= (Attributes
& ~OwnershipMask
) | ExistingOwnership
;
488 // If the redeclaration is 'weak' but the original property is not,
489 if ((Attributes
& ObjCPropertyAttribute::kind_weak
) &&
490 !(PIDecl
->getPropertyAttributesAsWritten() &
491 ObjCPropertyAttribute::kind_weak
) &&
492 PIDecl
->getType()->getAs
<ObjCObjectPointerType
>() &&
493 PIDecl
->getType().getObjCLifetime() == Qualifiers::OCL_None
) {
494 Diag(AtLoc
, diag::warn_property_implicitly_mismatched
);
495 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
499 // Create a new ObjCPropertyDecl with the DeclContext being
500 // the class extension.
501 ObjCPropertyDecl
*PDecl
= CreatePropertyDecl(S
, CDecl
, AtLoc
, LParenLoc
,
502 FD
, GetterSel
, GetterNameLoc
,
503 SetterSel
, SetterNameLoc
,
505 Attributes
, AttributesAsWritten
,
506 T
, TSI
, MethodImplKind
, DC
);
507 ASTContext
&Context
= getASTContext();
508 // If there was no declaration of a property with the same name in
509 // the primary class, we're done.
511 ProcessPropertyDecl(PDecl
);
515 if (!Context
.hasSameType(PIDecl
->getType(), PDecl
->getType())) {
516 bool IncompatibleObjC
= false;
517 QualType ConvertedType
;
518 // Relax the strict type matching for property type in continuation class.
519 // Allow property object type of continuation class to be different as long
520 // as it narrows the object type in its primary class property. Note that
521 // this conversion is safe only because the wider type is for a 'readonly'
522 // property in primary class and 'narrowed' type for a 'readwrite' property
523 // in continuation class.
524 QualType PrimaryClassPropertyT
= Context
.getCanonicalType(PIDecl
->getType());
525 QualType ClassExtPropertyT
= Context
.getCanonicalType(PDecl
->getType());
526 if (!isa
<ObjCObjectPointerType
>(PrimaryClassPropertyT
) ||
527 !isa
<ObjCObjectPointerType
>(ClassExtPropertyT
) ||
528 (!SemaRef
.isObjCPointerConversion(ClassExtPropertyT
,
529 PrimaryClassPropertyT
, ConvertedType
,
530 IncompatibleObjC
)) ||
533 diag::err_type_mismatch_continuation_class
) << PDecl
->getType();
534 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
539 // Check that atomicity of property in class extension matches the previous
541 checkAtomicPropertyMismatch(SemaRef
, PIDecl
, PDecl
, true);
543 // Make sure getter/setter are appropriately synthesized.
544 ProcessPropertyDecl(PDecl
);
548 ObjCPropertyDecl
*SemaObjC::CreatePropertyDecl(
549 Scope
*S
, ObjCContainerDecl
*CDecl
, SourceLocation AtLoc
,
550 SourceLocation LParenLoc
, FieldDeclarator
&FD
, Selector GetterSel
,
551 SourceLocation GetterNameLoc
, Selector SetterSel
,
552 SourceLocation SetterNameLoc
, const bool isReadWrite
,
553 const unsigned Attributes
, const unsigned AttributesAsWritten
, QualType T
,
554 TypeSourceInfo
*TInfo
, tok::ObjCKeywordKind MethodImplKind
,
555 DeclContext
*lexicalDC
) {
556 ASTContext
&Context
= getASTContext();
557 const IdentifierInfo
*PropertyId
= FD
.D
.getIdentifier();
559 // Property defaults to 'assign' if it is readwrite, unless this is ARC
560 // and the type is retainable.
562 if (Attributes
& (ObjCPropertyAttribute::kind_assign
|
563 ObjCPropertyAttribute::kind_unsafe_unretained
)) {
565 } else if (getOwnershipRule(Attributes
) || !isReadWrite
) {
568 isAssign
= (!getLangOpts().ObjCAutoRefCount
||
569 !T
->isObjCRetainableType());
572 // Issue a warning if property is 'assign' as default and its
573 // object, which is gc'able conforms to NSCopying protocol
574 if (getLangOpts().getGC() != LangOptions::NonGC
&& isAssign
&&
575 !(Attributes
& ObjCPropertyAttribute::kind_assign
)) {
576 if (const ObjCObjectPointerType
*ObjPtrTy
=
577 T
->getAs
<ObjCObjectPointerType
>()) {
578 ObjCInterfaceDecl
*IDecl
= ObjPtrTy
->getObjectType()->getInterface();
580 if (ObjCProtocolDecl
* PNSCopying
=
581 LookupProtocol(&Context
.Idents
.get("NSCopying"), AtLoc
))
582 if (IDecl
->ClassImplementsProtocol(PNSCopying
, true))
583 Diag(AtLoc
, diag::warn_implements_nscopying
) << PropertyId
;
587 if (T
->isObjCObjectType()) {
588 SourceLocation StarLoc
= TInfo
->getTypeLoc().getEndLoc();
589 StarLoc
= SemaRef
.getLocForEndOfToken(StarLoc
);
590 Diag(FD
.D
.getIdentifierLoc(), diag::err_statically_allocated_object
)
591 << FixItHint::CreateInsertion(StarLoc
, "*");
592 T
= Context
.getObjCObjectPointerType(T
);
593 SourceLocation TLoc
= TInfo
->getTypeLoc().getBeginLoc();
594 TInfo
= Context
.getTrivialTypeSourceInfo(T
, TLoc
);
597 DeclContext
*DC
= CDecl
;
598 ObjCPropertyDecl
*PDecl
= ObjCPropertyDecl::Create(Context
, DC
,
599 FD
.D
.getIdentifierLoc(),
601 LParenLoc
, T
, TInfo
);
603 bool isClassProperty
=
604 (AttributesAsWritten
& ObjCPropertyAttribute::kind_class
) ||
605 (Attributes
& ObjCPropertyAttribute::kind_class
);
606 // Class property and instance property can have the same name.
607 if (ObjCPropertyDecl
*prevDecl
= ObjCPropertyDecl::findPropertyDecl(
608 DC
, PropertyId
, ObjCPropertyDecl::getQueryKind(isClassProperty
))) {
609 Diag(PDecl
->getLocation(), diag::err_duplicate_property
);
610 Diag(prevDecl
->getLocation(), diag::note_property_declare
);
611 PDecl
->setInvalidDecl();
616 PDecl
->setLexicalDeclContext(lexicalDC
);
619 if (T
->isArrayType() || T
->isFunctionType()) {
620 Diag(AtLoc
, diag::err_property_type
) << T
;
621 PDecl
->setInvalidDecl();
624 // Regardless of setter/getter attribute, we save the default getter/setter
625 // selector names in anticipation of declaration of setter/getter methods.
626 PDecl
->setGetterName(GetterSel
, GetterNameLoc
);
627 PDecl
->setSetterName(SetterSel
, SetterNameLoc
);
628 PDecl
->setPropertyAttributesAsWritten(
629 makePropertyAttributesAsWritten(AttributesAsWritten
));
631 SemaRef
.ProcessDeclAttributes(S
, PDecl
, FD
.D
);
633 if (Attributes
& ObjCPropertyAttribute::kind_readonly
)
634 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly
);
636 if (Attributes
& ObjCPropertyAttribute::kind_getter
)
637 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_getter
);
639 if (Attributes
& ObjCPropertyAttribute::kind_setter
)
640 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_setter
);
643 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite
);
645 if (Attributes
& ObjCPropertyAttribute::kind_retain
)
646 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_retain
);
648 if (Attributes
& ObjCPropertyAttribute::kind_strong
)
649 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
651 if (Attributes
& ObjCPropertyAttribute::kind_weak
)
652 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_weak
);
654 if (Attributes
& ObjCPropertyAttribute::kind_copy
)
655 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_copy
);
657 if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
)
658 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained
);
661 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_assign
);
663 // In the semantic attributes, one of nonatomic or atomic is always set.
664 if (Attributes
& ObjCPropertyAttribute::kind_nonatomic
)
665 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic
);
667 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_atomic
);
669 // 'unsafe_unretained' is alias for 'assign'.
670 if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
)
671 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_assign
);
673 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained
);
675 if (MethodImplKind
== tok::objc_required
)
676 PDecl
->setPropertyImplementation(ObjCPropertyDecl::Required
);
677 else if (MethodImplKind
== tok::objc_optional
)
678 PDecl
->setPropertyImplementation(ObjCPropertyDecl::Optional
);
680 if (Attributes
& ObjCPropertyAttribute::kind_nullability
)
681 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_nullability
);
683 if (Attributes
& ObjCPropertyAttribute::kind_null_resettable
)
684 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable
);
686 if (Attributes
& ObjCPropertyAttribute::kind_class
)
687 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_class
);
689 if ((Attributes
& ObjCPropertyAttribute::kind_direct
) ||
690 CDecl
->hasAttr
<ObjCDirectMembersAttr
>()) {
691 if (isa
<ObjCProtocolDecl
>(CDecl
)) {
692 Diag(PDecl
->getLocation(), diag::err_objc_direct_on_protocol
) << true;
693 } else if (getLangOpts().ObjCRuntime
.allowsDirectDispatch()) {
694 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_direct
);
696 Diag(PDecl
->getLocation(), diag::warn_objc_direct_property_ignored
)
697 << PDecl
->getDeclName();
704 static void checkARCPropertyImpl(Sema
&S
, SourceLocation propertyImplLoc
,
705 ObjCPropertyDecl
*property
,
706 ObjCIvarDecl
*ivar
) {
707 if (property
->isInvalidDecl() || ivar
->isInvalidDecl()) return;
709 QualType ivarType
= ivar
->getType();
710 Qualifiers::ObjCLifetime ivarLifetime
= ivarType
.getObjCLifetime();
712 // The lifetime implied by the property's attributes.
713 Qualifiers::ObjCLifetime propertyLifetime
=
714 getImpliedARCOwnership(property
->getPropertyAttributes(),
715 property
->getType());
717 // We're fine if they match.
718 if (propertyLifetime
== ivarLifetime
) return;
720 // None isn't a valid lifetime for an object ivar in ARC, and
721 // __autoreleasing is never valid; don't diagnose twice.
722 if ((ivarLifetime
== Qualifiers::OCL_None
&&
723 S
.getLangOpts().ObjCAutoRefCount
) ||
724 ivarLifetime
== Qualifiers::OCL_Autoreleasing
)
727 // If the ivar is private, and it's implicitly __unsafe_unretained
728 // because of its type, then pretend it was actually implicitly
729 // __strong. This is only sound because we're processing the
730 // property implementation before parsing any method bodies.
731 if (ivarLifetime
== Qualifiers::OCL_ExplicitNone
&&
732 propertyLifetime
== Qualifiers::OCL_Strong
&&
733 ivar
->getAccessControl() == ObjCIvarDecl::Private
) {
734 SplitQualType split
= ivarType
.split();
735 if (split
.Quals
.hasObjCLifetime()) {
736 assert(ivarType
->isObjCARCImplicitlyUnretainedType());
737 split
.Quals
.setObjCLifetime(Qualifiers::OCL_Strong
);
738 ivarType
= S
.Context
.getQualifiedType(split
);
739 ivar
->setType(ivarType
);
744 switch (propertyLifetime
) {
745 case Qualifiers::OCL_Strong
:
746 S
.Diag(ivar
->getLocation(), diag::err_arc_strong_property_ownership
)
747 << property
->getDeclName()
748 << ivar
->getDeclName()
752 case Qualifiers::OCL_Weak
:
753 S
.Diag(ivar
->getLocation(), diag::err_weak_property
)
754 << property
->getDeclName()
755 << ivar
->getDeclName();
758 case Qualifiers::OCL_ExplicitNone
:
759 S
.Diag(ivar
->getLocation(), diag::err_arc_assign_property_ownership
)
760 << property
->getDeclName() << ivar
->getDeclName()
761 << ((property
->getPropertyAttributesAsWritten() &
762 ObjCPropertyAttribute::kind_assign
) != 0);
765 case Qualifiers::OCL_Autoreleasing
:
766 llvm_unreachable("properties cannot be autoreleasing");
768 case Qualifiers::OCL_None
:
769 // Any other property should be ignored.
773 S
.Diag(property
->getLocation(), diag::note_property_declare
);
774 if (propertyImplLoc
.isValid())
775 S
.Diag(propertyImplLoc
, diag::note_property_synthesize
);
778 /// setImpliedPropertyAttributeForReadOnlyProperty -
779 /// This routine evaludates life-time attributes for a 'readonly'
780 /// property with no known lifetime of its own, using backing
781 /// 'ivar's attribute, if any. If no backing 'ivar', property's
782 /// life-time is assumed 'strong'.
783 static void setImpliedPropertyAttributeForReadOnlyProperty(
784 ObjCPropertyDecl
*property
, ObjCIvarDecl
*ivar
) {
785 Qualifiers::ObjCLifetime propertyLifetime
=
786 getImpliedARCOwnership(property
->getPropertyAttributes(),
787 property
->getType());
788 if (propertyLifetime
!= Qualifiers::OCL_None
)
792 // if no backing ivar, make property 'strong'.
793 property
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
796 // property assumes owenership of backing ivar.
797 QualType ivarType
= ivar
->getType();
798 Qualifiers::ObjCLifetime ivarLifetime
= ivarType
.getObjCLifetime();
799 if (ivarLifetime
== Qualifiers::OCL_Strong
)
800 property
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
801 else if (ivarLifetime
== Qualifiers::OCL_Weak
)
802 property
->setPropertyAttributes(ObjCPropertyAttribute::kind_weak
);
805 static bool isIncompatiblePropertyAttribute(unsigned Attr1
, unsigned Attr2
,
806 ObjCPropertyAttribute::Kind Kind
) {
807 return (Attr1
& Kind
) != (Attr2
& Kind
);
810 static bool areIncompatiblePropertyAttributes(unsigned Attr1
, unsigned Attr2
,
812 return ((Attr1
& Kinds
) != 0) != ((Attr2
& Kinds
) != 0);
815 /// SelectPropertyForSynthesisFromProtocols - Finds the most appropriate
816 /// property declaration that should be synthesised in all of the inherited
817 /// protocols. It also diagnoses properties declared in inherited protocols with
818 /// mismatched types or attributes, since any of them can be candidate for
820 static ObjCPropertyDecl
*
821 SelectPropertyForSynthesisFromProtocols(Sema
&S
, SourceLocation AtLoc
,
822 ObjCInterfaceDecl
*ClassDecl
,
823 ObjCPropertyDecl
*Property
) {
824 assert(isa
<ObjCProtocolDecl
>(Property
->getDeclContext()) &&
825 "Expected a property from a protocol");
826 ObjCInterfaceDecl::ProtocolPropertySet ProtocolSet
;
827 ObjCInterfaceDecl::PropertyDeclOrder Properties
;
828 for (const auto *PI
: ClassDecl
->all_referenced_protocols()) {
829 if (const ObjCProtocolDecl
*PDecl
= PI
->getDefinition())
830 PDecl
->collectInheritedProtocolProperties(Property
, ProtocolSet
,
833 if (ObjCInterfaceDecl
*SDecl
= ClassDecl
->getSuperClass()) {
835 for (const auto *PI
: SDecl
->all_referenced_protocols()) {
836 if (const ObjCProtocolDecl
*PDecl
= PI
->getDefinition())
837 PDecl
->collectInheritedProtocolProperties(Property
, ProtocolSet
,
840 SDecl
= SDecl
->getSuperClass();
844 if (Properties
.empty())
847 ObjCPropertyDecl
*OriginalProperty
= Property
;
848 size_t SelectedIndex
= 0;
849 for (const auto &Prop
: llvm::enumerate(Properties
)) {
850 // Select the 'readwrite' property if such property exists.
851 if (Property
->isReadOnly() && !Prop
.value()->isReadOnly()) {
852 Property
= Prop
.value();
853 SelectedIndex
= Prop
.index();
856 if (Property
!= OriginalProperty
) {
857 // Check that the old property is compatible with the new one.
858 Properties
[SelectedIndex
] = OriginalProperty
;
861 QualType RHSType
= S
.Context
.getCanonicalType(Property
->getType());
862 unsigned OriginalAttributes
= Property
->getPropertyAttributesAsWritten();
864 IncompatibleType
= 0,
865 HasNoExpectedAttribute
,
866 HasUnexpectedAttribute
,
870 // Represents a property from another protocol that conflicts with the
871 // selected declaration.
872 struct MismatchingProperty
{
873 const ObjCPropertyDecl
*Prop
;
875 StringRef AttributeName
;
877 SmallVector
<MismatchingProperty
, 4> Mismatches
;
878 for (ObjCPropertyDecl
*Prop
: Properties
) {
879 // Verify the property attributes.
880 unsigned Attr
= Prop
->getPropertyAttributesAsWritten();
881 if (Attr
!= OriginalAttributes
) {
882 auto Diag
= [&](bool OriginalHasAttribute
, StringRef AttributeName
) {
883 MismatchKind Kind
= OriginalHasAttribute
? HasNoExpectedAttribute
884 : HasUnexpectedAttribute
;
885 Mismatches
.push_back({Prop
, Kind
, AttributeName
});
887 // The ownership might be incompatible unless the property has no explicit
890 (Attr
& (ObjCPropertyAttribute::kind_retain
|
891 ObjCPropertyAttribute::kind_strong
|
892 ObjCPropertyAttribute::kind_copy
|
893 ObjCPropertyAttribute::kind_assign
|
894 ObjCPropertyAttribute::kind_unsafe_unretained
|
895 ObjCPropertyAttribute::kind_weak
)) != 0;
897 isIncompatiblePropertyAttribute(OriginalAttributes
, Attr
,
898 ObjCPropertyAttribute::kind_copy
)) {
899 Diag(OriginalAttributes
& ObjCPropertyAttribute::kind_copy
, "copy");
902 if (HasOwnership
&& areIncompatiblePropertyAttributes(
903 OriginalAttributes
, Attr
,
904 ObjCPropertyAttribute::kind_retain
|
905 ObjCPropertyAttribute::kind_strong
)) {
906 Diag(OriginalAttributes
& (ObjCPropertyAttribute::kind_retain
|
907 ObjCPropertyAttribute::kind_strong
),
908 "retain (or strong)");
911 if (isIncompatiblePropertyAttribute(OriginalAttributes
, Attr
,
912 ObjCPropertyAttribute::kind_atomic
)) {
913 Diag(OriginalAttributes
& ObjCPropertyAttribute::kind_atomic
, "atomic");
917 if (Property
->getGetterName() != Prop
->getGetterName()) {
918 Mismatches
.push_back({Prop
, DifferentGetter
, ""});
921 if (!Property
->isReadOnly() && !Prop
->isReadOnly() &&
922 Property
->getSetterName() != Prop
->getSetterName()) {
923 Mismatches
.push_back({Prop
, DifferentSetter
, ""});
926 QualType LHSType
= S
.Context
.getCanonicalType(Prop
->getType());
927 if (!S
.Context
.propertyTypesAreCompatible(LHSType
, RHSType
)) {
928 bool IncompatibleObjC
= false;
929 QualType ConvertedType
;
930 if (!S
.isObjCPointerConversion(RHSType
, LHSType
, ConvertedType
, IncompatibleObjC
)
931 || IncompatibleObjC
) {
932 Mismatches
.push_back({Prop
, IncompatibleType
, ""});
938 if (Mismatches
.empty())
941 // Diagnose incompability.
943 bool HasIncompatibleAttributes
= false;
944 for (const auto &Note
: Mismatches
)
945 HasIncompatibleAttributes
=
946 Note
.Kind
!= IncompatibleType
? true : HasIncompatibleAttributes
;
947 // Promote the warning to an error if there are incompatible attributes or
948 // incompatible types together with readwrite/readonly incompatibility.
949 auto Diag
= S
.Diag(Property
->getLocation(),
950 Property
!= OriginalProperty
|| HasIncompatibleAttributes
951 ? diag::err_protocol_property_mismatch
952 : diag::warn_protocol_property_mismatch
);
953 Diag
<< Mismatches
[0].Kind
;
954 switch (Mismatches
[0].Kind
) {
955 case IncompatibleType
:
956 Diag
<< Property
->getType();
958 case HasNoExpectedAttribute
:
959 case HasUnexpectedAttribute
:
960 Diag
<< Mismatches
[0].AttributeName
;
962 case DifferentGetter
:
963 Diag
<< Property
->getGetterName();
965 case DifferentSetter
:
966 Diag
<< Property
->getSetterName();
970 for (const auto &Note
: Mismatches
) {
972 S
.Diag(Note
.Prop
->getLocation(), diag::note_protocol_property_declare
)
975 case IncompatibleType
:
976 Diag
<< Note
.Prop
->getType();
978 case HasNoExpectedAttribute
:
979 case HasUnexpectedAttribute
:
980 Diag
<< Note
.AttributeName
;
982 case DifferentGetter
:
983 Diag
<< Note
.Prop
->getGetterName();
985 case DifferentSetter
:
986 Diag
<< Note
.Prop
->getSetterName();
991 S
.Diag(AtLoc
, diag::note_property_synthesize
);
996 /// Determine whether any storage attributes were written on the property.
997 static bool hasWrittenStorageAttribute(ObjCPropertyDecl
*Prop
,
998 ObjCPropertyQueryKind QueryKind
) {
999 if (Prop
->getPropertyAttributesAsWritten() & OwnershipMask
) return true;
1001 // If this is a readwrite property in a class extension that refines
1002 // a readonly property in the original class definition, check it as
1005 // If it's a readonly property, we're not interested.
1006 if (Prop
->isReadOnly()) return false;
1008 // Is it declared in an extension?
1009 auto Category
= dyn_cast
<ObjCCategoryDecl
>(Prop
->getDeclContext());
1010 if (!Category
|| !Category
->IsClassExtension()) return false;
1012 // Find the corresponding property in the primary class definition.
1013 auto OrigClass
= Category
->getClassInterface();
1014 for (auto *Found
: OrigClass
->lookup(Prop
->getDeclName())) {
1015 if (ObjCPropertyDecl
*OrigProp
= dyn_cast
<ObjCPropertyDecl
>(Found
))
1016 return OrigProp
->getPropertyAttributesAsWritten() & OwnershipMask
;
1019 // Look through all of the protocols.
1020 for (const auto *Proto
: OrigClass
->all_referenced_protocols()) {
1021 if (ObjCPropertyDecl
*OrigProp
= Proto
->FindPropertyDeclaration(
1022 Prop
->getIdentifier(), QueryKind
))
1023 return OrigProp
->getPropertyAttributesAsWritten() & OwnershipMask
;
1029 /// Create a synthesized property accessor stub inside the \@implementation.
1030 static ObjCMethodDecl
*
1031 RedeclarePropertyAccessor(ASTContext
&Context
, ObjCImplementationDecl
*Impl
,
1032 ObjCMethodDecl
*AccessorDecl
, SourceLocation AtLoc
,
1033 SourceLocation PropertyLoc
) {
1034 ObjCMethodDecl
*Decl
= AccessorDecl
;
1035 ObjCMethodDecl
*ImplDecl
= ObjCMethodDecl::Create(
1036 Context
, AtLoc
.isValid() ? AtLoc
: Decl
->getBeginLoc(),
1037 PropertyLoc
.isValid() ? PropertyLoc
: Decl
->getEndLoc(),
1038 Decl
->getSelector(), Decl
->getReturnType(),
1039 Decl
->getReturnTypeSourceInfo(), Impl
, Decl
->isInstanceMethod(),
1040 Decl
->isVariadic(), Decl
->isPropertyAccessor(),
1041 /* isSynthesized*/ true, Decl
->isImplicit(), Decl
->isDefined(),
1042 Decl
->getImplementationControl(), Decl
->hasRelatedResultType());
1043 ImplDecl
->getMethodFamily();
1044 if (Decl
->hasAttrs())
1045 ImplDecl
->setAttrs(Decl
->getAttrs());
1046 ImplDecl
->setSelfDecl(Decl
->getSelfDecl());
1047 ImplDecl
->setCmdDecl(Decl
->getCmdDecl());
1048 SmallVector
<SourceLocation
, 1> SelLocs
;
1049 Decl
->getSelectorLocs(SelLocs
);
1050 ImplDecl
->setMethodParams(Context
, Decl
->parameters(), SelLocs
);
1051 ImplDecl
->setLexicalDeclContext(Impl
);
1052 ImplDecl
->setDefined(false);
1056 /// ActOnPropertyImplDecl - This routine performs semantic checks and
1057 /// builds the AST node for a property implementation declaration; declared
1058 /// as \@synthesize or \@dynamic.
1060 Decl
*SemaObjC::ActOnPropertyImplDecl(
1061 Scope
*S
, SourceLocation AtLoc
, SourceLocation PropertyLoc
, bool Synthesize
,
1062 IdentifierInfo
*PropertyId
, IdentifierInfo
*PropertyIvar
,
1063 SourceLocation PropertyIvarLoc
, ObjCPropertyQueryKind QueryKind
) {
1064 ASTContext
&Context
= getASTContext();
1065 ObjCContainerDecl
*ClassImpDecl
=
1066 dyn_cast
<ObjCContainerDecl
>(SemaRef
.CurContext
);
1067 // Make sure we have a context for the property implementation declaration.
1068 if (!ClassImpDecl
) {
1069 Diag(AtLoc
, diag::err_missing_property_context
);
1072 if (PropertyIvarLoc
.isInvalid())
1073 PropertyIvarLoc
= PropertyLoc
;
1074 SourceLocation PropertyDiagLoc
= PropertyLoc
;
1075 if (PropertyDiagLoc
.isInvalid())
1076 PropertyDiagLoc
= ClassImpDecl
->getBeginLoc();
1077 ObjCPropertyDecl
*property
= nullptr;
1078 ObjCInterfaceDecl
*IDecl
= nullptr;
1079 // Find the class or category class where this property must have
1081 ObjCImplementationDecl
*IC
= nullptr;
1082 ObjCCategoryImplDecl
*CatImplClass
= nullptr;
1083 if ((IC
= dyn_cast
<ObjCImplementationDecl
>(ClassImpDecl
))) {
1084 IDecl
= IC
->getClassInterface();
1085 // We always synthesize an interface for an implementation
1086 // without an interface decl. So, IDecl is always non-zero.
1088 "ActOnPropertyImplDecl - @implementation without @interface");
1090 // Look for this property declaration in the @implementation's @interface
1091 property
= IDecl
->FindPropertyDeclaration(PropertyId
, QueryKind
);
1093 Diag(PropertyLoc
, diag::err_bad_property_decl
) << IDecl
->getDeclName();
1096 if (property
->isClassProperty() && Synthesize
) {
1097 Diag(PropertyLoc
, diag::err_synthesize_on_class_property
) << PropertyId
;
1100 unsigned PIkind
= property
->getPropertyAttributesAsWritten();
1101 if ((PIkind
& (ObjCPropertyAttribute::kind_atomic
|
1102 ObjCPropertyAttribute::kind_nonatomic
)) == 0) {
1103 if (AtLoc
.isValid())
1104 Diag(AtLoc
, diag::warn_implicit_atomic_property
);
1106 Diag(IC
->getLocation(), diag::warn_auto_implicit_atomic_property
);
1107 Diag(property
->getLocation(), diag::note_property_declare
);
1110 if (const ObjCCategoryDecl
*CD
=
1111 dyn_cast
<ObjCCategoryDecl
>(property
->getDeclContext())) {
1112 if (!CD
->IsClassExtension()) {
1113 Diag(PropertyLoc
, diag::err_category_property
) << CD
->getDeclName();
1114 Diag(property
->getLocation(), diag::note_property_declare
);
1118 if (Synthesize
&& (PIkind
& ObjCPropertyAttribute::kind_readonly
) &&
1119 property
->hasAttr
<IBOutletAttr
>() && !AtLoc
.isValid()) {
1120 bool ReadWriteProperty
= false;
1121 // Search into the class extensions and see if 'readonly property is
1122 // redeclared 'readwrite', then no warning is to be issued.
1123 for (auto *Ext
: IDecl
->known_extensions()) {
1124 DeclContext::lookup_result R
= Ext
->lookup(property
->getDeclName());
1125 if (auto *ExtProp
= R
.find_first
<ObjCPropertyDecl
>()) {
1126 PIkind
= ExtProp
->getPropertyAttributesAsWritten();
1127 if (PIkind
& ObjCPropertyAttribute::kind_readwrite
) {
1128 ReadWriteProperty
= true;
1134 if (!ReadWriteProperty
) {
1135 Diag(property
->getLocation(), diag::warn_auto_readonly_iboutlet_property
)
1137 SourceLocation readonlyLoc
;
1138 if (LocPropertyAttribute(Context
, "readonly",
1139 property
->getLParenLoc(), readonlyLoc
)) {
1140 SourceLocation endLoc
=
1141 readonlyLoc
.getLocWithOffset(strlen("readonly")-1);
1142 SourceRange
ReadonlySourceRange(readonlyLoc
, endLoc
);
1143 Diag(property
->getLocation(),
1144 diag::note_auto_readonly_iboutlet_fixup_suggest
) <<
1145 FixItHint::CreateReplacement(ReadonlySourceRange
, "readwrite");
1149 if (Synthesize
&& isa
<ObjCProtocolDecl
>(property
->getDeclContext()))
1150 property
= SelectPropertyForSynthesisFromProtocols(SemaRef
, AtLoc
, IDecl
,
1153 } else if ((CatImplClass
= dyn_cast
<ObjCCategoryImplDecl
>(ClassImpDecl
))) {
1155 Diag(AtLoc
, diag::err_synthesize_category_decl
);
1158 IDecl
= CatImplClass
->getClassInterface();
1160 Diag(AtLoc
, diag::err_missing_property_interface
);
1163 ObjCCategoryDecl
*Category
=
1164 IDecl
->FindCategoryDeclaration(CatImplClass
->getIdentifier());
1166 // If category for this implementation not found, it is an error which
1167 // has already been reported eralier.
1170 // Look for this property declaration in @implementation's category
1171 property
= Category
->FindPropertyDeclaration(PropertyId
, QueryKind
);
1173 Diag(PropertyLoc
, diag::err_bad_category_property_decl
)
1174 << Category
->getDeclName();
1178 Diag(AtLoc
, diag::err_bad_property_context
);
1181 ObjCIvarDecl
*Ivar
= nullptr;
1182 bool CompleteTypeErr
= false;
1184 // Check that we have a valid, previously declared ivar for @synthesize
1188 PropertyIvar
= PropertyId
;
1189 // Check that this is a previously declared 'ivar' in 'IDecl' interface
1190 ObjCInterfaceDecl
*ClassDeclared
;
1191 Ivar
= IDecl
->lookupInstanceVariable(PropertyIvar
, ClassDeclared
);
1192 QualType PropType
= property
->getType();
1193 QualType PropertyIvarType
= PropType
.getNonReferenceType();
1195 if (SemaRef
.RequireCompleteType(PropertyDiagLoc
, PropertyIvarType
,
1196 diag::err_incomplete_synthesized_property
,
1197 property
->getDeclName())) {
1198 Diag(property
->getLocation(), diag::note_property_declare
);
1199 CompleteTypeErr
= true;
1202 if (getLangOpts().ObjCAutoRefCount
&&
1203 (property
->getPropertyAttributesAsWritten() &
1204 ObjCPropertyAttribute::kind_readonly
) &&
1205 PropertyIvarType
->isObjCRetainableType()) {
1206 setImpliedPropertyAttributeForReadOnlyProperty(property
, Ivar
);
1209 ObjCPropertyAttribute::Kind kind
= property
->getPropertyAttributes();
1211 bool isARCWeak
= false;
1212 if (kind
& ObjCPropertyAttribute::kind_weak
) {
1213 // Add GC __weak to the ivar type if the property is weak.
1214 if (getLangOpts().getGC() != LangOptions::NonGC
) {
1215 assert(!getLangOpts().ObjCAutoRefCount
);
1216 if (PropertyIvarType
.isObjCGCStrong()) {
1217 Diag(PropertyDiagLoc
, diag::err_gc_weak_property_strong_type
);
1218 Diag(property
->getLocation(), diag::note_property_declare
);
1221 Context
.getObjCGCQualType(PropertyIvarType
, Qualifiers::Weak
);
1224 // Otherwise, check whether ARC __weak is enabled and works with
1225 // the property type.
1227 if (!getLangOpts().ObjCWeak
) {
1228 // Only complain here when synthesizing an ivar.
1230 Diag(PropertyDiagLoc
,
1231 getLangOpts().ObjCWeakRuntime
1232 ? diag::err_synthesizing_arc_weak_property_disabled
1233 : diag::err_synthesizing_arc_weak_property_no_runtime
);
1234 Diag(property
->getLocation(), diag::note_property_declare
);
1236 CompleteTypeErr
= true; // suppress later diagnostics about the ivar
1239 if (const ObjCObjectPointerType
*ObjT
=
1240 PropertyIvarType
->getAs
<ObjCObjectPointerType
>()) {
1241 const ObjCInterfaceDecl
*ObjI
= ObjT
->getInterfaceDecl();
1242 if (ObjI
&& ObjI
->isArcWeakrefUnavailable()) {
1243 Diag(property
->getLocation(),
1244 diag::err_arc_weak_unavailable_property
)
1245 << PropertyIvarType
;
1246 Diag(ClassImpDecl
->getLocation(), diag::note_implemented_by_class
)
1247 << ClassImpDecl
->getName();
1254 if (AtLoc
.isInvalid()) {
1255 // Check when default synthesizing a property that there is
1256 // an ivar matching property name and issue warning; since this
1257 // is the most common case of not using an ivar used for backing
1258 // property in non-default synthesis case.
1259 ObjCInterfaceDecl
*ClassDeclared
=nullptr;
1260 ObjCIvarDecl
*originalIvar
=
1261 IDecl
->lookupInstanceVariable(property
->getIdentifier(),
1264 Diag(PropertyDiagLoc
,
1265 diag::warn_autosynthesis_property_ivar_match
)
1266 << PropertyId
<< (Ivar
== nullptr) << PropertyIvar
1267 << originalIvar
->getIdentifier();
1268 Diag(property
->getLocation(), diag::note_property_declare
);
1269 Diag(originalIvar
->getLocation(), diag::note_ivar_decl
);
1274 // In ARC, give the ivar a lifetime qualifier based on the
1275 // property attributes.
1276 if ((getLangOpts().ObjCAutoRefCount
|| isARCWeak
) &&
1277 !PropertyIvarType
.getObjCLifetime() &&
1278 PropertyIvarType
->isObjCRetainableType()) {
1280 // It's an error if we have to do this and the user didn't
1281 // explicitly write an ownership attribute on the property.
1282 if (!hasWrittenStorageAttribute(property
, QueryKind
) &&
1283 !(kind
& ObjCPropertyAttribute::kind_strong
)) {
1284 Diag(PropertyDiagLoc
,
1285 diag::err_arc_objc_property_default_assign_on_object
);
1286 Diag(property
->getLocation(), diag::note_property_declare
);
1288 Qualifiers::ObjCLifetime lifetime
=
1289 getImpliedARCOwnership(kind
, PropertyIvarType
);
1290 assert(lifetime
&& "no lifetime for property?");
1293 qs
.addObjCLifetime(lifetime
);
1294 PropertyIvarType
= Context
.getQualifiedType(PropertyIvarType
, qs
);
1298 Ivar
= ObjCIvarDecl::Create(Context
, ClassImpDecl
,
1299 PropertyIvarLoc
,PropertyIvarLoc
, PropertyIvar
,
1300 PropertyIvarType
, /*TInfo=*/nullptr,
1301 ObjCIvarDecl::Private
,
1302 (Expr
*)nullptr, true);
1303 if (SemaRef
.RequireNonAbstractType(PropertyIvarLoc
, PropertyIvarType
,
1304 diag::err_abstract_type_in_decl
,
1305 Sema::AbstractSynthesizedIvarType
)) {
1306 Diag(property
->getLocation(), diag::note_property_declare
);
1307 // An abstract type is as bad as an incomplete type.
1308 CompleteTypeErr
= true;
1310 if (!CompleteTypeErr
) {
1311 const RecordType
*RecordTy
= PropertyIvarType
->getAs
<RecordType
>();
1312 if (RecordTy
&& RecordTy
->getDecl()->hasFlexibleArrayMember()) {
1313 Diag(PropertyIvarLoc
, diag::err_synthesize_variable_sized_ivar
)
1314 << PropertyIvarType
;
1315 CompleteTypeErr
= true; // suppress later diagnostics about the ivar
1318 if (CompleteTypeErr
)
1319 Ivar
->setInvalidDecl();
1320 ClassImpDecl
->addDecl(Ivar
);
1321 IDecl
->makeDeclVisibleInContext(Ivar
);
1323 if (getLangOpts().ObjCRuntime
.isFragile())
1324 Diag(PropertyDiagLoc
, diag::err_missing_property_ivar_decl
)
1326 // Note! I deliberately want it to fall thru so, we have a
1327 // a property implementation and to avoid future warnings.
1328 } else if (getLangOpts().ObjCRuntime
.isNonFragile() &&
1329 !declaresSameEntity(ClassDeclared
, IDecl
)) {
1330 Diag(PropertyDiagLoc
, diag::err_ivar_in_superclass_use
)
1331 << property
->getDeclName() << Ivar
->getDeclName()
1332 << ClassDeclared
->getDeclName();
1333 Diag(Ivar
->getLocation(), diag::note_previous_access_declaration
)
1334 << Ivar
<< Ivar
->getName();
1335 // Note! I deliberately want it to fall thru so more errors are caught.
1337 property
->setPropertyIvarDecl(Ivar
);
1339 QualType IvarType
= Context
.getCanonicalType(Ivar
->getType());
1341 // Check that type of property and its ivar are type compatible.
1342 if (!Context
.hasSameType(PropertyIvarType
, IvarType
)) {
1343 if (isa
<ObjCObjectPointerType
>(PropertyIvarType
)
1344 && isa
<ObjCObjectPointerType
>(IvarType
))
1345 compat
= Context
.canAssignObjCInterfaces(
1346 PropertyIvarType
->castAs
<ObjCObjectPointerType
>(),
1347 IvarType
->castAs
<ObjCObjectPointerType
>());
1349 compat
= (SemaRef
.CheckAssignmentConstraints(
1350 PropertyIvarLoc
, PropertyIvarType
, IvarType
) ==
1354 Diag(PropertyDiagLoc
, diag::err_property_ivar_type
)
1355 << property
->getDeclName() << PropType
1356 << Ivar
->getDeclName() << IvarType
;
1357 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1358 // Note! I deliberately want it to fall thru so, we have a
1359 // a property implementation and to avoid future warnings.
1362 // FIXME! Rules for properties are somewhat different that those
1363 // for assignments. Use a new routine to consolidate all cases;
1364 // specifically for property redeclarations as well as for ivars.
1365 QualType lhsType
=Context
.getCanonicalType(PropertyIvarType
).getUnqualifiedType();
1366 QualType rhsType
=Context
.getCanonicalType(IvarType
).getUnqualifiedType();
1367 if (lhsType
!= rhsType
&&
1368 lhsType
->isArithmeticType()) {
1369 Diag(PropertyDiagLoc
, diag::err_property_ivar_type
)
1370 << property
->getDeclName() << PropType
1371 << Ivar
->getDeclName() << IvarType
;
1372 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1373 // Fall thru - see previous comment
1376 // __weak is explicit. So it works on Canonical type.
1377 if ((PropType
.isObjCGCWeak() && !IvarType
.isObjCGCWeak() &&
1378 getLangOpts().getGC() != LangOptions::NonGC
)) {
1379 Diag(PropertyDiagLoc
, diag::err_weak_property
)
1380 << property
->getDeclName() << Ivar
->getDeclName();
1381 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1382 // Fall thru - see previous comment
1384 // Fall thru - see previous comment
1385 if ((property
->getType()->isObjCObjectPointerType() ||
1386 PropType
.isObjCGCStrong()) && IvarType
.isObjCGCWeak() &&
1387 getLangOpts().getGC() != LangOptions::NonGC
) {
1388 Diag(PropertyDiagLoc
, diag::err_strong_property
)
1389 << property
->getDeclName() << Ivar
->getDeclName();
1390 // Fall thru - see previous comment
1393 if (getLangOpts().ObjCAutoRefCount
|| isARCWeak
||
1394 Ivar
->getType().getObjCLifetime())
1395 checkARCPropertyImpl(SemaRef
, PropertyLoc
, property
, Ivar
);
1396 } else if (PropertyIvar
)
1398 Diag(PropertyDiagLoc
, diag::err_dynamic_property_ivar_decl
);
1400 assert (property
&& "ActOnPropertyImplDecl - property declaration missing");
1401 ObjCPropertyImplDecl
*PIDecl
= ObjCPropertyImplDecl::Create(
1402 Context
, SemaRef
.CurContext
, AtLoc
, PropertyLoc
, property
,
1403 (Synthesize
? ObjCPropertyImplDecl::Synthesize
1404 : ObjCPropertyImplDecl::Dynamic
),
1405 Ivar
, PropertyIvarLoc
);
1407 if (CompleteTypeErr
|| !compat
)
1408 PIDecl
->setInvalidDecl();
1410 if (ObjCMethodDecl
*getterMethod
= property
->getGetterMethodDecl()) {
1411 getterMethod
->createImplicitParams(Context
, IDecl
);
1413 // Redeclare the getter within the implementation as DeclContext.
1415 // If the method hasn't been overridden, create a synthesized implementation.
1416 ObjCMethodDecl
*OMD
= ClassImpDecl
->getMethod(
1417 getterMethod
->getSelector(), getterMethod
->isInstanceMethod());
1419 OMD
= RedeclarePropertyAccessor(Context
, IC
, getterMethod
, AtLoc
,
1421 PIDecl
->setGetterMethodDecl(OMD
);
1424 if (getLangOpts().CPlusPlus
&& Synthesize
&& !CompleteTypeErr
&&
1425 Ivar
->getType()->isRecordType()) {
1426 // For Objective-C++, need to synthesize the AST for the IVAR object to be
1427 // returned by the getter as it must conform to C++'s copy-return rules.
1428 // FIXME. Eventually we want to do this for Objective-C as well.
1429 Sema::SynthesizedFunctionScope
Scope(SemaRef
, getterMethod
);
1430 ImplicitParamDecl
*SelfDecl
= getterMethod
->getSelfDecl();
1431 DeclRefExpr
*SelfExpr
= new (Context
)
1432 DeclRefExpr(Context
, SelfDecl
, false, SelfDecl
->getType(), VK_LValue
,
1434 SemaRef
.MarkDeclRefReferenced(SelfExpr
);
1435 Expr
*LoadSelfExpr
= ImplicitCastExpr::Create(
1436 Context
, SelfDecl
->getType(), CK_LValueToRValue
, SelfExpr
, nullptr,
1437 VK_PRValue
, FPOptionsOverride());
1439 new (Context
) ObjCIvarRefExpr(Ivar
,
1440 Ivar
->getUsageType(SelfDecl
->getType()),
1442 Ivar
->getLocation(),
1443 LoadSelfExpr
, true, true);
1444 ExprResult Res
= SemaRef
.PerformCopyInitialization(
1445 InitializedEntity::InitializeResult(PropertyDiagLoc
,
1446 getterMethod
->getReturnType()),
1447 PropertyDiagLoc
, IvarRefExpr
);
1448 if (!Res
.isInvalid()) {
1449 Expr
*ResExpr
= Res
.getAs
<Expr
>();
1451 ResExpr
= SemaRef
.MaybeCreateExprWithCleanups(ResExpr
);
1452 PIDecl
->setGetterCXXConstructor(ResExpr
);
1455 if (property
->hasAttr
<NSReturnsNotRetainedAttr
>() &&
1456 !getterMethod
->hasAttr
<NSReturnsNotRetainedAttr
>()) {
1457 Diag(getterMethod
->getLocation(),
1458 diag::warn_property_getter_owning_mismatch
);
1459 Diag(property
->getLocation(), diag::note_property_declare
);
1461 if (getLangOpts().ObjCAutoRefCount
&& Synthesize
)
1462 switch (getterMethod
->getMethodFamily()) {
1464 case OMF_retainCount
:
1466 case OMF_autorelease
:
1467 Diag(getterMethod
->getLocation(), diag::err_arc_illegal_method_def
)
1468 << 1 << getterMethod
->getSelector();
1475 if (ObjCMethodDecl
*setterMethod
= property
->getSetterMethodDecl()) {
1476 setterMethod
->createImplicitParams(Context
, IDecl
);
1478 // Redeclare the setter within the implementation as DeclContext.
1480 ObjCMethodDecl
*OMD
= ClassImpDecl
->getMethod(
1481 setterMethod
->getSelector(), setterMethod
->isInstanceMethod());
1483 OMD
= RedeclarePropertyAccessor(Context
, IC
, setterMethod
,
1484 AtLoc
, PropertyLoc
);
1485 PIDecl
->setSetterMethodDecl(OMD
);
1488 if (getLangOpts().CPlusPlus
&& Synthesize
&& !CompleteTypeErr
&&
1489 Ivar
->getType()->isRecordType()) {
1490 // FIXME. Eventually we want to do this for Objective-C as well.
1491 Sema::SynthesizedFunctionScope
Scope(SemaRef
, setterMethod
);
1492 ImplicitParamDecl
*SelfDecl
= setterMethod
->getSelfDecl();
1493 DeclRefExpr
*SelfExpr
= new (Context
)
1494 DeclRefExpr(Context
, SelfDecl
, false, SelfDecl
->getType(), VK_LValue
,
1496 SemaRef
.MarkDeclRefReferenced(SelfExpr
);
1497 Expr
*LoadSelfExpr
= ImplicitCastExpr::Create(
1498 Context
, SelfDecl
->getType(), CK_LValueToRValue
, SelfExpr
, nullptr,
1499 VK_PRValue
, FPOptionsOverride());
1501 new (Context
) ObjCIvarRefExpr(Ivar
,
1502 Ivar
->getUsageType(SelfDecl
->getType()),
1504 Ivar
->getLocation(),
1505 LoadSelfExpr
, true, true);
1506 ObjCMethodDecl::param_iterator P
= setterMethod
->param_begin();
1507 ParmVarDecl
*Param
= (*P
);
1508 QualType T
= Param
->getType().getNonReferenceType();
1509 DeclRefExpr
*rhs
= new (Context
)
1510 DeclRefExpr(Context
, Param
, false, T
, VK_LValue
, PropertyDiagLoc
);
1511 SemaRef
.MarkDeclRefReferenced(rhs
);
1513 SemaRef
.BuildBinOp(S
, PropertyDiagLoc
, BO_Assign
, lhs
, rhs
);
1514 if (property
->getPropertyAttributes() &
1515 ObjCPropertyAttribute::kind_atomic
) {
1516 Expr
*callExpr
= Res
.getAs
<Expr
>();
1517 if (const CXXOperatorCallExpr
*CXXCE
=
1518 dyn_cast_or_null
<CXXOperatorCallExpr
>(callExpr
))
1519 if (const FunctionDecl
*FuncDecl
= CXXCE
->getDirectCallee())
1520 if (!FuncDecl
->isTrivial())
1521 if (property
->getType()->isReferenceType()) {
1522 Diag(PropertyDiagLoc
,
1523 diag::err_atomic_property_nontrivial_assign_op
)
1524 << property
->getType();
1525 Diag(FuncDecl
->getBeginLoc(), diag::note_callee_decl
)
1529 PIDecl
->setSetterCXXAssignment(Res
.getAs
<Expr
>());
1535 if (ObjCPropertyImplDecl
*PPIDecl
=
1536 IC
->FindPropertyImplIvarDecl(PropertyIvar
)) {
1537 Diag(PropertyLoc
, diag::err_duplicate_ivar_use
)
1538 << PropertyId
<< PPIDecl
->getPropertyDecl()->getIdentifier()
1540 Diag(PPIDecl
->getLocation(), diag::note_previous_use
);
1543 if (ObjCPropertyImplDecl
*PPIDecl
1544 = IC
->FindPropertyImplDecl(PropertyId
, QueryKind
)) {
1545 Diag(PropertyLoc
, diag::err_property_implemented
) << PropertyId
;
1546 Diag(PPIDecl
->getLocation(), diag::note_previous_declaration
);
1549 IC
->addPropertyImplementation(PIDecl
);
1550 if (getLangOpts().ObjCDefaultSynthProperties
&&
1551 getLangOpts().ObjCRuntime
.isNonFragile() &&
1552 !IDecl
->isObjCRequiresPropertyDefs()) {
1553 // Diagnose if an ivar was lazily synthesdized due to a previous
1554 // use and if 1) property is @dynamic or 2) property is synthesized
1555 // but it requires an ivar of different name.
1556 ObjCInterfaceDecl
*ClassDeclared
=nullptr;
1557 ObjCIvarDecl
*Ivar
= nullptr;
1559 Ivar
= IDecl
->lookupInstanceVariable(PropertyId
, ClassDeclared
);
1561 if (PropertyIvar
&& PropertyIvar
!= PropertyId
)
1562 Ivar
= IDecl
->lookupInstanceVariable(PropertyId
, ClassDeclared
);
1564 // Issue diagnostics only if Ivar belongs to current class.
1565 if (Ivar
&& Ivar
->getSynthesize() &&
1566 declaresSameEntity(IC
->getClassInterface(), ClassDeclared
)) {
1567 Diag(Ivar
->getLocation(), diag::err_undeclared_var_use
)
1569 Ivar
->setInvalidDecl();
1574 if (ObjCPropertyImplDecl
*PPIDecl
=
1575 CatImplClass
->FindPropertyImplIvarDecl(PropertyIvar
)) {
1576 Diag(PropertyDiagLoc
, diag::err_duplicate_ivar_use
)
1577 << PropertyId
<< PPIDecl
->getPropertyDecl()->getIdentifier()
1579 Diag(PPIDecl
->getLocation(), diag::note_previous_use
);
1582 if (ObjCPropertyImplDecl
*PPIDecl
=
1583 CatImplClass
->FindPropertyImplDecl(PropertyId
, QueryKind
)) {
1584 Diag(PropertyDiagLoc
, diag::err_property_implemented
) << PropertyId
;
1585 Diag(PPIDecl
->getLocation(), diag::note_previous_declaration
);
1588 CatImplClass
->addPropertyImplementation(PIDecl
);
1591 if (PIDecl
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
&&
1592 PIDecl
->getPropertyDecl() &&
1593 PIDecl
->getPropertyDecl()->isDirectProperty()) {
1594 Diag(PropertyLoc
, diag::err_objc_direct_dynamic_property
);
1595 Diag(PIDecl
->getPropertyDecl()->getLocation(),
1596 diag::note_previous_declaration
);
1603 //===----------------------------------------------------------------------===//
1605 //===----------------------------------------------------------------------===//
1607 /// DiagnosePropertyMismatch - Compares two properties for their
1608 /// attributes and types and warns on a variety of inconsistencies.
1610 void SemaObjC::DiagnosePropertyMismatch(ObjCPropertyDecl
*Property
,
1611 ObjCPropertyDecl
*SuperProperty
,
1612 const IdentifierInfo
*inheritedName
,
1613 bool OverridingProtocolProperty
) {
1614 ASTContext
&Context
= getASTContext();
1615 ObjCPropertyAttribute::Kind CAttr
= Property
->getPropertyAttributes();
1616 ObjCPropertyAttribute::Kind SAttr
= SuperProperty
->getPropertyAttributes();
1618 // We allow readonly properties without an explicit ownership
1619 // (assign/unsafe_unretained/weak/retain/strong/copy) in super class
1620 // to be overridden by a property with any explicit ownership in the subclass.
1621 if (!OverridingProtocolProperty
&&
1622 !getOwnershipRule(SAttr
) && getOwnershipRule(CAttr
))
1625 if ((CAttr
& ObjCPropertyAttribute::kind_readonly
) &&
1626 (SAttr
& ObjCPropertyAttribute::kind_readwrite
))
1627 Diag(Property
->getLocation(), diag::warn_readonly_property
)
1628 << Property
->getDeclName() << inheritedName
;
1629 if ((CAttr
& ObjCPropertyAttribute::kind_copy
) !=
1630 (SAttr
& ObjCPropertyAttribute::kind_copy
))
1631 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1632 << Property
->getDeclName() << "copy" << inheritedName
;
1633 else if (!(SAttr
& ObjCPropertyAttribute::kind_readonly
)) {
1634 unsigned CAttrRetain
= (CAttr
& (ObjCPropertyAttribute::kind_retain
|
1635 ObjCPropertyAttribute::kind_strong
));
1636 unsigned SAttrRetain
= (SAttr
& (ObjCPropertyAttribute::kind_retain
|
1637 ObjCPropertyAttribute::kind_strong
));
1638 bool CStrong
= (CAttrRetain
!= 0);
1639 bool SStrong
= (SAttrRetain
!= 0);
1640 if (CStrong
!= SStrong
)
1641 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1642 << Property
->getDeclName() << "retain (or strong)" << inheritedName
;
1646 // Check for nonatomic; note that nonatomic is effectively
1647 // meaningless for readonly properties, so don't diagnose if the
1648 // atomic property is 'readonly'.
1649 checkAtomicPropertyMismatch(SemaRef
, SuperProperty
, Property
, false);
1650 // Readonly properties from protocols can be implemented as "readwrite"
1651 // with a custom setter name.
1652 if (Property
->getSetterName() != SuperProperty
->getSetterName() &&
1653 !(SuperProperty
->isReadOnly() &&
1654 isa
<ObjCProtocolDecl
>(SuperProperty
->getDeclContext()))) {
1655 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1656 << Property
->getDeclName() << "setter" << inheritedName
;
1657 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1659 if (Property
->getGetterName() != SuperProperty
->getGetterName()) {
1660 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1661 << Property
->getDeclName() << "getter" << inheritedName
;
1662 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1666 Context
.getCanonicalType(SuperProperty
->getType());
1668 Context
.getCanonicalType(Property
->getType());
1670 if (!Context
.propertyTypesAreCompatible(LHSType
, RHSType
)) {
1671 // Do cases not handled in above.
1672 // FIXME. For future support of covariant property types, revisit this.
1673 bool IncompatibleObjC
= false;
1674 QualType ConvertedType
;
1675 if (!SemaRef
.isObjCPointerConversion(RHSType
, LHSType
, ConvertedType
,
1676 IncompatibleObjC
) ||
1678 Diag(Property
->getLocation(), diag::warn_property_types_are_incompatible
)
1679 << Property
->getType() << SuperProperty
->getType() << inheritedName
;
1680 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1685 bool SemaObjC::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl
*property
,
1686 ObjCMethodDecl
*GetterMethod
,
1687 SourceLocation Loc
) {
1688 ASTContext
&Context
= getASTContext();
1691 QualType GetterType
= GetterMethod
->getReturnType().getNonReferenceType();
1692 QualType PropertyRValueType
=
1693 property
->getType().getNonReferenceType().getAtomicUnqualifiedType();
1694 bool compat
= Context
.hasSameType(PropertyRValueType
, GetterType
);
1696 const ObjCObjectPointerType
*propertyObjCPtr
= nullptr;
1697 const ObjCObjectPointerType
*getterObjCPtr
= nullptr;
1698 if ((propertyObjCPtr
=
1699 PropertyRValueType
->getAs
<ObjCObjectPointerType
>()) &&
1700 (getterObjCPtr
= GetterType
->getAs
<ObjCObjectPointerType
>()))
1701 compat
= Context
.canAssignObjCInterfaces(getterObjCPtr
, propertyObjCPtr
);
1702 else if (SemaRef
.CheckAssignmentConstraints(
1703 Loc
, GetterType
, PropertyRValueType
) != Sema::Compatible
) {
1704 Diag(Loc
, diag::err_property_accessor_type
)
1705 << property
->getDeclName() << PropertyRValueType
1706 << GetterMethod
->getSelector() << GetterType
;
1707 Diag(GetterMethod
->getLocation(), diag::note_declared_at
);
1711 QualType lhsType
= Context
.getCanonicalType(PropertyRValueType
);
1712 QualType rhsType
=Context
.getCanonicalType(GetterType
).getUnqualifiedType();
1713 if (lhsType
!= rhsType
&& lhsType
->isArithmeticType())
1719 Diag(Loc
, diag::warn_accessor_property_type_mismatch
)
1720 << property
->getDeclName()
1721 << GetterMethod
->getSelector();
1722 Diag(GetterMethod
->getLocation(), diag::note_declared_at
);
1729 /// CollectImmediateProperties - This routine collects all properties in
1730 /// the class and its conforming protocols; but not those in its super class.
1732 CollectImmediateProperties(ObjCContainerDecl
*CDecl
,
1733 ObjCContainerDecl::PropertyMap
&PropMap
,
1734 ObjCContainerDecl::PropertyMap
&SuperPropMap
,
1735 bool CollectClassPropsOnly
= false,
1736 bool IncludeProtocols
= true) {
1737 if (ObjCInterfaceDecl
*IDecl
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
)) {
1738 for (auto *Prop
: IDecl
->properties()) {
1739 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1741 PropMap
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] =
1745 // Collect the properties from visible extensions.
1746 for (auto *Ext
: IDecl
->visible_extensions())
1747 CollectImmediateProperties(Ext
, PropMap
, SuperPropMap
,
1748 CollectClassPropsOnly
, IncludeProtocols
);
1750 if (IncludeProtocols
) {
1751 // Scan through class's protocols.
1752 for (auto *PI
: IDecl
->all_referenced_protocols())
1753 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1754 CollectClassPropsOnly
);
1757 if (ObjCCategoryDecl
*CATDecl
= dyn_cast
<ObjCCategoryDecl
>(CDecl
)) {
1758 for (auto *Prop
: CATDecl
->properties()) {
1759 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1761 PropMap
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] =
1764 if (IncludeProtocols
) {
1765 // Scan through class's protocols.
1766 for (auto *PI
: CATDecl
->protocols())
1767 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1768 CollectClassPropsOnly
);
1771 else if (ObjCProtocolDecl
*PDecl
= dyn_cast
<ObjCProtocolDecl
>(CDecl
)) {
1772 for (auto *Prop
: PDecl
->properties()) {
1773 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1775 ObjCPropertyDecl
*PropertyFromSuper
=
1776 SuperPropMap
[std::make_pair(Prop
->getIdentifier(),
1777 Prop
->isClassProperty())];
1778 // Exclude property for protocols which conform to class's super-class,
1779 // as super-class has to implement the property.
1780 if (!PropertyFromSuper
||
1781 PropertyFromSuper
->getIdentifier() != Prop
->getIdentifier()) {
1782 ObjCPropertyDecl
*&PropEntry
=
1783 PropMap
[std::make_pair(Prop
->getIdentifier(),
1784 Prop
->isClassProperty())];
1789 // Scan through protocol's protocols.
1790 for (auto *PI
: PDecl
->protocols())
1791 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1792 CollectClassPropsOnly
);
1796 /// CollectSuperClassPropertyImplementations - This routine collects list of
1797 /// properties to be implemented in super class(s) and also coming from their
1798 /// conforming protocols.
1799 static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl
*CDecl
,
1800 ObjCInterfaceDecl::PropertyMap
&PropMap
) {
1801 if (ObjCInterfaceDecl
*SDecl
= CDecl
->getSuperClass()) {
1803 SDecl
->collectPropertiesToImplement(PropMap
);
1804 SDecl
= SDecl
->getSuperClass();
1809 /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
1810 /// an ivar synthesized for 'Method' and 'Method' is a property accessor
1811 /// declared in class 'IFace'.
1812 bool SemaObjC::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl
*IFace
,
1813 ObjCMethodDecl
*Method
,
1815 if (!IV
->getSynthesize())
1817 ObjCMethodDecl
*IMD
= IFace
->lookupMethod(Method
->getSelector(),
1818 Method
->isInstanceMethod());
1819 if (!IMD
|| !IMD
->isPropertyAccessor())
1822 // look up a property declaration whose one of its accessors is implemented
1824 for (const auto *Property
: IFace
->instance_properties()) {
1825 if ((Property
->getGetterName() == IMD
->getSelector() ||
1826 Property
->getSetterName() == IMD
->getSelector()) &&
1827 (Property
->getPropertyIvarDecl() == IV
))
1830 // Also look up property declaration in class extension whose one of its
1831 // accessors is implemented by this method.
1832 for (const auto *Ext
: IFace
->known_extensions())
1833 for (const auto *Property
: Ext
->instance_properties())
1834 if ((Property
->getGetterName() == IMD
->getSelector() ||
1835 Property
->getSetterName() == IMD
->getSelector()) &&
1836 (Property
->getPropertyIvarDecl() == IV
))
1841 static bool SuperClassImplementsProperty(ObjCInterfaceDecl
*IDecl
,
1842 ObjCPropertyDecl
*Prop
) {
1843 bool SuperClassImplementsGetter
= false;
1844 bool SuperClassImplementsSetter
= false;
1845 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly
)
1846 SuperClassImplementsSetter
= true;
1848 while (IDecl
->getSuperClass()) {
1849 ObjCInterfaceDecl
*SDecl
= IDecl
->getSuperClass();
1850 if (!SuperClassImplementsGetter
&& SDecl
->getInstanceMethod(Prop
->getGetterName()))
1851 SuperClassImplementsGetter
= true;
1853 if (!SuperClassImplementsSetter
&& SDecl
->getInstanceMethod(Prop
->getSetterName()))
1854 SuperClassImplementsSetter
= true;
1855 if (SuperClassImplementsGetter
&& SuperClassImplementsSetter
)
1857 IDecl
= IDecl
->getSuperClass();
1862 /// Default synthesizes all properties which must be synthesized
1863 /// in class's \@implementation.
1864 void SemaObjC::DefaultSynthesizeProperties(Scope
*S
, ObjCImplDecl
*IMPDecl
,
1865 ObjCInterfaceDecl
*IDecl
,
1866 SourceLocation AtEnd
) {
1867 ASTContext
&Context
= getASTContext();
1868 ObjCInterfaceDecl::PropertyMap PropMap
;
1869 IDecl
->collectPropertiesToImplement(PropMap
);
1870 if (PropMap
.empty())
1872 ObjCInterfaceDecl::PropertyMap SuperPropMap
;
1873 CollectSuperClassPropertyImplementations(IDecl
, SuperPropMap
);
1875 for (const auto &PropEntry
: PropMap
) {
1876 ObjCPropertyDecl
*Prop
= PropEntry
.second
;
1877 // Is there a matching property synthesize/dynamic?
1878 if (Prop
->isInvalidDecl() ||
1879 Prop
->isClassProperty() ||
1880 Prop
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
1882 // Property may have been synthesized by user.
1883 if (IMPDecl
->FindPropertyImplDecl(
1884 Prop
->getIdentifier(), Prop
->getQueryKind()))
1886 ObjCMethodDecl
*ImpMethod
= IMPDecl
->getInstanceMethod(Prop
->getGetterName());
1887 if (ImpMethod
&& !ImpMethod
->getBody()) {
1888 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly
)
1890 ImpMethod
= IMPDecl
->getInstanceMethod(Prop
->getSetterName());
1891 if (ImpMethod
&& !ImpMethod
->getBody())
1894 if (ObjCPropertyImplDecl
*PID
=
1895 IMPDecl
->FindPropertyImplIvarDecl(Prop
->getIdentifier())) {
1896 Diag(Prop
->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property
)
1897 << Prop
->getIdentifier();
1898 if (PID
->getLocation().isValid())
1899 Diag(PID
->getLocation(), diag::note_property_synthesize
);
1902 ObjCPropertyDecl
*PropInSuperClass
=
1903 SuperPropMap
[std::make_pair(Prop
->getIdentifier(),
1904 Prop
->isClassProperty())];
1905 if (ObjCProtocolDecl
*Proto
=
1906 dyn_cast
<ObjCProtocolDecl
>(Prop
->getDeclContext())) {
1907 // We won't auto-synthesize properties declared in protocols.
1908 // Suppress the warning if class's superclass implements property's
1909 // getter and implements property's setter (if readwrite property).
1910 // Or, if property is going to be implemented in its super class.
1911 if (!SuperClassImplementsProperty(IDecl
, Prop
) && !PropInSuperClass
) {
1912 Diag(IMPDecl
->getLocation(),
1913 diag::warn_auto_synthesizing_protocol_property
)
1915 Diag(Prop
->getLocation(), diag::note_property_declare
);
1917 (Twine("@synthesize ") + Prop
->getName() + ";\n\n").str();
1918 Diag(AtEnd
, diag::note_add_synthesize_directive
)
1919 << FixItHint::CreateInsertion(AtEnd
, FixIt
);
1923 // If property to be implemented in the super class, ignore.
1924 if (PropInSuperClass
) {
1925 if ((Prop
->getPropertyAttributes() &
1926 ObjCPropertyAttribute::kind_readwrite
) &&
1927 (PropInSuperClass
->getPropertyAttributes() &
1928 ObjCPropertyAttribute::kind_readonly
) &&
1929 !IMPDecl
->getInstanceMethod(Prop
->getSetterName()) &&
1930 !IDecl
->HasUserDeclaredSetterMethod(Prop
)) {
1931 Diag(Prop
->getLocation(), diag::warn_no_autosynthesis_property
)
1932 << Prop
->getIdentifier();
1933 Diag(PropInSuperClass
->getLocation(), diag::note_property_declare
);
1935 Diag(Prop
->getLocation(), diag::warn_autosynthesis_property_in_superclass
)
1936 << Prop
->getIdentifier();
1937 Diag(PropInSuperClass
->getLocation(), diag::note_property_declare
);
1938 Diag(IMPDecl
->getLocation(), diag::note_while_in_implementation
);
1942 // We use invalid SourceLocations for the synthesized ivars since they
1943 // aren't really synthesized at a particular location; they just exist.
1944 // Saying that they are located at the @implementation isn't really going
1946 ObjCPropertyImplDecl
*PIDecl
= dyn_cast_or_null
<ObjCPropertyImplDecl
>(
1947 ActOnPropertyImplDecl(S
, SourceLocation(), SourceLocation(),
1949 /* property = */ Prop
->getIdentifier(),
1950 /* ivar = */ Prop
->getDefaultSynthIvarName(Context
),
1951 Prop
->getLocation(), Prop
->getQueryKind()));
1952 if (PIDecl
&& !Prop
->isUnavailable()) {
1953 Diag(Prop
->getLocation(), diag::warn_missing_explicit_synthesis
);
1954 Diag(IMPDecl
->getLocation(), diag::note_while_in_implementation
);
1959 void SemaObjC::DefaultSynthesizeProperties(Scope
*S
, Decl
*D
,
1960 SourceLocation AtEnd
) {
1961 if (!getLangOpts().ObjCDefaultSynthProperties
||
1962 getLangOpts().ObjCRuntime
.isFragile())
1964 ObjCImplementationDecl
*IC
=dyn_cast_or_null
<ObjCImplementationDecl
>(D
);
1967 if (ObjCInterfaceDecl
* IDecl
= IC
->getClassInterface())
1968 if (!IDecl
->isObjCRequiresPropertyDefs())
1969 DefaultSynthesizeProperties(S
, IC
, IDecl
, AtEnd
);
1972 static void DiagnoseUnimplementedAccessor(
1973 Sema
&S
, ObjCInterfaceDecl
*PrimaryClass
, Selector Method
,
1974 ObjCImplDecl
*IMPDecl
, ObjCContainerDecl
*CDecl
, ObjCCategoryDecl
*C
,
1975 ObjCPropertyDecl
*Prop
,
1976 llvm::SmallPtrSet
<const ObjCMethodDecl
*, 8> &SMap
) {
1977 // Check to see if we have a corresponding selector in SMap and with the
1978 // right method type.
1979 auto I
= llvm::find_if(SMap
, [&](const ObjCMethodDecl
*x
) {
1980 return x
->getSelector() == Method
&&
1981 x
->isClassMethod() == Prop
->isClassProperty();
1983 // When reporting on missing property setter/getter implementation in
1984 // categories, do not report when they are declared in primary class,
1985 // class's protocol, or one of it super classes. This is because,
1986 // the class is going to implement them.
1987 if (I
== SMap
.end() &&
1988 (PrimaryClass
== nullptr ||
1989 !PrimaryClass
->lookupPropertyAccessor(Method
, C
,
1990 Prop
->isClassProperty()))) {
1992 isa
<ObjCCategoryDecl
>(CDecl
)
1993 ? (Prop
->isClassProperty()
1994 ? diag::warn_impl_required_in_category_for_class_property
1995 : diag::warn_setter_getter_impl_required_in_category
)
1996 : (Prop
->isClassProperty()
1997 ? diag::warn_impl_required_for_class_property
1998 : diag::warn_setter_getter_impl_required
);
1999 S
.Diag(IMPDecl
->getLocation(), diag
) << Prop
->getDeclName() << Method
;
2000 S
.Diag(Prop
->getLocation(), diag::note_property_declare
);
2001 if (S
.LangOpts
.ObjCDefaultSynthProperties
&&
2002 S
.LangOpts
.ObjCRuntime
.isNonFragile())
2003 if (ObjCInterfaceDecl
*ID
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
))
2004 if (const ObjCInterfaceDecl
*RID
= ID
->isObjCRequiresPropertyDefs())
2005 S
.Diag(RID
->getLocation(), diag::note_suppressed_class_declare
);
2009 void SemaObjC::DiagnoseUnimplementedProperties(Scope
*S
, ObjCImplDecl
*IMPDecl
,
2010 ObjCContainerDecl
*CDecl
,
2011 bool SynthesizeProperties
) {
2012 ObjCContainerDecl::PropertyMap PropMap
;
2013 ObjCInterfaceDecl
*IDecl
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
);
2015 // Since we don't synthesize class properties, we should emit diagnose even
2016 // if SynthesizeProperties is true.
2017 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap
;
2018 // Gather properties which need not be implemented in this class
2021 if (ObjCCategoryDecl
*C
= dyn_cast
<ObjCCategoryDecl
>(CDecl
)) {
2022 // For categories, no need to implement properties declared in
2023 // its primary class (and its super classes) if property is
2024 // declared in one of those containers.
2025 if ((IDecl
= C
->getClassInterface())) {
2026 IDecl
->collectPropertiesToImplement(NoNeedToImplPropMap
);
2030 CollectSuperClassPropertyImplementations(IDecl
, NoNeedToImplPropMap
);
2032 // When SynthesizeProperties is true, we only check class properties.
2033 CollectImmediateProperties(CDecl
, PropMap
, NoNeedToImplPropMap
,
2034 SynthesizeProperties
/*CollectClassPropsOnly*/);
2036 // Scan the @interface to see if any of the protocols it adopts
2037 // require an explicit implementation, via attribute
2038 // 'objc_protocol_requires_explicit_implementation'.
2040 std::unique_ptr
<ObjCContainerDecl::PropertyMap
> LazyMap
;
2042 for (auto *PDecl
: IDecl
->all_referenced_protocols()) {
2043 if (!PDecl
->hasAttr
<ObjCExplicitProtocolImplAttr
>())
2045 // Lazily construct a set of all the properties in the @interface
2046 // of the class, without looking at the superclass. We cannot
2047 // use the call to CollectImmediateProperties() above as that
2048 // utilizes information from the super class's properties as well
2049 // as scans the adopted protocols. This work only triggers for protocols
2050 // with the attribute, which is very rare, and only occurs when
2051 // analyzing the @implementation.
2053 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap
;
2054 LazyMap
.reset(new ObjCContainerDecl::PropertyMap());
2055 CollectImmediateProperties(CDecl
, *LazyMap
, NoNeedToImplPropMap
,
2056 /* CollectClassPropsOnly */ false,
2057 /* IncludeProtocols */ false);
2059 // Add the properties of 'PDecl' to the list of properties that
2060 // need to be implemented.
2061 for (auto *PropDecl
: PDecl
->properties()) {
2062 if ((*LazyMap
)[std::make_pair(PropDecl
->getIdentifier(),
2063 PropDecl
->isClassProperty())])
2065 PropMap
[std::make_pair(PropDecl
->getIdentifier(),
2066 PropDecl
->isClassProperty())] = PropDecl
;
2071 if (PropMap
.empty())
2074 llvm::DenseSet
<ObjCPropertyDecl
*> PropImplMap
;
2075 for (const auto *I
: IMPDecl
->property_impls())
2076 PropImplMap
.insert(I
->getPropertyDecl());
2078 llvm::SmallPtrSet
<const ObjCMethodDecl
*, 8> InsMap
;
2079 // Collect property accessors implemented in current implementation.
2080 for (const auto *I
: IMPDecl
->methods())
2083 ObjCCategoryDecl
*C
= dyn_cast
<ObjCCategoryDecl
>(CDecl
);
2084 ObjCInterfaceDecl
*PrimaryClass
= nullptr;
2085 if (C
&& !C
->IsClassExtension())
2086 if ((PrimaryClass
= C
->getClassInterface()))
2087 // Report unimplemented properties in the category as well.
2088 if (ObjCImplDecl
*IMP
= PrimaryClass
->getImplementation()) {
2089 // When reporting on missing setter/getters, do not report when
2090 // setter/getter is implemented in category's primary class
2092 for (const auto *I
: IMP
->methods())
2096 for (ObjCContainerDecl::PropertyMap::iterator
2097 P
= PropMap
.begin(), E
= PropMap
.end(); P
!= E
; ++P
) {
2098 ObjCPropertyDecl
*Prop
= P
->second
;
2099 // Is there a matching property synthesize/dynamic?
2100 if (Prop
->isInvalidDecl() ||
2101 Prop
->getPropertyImplementation() == ObjCPropertyDecl::Optional
||
2102 PropImplMap
.count(Prop
) ||
2103 Prop
->getAvailability() == AR_Unavailable
)
2106 // Diagnose unimplemented getters and setters.
2107 DiagnoseUnimplementedAccessor(SemaRef
, PrimaryClass
, Prop
->getGetterName(),
2108 IMPDecl
, CDecl
, C
, Prop
, InsMap
);
2109 if (!Prop
->isReadOnly())
2110 DiagnoseUnimplementedAccessor(SemaRef
, PrimaryClass
,
2111 Prop
->getSetterName(), IMPDecl
, CDecl
, C
,
2116 void SemaObjC::diagnoseNullResettableSynthesizedSetters(
2117 const ObjCImplDecl
*impDecl
) {
2118 for (const auto *propertyImpl
: impDecl
->property_impls()) {
2119 const auto *property
= propertyImpl
->getPropertyDecl();
2120 // Warn about null_resettable properties with synthesized setters,
2121 // because the setter won't properly handle nil.
2122 if (propertyImpl
->getPropertyImplementation() ==
2123 ObjCPropertyImplDecl::Synthesize
&&
2124 (property
->getPropertyAttributes() &
2125 ObjCPropertyAttribute::kind_null_resettable
) &&
2126 property
->getGetterMethodDecl() && property
->getSetterMethodDecl()) {
2127 auto *getterImpl
= propertyImpl
->getGetterMethodDecl();
2128 auto *setterImpl
= propertyImpl
->getSetterMethodDecl();
2129 if ((!getterImpl
|| getterImpl
->isSynthesizedAccessorStub()) &&
2130 (!setterImpl
|| setterImpl
->isSynthesizedAccessorStub())) {
2131 SourceLocation loc
= propertyImpl
->getLocation();
2132 if (loc
.isInvalid())
2133 loc
= impDecl
->getBeginLoc();
2135 Diag(loc
, diag::warn_null_resettable_setter
)
2136 << setterImpl
->getSelector() << property
->getDeclName();
2142 void SemaObjC::AtomicPropertySetterGetterRules(ObjCImplDecl
*IMPDecl
,
2143 ObjCInterfaceDecl
*IDecl
) {
2144 // Rules apply in non-GC mode only
2145 if (getLangOpts().getGC() != LangOptions::NonGC
)
2147 ObjCContainerDecl::PropertyMap PM
;
2148 for (auto *Prop
: IDecl
->properties())
2149 PM
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] = Prop
;
2150 for (const auto *Ext
: IDecl
->known_extensions())
2151 for (auto *Prop
: Ext
->properties())
2152 PM
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] = Prop
;
2154 for (ObjCContainerDecl::PropertyMap::iterator I
= PM
.begin(), E
= PM
.end();
2156 const ObjCPropertyDecl
*Property
= I
->second
;
2157 ObjCMethodDecl
*GetterMethod
= nullptr;
2158 ObjCMethodDecl
*SetterMethod
= nullptr;
2160 unsigned Attributes
= Property
->getPropertyAttributes();
2161 unsigned AttributesAsWritten
= Property
->getPropertyAttributesAsWritten();
2163 if (!(AttributesAsWritten
& ObjCPropertyAttribute::kind_atomic
) &&
2164 !(AttributesAsWritten
& ObjCPropertyAttribute::kind_nonatomic
)) {
2165 GetterMethod
= Property
->isClassProperty() ?
2166 IMPDecl
->getClassMethod(Property
->getGetterName()) :
2167 IMPDecl
->getInstanceMethod(Property
->getGetterName());
2168 SetterMethod
= Property
->isClassProperty() ?
2169 IMPDecl
->getClassMethod(Property
->getSetterName()) :
2170 IMPDecl
->getInstanceMethod(Property
->getSetterName());
2171 if (GetterMethod
&& GetterMethod
->isSynthesizedAccessorStub())
2172 GetterMethod
= nullptr;
2173 if (SetterMethod
&& SetterMethod
->isSynthesizedAccessorStub())
2174 SetterMethod
= nullptr;
2176 Diag(GetterMethod
->getLocation(),
2177 diag::warn_default_atomic_custom_getter_setter
)
2178 << Property
->getIdentifier() << 0;
2179 Diag(Property
->getLocation(), diag::note_property_declare
);
2182 Diag(SetterMethod
->getLocation(),
2183 diag::warn_default_atomic_custom_getter_setter
)
2184 << Property
->getIdentifier() << 1;
2185 Diag(Property
->getLocation(), diag::note_property_declare
);
2189 // We only care about readwrite atomic property.
2190 if ((Attributes
& ObjCPropertyAttribute::kind_nonatomic
) ||
2191 !(Attributes
& ObjCPropertyAttribute::kind_readwrite
))
2193 if (const ObjCPropertyImplDecl
*PIDecl
= IMPDecl
->FindPropertyImplDecl(
2194 Property
->getIdentifier(), Property
->getQueryKind())) {
2195 if (PIDecl
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
)
2197 GetterMethod
= PIDecl
->getGetterMethodDecl();
2198 SetterMethod
= PIDecl
->getSetterMethodDecl();
2199 if (GetterMethod
&& GetterMethod
->isSynthesizedAccessorStub())
2200 GetterMethod
= nullptr;
2201 if (SetterMethod
&& SetterMethod
->isSynthesizedAccessorStub())
2202 SetterMethod
= nullptr;
2203 if ((bool)GetterMethod
^ (bool)SetterMethod
) {
2204 SourceLocation MethodLoc
=
2205 (GetterMethod
? GetterMethod
->getLocation()
2206 : SetterMethod
->getLocation());
2207 Diag(MethodLoc
, diag::warn_atomic_property_rule
)
2208 << Property
->getIdentifier() << (GetterMethod
!= nullptr)
2209 << (SetterMethod
!= nullptr);
2211 if (Property
->getLParenLoc().isValid() &&
2212 !(AttributesAsWritten
& ObjCPropertyAttribute::kind_atomic
)) {
2213 // @property () ... case.
2214 SourceLocation AfterLParen
=
2215 SemaRef
.getLocForEndOfToken(Property
->getLParenLoc());
2216 StringRef NonatomicStr
= AttributesAsWritten
? "nonatomic, "
2218 Diag(Property
->getLocation(),
2219 diag::note_atomic_property_fixup_suggest
)
2220 << FixItHint::CreateInsertion(AfterLParen
, NonatomicStr
);
2221 } else if (Property
->getLParenLoc().isInvalid()) {
2223 SourceLocation startLoc
=
2224 Property
->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
2225 Diag(Property
->getLocation(),
2226 diag::note_atomic_property_fixup_suggest
)
2227 << FixItHint::CreateInsertion(startLoc
, "(nonatomic) ");
2229 Diag(MethodLoc
, diag::note_atomic_property_fixup_suggest
);
2230 Diag(Property
->getLocation(), diag::note_property_declare
);
2236 void SemaObjC::DiagnoseOwningPropertyGetterSynthesis(
2237 const ObjCImplementationDecl
*D
) {
2238 if (getLangOpts().getGC() == LangOptions::GCOnly
)
2241 for (const auto *PID
: D
->property_impls()) {
2242 const ObjCPropertyDecl
*PD
= PID
->getPropertyDecl();
2243 if (PD
&& !PD
->hasAttr
<NSReturnsNotRetainedAttr
>() &&
2244 !PD
->isClassProperty()) {
2245 ObjCMethodDecl
*IM
= PID
->getGetterMethodDecl();
2246 if (IM
&& !IM
->isSynthesizedAccessorStub())
2248 ObjCMethodDecl
*method
= PD
->getGetterMethodDecl();
2251 ObjCMethodFamily family
= method
->getMethodFamily();
2252 if (family
== OMF_alloc
|| family
== OMF_copy
||
2253 family
== OMF_mutableCopy
|| family
== OMF_new
) {
2254 if (getLangOpts().ObjCAutoRefCount
)
2255 Diag(PD
->getLocation(), diag::err_cocoa_naming_owned_rule
);
2257 Diag(PD
->getLocation(), diag::warn_cocoa_naming_owned_rule
);
2259 // Look for a getter explicitly declared alongside the property.
2260 // If we find one, use its location for the note.
2261 SourceLocation noteLoc
= PD
->getLocation();
2262 SourceLocation fixItLoc
;
2263 for (auto *getterRedecl
: method
->redecls()) {
2264 if (getterRedecl
->isImplicit())
2266 if (getterRedecl
->getDeclContext() != PD
->getDeclContext())
2268 noteLoc
= getterRedecl
->getLocation();
2269 fixItLoc
= getterRedecl
->getEndLoc();
2272 Preprocessor
&PP
= SemaRef
.getPreprocessor();
2273 TokenValue tokens
[] = {
2274 tok::kw___attribute
, tok::l_paren
, tok::l_paren
,
2275 PP
.getIdentifierInfo("objc_method_family"), tok::l_paren
,
2276 PP
.getIdentifierInfo("none"), tok::r_paren
,
2277 tok::r_paren
, tok::r_paren
2279 StringRef spelling
= "__attribute__((objc_method_family(none)))";
2280 StringRef macroName
= PP
.getLastMacroWithSpelling(noteLoc
, tokens
);
2281 if (!macroName
.empty())
2282 spelling
= macroName
;
2284 auto noteDiag
= Diag(noteLoc
, diag::note_cocoa_naming_declare_family
)
2285 << method
->getDeclName() << spelling
;
2286 if (fixItLoc
.isValid()) {
2287 SmallString
<64> fixItText(" ");
2288 fixItText
+= spelling
;
2289 noteDiag
<< FixItHint::CreateInsertion(fixItLoc
, fixItText
);
2296 void SemaObjC::DiagnoseMissingDesignatedInitOverrides(
2297 const ObjCImplementationDecl
*ImplD
, const ObjCInterfaceDecl
*IFD
) {
2298 assert(IFD
->hasDesignatedInitializers());
2299 const ObjCInterfaceDecl
*SuperD
= IFD
->getSuperClass();
2303 SelectorSet InitSelSet
;
2304 for (const auto *I
: ImplD
->instance_methods())
2305 if (I
->getMethodFamily() == OMF_init
)
2306 InitSelSet
.insert(I
->getSelector());
2308 SmallVector
<const ObjCMethodDecl
*, 8> DesignatedInits
;
2309 SuperD
->getDesignatedInitializers(DesignatedInits
);
2310 for (SmallVector
<const ObjCMethodDecl
*, 8>::iterator
2311 I
= DesignatedInits
.begin(), E
= DesignatedInits
.end(); I
!= E
; ++I
) {
2312 const ObjCMethodDecl
*MD
= *I
;
2313 if (!InitSelSet
.count(MD
->getSelector())) {
2314 // Don't emit a diagnostic if the overriding method in the subclass is
2315 // marked as unavailable.
2316 bool Ignore
= false;
2317 if (auto *IMD
= IFD
->getInstanceMethod(MD
->getSelector())) {
2318 Ignore
= IMD
->isUnavailable();
2320 // Check the methods declared in the class extensions too.
2321 for (auto *Ext
: IFD
->visible_extensions())
2322 if (auto *IMD
= Ext
->getInstanceMethod(MD
->getSelector())) {
2323 Ignore
= IMD
->isUnavailable();
2328 Diag(ImplD
->getLocation(),
2329 diag::warn_objc_implementation_missing_designated_init_override
)
2330 << MD
->getSelector();
2331 Diag(MD
->getLocation(), diag::note_objc_designated_init_marked_here
);
2337 /// AddPropertyAttrs - Propagates attributes from a property to the
2338 /// implicitly-declared getter or setter for that property.
2339 static void AddPropertyAttrs(Sema
&S
, ObjCMethodDecl
*PropertyMethod
,
2340 ObjCPropertyDecl
*Property
) {
2341 // Should we just clone all attributes over?
2342 for (const auto *A
: Property
->attrs()) {
2343 if (isa
<DeprecatedAttr
>(A
) ||
2344 isa
<UnavailableAttr
>(A
) ||
2345 isa
<AvailabilityAttr
>(A
))
2346 PropertyMethod
->addAttr(A
->clone(S
.Context
));
2350 /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
2351 /// have the property type and issue diagnostics if they don't.
2352 /// Also synthesize a getter/setter method if none exist (and update the
2353 /// appropriate lookup tables.
2354 void SemaObjC::ProcessPropertyDecl(ObjCPropertyDecl
*property
) {
2355 ASTContext
&Context
= getASTContext();
2356 ObjCMethodDecl
*GetterMethod
, *SetterMethod
;
2357 ObjCContainerDecl
*CD
= cast
<ObjCContainerDecl
>(property
->getDeclContext());
2358 if (CD
->isInvalidDecl())
2361 bool IsClassProperty
= property
->isClassProperty();
2362 GetterMethod
= IsClassProperty
?
2363 CD
->getClassMethod(property
->getGetterName()) :
2364 CD
->getInstanceMethod(property
->getGetterName());
2366 // if setter or getter is not found in class extension, it might be
2367 // in the primary class.
2369 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2370 if (CatDecl
->IsClassExtension())
2371 GetterMethod
= IsClassProperty
? CatDecl
->getClassInterface()->
2372 getClassMethod(property
->getGetterName()) :
2373 CatDecl
->getClassInterface()->
2374 getInstanceMethod(property
->getGetterName());
2376 SetterMethod
= IsClassProperty
?
2377 CD
->getClassMethod(property
->getSetterName()) :
2378 CD
->getInstanceMethod(property
->getSetterName());
2380 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2381 if (CatDecl
->IsClassExtension())
2382 SetterMethod
= IsClassProperty
? CatDecl
->getClassInterface()->
2383 getClassMethod(property
->getSetterName()) :
2384 CatDecl
->getClassInterface()->
2385 getInstanceMethod(property
->getSetterName());
2386 DiagnosePropertyAccessorMismatch(property
, GetterMethod
,
2387 property
->getLocation());
2389 // synthesizing accessors must not result in a direct method that is not
2391 if (!GetterMethod
) {
2392 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
)) {
2393 auto *ExistingGetter
= CatDecl
->getClassInterface()->lookupMethod(
2394 property
->getGetterName(), !IsClassProperty
, true, false, CatDecl
);
2395 if (ExistingGetter
) {
2396 if (ExistingGetter
->isDirectMethod() || property
->isDirectProperty()) {
2397 Diag(property
->getLocation(), diag::err_objc_direct_duplicate_decl
)
2398 << property
->isDirectProperty() << 1 /* property */
2399 << ExistingGetter
->isDirectMethod()
2400 << ExistingGetter
->getDeclName();
2401 Diag(ExistingGetter
->getLocation(), diag::note_previous_declaration
);
2407 if (!property
->isReadOnly() && !SetterMethod
) {
2408 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
)) {
2409 auto *ExistingSetter
= CatDecl
->getClassInterface()->lookupMethod(
2410 property
->getSetterName(), !IsClassProperty
, true, false, CatDecl
);
2411 if (ExistingSetter
) {
2412 if (ExistingSetter
->isDirectMethod() || property
->isDirectProperty()) {
2413 Diag(property
->getLocation(), diag::err_objc_direct_duplicate_decl
)
2414 << property
->isDirectProperty() << 1 /* property */
2415 << ExistingSetter
->isDirectMethod()
2416 << ExistingSetter
->getDeclName();
2417 Diag(ExistingSetter
->getLocation(), diag::note_previous_declaration
);
2423 if (!property
->isReadOnly() && SetterMethod
) {
2424 if (Context
.getCanonicalType(SetterMethod
->getReturnType()) !=
2426 Diag(SetterMethod
->getLocation(), diag::err_setter_type_void
);
2427 if (SetterMethod
->param_size() != 1 ||
2428 !Context
.hasSameUnqualifiedType(
2429 (*SetterMethod
->param_begin())->getType().getNonReferenceType(),
2430 property
->getType().getNonReferenceType())) {
2431 Diag(property
->getLocation(),
2432 diag::warn_accessor_property_type_mismatch
)
2433 << property
->getDeclName()
2434 << SetterMethod
->getSelector();
2435 Diag(SetterMethod
->getLocation(), diag::note_declared_at
);
2439 // Synthesize getter/setter methods if none exist.
2440 // Find the default getter and if one not found, add one.
2441 // FIXME: The synthesized property we set here is misleading. We almost always
2442 // synthesize these methods unless the user explicitly provided prototypes
2443 // (which is odd, but allowed). Sema should be typechecking that the
2444 // declarations jive in that situation (which it is not currently).
2445 if (!GetterMethod
) {
2446 // No instance/class method of same name as property getter name was found.
2447 // Declare a getter method and add it to the list of methods
2449 SourceLocation Loc
= property
->getLocation();
2451 // The getter returns the declared property type with all qualifiers
2453 QualType resultTy
= property
->getType().getAtomicUnqualifiedType();
2455 // If the property is null_resettable, the getter returns nonnull.
2456 if (property
->getPropertyAttributes() &
2457 ObjCPropertyAttribute::kind_null_resettable
) {
2458 QualType modifiedTy
= resultTy
;
2459 if (auto nullability
= AttributedType::stripOuterNullability(modifiedTy
)) {
2460 if (*nullability
== NullabilityKind::Unspecified
)
2461 resultTy
= Context
.getAttributedType(NullabilityKind::NonNull
,
2462 modifiedTy
, modifiedTy
);
2466 GetterMethod
= ObjCMethodDecl::Create(
2467 Context
, Loc
, Loc
, property
->getGetterName(), resultTy
, nullptr, CD
,
2468 !IsClassProperty
, /*isVariadic=*/false,
2469 /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
2470 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
2471 (property
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
2472 ? ObjCImplementationControl::Optional
2473 : ObjCImplementationControl::Required
);
2474 CD
->addDecl(GetterMethod
);
2476 AddPropertyAttrs(SemaRef
, GetterMethod
, property
);
2478 if (property
->isDirectProperty())
2479 GetterMethod
->addAttr(ObjCDirectAttr::CreateImplicit(Context
, Loc
));
2481 if (property
->hasAttr
<NSReturnsNotRetainedAttr
>())
2482 GetterMethod
->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context
,
2485 if (property
->hasAttr
<ObjCReturnsInnerPointerAttr
>())
2486 GetterMethod
->addAttr(
2487 ObjCReturnsInnerPointerAttr::CreateImplicit(Context
, Loc
));
2489 if (const SectionAttr
*SA
= property
->getAttr
<SectionAttr
>())
2490 GetterMethod
->addAttr(SectionAttr::CreateImplicit(
2491 Context
, SA
->getName(), Loc
, SectionAttr::GNU_section
));
2493 SemaRef
.ProcessAPINotes(GetterMethod
);
2495 if (getLangOpts().ObjCAutoRefCount
)
2496 CheckARCMethodDecl(GetterMethod
);
2498 // A user declared getter will be synthesize when @synthesize of
2499 // the property with the same name is seen in the @implementation
2500 GetterMethod
->setPropertyAccessor(true);
2502 GetterMethod
->createImplicitParams(Context
,
2503 GetterMethod
->getClassInterface());
2504 property
->setGetterMethodDecl(GetterMethod
);
2506 // Skip setter if property is read-only.
2507 if (!property
->isReadOnly()) {
2508 // Find the default setter and if one not found, add one.
2509 if (!SetterMethod
) {
2510 // No instance/class method of same name as property setter name was
2512 // Declare a setter method and add it to the list of methods
2514 SourceLocation Loc
= property
->getLocation();
2516 SetterMethod
= ObjCMethodDecl::Create(
2517 Context
, Loc
, Loc
, property
->getSetterName(), Context
.VoidTy
, nullptr,
2518 CD
, !IsClassProperty
,
2519 /*isVariadic=*/false,
2520 /*isPropertyAccessor=*/true,
2521 /*isSynthesizedAccessorStub=*/false,
2522 /*isImplicitlyDeclared=*/true,
2523 /*isDefined=*/false,
2524 (property
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
2525 ? ObjCImplementationControl::Optional
2526 : ObjCImplementationControl::Required
);
2528 // Remove all qualifiers from the setter's parameter type.
2530 property
->getType().getUnqualifiedType().getAtomicUnqualifiedType();
2532 // If the property is null_resettable, the setter accepts a
2534 if (property
->getPropertyAttributes() &
2535 ObjCPropertyAttribute::kind_null_resettable
) {
2536 QualType modifiedTy
= paramTy
;
2537 if (auto nullability
= AttributedType::stripOuterNullability(modifiedTy
)){
2538 if (*nullability
== NullabilityKind::Unspecified
)
2539 paramTy
= Context
.getAttributedType(NullabilityKind::Nullable
,
2540 modifiedTy
, modifiedTy
);
2544 // Invent the arguments for the setter. We don't bother making a
2545 // nice name for the argument.
2546 ParmVarDecl
*Argument
= ParmVarDecl::Create(Context
, SetterMethod
,
2548 property
->getIdentifier(),
2553 SetterMethod
->setMethodParams(Context
, Argument
, {});
2555 AddPropertyAttrs(SemaRef
, SetterMethod
, property
);
2557 if (property
->isDirectProperty())
2558 SetterMethod
->addAttr(ObjCDirectAttr::CreateImplicit(Context
, Loc
));
2560 CD
->addDecl(SetterMethod
);
2561 if (const SectionAttr
*SA
= property
->getAttr
<SectionAttr
>())
2562 SetterMethod
->addAttr(SectionAttr::CreateImplicit(
2563 Context
, SA
->getName(), Loc
, SectionAttr::GNU_section
));
2565 SemaRef
.ProcessAPINotes(SetterMethod
);
2567 // It's possible for the user to have set a very odd custom
2568 // setter selector that causes it to have a method family.
2569 if (getLangOpts().ObjCAutoRefCount
)
2570 CheckARCMethodDecl(SetterMethod
);
2572 // A user declared setter will be synthesize when @synthesize of
2573 // the property with the same name is seen in the @implementation
2574 SetterMethod
->setPropertyAccessor(true);
2576 SetterMethod
->createImplicitParams(Context
,
2577 SetterMethod
->getClassInterface());
2578 property
->setSetterMethodDecl(SetterMethod
);
2580 // Add any synthesized methods to the global pool. This allows us to
2581 // handle the following, which is supported by GCC (and part of the design).
2584 // @property double bar;
2587 // void thisIsUnfortunate() {
2589 // double bar = [foo bar];
2592 if (!IsClassProperty
) {
2594 AddInstanceMethodToGlobalPool(GetterMethod
);
2596 AddInstanceMethodToGlobalPool(SetterMethod
);
2599 AddFactoryMethodToGlobalPool(GetterMethod
);
2601 AddFactoryMethodToGlobalPool(SetterMethod
);
2604 ObjCInterfaceDecl
*CurrentClass
= dyn_cast
<ObjCInterfaceDecl
>(CD
);
2605 if (!CurrentClass
) {
2606 if (ObjCCategoryDecl
*Cat
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2607 CurrentClass
= Cat
->getClassInterface();
2608 else if (ObjCImplDecl
*Impl
= dyn_cast
<ObjCImplDecl
>(CD
))
2609 CurrentClass
= Impl
->getClassInterface();
2612 CheckObjCMethodOverrides(GetterMethod
, CurrentClass
, SemaObjC::RTC_Unknown
);
2614 CheckObjCMethodOverrides(SetterMethod
, CurrentClass
, SemaObjC::RTC_Unknown
);
2617 void SemaObjC::CheckObjCPropertyAttributes(Decl
*PDecl
, SourceLocation Loc
,
2618 unsigned &Attributes
,
2619 bool propertyInPrimaryClass
) {
2620 // FIXME: Improve the reported location.
2621 if (!PDecl
|| PDecl
->isInvalidDecl())
2624 if ((Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2625 (Attributes
& ObjCPropertyAttribute::kind_readwrite
))
2626 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2627 << "readonly" << "readwrite";
2629 ObjCPropertyDecl
*PropertyDecl
= cast
<ObjCPropertyDecl
>(PDecl
);
2630 QualType PropertyTy
= PropertyDecl
->getType();
2632 // Check for copy or retain on non-object types.
2634 (ObjCPropertyAttribute::kind_weak
| ObjCPropertyAttribute::kind_copy
|
2635 ObjCPropertyAttribute::kind_retain
|
2636 ObjCPropertyAttribute::kind_strong
)) &&
2637 !PropertyTy
->isObjCRetainableType() &&
2638 !PropertyDecl
->hasAttr
<ObjCNSObjectAttr
>()) {
2639 Diag(Loc
, diag::err_objc_property_requires_object
)
2640 << (Attributes
& ObjCPropertyAttribute::kind_weak
2642 : Attributes
& ObjCPropertyAttribute::kind_copy
2644 : "retain (or strong)");
2646 ~(ObjCPropertyAttribute::kind_weak
| ObjCPropertyAttribute::kind_copy
|
2647 ObjCPropertyAttribute::kind_retain
|
2648 ObjCPropertyAttribute::kind_strong
);
2649 PropertyDecl
->setInvalidDecl();
2652 // Check for assign on object types.
2653 if ((Attributes
& ObjCPropertyAttribute::kind_assign
) &&
2654 !(Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
) &&
2655 PropertyTy
->isObjCRetainableType() &&
2656 !PropertyTy
->isObjCARCImplicitlyUnretainedType()) {
2657 Diag(Loc
, diag::warn_objc_property_assign_on_object
);
2660 // Check for more than one of { assign, copy, retain }.
2661 if (Attributes
& ObjCPropertyAttribute::kind_assign
) {
2662 if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2663 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2664 << "assign" << "copy";
2665 Attributes
&= ~ObjCPropertyAttribute::kind_copy
;
2667 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2668 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2669 << "assign" << "retain";
2670 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2672 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2673 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2674 << "assign" << "strong";
2675 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2677 if (getLangOpts().ObjCAutoRefCount
&&
2678 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2679 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2680 << "assign" << "weak";
2681 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2683 if (PropertyDecl
->hasAttr
<IBOutletCollectionAttr
>())
2684 Diag(Loc
, diag::warn_iboutletcollection_property_assign
);
2685 } else if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
) {
2686 if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2687 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2688 << "unsafe_unretained" << "copy";
2689 Attributes
&= ~ObjCPropertyAttribute::kind_copy
;
2691 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2692 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2693 << "unsafe_unretained" << "retain";
2694 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2696 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2697 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2698 << "unsafe_unretained" << "strong";
2699 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2701 if (getLangOpts().ObjCAutoRefCount
&&
2702 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2703 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2704 << "unsafe_unretained" << "weak";
2705 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2707 } else if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2708 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2709 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2710 << "copy" << "retain";
2711 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2713 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2714 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2715 << "copy" << "strong";
2716 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2718 if (Attributes
& ObjCPropertyAttribute::kind_weak
) {
2719 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2720 << "copy" << "weak";
2721 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2723 } else if ((Attributes
& ObjCPropertyAttribute::kind_retain
) &&
2724 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2725 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "retain"
2727 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2728 } else if ((Attributes
& ObjCPropertyAttribute::kind_strong
) &&
2729 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2730 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "strong"
2732 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2735 if (Attributes
& ObjCPropertyAttribute::kind_weak
) {
2736 // 'weak' and 'nonnull' are mutually exclusive.
2737 if (auto nullability
= PropertyTy
->getNullability()) {
2738 if (*nullability
== NullabilityKind::NonNull
)
2739 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2740 << "nonnull" << "weak";
2744 if ((Attributes
& ObjCPropertyAttribute::kind_atomic
) &&
2745 (Attributes
& ObjCPropertyAttribute::kind_nonatomic
)) {
2746 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "atomic"
2748 Attributes
&= ~ObjCPropertyAttribute::kind_atomic
;
2751 // Warn if user supplied no assignment attribute, property is
2752 // readwrite, and this is an object type.
2753 if (!getOwnershipRule(Attributes
) && PropertyTy
->isObjCRetainableType()) {
2754 if (Attributes
& ObjCPropertyAttribute::kind_readonly
) {
2756 } else if (getLangOpts().ObjCAutoRefCount
) {
2757 // With arc, @property definitions should default to strong when
2759 PropertyDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
2760 } else if (PropertyTy
->isObjCObjectPointerType()) {
2761 bool isAnyClassTy
= (PropertyTy
->isObjCClassType() ||
2762 PropertyTy
->isObjCQualifiedClassType());
2763 // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
2764 // issue any warning.
2765 if (isAnyClassTy
&& getLangOpts().getGC() == LangOptions::NonGC
)
2767 else if (propertyInPrimaryClass
) {
2768 // Don't issue warning on property with no life time in class
2769 // extension as it is inherited from property in primary class.
2770 // Skip this warning in gc-only mode.
2771 if (getLangOpts().getGC() != LangOptions::GCOnly
)
2772 Diag(Loc
, diag::warn_objc_property_no_assignment_attribute
);
2774 // If non-gc code warn that this is likely inappropriate.
2775 if (getLangOpts().getGC() == LangOptions::NonGC
)
2776 Diag(Loc
, diag::warn_objc_property_default_assign_on_object
);
2780 // FIXME: Implement warning dependent on NSCopying being
2784 if (!(Attributes
& ObjCPropertyAttribute::kind_copy
) &&
2785 !(Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2786 getLangOpts().getGC() == LangOptions::GCOnly
&&
2787 PropertyTy
->isBlockPointerType())
2788 Diag(Loc
, diag::warn_objc_property_copy_missing_on_block
);
2789 else if ((Attributes
& ObjCPropertyAttribute::kind_retain
) &&
2790 !(Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2791 !(Attributes
& ObjCPropertyAttribute::kind_strong
) &&
2792 PropertyTy
->isBlockPointerType())
2793 Diag(Loc
, diag::warn_objc_property_retain_of_block
);
2795 if ((Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2796 (Attributes
& ObjCPropertyAttribute::kind_setter
))
2797 Diag(Loc
, diag::warn_objc_readonly_property_has_setter
);