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/Sema/SemaInternal.h"
15 #include "clang/AST/ASTMutationListener.h"
16 #include "clang/AST/DeclObjC.h"
17 #include "clang/AST/ExprCXX.h"
18 #include "clang/AST/ExprObjC.h"
19 #include "clang/Basic/SourceManager.h"
20 #include "clang/Lex/Lexer.h"
21 #include "clang/Lex/Preprocessor.h"
22 #include "clang/Sema/Initialization.h"
23 #include "llvm/ADT/DenseSet.h"
24 #include "llvm/ADT/SmallString.h"
26 using namespace clang
;
28 //===----------------------------------------------------------------------===//
30 //===----------------------------------------------------------------------===//
32 /// getImpliedARCOwnership - Given a set of property attributes and a
33 /// type, infer an expected lifetime. The type's ownership qualification
34 /// is not considered.
36 /// Returns OCL_None if the attributes as stated do not imply an ownership.
37 /// Never returns OCL_Autoreleasing.
38 static Qualifiers::ObjCLifetime
39 getImpliedARCOwnership(ObjCPropertyAttribute::Kind attrs
, QualType type
) {
40 // retain, strong, copy, weak, and unsafe_unretained are only legal
41 // on properties of retainable pointer type.
43 (ObjCPropertyAttribute::kind_retain
| ObjCPropertyAttribute::kind_strong
|
44 ObjCPropertyAttribute::kind_copy
)) {
45 return Qualifiers::OCL_Strong
;
46 } else if (attrs
& ObjCPropertyAttribute::kind_weak
) {
47 return Qualifiers::OCL_Weak
;
48 } else if (attrs
& ObjCPropertyAttribute::kind_unsafe_unretained
) {
49 return Qualifiers::OCL_ExplicitNone
;
52 // assign can appear on other types, so we have to check the
54 if (attrs
& ObjCPropertyAttribute::kind_assign
&&
55 type
->isObjCRetainableType()) {
56 return Qualifiers::OCL_ExplicitNone
;
59 return Qualifiers::OCL_None
;
62 /// Check the internal consistency of a property declaration with
63 /// an explicit ownership qualifier.
64 static void checkPropertyDeclWithOwnership(Sema
&S
,
65 ObjCPropertyDecl
*property
) {
66 if (property
->isInvalidDecl()) return;
68 ObjCPropertyAttribute::Kind propertyKind
= property
->getPropertyAttributes();
69 Qualifiers::ObjCLifetime propertyLifetime
70 = property
->getType().getObjCLifetime();
72 assert(propertyLifetime
!= Qualifiers::OCL_None
);
74 Qualifiers::ObjCLifetime expectedLifetime
75 = getImpliedARCOwnership(propertyKind
, property
->getType());
76 if (!expectedLifetime
) {
77 // We have a lifetime qualifier but no dominating property
78 // attribute. That's okay, but restore reasonable invariants by
79 // setting the property attribute according to the lifetime
81 ObjCPropertyAttribute::Kind attr
;
82 if (propertyLifetime
== Qualifiers::OCL_Strong
) {
83 attr
= ObjCPropertyAttribute::kind_strong
;
84 } else if (propertyLifetime
== Qualifiers::OCL_Weak
) {
85 attr
= ObjCPropertyAttribute::kind_weak
;
87 assert(propertyLifetime
== Qualifiers::OCL_ExplicitNone
);
88 attr
= ObjCPropertyAttribute::kind_unsafe_unretained
;
90 property
->setPropertyAttributes(attr
);
94 if (propertyLifetime
== expectedLifetime
) return;
96 property
->setInvalidDecl();
97 S
.Diag(property
->getLocation(),
98 diag::err_arc_inconsistent_property_ownership
)
99 << property
->getDeclName()
104 /// Check this Objective-C property against a property declared in the
107 CheckPropertyAgainstProtocol(Sema
&S
, ObjCPropertyDecl
*Prop
,
108 ObjCProtocolDecl
*Proto
,
109 llvm::SmallPtrSetImpl
<ObjCProtocolDecl
*> &Known
) {
110 // Have we seen this protocol before?
111 if (!Known
.insert(Proto
).second
)
114 // Look for a property with the same name.
115 if (ObjCPropertyDecl
*ProtoProp
= Proto
->getProperty(
116 Prop
->getIdentifier(), Prop
->isInstanceProperty())) {
117 S
.DiagnosePropertyMismatch(Prop
, ProtoProp
, Proto
->getIdentifier(), true);
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
*Sema::ActOnProperty(Scope
*S
, SourceLocation AtLoc
,
173 SourceLocation LParenLoc
,
178 tok::ObjCKeywordKind MethodImplKind
,
179 DeclContext
*lexicalDC
) {
180 unsigned Attributes
= ODS
.getPropertyAttributes();
181 FD
.D
.setObjCWeakProperty((Attributes
& ObjCPropertyAttribute::kind_weak
) !=
183 TypeSourceInfo
*TSI
= GetTypeForDeclarator(FD
.D
, S
);
184 QualType T
= TSI
->getType();
185 if (!getOwnershipRule(Attributes
)) {
186 Attributes
|= deducePropertyOwnershipFromType(*this, T
);
188 bool isReadWrite
= ((Attributes
& ObjCPropertyAttribute::kind_readwrite
) ||
189 // default is readwrite!
190 !(Attributes
& ObjCPropertyAttribute::kind_readonly
));
192 // Proceed with constructing the ObjCPropertyDecls.
193 ObjCContainerDecl
*ClassDecl
= cast
<ObjCContainerDecl
>(CurContext
);
194 ObjCPropertyDecl
*Res
= nullptr;
195 if (ObjCCategoryDecl
*CDecl
= dyn_cast
<ObjCCategoryDecl
>(ClassDecl
)) {
196 if (CDecl
->IsClassExtension()) {
197 Res
= HandlePropertyInClassExtension(S
, AtLoc
, LParenLoc
,
199 GetterSel
, ODS
.getGetterNameLoc(),
200 SetterSel
, ODS
.getSetterNameLoc(),
201 isReadWrite
, Attributes
,
202 ODS
.getPropertyAttributes(),
203 T
, TSI
, MethodImplKind
);
210 Res
= CreatePropertyDecl(S
, ClassDecl
, AtLoc
, LParenLoc
, FD
,
211 GetterSel
, ODS
.getGetterNameLoc(), SetterSel
,
212 ODS
.getSetterNameLoc(), isReadWrite
, Attributes
,
213 ODS
.getPropertyAttributes(), T
, TSI
,
216 Res
->setLexicalDeclContext(lexicalDC
);
219 // Validate the attributes on the @property.
220 CheckObjCPropertyAttributes(Res
, AtLoc
, Attributes
,
221 (isa
<ObjCInterfaceDecl
>(ClassDecl
) ||
222 isa
<ObjCProtocolDecl
>(ClassDecl
)));
224 // Check consistency if the type has explicit ownership qualification.
225 if (Res
->getType().getObjCLifetime())
226 checkPropertyDeclWithOwnership(*this, Res
);
228 llvm::SmallPtrSet
<ObjCProtocolDecl
*, 16> KnownProtos
;
229 if (ObjCInterfaceDecl
*IFace
= dyn_cast
<ObjCInterfaceDecl
>(ClassDecl
)) {
230 // For a class, compare the property against a property in our superclass.
231 bool FoundInSuper
= false;
232 ObjCInterfaceDecl
*CurrentInterfaceDecl
= IFace
;
233 while (ObjCInterfaceDecl
*Super
= CurrentInterfaceDecl
->getSuperClass()) {
234 if (ObjCPropertyDecl
*SuperProp
= Super
->getProperty(
235 Res
->getIdentifier(), Res
->isInstanceProperty())) {
236 DiagnosePropertyMismatch(Res
, SuperProp
, Super
->getIdentifier(), false);
240 CurrentInterfaceDecl
= Super
;
244 // Also compare the property against a property in our protocols.
245 for (auto *P
: CurrentInterfaceDecl
->protocols()) {
246 CheckPropertyAgainstProtocol(*this, Res
, P
, KnownProtos
);
249 // Slower path: look in all protocols we referenced.
250 for (auto *P
: IFace
->all_referenced_protocols()) {
251 CheckPropertyAgainstProtocol(*this, Res
, P
, KnownProtos
);
254 } else if (ObjCCategoryDecl
*Cat
= dyn_cast
<ObjCCategoryDecl
>(ClassDecl
)) {
255 // We don't check if class extension. Because properties in class extension
256 // are meant to override some of the attributes and checking has already done
257 // when property in class extension is constructed.
258 if (!Cat
->IsClassExtension())
259 for (auto *P
: Cat
->protocols())
260 CheckPropertyAgainstProtocol(*this, Res
, P
, KnownProtos
);
262 ObjCProtocolDecl
*Proto
= cast
<ObjCProtocolDecl
>(ClassDecl
);
263 for (auto *P
: Proto
->protocols())
264 CheckPropertyAgainstProtocol(*this, Res
, P
, KnownProtos
);
267 ActOnDocumentableDecl(Res
);
271 static ObjCPropertyAttribute::Kind
272 makePropertyAttributesAsWritten(unsigned Attributes
) {
273 unsigned attributesAsWritten
= 0;
274 if (Attributes
& ObjCPropertyAttribute::kind_readonly
)
275 attributesAsWritten
|= ObjCPropertyAttribute::kind_readonly
;
276 if (Attributes
& ObjCPropertyAttribute::kind_readwrite
)
277 attributesAsWritten
|= ObjCPropertyAttribute::kind_readwrite
;
278 if (Attributes
& ObjCPropertyAttribute::kind_getter
)
279 attributesAsWritten
|= ObjCPropertyAttribute::kind_getter
;
280 if (Attributes
& ObjCPropertyAttribute::kind_setter
)
281 attributesAsWritten
|= ObjCPropertyAttribute::kind_setter
;
282 if (Attributes
& ObjCPropertyAttribute::kind_assign
)
283 attributesAsWritten
|= ObjCPropertyAttribute::kind_assign
;
284 if (Attributes
& ObjCPropertyAttribute::kind_retain
)
285 attributesAsWritten
|= ObjCPropertyAttribute::kind_retain
;
286 if (Attributes
& ObjCPropertyAttribute::kind_strong
)
287 attributesAsWritten
|= ObjCPropertyAttribute::kind_strong
;
288 if (Attributes
& ObjCPropertyAttribute::kind_weak
)
289 attributesAsWritten
|= ObjCPropertyAttribute::kind_weak
;
290 if (Attributes
& ObjCPropertyAttribute::kind_copy
)
291 attributesAsWritten
|= ObjCPropertyAttribute::kind_copy
;
292 if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
)
293 attributesAsWritten
|= ObjCPropertyAttribute::kind_unsafe_unretained
;
294 if (Attributes
& ObjCPropertyAttribute::kind_nonatomic
)
295 attributesAsWritten
|= ObjCPropertyAttribute::kind_nonatomic
;
296 if (Attributes
& ObjCPropertyAttribute::kind_atomic
)
297 attributesAsWritten
|= ObjCPropertyAttribute::kind_atomic
;
298 if (Attributes
& ObjCPropertyAttribute::kind_class
)
299 attributesAsWritten
|= ObjCPropertyAttribute::kind_class
;
300 if (Attributes
& ObjCPropertyAttribute::kind_direct
)
301 attributesAsWritten
|= ObjCPropertyAttribute::kind_direct
;
303 return (ObjCPropertyAttribute::Kind
)attributesAsWritten
;
306 static bool LocPropertyAttribute( ASTContext
&Context
, const char *attrName
,
307 SourceLocation LParenLoc
, SourceLocation
&Loc
) {
308 if (LParenLoc
.isMacroID())
311 SourceManager
&SM
= Context
.getSourceManager();
312 std::pair
<FileID
, unsigned> locInfo
= SM
.getDecomposedLoc(LParenLoc
);
313 // Try to load the file buffer.
314 bool invalidTemp
= false;
315 StringRef file
= SM
.getBufferData(locInfo
.first
, &invalidTemp
);
318 const char *tokenBegin
= file
.data() + locInfo
.second
;
320 // Lex from the start of the given location.
321 Lexer
lexer(SM
.getLocForStartOfFile(locInfo
.first
),
322 Context
.getLangOpts(),
323 file
.begin(), tokenBegin
, file
.end());
326 lexer
.LexFromRawLexer(Tok
);
327 if (Tok
.is(tok::raw_identifier
) && Tok
.getRawIdentifier() == attrName
) {
328 Loc
= Tok
.getLocation();
331 } while (Tok
.isNot(tok::r_paren
));
335 /// Check for a mismatch in the atomicity of the given properties.
336 static void checkAtomicPropertyMismatch(Sema
&S
,
337 ObjCPropertyDecl
*OldProperty
,
338 ObjCPropertyDecl
*NewProperty
,
339 bool PropagateAtomicity
) {
340 // If the atomicity of both matches, we're done.
341 bool OldIsAtomic
= (OldProperty
->getPropertyAttributes() &
342 ObjCPropertyAttribute::kind_nonatomic
) == 0;
343 bool NewIsAtomic
= (NewProperty
->getPropertyAttributes() &
344 ObjCPropertyAttribute::kind_nonatomic
) == 0;
345 if (OldIsAtomic
== NewIsAtomic
) return;
347 // Determine whether the given property is readonly and implicitly
349 auto isImplicitlyReadonlyAtomic
= [](ObjCPropertyDecl
*Property
) -> bool {
351 auto Attrs
= Property
->getPropertyAttributes();
352 if ((Attrs
& ObjCPropertyAttribute::kind_readonly
) == 0)
356 if (Attrs
& ObjCPropertyAttribute::kind_nonatomic
)
359 // Was 'atomic' specified directly?
360 if (Property
->getPropertyAttributesAsWritten() &
361 ObjCPropertyAttribute::kind_atomic
)
367 // If we're allowed to propagate atomicity, and the new property did
368 // not specify atomicity at all, propagate.
369 const unsigned AtomicityMask
= (ObjCPropertyAttribute::kind_atomic
|
370 ObjCPropertyAttribute::kind_nonatomic
);
371 if (PropagateAtomicity
&&
372 ((NewProperty
->getPropertyAttributesAsWritten() & AtomicityMask
) == 0)) {
373 unsigned Attrs
= NewProperty
->getPropertyAttributes();
374 Attrs
= Attrs
& ~AtomicityMask
;
376 Attrs
|= ObjCPropertyAttribute::kind_atomic
;
378 Attrs
|= ObjCPropertyAttribute::kind_nonatomic
;
380 NewProperty
->overwritePropertyAttributes(Attrs
);
384 // One of the properties is atomic; if it's a readonly property, and
385 // 'atomic' wasn't explicitly specified, we're okay.
386 if ((OldIsAtomic
&& isImplicitlyReadonlyAtomic(OldProperty
)) ||
387 (NewIsAtomic
&& isImplicitlyReadonlyAtomic(NewProperty
)))
390 // Diagnose the conflict.
391 const IdentifierInfo
*OldContextName
;
392 auto *OldDC
= OldProperty
->getDeclContext();
393 if (auto Category
= dyn_cast
<ObjCCategoryDecl
>(OldDC
))
394 OldContextName
= Category
->getClassInterface()->getIdentifier();
396 OldContextName
= cast
<ObjCContainerDecl
>(OldDC
)->getIdentifier();
398 S
.Diag(NewProperty
->getLocation(), diag::warn_property_attribute
)
399 << NewProperty
->getDeclName() << "atomic"
401 S
.Diag(OldProperty
->getLocation(), diag::note_property_declare
);
405 Sema::HandlePropertyInClassExtension(Scope
*S
,
406 SourceLocation AtLoc
,
407 SourceLocation LParenLoc
,
410 SourceLocation GetterNameLoc
,
412 SourceLocation SetterNameLoc
,
413 const bool isReadWrite
,
414 unsigned &Attributes
,
415 const unsigned AttributesAsWritten
,
418 tok::ObjCKeywordKind MethodImplKind
) {
419 ObjCCategoryDecl
*CDecl
= cast
<ObjCCategoryDecl
>(CurContext
);
420 // Diagnose if this property is already in continuation class.
421 DeclContext
*DC
= CurContext
;
422 IdentifierInfo
*PropertyId
= FD
.D
.getIdentifier();
423 ObjCInterfaceDecl
*CCPrimary
= CDecl
->getClassInterface();
425 // We need to look in the @interface to see if the @property was
428 Diag(CDecl
->getLocation(), diag::err_continuation_class
);
432 bool isClassProperty
=
433 (AttributesAsWritten
& ObjCPropertyAttribute::kind_class
) ||
434 (Attributes
& ObjCPropertyAttribute::kind_class
);
436 // Find the property in the extended class's primary class or
438 ObjCPropertyDecl
*PIDecl
= CCPrimary
->FindPropertyVisibleInPrimaryClass(
439 PropertyId
, ObjCPropertyDecl::getQueryKind(isClassProperty
));
441 // If we found a property in an extension, complain.
442 if (PIDecl
&& isa
<ObjCCategoryDecl
>(PIDecl
->getDeclContext())) {
443 Diag(AtLoc
, diag::err_duplicate_property
);
444 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
448 // Check for consistency with the previous declaration, if there is one.
450 // A readonly property declared in the primary class can be refined
451 // by adding a readwrite property within an extension.
452 // Anything else is an error.
453 if (!(PIDecl
->isReadOnly() && isReadWrite
)) {
454 // Tailor the diagnostics for the common case where a readwrite
455 // property is declared both in the @interface and the continuation.
456 // This is a common error where the user often intended the original
457 // declaration to be readonly.
459 (Attributes
& ObjCPropertyAttribute::kind_readwrite
) &&
460 (PIDecl
->getPropertyAttributesAsWritten() &
461 ObjCPropertyAttribute::kind_readwrite
)
462 ? diag::err_use_continuation_class_redeclaration_readwrite
463 : diag::err_use_continuation_class
;
465 << CCPrimary
->getDeclName();
466 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
470 // Check for consistency of getters.
471 if (PIDecl
->getGetterName() != GetterSel
) {
472 // If the getter was written explicitly, complain.
473 if (AttributesAsWritten
& ObjCPropertyAttribute::kind_getter
) {
474 Diag(AtLoc
, diag::warn_property_redecl_getter_mismatch
)
475 << PIDecl
->getGetterName() << GetterSel
;
476 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
479 // Always adopt the getter from the original declaration.
480 GetterSel
= PIDecl
->getGetterName();
481 Attributes
|= ObjCPropertyAttribute::kind_getter
;
484 // Check consistency of ownership.
485 unsigned ExistingOwnership
486 = getOwnershipRule(PIDecl
->getPropertyAttributes());
487 unsigned NewOwnership
= getOwnershipRule(Attributes
);
488 if (ExistingOwnership
&& NewOwnership
!= ExistingOwnership
) {
489 // If the ownership was written explicitly, complain.
490 if (getOwnershipRule(AttributesAsWritten
)) {
491 Diag(AtLoc
, diag::warn_property_attr_mismatch
);
492 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
495 // Take the ownership from the original property.
496 Attributes
= (Attributes
& ~OwnershipMask
) | ExistingOwnership
;
499 // If the redeclaration is 'weak' but the original property is not,
500 if ((Attributes
& ObjCPropertyAttribute::kind_weak
) &&
501 !(PIDecl
->getPropertyAttributesAsWritten() &
502 ObjCPropertyAttribute::kind_weak
) &&
503 PIDecl
->getType()->getAs
<ObjCObjectPointerType
>() &&
504 PIDecl
->getType().getObjCLifetime() == Qualifiers::OCL_None
) {
505 Diag(AtLoc
, diag::warn_property_implicitly_mismatched
);
506 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
510 // Create a new ObjCPropertyDecl with the DeclContext being
511 // the class extension.
512 ObjCPropertyDecl
*PDecl
= CreatePropertyDecl(S
, CDecl
, AtLoc
, LParenLoc
,
513 FD
, GetterSel
, GetterNameLoc
,
514 SetterSel
, SetterNameLoc
,
516 Attributes
, AttributesAsWritten
,
517 T
, TSI
, MethodImplKind
, DC
);
519 // If there was no declaration of a property with the same name in
520 // the primary class, we're done.
522 ProcessPropertyDecl(PDecl
);
526 if (!Context
.hasSameType(PIDecl
->getType(), PDecl
->getType())) {
527 bool IncompatibleObjC
= false;
528 QualType ConvertedType
;
529 // Relax the strict type matching for property type in continuation class.
530 // Allow property object type of continuation class to be different as long
531 // as it narrows the object type in its primary class property. Note that
532 // this conversion is safe only because the wider type is for a 'readonly'
533 // property in primary class and 'narrowed' type for a 'readwrite' property
534 // in continuation class.
535 QualType PrimaryClassPropertyT
= Context
.getCanonicalType(PIDecl
->getType());
536 QualType ClassExtPropertyT
= Context
.getCanonicalType(PDecl
->getType());
537 if (!isa
<ObjCObjectPointerType
>(PrimaryClassPropertyT
) ||
538 !isa
<ObjCObjectPointerType
>(ClassExtPropertyT
) ||
539 (!isObjCPointerConversion(ClassExtPropertyT
, PrimaryClassPropertyT
,
540 ConvertedType
, IncompatibleObjC
))
541 || IncompatibleObjC
) {
543 diag::err_type_mismatch_continuation_class
) << PDecl
->getType();
544 Diag(PIDecl
->getLocation(), diag::note_property_declare
);
549 // Check that atomicity of property in class extension matches the previous
551 checkAtomicPropertyMismatch(*this, PIDecl
, PDecl
, true);
553 // Make sure getter/setter are appropriately synthesized.
554 ProcessPropertyDecl(PDecl
);
558 ObjCPropertyDecl
*Sema::CreatePropertyDecl(Scope
*S
,
559 ObjCContainerDecl
*CDecl
,
560 SourceLocation AtLoc
,
561 SourceLocation LParenLoc
,
564 SourceLocation GetterNameLoc
,
566 SourceLocation SetterNameLoc
,
567 const bool isReadWrite
,
568 const unsigned Attributes
,
569 const unsigned AttributesAsWritten
,
571 TypeSourceInfo
*TInfo
,
572 tok::ObjCKeywordKind MethodImplKind
,
573 DeclContext
*lexicalDC
){
574 IdentifierInfo
*PropertyId
= FD
.D
.getIdentifier();
576 // Property defaults to 'assign' if it is readwrite, unless this is ARC
577 // and the type is retainable.
579 if (Attributes
& (ObjCPropertyAttribute::kind_assign
|
580 ObjCPropertyAttribute::kind_unsafe_unretained
)) {
582 } else if (getOwnershipRule(Attributes
) || !isReadWrite
) {
585 isAssign
= (!getLangOpts().ObjCAutoRefCount
||
586 !T
->isObjCRetainableType());
589 // Issue a warning if property is 'assign' as default and its
590 // object, which is gc'able conforms to NSCopying protocol
591 if (getLangOpts().getGC() != LangOptions::NonGC
&& isAssign
&&
592 !(Attributes
& ObjCPropertyAttribute::kind_assign
)) {
593 if (const ObjCObjectPointerType
*ObjPtrTy
=
594 T
->getAs
<ObjCObjectPointerType
>()) {
595 ObjCInterfaceDecl
*IDecl
= ObjPtrTy
->getObjectType()->getInterface();
597 if (ObjCProtocolDecl
* PNSCopying
=
598 LookupProtocol(&Context
.Idents
.get("NSCopying"), AtLoc
))
599 if (IDecl
->ClassImplementsProtocol(PNSCopying
, true))
600 Diag(AtLoc
, diag::warn_implements_nscopying
) << PropertyId
;
604 if (T
->isObjCObjectType()) {
605 SourceLocation StarLoc
= TInfo
->getTypeLoc().getEndLoc();
606 StarLoc
= getLocForEndOfToken(StarLoc
);
607 Diag(FD
.D
.getIdentifierLoc(), diag::err_statically_allocated_object
)
608 << FixItHint::CreateInsertion(StarLoc
, "*");
609 T
= Context
.getObjCObjectPointerType(T
);
610 SourceLocation TLoc
= TInfo
->getTypeLoc().getBeginLoc();
611 TInfo
= Context
.getTrivialTypeSourceInfo(T
, TLoc
);
614 DeclContext
*DC
= CDecl
;
615 ObjCPropertyDecl
*PDecl
= ObjCPropertyDecl::Create(Context
, DC
,
616 FD
.D
.getIdentifierLoc(),
618 LParenLoc
, T
, TInfo
);
620 bool isClassProperty
=
621 (AttributesAsWritten
& ObjCPropertyAttribute::kind_class
) ||
622 (Attributes
& ObjCPropertyAttribute::kind_class
);
623 // Class property and instance property can have the same name.
624 if (ObjCPropertyDecl
*prevDecl
= ObjCPropertyDecl::findPropertyDecl(
625 DC
, PropertyId
, ObjCPropertyDecl::getQueryKind(isClassProperty
))) {
626 Diag(PDecl
->getLocation(), diag::err_duplicate_property
);
627 Diag(prevDecl
->getLocation(), diag::note_property_declare
);
628 PDecl
->setInvalidDecl();
633 PDecl
->setLexicalDeclContext(lexicalDC
);
636 if (T
->isArrayType() || T
->isFunctionType()) {
637 Diag(AtLoc
, diag::err_property_type
) << T
;
638 PDecl
->setInvalidDecl();
641 ProcessDeclAttributes(S
, PDecl
, FD
.D
);
643 // Regardless of setter/getter attribute, we save the default getter/setter
644 // selector names in anticipation of declaration of setter/getter methods.
645 PDecl
->setGetterName(GetterSel
, GetterNameLoc
);
646 PDecl
->setSetterName(SetterSel
, SetterNameLoc
);
647 PDecl
->setPropertyAttributesAsWritten(
648 makePropertyAttributesAsWritten(AttributesAsWritten
));
650 if (Attributes
& ObjCPropertyAttribute::kind_readonly
)
651 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly
);
653 if (Attributes
& ObjCPropertyAttribute::kind_getter
)
654 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_getter
);
656 if (Attributes
& ObjCPropertyAttribute::kind_setter
)
657 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_setter
);
660 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_readwrite
);
662 if (Attributes
& ObjCPropertyAttribute::kind_retain
)
663 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_retain
);
665 if (Attributes
& ObjCPropertyAttribute::kind_strong
)
666 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
668 if (Attributes
& ObjCPropertyAttribute::kind_weak
)
669 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_weak
);
671 if (Attributes
& ObjCPropertyAttribute::kind_copy
)
672 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_copy
);
674 if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
)
675 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained
);
678 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_assign
);
680 // In the semantic attributes, one of nonatomic or atomic is always set.
681 if (Attributes
& ObjCPropertyAttribute::kind_nonatomic
)
682 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_nonatomic
);
684 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_atomic
);
686 // 'unsafe_unretained' is alias for 'assign'.
687 if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
)
688 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_assign
);
690 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_unsafe_unretained
);
692 if (MethodImplKind
== tok::objc_required
)
693 PDecl
->setPropertyImplementation(ObjCPropertyDecl::Required
);
694 else if (MethodImplKind
== tok::objc_optional
)
695 PDecl
->setPropertyImplementation(ObjCPropertyDecl::Optional
);
697 if (Attributes
& ObjCPropertyAttribute::kind_nullability
)
698 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_nullability
);
700 if (Attributes
& ObjCPropertyAttribute::kind_null_resettable
)
701 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_null_resettable
);
703 if (Attributes
& ObjCPropertyAttribute::kind_class
)
704 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_class
);
706 if ((Attributes
& ObjCPropertyAttribute::kind_direct
) ||
707 CDecl
->hasAttr
<ObjCDirectMembersAttr
>()) {
708 if (isa
<ObjCProtocolDecl
>(CDecl
)) {
709 Diag(PDecl
->getLocation(), diag::err_objc_direct_on_protocol
) << true;
710 } else if (getLangOpts().ObjCRuntime
.allowsDirectDispatch()) {
711 PDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_direct
);
713 Diag(PDecl
->getLocation(), diag::warn_objc_direct_property_ignored
)
714 << PDecl
->getDeclName();
721 static void checkARCPropertyImpl(Sema
&S
, SourceLocation propertyImplLoc
,
722 ObjCPropertyDecl
*property
,
723 ObjCIvarDecl
*ivar
) {
724 if (property
->isInvalidDecl() || ivar
->isInvalidDecl()) return;
726 QualType ivarType
= ivar
->getType();
727 Qualifiers::ObjCLifetime ivarLifetime
= ivarType
.getObjCLifetime();
729 // The lifetime implied by the property's attributes.
730 Qualifiers::ObjCLifetime propertyLifetime
=
731 getImpliedARCOwnership(property
->getPropertyAttributes(),
732 property
->getType());
734 // We're fine if they match.
735 if (propertyLifetime
== ivarLifetime
) return;
737 // None isn't a valid lifetime for an object ivar in ARC, and
738 // __autoreleasing is never valid; don't diagnose twice.
739 if ((ivarLifetime
== Qualifiers::OCL_None
&&
740 S
.getLangOpts().ObjCAutoRefCount
) ||
741 ivarLifetime
== Qualifiers::OCL_Autoreleasing
)
744 // If the ivar is private, and it's implicitly __unsafe_unretained
745 // because of its type, then pretend it was actually implicitly
746 // __strong. This is only sound because we're processing the
747 // property implementation before parsing any method bodies.
748 if (ivarLifetime
== Qualifiers::OCL_ExplicitNone
&&
749 propertyLifetime
== Qualifiers::OCL_Strong
&&
750 ivar
->getAccessControl() == ObjCIvarDecl::Private
) {
751 SplitQualType split
= ivarType
.split();
752 if (split
.Quals
.hasObjCLifetime()) {
753 assert(ivarType
->isObjCARCImplicitlyUnretainedType());
754 split
.Quals
.setObjCLifetime(Qualifiers::OCL_Strong
);
755 ivarType
= S
.Context
.getQualifiedType(split
);
756 ivar
->setType(ivarType
);
761 switch (propertyLifetime
) {
762 case Qualifiers::OCL_Strong
:
763 S
.Diag(ivar
->getLocation(), diag::err_arc_strong_property_ownership
)
764 << property
->getDeclName()
765 << ivar
->getDeclName()
769 case Qualifiers::OCL_Weak
:
770 S
.Diag(ivar
->getLocation(), diag::err_weak_property
)
771 << property
->getDeclName()
772 << ivar
->getDeclName();
775 case Qualifiers::OCL_ExplicitNone
:
776 S
.Diag(ivar
->getLocation(), diag::err_arc_assign_property_ownership
)
777 << property
->getDeclName() << ivar
->getDeclName()
778 << ((property
->getPropertyAttributesAsWritten() &
779 ObjCPropertyAttribute::kind_assign
) != 0);
782 case Qualifiers::OCL_Autoreleasing
:
783 llvm_unreachable("properties cannot be autoreleasing");
785 case Qualifiers::OCL_None
:
786 // Any other property should be ignored.
790 S
.Diag(property
->getLocation(), diag::note_property_declare
);
791 if (propertyImplLoc
.isValid())
792 S
.Diag(propertyImplLoc
, diag::note_property_synthesize
);
795 /// setImpliedPropertyAttributeForReadOnlyProperty -
796 /// This routine evaludates life-time attributes for a 'readonly'
797 /// property with no known lifetime of its own, using backing
798 /// 'ivar's attribute, if any. If no backing 'ivar', property's
799 /// life-time is assumed 'strong'.
800 static void setImpliedPropertyAttributeForReadOnlyProperty(
801 ObjCPropertyDecl
*property
, ObjCIvarDecl
*ivar
) {
802 Qualifiers::ObjCLifetime propertyLifetime
=
803 getImpliedARCOwnership(property
->getPropertyAttributes(),
804 property
->getType());
805 if (propertyLifetime
!= Qualifiers::OCL_None
)
809 // if no backing ivar, make property 'strong'.
810 property
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
813 // property assumes owenership of backing ivar.
814 QualType ivarType
= ivar
->getType();
815 Qualifiers::ObjCLifetime ivarLifetime
= ivarType
.getObjCLifetime();
816 if (ivarLifetime
== Qualifiers::OCL_Strong
)
817 property
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
818 else if (ivarLifetime
== Qualifiers::OCL_Weak
)
819 property
->setPropertyAttributes(ObjCPropertyAttribute::kind_weak
);
822 static bool isIncompatiblePropertyAttribute(unsigned Attr1
, unsigned Attr2
,
823 ObjCPropertyAttribute::Kind Kind
) {
824 return (Attr1
& Kind
) != (Attr2
& Kind
);
827 static bool areIncompatiblePropertyAttributes(unsigned Attr1
, unsigned Attr2
,
829 return ((Attr1
& Kinds
) != 0) != ((Attr2
& Kinds
) != 0);
832 /// SelectPropertyForSynthesisFromProtocols - Finds the most appropriate
833 /// property declaration that should be synthesised in all of the inherited
834 /// protocols. It also diagnoses properties declared in inherited protocols with
835 /// mismatched types or attributes, since any of them can be candidate for
837 static ObjCPropertyDecl
*
838 SelectPropertyForSynthesisFromProtocols(Sema
&S
, SourceLocation AtLoc
,
839 ObjCInterfaceDecl
*ClassDecl
,
840 ObjCPropertyDecl
*Property
) {
841 assert(isa
<ObjCProtocolDecl
>(Property
->getDeclContext()) &&
842 "Expected a property from a protocol");
843 ObjCInterfaceDecl::ProtocolPropertySet ProtocolSet
;
844 ObjCInterfaceDecl::PropertyDeclOrder Properties
;
845 for (const auto *PI
: ClassDecl
->all_referenced_protocols()) {
846 if (const ObjCProtocolDecl
*PDecl
= PI
->getDefinition())
847 PDecl
->collectInheritedProtocolProperties(Property
, ProtocolSet
,
850 if (ObjCInterfaceDecl
*SDecl
= ClassDecl
->getSuperClass()) {
852 for (const auto *PI
: SDecl
->all_referenced_protocols()) {
853 if (const ObjCProtocolDecl
*PDecl
= PI
->getDefinition())
854 PDecl
->collectInheritedProtocolProperties(Property
, ProtocolSet
,
857 SDecl
= SDecl
->getSuperClass();
861 if (Properties
.empty())
864 ObjCPropertyDecl
*OriginalProperty
= Property
;
865 size_t SelectedIndex
= 0;
866 for (const auto &Prop
: llvm::enumerate(Properties
)) {
867 // Select the 'readwrite' property if such property exists.
868 if (Property
->isReadOnly() && !Prop
.value()->isReadOnly()) {
869 Property
= Prop
.value();
870 SelectedIndex
= Prop
.index();
873 if (Property
!= OriginalProperty
) {
874 // Check that the old property is compatible with the new one.
875 Properties
[SelectedIndex
] = OriginalProperty
;
878 QualType RHSType
= S
.Context
.getCanonicalType(Property
->getType());
879 unsigned OriginalAttributes
= Property
->getPropertyAttributesAsWritten();
881 IncompatibleType
= 0,
882 HasNoExpectedAttribute
,
883 HasUnexpectedAttribute
,
887 // Represents a property from another protocol that conflicts with the
888 // selected declaration.
889 struct MismatchingProperty
{
890 const ObjCPropertyDecl
*Prop
;
892 StringRef AttributeName
;
894 SmallVector
<MismatchingProperty
, 4> Mismatches
;
895 for (ObjCPropertyDecl
*Prop
: Properties
) {
896 // Verify the property attributes.
897 unsigned Attr
= Prop
->getPropertyAttributesAsWritten();
898 if (Attr
!= OriginalAttributes
) {
899 auto Diag
= [&](bool OriginalHasAttribute
, StringRef AttributeName
) {
900 MismatchKind Kind
= OriginalHasAttribute
? HasNoExpectedAttribute
901 : HasUnexpectedAttribute
;
902 Mismatches
.push_back({Prop
, Kind
, AttributeName
});
904 // The ownership might be incompatible unless the property has no explicit
907 (Attr
& (ObjCPropertyAttribute::kind_retain
|
908 ObjCPropertyAttribute::kind_strong
|
909 ObjCPropertyAttribute::kind_copy
|
910 ObjCPropertyAttribute::kind_assign
|
911 ObjCPropertyAttribute::kind_unsafe_unretained
|
912 ObjCPropertyAttribute::kind_weak
)) != 0;
914 isIncompatiblePropertyAttribute(OriginalAttributes
, Attr
,
915 ObjCPropertyAttribute::kind_copy
)) {
916 Diag(OriginalAttributes
& ObjCPropertyAttribute::kind_copy
, "copy");
919 if (HasOwnership
&& areIncompatiblePropertyAttributes(
920 OriginalAttributes
, Attr
,
921 ObjCPropertyAttribute::kind_retain
|
922 ObjCPropertyAttribute::kind_strong
)) {
923 Diag(OriginalAttributes
& (ObjCPropertyAttribute::kind_retain
|
924 ObjCPropertyAttribute::kind_strong
),
925 "retain (or strong)");
928 if (isIncompatiblePropertyAttribute(OriginalAttributes
, Attr
,
929 ObjCPropertyAttribute::kind_atomic
)) {
930 Diag(OriginalAttributes
& ObjCPropertyAttribute::kind_atomic
, "atomic");
934 if (Property
->getGetterName() != Prop
->getGetterName()) {
935 Mismatches
.push_back({Prop
, DifferentGetter
, ""});
938 if (!Property
->isReadOnly() && !Prop
->isReadOnly() &&
939 Property
->getSetterName() != Prop
->getSetterName()) {
940 Mismatches
.push_back({Prop
, DifferentSetter
, ""});
943 QualType LHSType
= S
.Context
.getCanonicalType(Prop
->getType());
944 if (!S
.Context
.propertyTypesAreCompatible(LHSType
, RHSType
)) {
945 bool IncompatibleObjC
= false;
946 QualType ConvertedType
;
947 if (!S
.isObjCPointerConversion(RHSType
, LHSType
, ConvertedType
, IncompatibleObjC
)
948 || IncompatibleObjC
) {
949 Mismatches
.push_back({Prop
, IncompatibleType
, ""});
955 if (Mismatches
.empty())
958 // Diagnose incompability.
960 bool HasIncompatibleAttributes
= false;
961 for (const auto &Note
: Mismatches
)
962 HasIncompatibleAttributes
=
963 Note
.Kind
!= IncompatibleType
? true : HasIncompatibleAttributes
;
964 // Promote the warning to an error if there are incompatible attributes or
965 // incompatible types together with readwrite/readonly incompatibility.
966 auto Diag
= S
.Diag(Property
->getLocation(),
967 Property
!= OriginalProperty
|| HasIncompatibleAttributes
968 ? diag::err_protocol_property_mismatch
969 : diag::warn_protocol_property_mismatch
);
970 Diag
<< Mismatches
[0].Kind
;
971 switch (Mismatches
[0].Kind
) {
972 case IncompatibleType
:
973 Diag
<< Property
->getType();
975 case HasNoExpectedAttribute
:
976 case HasUnexpectedAttribute
:
977 Diag
<< Mismatches
[0].AttributeName
;
979 case DifferentGetter
:
980 Diag
<< Property
->getGetterName();
982 case DifferentSetter
:
983 Diag
<< Property
->getSetterName();
987 for (const auto &Note
: Mismatches
) {
989 S
.Diag(Note
.Prop
->getLocation(), diag::note_protocol_property_declare
)
992 case IncompatibleType
:
993 Diag
<< Note
.Prop
->getType();
995 case HasNoExpectedAttribute
:
996 case HasUnexpectedAttribute
:
997 Diag
<< Note
.AttributeName
;
999 case DifferentGetter
:
1000 Diag
<< Note
.Prop
->getGetterName();
1002 case DifferentSetter
:
1003 Diag
<< Note
.Prop
->getSetterName();
1007 if (AtLoc
.isValid())
1008 S
.Diag(AtLoc
, diag::note_property_synthesize
);
1013 /// Determine whether any storage attributes were written on the property.
1014 static bool hasWrittenStorageAttribute(ObjCPropertyDecl
*Prop
,
1015 ObjCPropertyQueryKind QueryKind
) {
1016 if (Prop
->getPropertyAttributesAsWritten() & OwnershipMask
) return true;
1018 // If this is a readwrite property in a class extension that refines
1019 // a readonly property in the original class definition, check it as
1022 // If it's a readonly property, we're not interested.
1023 if (Prop
->isReadOnly()) return false;
1025 // Is it declared in an extension?
1026 auto Category
= dyn_cast
<ObjCCategoryDecl
>(Prop
->getDeclContext());
1027 if (!Category
|| !Category
->IsClassExtension()) return false;
1029 // Find the corresponding property in the primary class definition.
1030 auto OrigClass
= Category
->getClassInterface();
1031 for (auto *Found
: OrigClass
->lookup(Prop
->getDeclName())) {
1032 if (ObjCPropertyDecl
*OrigProp
= dyn_cast
<ObjCPropertyDecl
>(Found
))
1033 return OrigProp
->getPropertyAttributesAsWritten() & OwnershipMask
;
1036 // Look through all of the protocols.
1037 for (const auto *Proto
: OrigClass
->all_referenced_protocols()) {
1038 if (ObjCPropertyDecl
*OrigProp
= Proto
->FindPropertyDeclaration(
1039 Prop
->getIdentifier(), QueryKind
))
1040 return OrigProp
->getPropertyAttributesAsWritten() & OwnershipMask
;
1046 /// Create a synthesized property accessor stub inside the \@implementation.
1047 static ObjCMethodDecl
*
1048 RedeclarePropertyAccessor(ASTContext
&Context
, ObjCImplementationDecl
*Impl
,
1049 ObjCMethodDecl
*AccessorDecl
, SourceLocation AtLoc
,
1050 SourceLocation PropertyLoc
) {
1051 ObjCMethodDecl
*Decl
= AccessorDecl
;
1052 ObjCMethodDecl
*ImplDecl
= ObjCMethodDecl::Create(
1053 Context
, AtLoc
.isValid() ? AtLoc
: Decl
->getBeginLoc(),
1054 PropertyLoc
.isValid() ? PropertyLoc
: Decl
->getEndLoc(),
1055 Decl
->getSelector(), Decl
->getReturnType(),
1056 Decl
->getReturnTypeSourceInfo(), Impl
, Decl
->isInstanceMethod(),
1057 Decl
->isVariadic(), Decl
->isPropertyAccessor(),
1058 /* isSynthesized*/ true, Decl
->isImplicit(), Decl
->isDefined(),
1059 Decl
->getImplementationControl(), Decl
->hasRelatedResultType());
1060 ImplDecl
->getMethodFamily();
1061 if (Decl
->hasAttrs())
1062 ImplDecl
->setAttrs(Decl
->getAttrs());
1063 ImplDecl
->setSelfDecl(Decl
->getSelfDecl());
1064 ImplDecl
->setCmdDecl(Decl
->getCmdDecl());
1065 SmallVector
<SourceLocation
, 1> SelLocs
;
1066 Decl
->getSelectorLocs(SelLocs
);
1067 ImplDecl
->setMethodParams(Context
, Decl
->parameters(), SelLocs
);
1068 ImplDecl
->setLexicalDeclContext(Impl
);
1069 ImplDecl
->setDefined(false);
1073 /// ActOnPropertyImplDecl - This routine performs semantic checks and
1074 /// builds the AST node for a property implementation declaration; declared
1075 /// as \@synthesize or \@dynamic.
1077 Decl
*Sema::ActOnPropertyImplDecl(Scope
*S
,
1078 SourceLocation AtLoc
,
1079 SourceLocation PropertyLoc
,
1081 IdentifierInfo
*PropertyId
,
1082 IdentifierInfo
*PropertyIvar
,
1083 SourceLocation PropertyIvarLoc
,
1084 ObjCPropertyQueryKind QueryKind
) {
1085 ObjCContainerDecl
*ClassImpDecl
=
1086 dyn_cast
<ObjCContainerDecl
>(CurContext
);
1087 // Make sure we have a context for the property implementation declaration.
1088 if (!ClassImpDecl
) {
1089 Diag(AtLoc
, diag::err_missing_property_context
);
1092 if (PropertyIvarLoc
.isInvalid())
1093 PropertyIvarLoc
= PropertyLoc
;
1094 SourceLocation PropertyDiagLoc
= PropertyLoc
;
1095 if (PropertyDiagLoc
.isInvalid())
1096 PropertyDiagLoc
= ClassImpDecl
->getBeginLoc();
1097 ObjCPropertyDecl
*property
= nullptr;
1098 ObjCInterfaceDecl
*IDecl
= nullptr;
1099 // Find the class or category class where this property must have
1101 ObjCImplementationDecl
*IC
= nullptr;
1102 ObjCCategoryImplDecl
*CatImplClass
= nullptr;
1103 if ((IC
= dyn_cast
<ObjCImplementationDecl
>(ClassImpDecl
))) {
1104 IDecl
= IC
->getClassInterface();
1105 // We always synthesize an interface for an implementation
1106 // without an interface decl. So, IDecl is always non-zero.
1108 "ActOnPropertyImplDecl - @implementation without @interface");
1110 // Look for this property declaration in the @implementation's @interface
1111 property
= IDecl
->FindPropertyDeclaration(PropertyId
, QueryKind
);
1113 Diag(PropertyLoc
, diag::err_bad_property_decl
) << IDecl
->getDeclName();
1116 if (property
->isClassProperty() && Synthesize
) {
1117 Diag(PropertyLoc
, diag::err_synthesize_on_class_property
) << PropertyId
;
1120 unsigned PIkind
= property
->getPropertyAttributesAsWritten();
1121 if ((PIkind
& (ObjCPropertyAttribute::kind_atomic
|
1122 ObjCPropertyAttribute::kind_nonatomic
)) == 0) {
1123 if (AtLoc
.isValid())
1124 Diag(AtLoc
, diag::warn_implicit_atomic_property
);
1126 Diag(IC
->getLocation(), diag::warn_auto_implicit_atomic_property
);
1127 Diag(property
->getLocation(), diag::note_property_declare
);
1130 if (const ObjCCategoryDecl
*CD
=
1131 dyn_cast
<ObjCCategoryDecl
>(property
->getDeclContext())) {
1132 if (!CD
->IsClassExtension()) {
1133 Diag(PropertyLoc
, diag::err_category_property
) << CD
->getDeclName();
1134 Diag(property
->getLocation(), diag::note_property_declare
);
1138 if (Synthesize
&& (PIkind
& ObjCPropertyAttribute::kind_readonly
) &&
1139 property
->hasAttr
<IBOutletAttr
>() && !AtLoc
.isValid()) {
1140 bool ReadWriteProperty
= false;
1141 // Search into the class extensions and see if 'readonly property is
1142 // redeclared 'readwrite', then no warning is to be issued.
1143 for (auto *Ext
: IDecl
->known_extensions()) {
1144 DeclContext::lookup_result R
= Ext
->lookup(property
->getDeclName());
1145 if (auto *ExtProp
= R
.find_first
<ObjCPropertyDecl
>()) {
1146 PIkind
= ExtProp
->getPropertyAttributesAsWritten();
1147 if (PIkind
& ObjCPropertyAttribute::kind_readwrite
) {
1148 ReadWriteProperty
= true;
1154 if (!ReadWriteProperty
) {
1155 Diag(property
->getLocation(), diag::warn_auto_readonly_iboutlet_property
)
1157 SourceLocation readonlyLoc
;
1158 if (LocPropertyAttribute(Context
, "readonly",
1159 property
->getLParenLoc(), readonlyLoc
)) {
1160 SourceLocation endLoc
=
1161 readonlyLoc
.getLocWithOffset(strlen("readonly")-1);
1162 SourceRange
ReadonlySourceRange(readonlyLoc
, endLoc
);
1163 Diag(property
->getLocation(),
1164 diag::note_auto_readonly_iboutlet_fixup_suggest
) <<
1165 FixItHint::CreateReplacement(ReadonlySourceRange
, "readwrite");
1169 if (Synthesize
&& isa
<ObjCProtocolDecl
>(property
->getDeclContext()))
1170 property
= SelectPropertyForSynthesisFromProtocols(*this, AtLoc
, IDecl
,
1173 } else if ((CatImplClass
= dyn_cast
<ObjCCategoryImplDecl
>(ClassImpDecl
))) {
1175 Diag(AtLoc
, diag::err_synthesize_category_decl
);
1178 IDecl
= CatImplClass
->getClassInterface();
1180 Diag(AtLoc
, diag::err_missing_property_interface
);
1183 ObjCCategoryDecl
*Category
=
1184 IDecl
->FindCategoryDeclaration(CatImplClass
->getIdentifier());
1186 // If category for this implementation not found, it is an error which
1187 // has already been reported eralier.
1190 // Look for this property declaration in @implementation's category
1191 property
= Category
->FindPropertyDeclaration(PropertyId
, QueryKind
);
1193 Diag(PropertyLoc
, diag::err_bad_category_property_decl
)
1194 << Category
->getDeclName();
1198 Diag(AtLoc
, diag::err_bad_property_context
);
1201 ObjCIvarDecl
*Ivar
= nullptr;
1202 bool CompleteTypeErr
= false;
1204 // Check that we have a valid, previously declared ivar for @synthesize
1208 PropertyIvar
= PropertyId
;
1209 // Check that this is a previously declared 'ivar' in 'IDecl' interface
1210 ObjCInterfaceDecl
*ClassDeclared
;
1211 Ivar
= IDecl
->lookupInstanceVariable(PropertyIvar
, ClassDeclared
);
1212 QualType PropType
= property
->getType();
1213 QualType PropertyIvarType
= PropType
.getNonReferenceType();
1215 if (RequireCompleteType(PropertyDiagLoc
, PropertyIvarType
,
1216 diag::err_incomplete_synthesized_property
,
1217 property
->getDeclName())) {
1218 Diag(property
->getLocation(), diag::note_property_declare
);
1219 CompleteTypeErr
= true;
1222 if (getLangOpts().ObjCAutoRefCount
&&
1223 (property
->getPropertyAttributesAsWritten() &
1224 ObjCPropertyAttribute::kind_readonly
) &&
1225 PropertyIvarType
->isObjCRetainableType()) {
1226 setImpliedPropertyAttributeForReadOnlyProperty(property
, Ivar
);
1229 ObjCPropertyAttribute::Kind kind
= property
->getPropertyAttributes();
1231 bool isARCWeak
= false;
1232 if (kind
& ObjCPropertyAttribute::kind_weak
) {
1233 // Add GC __weak to the ivar type if the property is weak.
1234 if (getLangOpts().getGC() != LangOptions::NonGC
) {
1235 assert(!getLangOpts().ObjCAutoRefCount
);
1236 if (PropertyIvarType
.isObjCGCStrong()) {
1237 Diag(PropertyDiagLoc
, diag::err_gc_weak_property_strong_type
);
1238 Diag(property
->getLocation(), diag::note_property_declare
);
1241 Context
.getObjCGCQualType(PropertyIvarType
, Qualifiers::Weak
);
1244 // Otherwise, check whether ARC __weak is enabled and works with
1245 // the property type.
1247 if (!getLangOpts().ObjCWeak
) {
1248 // Only complain here when synthesizing an ivar.
1250 Diag(PropertyDiagLoc
,
1251 getLangOpts().ObjCWeakRuntime
1252 ? diag::err_synthesizing_arc_weak_property_disabled
1253 : diag::err_synthesizing_arc_weak_property_no_runtime
);
1254 Diag(property
->getLocation(), diag::note_property_declare
);
1256 CompleteTypeErr
= true; // suppress later diagnostics about the ivar
1259 if (const ObjCObjectPointerType
*ObjT
=
1260 PropertyIvarType
->getAs
<ObjCObjectPointerType
>()) {
1261 const ObjCInterfaceDecl
*ObjI
= ObjT
->getInterfaceDecl();
1262 if (ObjI
&& ObjI
->isArcWeakrefUnavailable()) {
1263 Diag(property
->getLocation(),
1264 diag::err_arc_weak_unavailable_property
)
1265 << PropertyIvarType
;
1266 Diag(ClassImpDecl
->getLocation(), diag::note_implemented_by_class
)
1267 << ClassImpDecl
->getName();
1274 if (AtLoc
.isInvalid()) {
1275 // Check when default synthesizing a property that there is
1276 // an ivar matching property name and issue warning; since this
1277 // is the most common case of not using an ivar used for backing
1278 // property in non-default synthesis case.
1279 ObjCInterfaceDecl
*ClassDeclared
=nullptr;
1280 ObjCIvarDecl
*originalIvar
=
1281 IDecl
->lookupInstanceVariable(property
->getIdentifier(),
1284 Diag(PropertyDiagLoc
,
1285 diag::warn_autosynthesis_property_ivar_match
)
1286 << PropertyId
<< (Ivar
== nullptr) << PropertyIvar
1287 << originalIvar
->getIdentifier();
1288 Diag(property
->getLocation(), diag::note_property_declare
);
1289 Diag(originalIvar
->getLocation(), diag::note_ivar_decl
);
1294 // In ARC, give the ivar a lifetime qualifier based on the
1295 // property attributes.
1296 if ((getLangOpts().ObjCAutoRefCount
|| isARCWeak
) &&
1297 !PropertyIvarType
.getObjCLifetime() &&
1298 PropertyIvarType
->isObjCRetainableType()) {
1300 // It's an error if we have to do this and the user didn't
1301 // explicitly write an ownership attribute on the property.
1302 if (!hasWrittenStorageAttribute(property
, QueryKind
) &&
1303 !(kind
& ObjCPropertyAttribute::kind_strong
)) {
1304 Diag(PropertyDiagLoc
,
1305 diag::err_arc_objc_property_default_assign_on_object
);
1306 Diag(property
->getLocation(), diag::note_property_declare
);
1308 Qualifiers::ObjCLifetime lifetime
=
1309 getImpliedARCOwnership(kind
, PropertyIvarType
);
1310 assert(lifetime
&& "no lifetime for property?");
1313 qs
.addObjCLifetime(lifetime
);
1314 PropertyIvarType
= Context
.getQualifiedType(PropertyIvarType
, qs
);
1318 Ivar
= ObjCIvarDecl::Create(Context
, ClassImpDecl
,
1319 PropertyIvarLoc
,PropertyIvarLoc
, PropertyIvar
,
1320 PropertyIvarType
, /*TInfo=*/nullptr,
1321 ObjCIvarDecl::Private
,
1322 (Expr
*)nullptr, true);
1323 if (RequireNonAbstractType(PropertyIvarLoc
,
1325 diag::err_abstract_type_in_decl
,
1326 AbstractSynthesizedIvarType
)) {
1327 Diag(property
->getLocation(), diag::note_property_declare
);
1328 // An abstract type is as bad as an incomplete type.
1329 CompleteTypeErr
= true;
1331 if (!CompleteTypeErr
) {
1332 const RecordType
*RecordTy
= PropertyIvarType
->getAs
<RecordType
>();
1333 if (RecordTy
&& RecordTy
->getDecl()->hasFlexibleArrayMember()) {
1334 Diag(PropertyIvarLoc
, diag::err_synthesize_variable_sized_ivar
)
1335 << PropertyIvarType
;
1336 CompleteTypeErr
= true; // suppress later diagnostics about the ivar
1339 if (CompleteTypeErr
)
1340 Ivar
->setInvalidDecl();
1341 ClassImpDecl
->addDecl(Ivar
);
1342 IDecl
->makeDeclVisibleInContext(Ivar
);
1344 if (getLangOpts().ObjCRuntime
.isFragile())
1345 Diag(PropertyDiagLoc
, diag::err_missing_property_ivar_decl
)
1347 // Note! I deliberately want it to fall thru so, we have a
1348 // a property implementation and to avoid future warnings.
1349 } else if (getLangOpts().ObjCRuntime
.isNonFragile() &&
1350 !declaresSameEntity(ClassDeclared
, IDecl
)) {
1351 Diag(PropertyDiagLoc
, diag::err_ivar_in_superclass_use
)
1352 << property
->getDeclName() << Ivar
->getDeclName()
1353 << ClassDeclared
->getDeclName();
1354 Diag(Ivar
->getLocation(), diag::note_previous_access_declaration
)
1355 << Ivar
<< Ivar
->getName();
1356 // Note! I deliberately want it to fall thru so more errors are caught.
1358 property
->setPropertyIvarDecl(Ivar
);
1360 QualType IvarType
= Context
.getCanonicalType(Ivar
->getType());
1362 // Check that type of property and its ivar are type compatible.
1363 if (!Context
.hasSameType(PropertyIvarType
, IvarType
)) {
1364 if (isa
<ObjCObjectPointerType
>(PropertyIvarType
)
1365 && isa
<ObjCObjectPointerType
>(IvarType
))
1366 compat
= Context
.canAssignObjCInterfaces(
1367 PropertyIvarType
->castAs
<ObjCObjectPointerType
>(),
1368 IvarType
->castAs
<ObjCObjectPointerType
>());
1370 compat
= (CheckAssignmentConstraints(PropertyIvarLoc
, PropertyIvarType
,
1375 Diag(PropertyDiagLoc
, diag::err_property_ivar_type
)
1376 << property
->getDeclName() << PropType
1377 << Ivar
->getDeclName() << IvarType
;
1378 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1379 // Note! I deliberately want it to fall thru so, we have a
1380 // a property implementation and to avoid future warnings.
1383 // FIXME! Rules for properties are somewhat different that those
1384 // for assignments. Use a new routine to consolidate all cases;
1385 // specifically for property redeclarations as well as for ivars.
1386 QualType lhsType
=Context
.getCanonicalType(PropertyIvarType
).getUnqualifiedType();
1387 QualType rhsType
=Context
.getCanonicalType(IvarType
).getUnqualifiedType();
1388 if (lhsType
!= rhsType
&&
1389 lhsType
->isArithmeticType()) {
1390 Diag(PropertyDiagLoc
, diag::err_property_ivar_type
)
1391 << property
->getDeclName() << PropType
1392 << Ivar
->getDeclName() << IvarType
;
1393 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1394 // Fall thru - see previous comment
1397 // __weak is explicit. So it works on Canonical type.
1398 if ((PropType
.isObjCGCWeak() && !IvarType
.isObjCGCWeak() &&
1399 getLangOpts().getGC() != LangOptions::NonGC
)) {
1400 Diag(PropertyDiagLoc
, diag::err_weak_property
)
1401 << property
->getDeclName() << Ivar
->getDeclName();
1402 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1403 // Fall thru - see previous comment
1405 // Fall thru - see previous comment
1406 if ((property
->getType()->isObjCObjectPointerType() ||
1407 PropType
.isObjCGCStrong()) && IvarType
.isObjCGCWeak() &&
1408 getLangOpts().getGC() != LangOptions::NonGC
) {
1409 Diag(PropertyDiagLoc
, diag::err_strong_property
)
1410 << property
->getDeclName() << Ivar
->getDeclName();
1411 // Fall thru - see previous comment
1414 if (getLangOpts().ObjCAutoRefCount
|| isARCWeak
||
1415 Ivar
->getType().getObjCLifetime())
1416 checkARCPropertyImpl(*this, PropertyLoc
, property
, Ivar
);
1417 } else if (PropertyIvar
)
1419 Diag(PropertyDiagLoc
, diag::err_dynamic_property_ivar_decl
);
1421 assert (property
&& "ActOnPropertyImplDecl - property declaration missing");
1422 ObjCPropertyImplDecl
*PIDecl
=
1423 ObjCPropertyImplDecl::Create(Context
, CurContext
, AtLoc
, PropertyLoc
,
1426 ObjCPropertyImplDecl::Synthesize
1427 : ObjCPropertyImplDecl::Dynamic
),
1428 Ivar
, PropertyIvarLoc
);
1430 if (CompleteTypeErr
|| !compat
)
1431 PIDecl
->setInvalidDecl();
1433 if (ObjCMethodDecl
*getterMethod
= property
->getGetterMethodDecl()) {
1434 getterMethod
->createImplicitParams(Context
, IDecl
);
1436 // Redeclare the getter within the implementation as DeclContext.
1438 // If the method hasn't been overridden, create a synthesized implementation.
1439 ObjCMethodDecl
*OMD
= ClassImpDecl
->getMethod(
1440 getterMethod
->getSelector(), getterMethod
->isInstanceMethod());
1442 OMD
= RedeclarePropertyAccessor(Context
, IC
, getterMethod
, AtLoc
,
1444 PIDecl
->setGetterMethodDecl(OMD
);
1447 if (getLangOpts().CPlusPlus
&& Synthesize
&& !CompleteTypeErr
&&
1448 Ivar
->getType()->isRecordType()) {
1449 // For Objective-C++, need to synthesize the AST for the IVAR object to be
1450 // returned by the getter as it must conform to C++'s copy-return rules.
1451 // FIXME. Eventually we want to do this for Objective-C as well.
1452 SynthesizedFunctionScope
Scope(*this, getterMethod
);
1453 ImplicitParamDecl
*SelfDecl
= getterMethod
->getSelfDecl();
1454 DeclRefExpr
*SelfExpr
= new (Context
)
1455 DeclRefExpr(Context
, SelfDecl
, false, SelfDecl
->getType(), VK_LValue
,
1457 MarkDeclRefReferenced(SelfExpr
);
1458 Expr
*LoadSelfExpr
= ImplicitCastExpr::Create(
1459 Context
, SelfDecl
->getType(), CK_LValueToRValue
, SelfExpr
, nullptr,
1460 VK_PRValue
, FPOptionsOverride());
1462 new (Context
) ObjCIvarRefExpr(Ivar
,
1463 Ivar
->getUsageType(SelfDecl
->getType()),
1465 Ivar
->getLocation(),
1466 LoadSelfExpr
, true, true);
1467 ExprResult Res
= PerformCopyInitialization(
1468 InitializedEntity::InitializeResult(PropertyDiagLoc
,
1469 getterMethod
->getReturnType()),
1470 PropertyDiagLoc
, IvarRefExpr
);
1471 if (!Res
.isInvalid()) {
1472 Expr
*ResExpr
= Res
.getAs
<Expr
>();
1474 ResExpr
= MaybeCreateExprWithCleanups(ResExpr
);
1475 PIDecl
->setGetterCXXConstructor(ResExpr
);
1478 if (property
->hasAttr
<NSReturnsNotRetainedAttr
>() &&
1479 !getterMethod
->hasAttr
<NSReturnsNotRetainedAttr
>()) {
1480 Diag(getterMethod
->getLocation(),
1481 diag::warn_property_getter_owning_mismatch
);
1482 Diag(property
->getLocation(), diag::note_property_declare
);
1484 if (getLangOpts().ObjCAutoRefCount
&& Synthesize
)
1485 switch (getterMethod
->getMethodFamily()) {
1487 case OMF_retainCount
:
1489 case OMF_autorelease
:
1490 Diag(getterMethod
->getLocation(), diag::err_arc_illegal_method_def
)
1491 << 1 << getterMethod
->getSelector();
1498 if (ObjCMethodDecl
*setterMethod
= property
->getSetterMethodDecl()) {
1499 setterMethod
->createImplicitParams(Context
, IDecl
);
1501 // Redeclare the setter within the implementation as DeclContext.
1503 ObjCMethodDecl
*OMD
= ClassImpDecl
->getMethod(
1504 setterMethod
->getSelector(), setterMethod
->isInstanceMethod());
1506 OMD
= RedeclarePropertyAccessor(Context
, IC
, setterMethod
,
1507 AtLoc
, PropertyLoc
);
1508 PIDecl
->setSetterMethodDecl(OMD
);
1511 if (getLangOpts().CPlusPlus
&& Synthesize
&& !CompleteTypeErr
&&
1512 Ivar
->getType()->isRecordType()) {
1513 // FIXME. Eventually we want to do this for Objective-C as well.
1514 SynthesizedFunctionScope
Scope(*this, setterMethod
);
1515 ImplicitParamDecl
*SelfDecl
= setterMethod
->getSelfDecl();
1516 DeclRefExpr
*SelfExpr
= new (Context
)
1517 DeclRefExpr(Context
, SelfDecl
, false, SelfDecl
->getType(), VK_LValue
,
1519 MarkDeclRefReferenced(SelfExpr
);
1520 Expr
*LoadSelfExpr
= ImplicitCastExpr::Create(
1521 Context
, SelfDecl
->getType(), CK_LValueToRValue
, SelfExpr
, nullptr,
1522 VK_PRValue
, FPOptionsOverride());
1524 new (Context
) ObjCIvarRefExpr(Ivar
,
1525 Ivar
->getUsageType(SelfDecl
->getType()),
1527 Ivar
->getLocation(),
1528 LoadSelfExpr
, true, true);
1529 ObjCMethodDecl::param_iterator P
= setterMethod
->param_begin();
1530 ParmVarDecl
*Param
= (*P
);
1531 QualType T
= Param
->getType().getNonReferenceType();
1532 DeclRefExpr
*rhs
= new (Context
)
1533 DeclRefExpr(Context
, Param
, false, T
, VK_LValue
, PropertyDiagLoc
);
1534 MarkDeclRefReferenced(rhs
);
1535 ExprResult Res
= BuildBinOp(S
, PropertyDiagLoc
,
1536 BO_Assign
, lhs
, rhs
);
1537 if (property
->getPropertyAttributes() &
1538 ObjCPropertyAttribute::kind_atomic
) {
1539 Expr
*callExpr
= Res
.getAs
<Expr
>();
1540 if (const CXXOperatorCallExpr
*CXXCE
=
1541 dyn_cast_or_null
<CXXOperatorCallExpr
>(callExpr
))
1542 if (const FunctionDecl
*FuncDecl
= CXXCE
->getDirectCallee())
1543 if (!FuncDecl
->isTrivial())
1544 if (property
->getType()->isReferenceType()) {
1545 Diag(PropertyDiagLoc
,
1546 diag::err_atomic_property_nontrivial_assign_op
)
1547 << property
->getType();
1548 Diag(FuncDecl
->getBeginLoc(), diag::note_callee_decl
)
1552 PIDecl
->setSetterCXXAssignment(Res
.getAs
<Expr
>());
1558 if (ObjCPropertyImplDecl
*PPIDecl
=
1559 IC
->FindPropertyImplIvarDecl(PropertyIvar
)) {
1560 Diag(PropertyLoc
, diag::err_duplicate_ivar_use
)
1561 << PropertyId
<< PPIDecl
->getPropertyDecl()->getIdentifier()
1563 Diag(PPIDecl
->getLocation(), diag::note_previous_use
);
1566 if (ObjCPropertyImplDecl
*PPIDecl
1567 = IC
->FindPropertyImplDecl(PropertyId
, QueryKind
)) {
1568 Diag(PropertyLoc
, diag::err_property_implemented
) << PropertyId
;
1569 Diag(PPIDecl
->getLocation(), diag::note_previous_declaration
);
1572 IC
->addPropertyImplementation(PIDecl
);
1573 if (getLangOpts().ObjCDefaultSynthProperties
&&
1574 getLangOpts().ObjCRuntime
.isNonFragile() &&
1575 !IDecl
->isObjCRequiresPropertyDefs()) {
1576 // Diagnose if an ivar was lazily synthesdized due to a previous
1577 // use and if 1) property is @dynamic or 2) property is synthesized
1578 // but it requires an ivar of different name.
1579 ObjCInterfaceDecl
*ClassDeclared
=nullptr;
1580 ObjCIvarDecl
*Ivar
= nullptr;
1582 Ivar
= IDecl
->lookupInstanceVariable(PropertyId
, ClassDeclared
);
1584 if (PropertyIvar
&& PropertyIvar
!= PropertyId
)
1585 Ivar
= IDecl
->lookupInstanceVariable(PropertyId
, ClassDeclared
);
1587 // Issue diagnostics only if Ivar belongs to current class.
1588 if (Ivar
&& Ivar
->getSynthesize() &&
1589 declaresSameEntity(IC
->getClassInterface(), ClassDeclared
)) {
1590 Diag(Ivar
->getLocation(), diag::err_undeclared_var_use
)
1592 Ivar
->setInvalidDecl();
1597 if (ObjCPropertyImplDecl
*PPIDecl
=
1598 CatImplClass
->FindPropertyImplIvarDecl(PropertyIvar
)) {
1599 Diag(PropertyDiagLoc
, diag::err_duplicate_ivar_use
)
1600 << PropertyId
<< PPIDecl
->getPropertyDecl()->getIdentifier()
1602 Diag(PPIDecl
->getLocation(), diag::note_previous_use
);
1605 if (ObjCPropertyImplDecl
*PPIDecl
=
1606 CatImplClass
->FindPropertyImplDecl(PropertyId
, QueryKind
)) {
1607 Diag(PropertyDiagLoc
, diag::err_property_implemented
) << PropertyId
;
1608 Diag(PPIDecl
->getLocation(), diag::note_previous_declaration
);
1611 CatImplClass
->addPropertyImplementation(PIDecl
);
1614 if (PIDecl
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
&&
1615 PIDecl
->getPropertyDecl() &&
1616 PIDecl
->getPropertyDecl()->isDirectProperty()) {
1617 Diag(PropertyLoc
, diag::err_objc_direct_dynamic_property
);
1618 Diag(PIDecl
->getPropertyDecl()->getLocation(),
1619 diag::note_previous_declaration
);
1626 //===----------------------------------------------------------------------===//
1628 //===----------------------------------------------------------------------===//
1630 /// DiagnosePropertyMismatch - Compares two properties for their
1631 /// attributes and types and warns on a variety of inconsistencies.
1634 Sema::DiagnosePropertyMismatch(ObjCPropertyDecl
*Property
,
1635 ObjCPropertyDecl
*SuperProperty
,
1636 const IdentifierInfo
*inheritedName
,
1637 bool OverridingProtocolProperty
) {
1638 ObjCPropertyAttribute::Kind CAttr
= Property
->getPropertyAttributes();
1639 ObjCPropertyAttribute::Kind SAttr
= SuperProperty
->getPropertyAttributes();
1641 // We allow readonly properties without an explicit ownership
1642 // (assign/unsafe_unretained/weak/retain/strong/copy) in super class
1643 // to be overridden by a property with any explicit ownership in the subclass.
1644 if (!OverridingProtocolProperty
&&
1645 !getOwnershipRule(SAttr
) && getOwnershipRule(CAttr
))
1648 if ((CAttr
& ObjCPropertyAttribute::kind_readonly
) &&
1649 (SAttr
& ObjCPropertyAttribute::kind_readwrite
))
1650 Diag(Property
->getLocation(), diag::warn_readonly_property
)
1651 << Property
->getDeclName() << inheritedName
;
1652 if ((CAttr
& ObjCPropertyAttribute::kind_copy
) !=
1653 (SAttr
& ObjCPropertyAttribute::kind_copy
))
1654 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1655 << Property
->getDeclName() << "copy" << inheritedName
;
1656 else if (!(SAttr
& ObjCPropertyAttribute::kind_readonly
)) {
1657 unsigned CAttrRetain
= (CAttr
& (ObjCPropertyAttribute::kind_retain
|
1658 ObjCPropertyAttribute::kind_strong
));
1659 unsigned SAttrRetain
= (SAttr
& (ObjCPropertyAttribute::kind_retain
|
1660 ObjCPropertyAttribute::kind_strong
));
1661 bool CStrong
= (CAttrRetain
!= 0);
1662 bool SStrong
= (SAttrRetain
!= 0);
1663 if (CStrong
!= SStrong
)
1664 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1665 << Property
->getDeclName() << "retain (or strong)" << inheritedName
;
1669 // Check for nonatomic; note that nonatomic is effectively
1670 // meaningless for readonly properties, so don't diagnose if the
1671 // atomic property is 'readonly'.
1672 checkAtomicPropertyMismatch(*this, SuperProperty
, Property
, false);
1673 // Readonly properties from protocols can be implemented as "readwrite"
1674 // with a custom setter name.
1675 if (Property
->getSetterName() != SuperProperty
->getSetterName() &&
1676 !(SuperProperty
->isReadOnly() &&
1677 isa
<ObjCProtocolDecl
>(SuperProperty
->getDeclContext()))) {
1678 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1679 << Property
->getDeclName() << "setter" << inheritedName
;
1680 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1682 if (Property
->getGetterName() != SuperProperty
->getGetterName()) {
1683 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1684 << Property
->getDeclName() << "getter" << inheritedName
;
1685 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1689 Context
.getCanonicalType(SuperProperty
->getType());
1691 Context
.getCanonicalType(Property
->getType());
1693 if (!Context
.propertyTypesAreCompatible(LHSType
, RHSType
)) {
1694 // Do cases not handled in above.
1695 // FIXME. For future support of covariant property types, revisit this.
1696 bool IncompatibleObjC
= false;
1697 QualType ConvertedType
;
1698 if (!isObjCPointerConversion(RHSType
, LHSType
,
1699 ConvertedType
, IncompatibleObjC
) ||
1701 Diag(Property
->getLocation(), diag::warn_property_types_are_incompatible
)
1702 << Property
->getType() << SuperProperty
->getType() << inheritedName
;
1703 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1708 bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl
*property
,
1709 ObjCMethodDecl
*GetterMethod
,
1710 SourceLocation Loc
) {
1713 QualType GetterType
= GetterMethod
->getReturnType().getNonReferenceType();
1714 QualType PropertyRValueType
=
1715 property
->getType().getNonReferenceType().getAtomicUnqualifiedType();
1716 bool compat
= Context
.hasSameType(PropertyRValueType
, GetterType
);
1718 const ObjCObjectPointerType
*propertyObjCPtr
= nullptr;
1719 const ObjCObjectPointerType
*getterObjCPtr
= nullptr;
1720 if ((propertyObjCPtr
=
1721 PropertyRValueType
->getAs
<ObjCObjectPointerType
>()) &&
1722 (getterObjCPtr
= GetterType
->getAs
<ObjCObjectPointerType
>()))
1723 compat
= Context
.canAssignObjCInterfaces(getterObjCPtr
, propertyObjCPtr
);
1724 else if (CheckAssignmentConstraints(Loc
, GetterType
, PropertyRValueType
)
1726 Diag(Loc
, diag::err_property_accessor_type
)
1727 << property
->getDeclName() << PropertyRValueType
1728 << GetterMethod
->getSelector() << GetterType
;
1729 Diag(GetterMethod
->getLocation(), diag::note_declared_at
);
1733 QualType lhsType
= Context
.getCanonicalType(PropertyRValueType
);
1734 QualType rhsType
=Context
.getCanonicalType(GetterType
).getUnqualifiedType();
1735 if (lhsType
!= rhsType
&& lhsType
->isArithmeticType())
1741 Diag(Loc
, diag::warn_accessor_property_type_mismatch
)
1742 << property
->getDeclName()
1743 << GetterMethod
->getSelector();
1744 Diag(GetterMethod
->getLocation(), diag::note_declared_at
);
1751 /// CollectImmediateProperties - This routine collects all properties in
1752 /// the class and its conforming protocols; but not those in its super class.
1754 CollectImmediateProperties(ObjCContainerDecl
*CDecl
,
1755 ObjCContainerDecl::PropertyMap
&PropMap
,
1756 ObjCContainerDecl::PropertyMap
&SuperPropMap
,
1757 bool CollectClassPropsOnly
= false,
1758 bool IncludeProtocols
= true) {
1759 if (ObjCInterfaceDecl
*IDecl
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
)) {
1760 for (auto *Prop
: IDecl
->properties()) {
1761 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1763 PropMap
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] =
1767 // Collect the properties from visible extensions.
1768 for (auto *Ext
: IDecl
->visible_extensions())
1769 CollectImmediateProperties(Ext
, PropMap
, SuperPropMap
,
1770 CollectClassPropsOnly
, IncludeProtocols
);
1772 if (IncludeProtocols
) {
1773 // Scan through class's protocols.
1774 for (auto *PI
: IDecl
->all_referenced_protocols())
1775 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1776 CollectClassPropsOnly
);
1779 if (ObjCCategoryDecl
*CATDecl
= dyn_cast
<ObjCCategoryDecl
>(CDecl
)) {
1780 for (auto *Prop
: CATDecl
->properties()) {
1781 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1783 PropMap
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] =
1786 if (IncludeProtocols
) {
1787 // Scan through class's protocols.
1788 for (auto *PI
: CATDecl
->protocols())
1789 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1790 CollectClassPropsOnly
);
1793 else if (ObjCProtocolDecl
*PDecl
= dyn_cast
<ObjCProtocolDecl
>(CDecl
)) {
1794 for (auto *Prop
: PDecl
->properties()) {
1795 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1797 ObjCPropertyDecl
*PropertyFromSuper
=
1798 SuperPropMap
[std::make_pair(Prop
->getIdentifier(),
1799 Prop
->isClassProperty())];
1800 // Exclude property for protocols which conform to class's super-class,
1801 // as super-class has to implement the property.
1802 if (!PropertyFromSuper
||
1803 PropertyFromSuper
->getIdentifier() != Prop
->getIdentifier()) {
1804 ObjCPropertyDecl
*&PropEntry
=
1805 PropMap
[std::make_pair(Prop
->getIdentifier(),
1806 Prop
->isClassProperty())];
1811 // Scan through protocol's protocols.
1812 for (auto *PI
: PDecl
->protocols())
1813 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1814 CollectClassPropsOnly
);
1818 /// CollectSuperClassPropertyImplementations - This routine collects list of
1819 /// properties to be implemented in super class(s) and also coming from their
1820 /// conforming protocols.
1821 static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl
*CDecl
,
1822 ObjCInterfaceDecl::PropertyMap
&PropMap
) {
1823 if (ObjCInterfaceDecl
*SDecl
= CDecl
->getSuperClass()) {
1825 SDecl
->collectPropertiesToImplement(PropMap
);
1826 SDecl
= SDecl
->getSuperClass();
1831 /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
1832 /// an ivar synthesized for 'Method' and 'Method' is a property accessor
1833 /// declared in class 'IFace'.
1835 Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl
*IFace
,
1836 ObjCMethodDecl
*Method
, ObjCIvarDecl
*IV
) {
1837 if (!IV
->getSynthesize())
1839 ObjCMethodDecl
*IMD
= IFace
->lookupMethod(Method
->getSelector(),
1840 Method
->isInstanceMethod());
1841 if (!IMD
|| !IMD
->isPropertyAccessor())
1844 // look up a property declaration whose one of its accessors is implemented
1846 for (const auto *Property
: IFace
->instance_properties()) {
1847 if ((Property
->getGetterName() == IMD
->getSelector() ||
1848 Property
->getSetterName() == IMD
->getSelector()) &&
1849 (Property
->getPropertyIvarDecl() == IV
))
1852 // Also look up property declaration in class extension whose one of its
1853 // accessors is implemented by this method.
1854 for (const auto *Ext
: IFace
->known_extensions())
1855 for (const auto *Property
: Ext
->instance_properties())
1856 if ((Property
->getGetterName() == IMD
->getSelector() ||
1857 Property
->getSetterName() == IMD
->getSelector()) &&
1858 (Property
->getPropertyIvarDecl() == IV
))
1863 static bool SuperClassImplementsProperty(ObjCInterfaceDecl
*IDecl
,
1864 ObjCPropertyDecl
*Prop
) {
1865 bool SuperClassImplementsGetter
= false;
1866 bool SuperClassImplementsSetter
= false;
1867 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly
)
1868 SuperClassImplementsSetter
= true;
1870 while (IDecl
->getSuperClass()) {
1871 ObjCInterfaceDecl
*SDecl
= IDecl
->getSuperClass();
1872 if (!SuperClassImplementsGetter
&& SDecl
->getInstanceMethod(Prop
->getGetterName()))
1873 SuperClassImplementsGetter
= true;
1875 if (!SuperClassImplementsSetter
&& SDecl
->getInstanceMethod(Prop
->getSetterName()))
1876 SuperClassImplementsSetter
= true;
1877 if (SuperClassImplementsGetter
&& SuperClassImplementsSetter
)
1879 IDecl
= IDecl
->getSuperClass();
1884 /// Default synthesizes all properties which must be synthesized
1885 /// in class's \@implementation.
1886 void Sema::DefaultSynthesizeProperties(Scope
*S
, ObjCImplDecl
*IMPDecl
,
1887 ObjCInterfaceDecl
*IDecl
,
1888 SourceLocation AtEnd
) {
1889 ObjCInterfaceDecl::PropertyMap PropMap
;
1890 IDecl
->collectPropertiesToImplement(PropMap
);
1891 if (PropMap
.empty())
1893 ObjCInterfaceDecl::PropertyMap SuperPropMap
;
1894 CollectSuperClassPropertyImplementations(IDecl
, SuperPropMap
);
1896 for (const auto &PropEntry
: PropMap
) {
1897 ObjCPropertyDecl
*Prop
= PropEntry
.second
;
1898 // Is there a matching property synthesize/dynamic?
1899 if (Prop
->isInvalidDecl() ||
1900 Prop
->isClassProperty() ||
1901 Prop
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
1903 // Property may have been synthesized by user.
1904 if (IMPDecl
->FindPropertyImplDecl(
1905 Prop
->getIdentifier(), Prop
->getQueryKind()))
1907 ObjCMethodDecl
*ImpMethod
= IMPDecl
->getInstanceMethod(Prop
->getGetterName());
1908 if (ImpMethod
&& !ImpMethod
->getBody()) {
1909 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly
)
1911 ImpMethod
= IMPDecl
->getInstanceMethod(Prop
->getSetterName());
1912 if (ImpMethod
&& !ImpMethod
->getBody())
1915 if (ObjCPropertyImplDecl
*PID
=
1916 IMPDecl
->FindPropertyImplIvarDecl(Prop
->getIdentifier())) {
1917 Diag(Prop
->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property
)
1918 << Prop
->getIdentifier();
1919 if (PID
->getLocation().isValid())
1920 Diag(PID
->getLocation(), diag::note_property_synthesize
);
1923 ObjCPropertyDecl
*PropInSuperClass
=
1924 SuperPropMap
[std::make_pair(Prop
->getIdentifier(),
1925 Prop
->isClassProperty())];
1926 if (ObjCProtocolDecl
*Proto
=
1927 dyn_cast
<ObjCProtocolDecl
>(Prop
->getDeclContext())) {
1928 // We won't auto-synthesize properties declared in protocols.
1929 // Suppress the warning if class's superclass implements property's
1930 // getter and implements property's setter (if readwrite property).
1931 // Or, if property is going to be implemented in its super class.
1932 if (!SuperClassImplementsProperty(IDecl
, Prop
) && !PropInSuperClass
) {
1933 Diag(IMPDecl
->getLocation(),
1934 diag::warn_auto_synthesizing_protocol_property
)
1936 Diag(Prop
->getLocation(), diag::note_property_declare
);
1938 (Twine("@synthesize ") + Prop
->getName() + ";\n\n").str();
1939 Diag(AtEnd
, diag::note_add_synthesize_directive
)
1940 << FixItHint::CreateInsertion(AtEnd
, FixIt
);
1944 // If property to be implemented in the super class, ignore.
1945 if (PropInSuperClass
) {
1946 if ((Prop
->getPropertyAttributes() &
1947 ObjCPropertyAttribute::kind_readwrite
) &&
1948 (PropInSuperClass
->getPropertyAttributes() &
1949 ObjCPropertyAttribute::kind_readonly
) &&
1950 !IMPDecl
->getInstanceMethod(Prop
->getSetterName()) &&
1951 !IDecl
->HasUserDeclaredSetterMethod(Prop
)) {
1952 Diag(Prop
->getLocation(), diag::warn_no_autosynthesis_property
)
1953 << Prop
->getIdentifier();
1954 Diag(PropInSuperClass
->getLocation(), diag::note_property_declare
);
1956 Diag(Prop
->getLocation(), diag::warn_autosynthesis_property_in_superclass
)
1957 << Prop
->getIdentifier();
1958 Diag(PropInSuperClass
->getLocation(), diag::note_property_declare
);
1959 Diag(IMPDecl
->getLocation(), diag::note_while_in_implementation
);
1963 // We use invalid SourceLocations for the synthesized ivars since they
1964 // aren't really synthesized at a particular location; they just exist.
1965 // Saying that they are located at the @implementation isn't really going
1967 ObjCPropertyImplDecl
*PIDecl
= dyn_cast_or_null
<ObjCPropertyImplDecl
>(
1968 ActOnPropertyImplDecl(S
, SourceLocation(), SourceLocation(),
1970 /* property = */ Prop
->getIdentifier(),
1971 /* ivar = */ Prop
->getDefaultSynthIvarName(Context
),
1972 Prop
->getLocation(), Prop
->getQueryKind()));
1973 if (PIDecl
&& !Prop
->isUnavailable()) {
1974 Diag(Prop
->getLocation(), diag::warn_missing_explicit_synthesis
);
1975 Diag(IMPDecl
->getLocation(), diag::note_while_in_implementation
);
1980 void Sema::DefaultSynthesizeProperties(Scope
*S
, Decl
*D
,
1981 SourceLocation AtEnd
) {
1982 if (!LangOpts
.ObjCDefaultSynthProperties
|| LangOpts
.ObjCRuntime
.isFragile())
1984 ObjCImplementationDecl
*IC
=dyn_cast_or_null
<ObjCImplementationDecl
>(D
);
1987 if (ObjCInterfaceDecl
* IDecl
= IC
->getClassInterface())
1988 if (!IDecl
->isObjCRequiresPropertyDefs())
1989 DefaultSynthesizeProperties(S
, IC
, IDecl
, AtEnd
);
1992 static void DiagnoseUnimplementedAccessor(
1993 Sema
&S
, ObjCInterfaceDecl
*PrimaryClass
, Selector Method
,
1994 ObjCImplDecl
*IMPDecl
, ObjCContainerDecl
*CDecl
, ObjCCategoryDecl
*C
,
1995 ObjCPropertyDecl
*Prop
,
1996 llvm::SmallPtrSet
<const ObjCMethodDecl
*, 8> &SMap
) {
1997 // Check to see if we have a corresponding selector in SMap and with the
1998 // right method type.
1999 auto I
= llvm::find_if(SMap
, [&](const ObjCMethodDecl
*x
) {
2000 return x
->getSelector() == Method
&&
2001 x
->isClassMethod() == Prop
->isClassProperty();
2003 // When reporting on missing property setter/getter implementation in
2004 // categories, do not report when they are declared in primary class,
2005 // class's protocol, or one of it super classes. This is because,
2006 // the class is going to implement them.
2007 if (I
== SMap
.end() &&
2008 (PrimaryClass
== nullptr ||
2009 !PrimaryClass
->lookupPropertyAccessor(Method
, C
,
2010 Prop
->isClassProperty()))) {
2012 isa
<ObjCCategoryDecl
>(CDecl
)
2013 ? (Prop
->isClassProperty()
2014 ? diag::warn_impl_required_in_category_for_class_property
2015 : diag::warn_setter_getter_impl_required_in_category
)
2016 : (Prop
->isClassProperty()
2017 ? diag::warn_impl_required_for_class_property
2018 : diag::warn_setter_getter_impl_required
);
2019 S
.Diag(IMPDecl
->getLocation(), diag
) << Prop
->getDeclName() << Method
;
2020 S
.Diag(Prop
->getLocation(), diag::note_property_declare
);
2021 if (S
.LangOpts
.ObjCDefaultSynthProperties
&&
2022 S
.LangOpts
.ObjCRuntime
.isNonFragile())
2023 if (ObjCInterfaceDecl
*ID
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
))
2024 if (const ObjCInterfaceDecl
*RID
= ID
->isObjCRequiresPropertyDefs())
2025 S
.Diag(RID
->getLocation(), diag::note_suppressed_class_declare
);
2029 void Sema::DiagnoseUnimplementedProperties(Scope
*S
, ObjCImplDecl
* IMPDecl
,
2030 ObjCContainerDecl
*CDecl
,
2031 bool SynthesizeProperties
) {
2032 ObjCContainerDecl::PropertyMap PropMap
;
2033 ObjCInterfaceDecl
*IDecl
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
);
2035 // Since we don't synthesize class properties, we should emit diagnose even
2036 // if SynthesizeProperties is true.
2037 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap
;
2038 // Gather properties which need not be implemented in this class
2041 if (ObjCCategoryDecl
*C
= dyn_cast
<ObjCCategoryDecl
>(CDecl
)) {
2042 // For categories, no need to implement properties declared in
2043 // its primary class (and its super classes) if property is
2044 // declared in one of those containers.
2045 if ((IDecl
= C
->getClassInterface())) {
2046 IDecl
->collectPropertiesToImplement(NoNeedToImplPropMap
);
2050 CollectSuperClassPropertyImplementations(IDecl
, NoNeedToImplPropMap
);
2052 // When SynthesizeProperties is true, we only check class properties.
2053 CollectImmediateProperties(CDecl
, PropMap
, NoNeedToImplPropMap
,
2054 SynthesizeProperties
/*CollectClassPropsOnly*/);
2056 // Scan the @interface to see if any of the protocols it adopts
2057 // require an explicit implementation, via attribute
2058 // 'objc_protocol_requires_explicit_implementation'.
2060 std::unique_ptr
<ObjCContainerDecl::PropertyMap
> LazyMap
;
2062 for (auto *PDecl
: IDecl
->all_referenced_protocols()) {
2063 if (!PDecl
->hasAttr
<ObjCExplicitProtocolImplAttr
>())
2065 // Lazily construct a set of all the properties in the @interface
2066 // of the class, without looking at the superclass. We cannot
2067 // use the call to CollectImmediateProperties() above as that
2068 // utilizes information from the super class's properties as well
2069 // as scans the adopted protocols. This work only triggers for protocols
2070 // with the attribute, which is very rare, and only occurs when
2071 // analyzing the @implementation.
2073 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap
;
2074 LazyMap
.reset(new ObjCContainerDecl::PropertyMap());
2075 CollectImmediateProperties(CDecl
, *LazyMap
, NoNeedToImplPropMap
,
2076 /* CollectClassPropsOnly */ false,
2077 /* IncludeProtocols */ false);
2079 // Add the properties of 'PDecl' to the list of properties that
2080 // need to be implemented.
2081 for (auto *PropDecl
: PDecl
->properties()) {
2082 if ((*LazyMap
)[std::make_pair(PropDecl
->getIdentifier(),
2083 PropDecl
->isClassProperty())])
2085 PropMap
[std::make_pair(PropDecl
->getIdentifier(),
2086 PropDecl
->isClassProperty())] = PropDecl
;
2091 if (PropMap
.empty())
2094 llvm::DenseSet
<ObjCPropertyDecl
*> PropImplMap
;
2095 for (const auto *I
: IMPDecl
->property_impls())
2096 PropImplMap
.insert(I
->getPropertyDecl());
2098 llvm::SmallPtrSet
<const ObjCMethodDecl
*, 8> InsMap
;
2099 // Collect property accessors implemented in current implementation.
2100 for (const auto *I
: IMPDecl
->methods())
2103 ObjCCategoryDecl
*C
= dyn_cast
<ObjCCategoryDecl
>(CDecl
);
2104 ObjCInterfaceDecl
*PrimaryClass
= nullptr;
2105 if (C
&& !C
->IsClassExtension())
2106 if ((PrimaryClass
= C
->getClassInterface()))
2107 // Report unimplemented properties in the category as well.
2108 if (ObjCImplDecl
*IMP
= PrimaryClass
->getImplementation()) {
2109 // When reporting on missing setter/getters, do not report when
2110 // setter/getter is implemented in category's primary class
2112 for (const auto *I
: IMP
->methods())
2116 for (ObjCContainerDecl::PropertyMap::iterator
2117 P
= PropMap
.begin(), E
= PropMap
.end(); P
!= E
; ++P
) {
2118 ObjCPropertyDecl
*Prop
= P
->second
;
2119 // Is there a matching property synthesize/dynamic?
2120 if (Prop
->isInvalidDecl() ||
2121 Prop
->getPropertyImplementation() == ObjCPropertyDecl::Optional
||
2122 PropImplMap
.count(Prop
) ||
2123 Prop
->getAvailability() == AR_Unavailable
)
2126 // Diagnose unimplemented getters and setters.
2127 DiagnoseUnimplementedAccessor(*this,
2128 PrimaryClass
, Prop
->getGetterName(), IMPDecl
, CDecl
, C
, Prop
, InsMap
);
2129 if (!Prop
->isReadOnly())
2130 DiagnoseUnimplementedAccessor(*this,
2131 PrimaryClass
, Prop
->getSetterName(),
2132 IMPDecl
, CDecl
, C
, Prop
, InsMap
);
2136 void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl
*impDecl
) {
2137 for (const auto *propertyImpl
: impDecl
->property_impls()) {
2138 const auto *property
= propertyImpl
->getPropertyDecl();
2139 // Warn about null_resettable properties with synthesized setters,
2140 // because the setter won't properly handle nil.
2141 if (propertyImpl
->getPropertyImplementation() ==
2142 ObjCPropertyImplDecl::Synthesize
&&
2143 (property
->getPropertyAttributes() &
2144 ObjCPropertyAttribute::kind_null_resettable
) &&
2145 property
->getGetterMethodDecl() && property
->getSetterMethodDecl()) {
2146 auto *getterImpl
= propertyImpl
->getGetterMethodDecl();
2147 auto *setterImpl
= propertyImpl
->getSetterMethodDecl();
2148 if ((!getterImpl
|| getterImpl
->isSynthesizedAccessorStub()) &&
2149 (!setterImpl
|| setterImpl
->isSynthesizedAccessorStub())) {
2150 SourceLocation loc
= propertyImpl
->getLocation();
2151 if (loc
.isInvalid())
2152 loc
= impDecl
->getBeginLoc();
2154 Diag(loc
, diag::warn_null_resettable_setter
)
2155 << setterImpl
->getSelector() << property
->getDeclName();
2162 Sema::AtomicPropertySetterGetterRules (ObjCImplDecl
* IMPDecl
,
2163 ObjCInterfaceDecl
* IDecl
) {
2164 // Rules apply in non-GC mode only
2165 if (getLangOpts().getGC() != LangOptions::NonGC
)
2167 ObjCContainerDecl::PropertyMap PM
;
2168 for (auto *Prop
: IDecl
->properties())
2169 PM
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] = Prop
;
2170 for (const auto *Ext
: IDecl
->known_extensions())
2171 for (auto *Prop
: Ext
->properties())
2172 PM
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] = Prop
;
2174 for (ObjCContainerDecl::PropertyMap::iterator I
= PM
.begin(), E
= PM
.end();
2176 const ObjCPropertyDecl
*Property
= I
->second
;
2177 ObjCMethodDecl
*GetterMethod
= nullptr;
2178 ObjCMethodDecl
*SetterMethod
= nullptr;
2180 unsigned Attributes
= Property
->getPropertyAttributes();
2181 unsigned AttributesAsWritten
= Property
->getPropertyAttributesAsWritten();
2183 if (!(AttributesAsWritten
& ObjCPropertyAttribute::kind_atomic
) &&
2184 !(AttributesAsWritten
& ObjCPropertyAttribute::kind_nonatomic
)) {
2185 GetterMethod
= Property
->isClassProperty() ?
2186 IMPDecl
->getClassMethod(Property
->getGetterName()) :
2187 IMPDecl
->getInstanceMethod(Property
->getGetterName());
2188 SetterMethod
= Property
->isClassProperty() ?
2189 IMPDecl
->getClassMethod(Property
->getSetterName()) :
2190 IMPDecl
->getInstanceMethod(Property
->getSetterName());
2191 if (GetterMethod
&& GetterMethod
->isSynthesizedAccessorStub())
2192 GetterMethod
= nullptr;
2193 if (SetterMethod
&& SetterMethod
->isSynthesizedAccessorStub())
2194 SetterMethod
= nullptr;
2196 Diag(GetterMethod
->getLocation(),
2197 diag::warn_default_atomic_custom_getter_setter
)
2198 << Property
->getIdentifier() << 0;
2199 Diag(Property
->getLocation(), diag::note_property_declare
);
2202 Diag(SetterMethod
->getLocation(),
2203 diag::warn_default_atomic_custom_getter_setter
)
2204 << Property
->getIdentifier() << 1;
2205 Diag(Property
->getLocation(), diag::note_property_declare
);
2209 // We only care about readwrite atomic property.
2210 if ((Attributes
& ObjCPropertyAttribute::kind_nonatomic
) ||
2211 !(Attributes
& ObjCPropertyAttribute::kind_readwrite
))
2213 if (const ObjCPropertyImplDecl
*PIDecl
= IMPDecl
->FindPropertyImplDecl(
2214 Property
->getIdentifier(), Property
->getQueryKind())) {
2215 if (PIDecl
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
)
2217 GetterMethod
= PIDecl
->getGetterMethodDecl();
2218 SetterMethod
= PIDecl
->getSetterMethodDecl();
2219 if (GetterMethod
&& GetterMethod
->isSynthesizedAccessorStub())
2220 GetterMethod
= nullptr;
2221 if (SetterMethod
&& SetterMethod
->isSynthesizedAccessorStub())
2222 SetterMethod
= nullptr;
2223 if ((bool)GetterMethod
^ (bool)SetterMethod
) {
2224 SourceLocation MethodLoc
=
2225 (GetterMethod
? GetterMethod
->getLocation()
2226 : SetterMethod
->getLocation());
2227 Diag(MethodLoc
, diag::warn_atomic_property_rule
)
2228 << Property
->getIdentifier() << (GetterMethod
!= nullptr)
2229 << (SetterMethod
!= nullptr);
2231 if (Property
->getLParenLoc().isValid() &&
2232 !(AttributesAsWritten
& ObjCPropertyAttribute::kind_atomic
)) {
2233 // @property () ... case.
2234 SourceLocation AfterLParen
=
2235 getLocForEndOfToken(Property
->getLParenLoc());
2236 StringRef NonatomicStr
= AttributesAsWritten
? "nonatomic, "
2238 Diag(Property
->getLocation(),
2239 diag::note_atomic_property_fixup_suggest
)
2240 << FixItHint::CreateInsertion(AfterLParen
, NonatomicStr
);
2241 } else if (Property
->getLParenLoc().isInvalid()) {
2243 SourceLocation startLoc
=
2244 Property
->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
2245 Diag(Property
->getLocation(),
2246 diag::note_atomic_property_fixup_suggest
)
2247 << FixItHint::CreateInsertion(startLoc
, "(nonatomic) ");
2249 Diag(MethodLoc
, diag::note_atomic_property_fixup_suggest
);
2250 Diag(Property
->getLocation(), diag::note_property_declare
);
2256 void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl
*D
) {
2257 if (getLangOpts().getGC() == LangOptions::GCOnly
)
2260 for (const auto *PID
: D
->property_impls()) {
2261 const ObjCPropertyDecl
*PD
= PID
->getPropertyDecl();
2262 if (PD
&& !PD
->hasAttr
<NSReturnsNotRetainedAttr
>() &&
2263 !PD
->isClassProperty()) {
2264 ObjCMethodDecl
*IM
= PID
->getGetterMethodDecl();
2265 if (IM
&& !IM
->isSynthesizedAccessorStub())
2267 ObjCMethodDecl
*method
= PD
->getGetterMethodDecl();
2270 ObjCMethodFamily family
= method
->getMethodFamily();
2271 if (family
== OMF_alloc
|| family
== OMF_copy
||
2272 family
== OMF_mutableCopy
|| family
== OMF_new
) {
2273 if (getLangOpts().ObjCAutoRefCount
)
2274 Diag(PD
->getLocation(), diag::err_cocoa_naming_owned_rule
);
2276 Diag(PD
->getLocation(), diag::warn_cocoa_naming_owned_rule
);
2278 // Look for a getter explicitly declared alongside the property.
2279 // If we find one, use its location for the note.
2280 SourceLocation noteLoc
= PD
->getLocation();
2281 SourceLocation fixItLoc
;
2282 for (auto *getterRedecl
: method
->redecls()) {
2283 if (getterRedecl
->isImplicit())
2285 if (getterRedecl
->getDeclContext() != PD
->getDeclContext())
2287 noteLoc
= getterRedecl
->getLocation();
2288 fixItLoc
= getterRedecl
->getEndLoc();
2291 Preprocessor
&PP
= getPreprocessor();
2292 TokenValue tokens
[] = {
2293 tok::kw___attribute
, tok::l_paren
, tok::l_paren
,
2294 PP
.getIdentifierInfo("objc_method_family"), tok::l_paren
,
2295 PP
.getIdentifierInfo("none"), tok::r_paren
,
2296 tok::r_paren
, tok::r_paren
2298 StringRef spelling
= "__attribute__((objc_method_family(none)))";
2299 StringRef macroName
= PP
.getLastMacroWithSpelling(noteLoc
, tokens
);
2300 if (!macroName
.empty())
2301 spelling
= macroName
;
2303 auto noteDiag
= Diag(noteLoc
, diag::note_cocoa_naming_declare_family
)
2304 << method
->getDeclName() << spelling
;
2305 if (fixItLoc
.isValid()) {
2306 SmallString
<64> fixItText(" ");
2307 fixItText
+= spelling
;
2308 noteDiag
<< FixItHint::CreateInsertion(fixItLoc
, fixItText
);
2315 void Sema::DiagnoseMissingDesignatedInitOverrides(
2316 const ObjCImplementationDecl
*ImplD
,
2317 const ObjCInterfaceDecl
*IFD
) {
2318 assert(IFD
->hasDesignatedInitializers());
2319 const ObjCInterfaceDecl
*SuperD
= IFD
->getSuperClass();
2323 SelectorSet InitSelSet
;
2324 for (const auto *I
: ImplD
->instance_methods())
2325 if (I
->getMethodFamily() == OMF_init
)
2326 InitSelSet
.insert(I
->getSelector());
2328 SmallVector
<const ObjCMethodDecl
*, 8> DesignatedInits
;
2329 SuperD
->getDesignatedInitializers(DesignatedInits
);
2330 for (SmallVector
<const ObjCMethodDecl
*, 8>::iterator
2331 I
= DesignatedInits
.begin(), E
= DesignatedInits
.end(); I
!= E
; ++I
) {
2332 const ObjCMethodDecl
*MD
= *I
;
2333 if (!InitSelSet
.count(MD
->getSelector())) {
2334 // Don't emit a diagnostic if the overriding method in the subclass is
2335 // marked as unavailable.
2336 bool Ignore
= false;
2337 if (auto *IMD
= IFD
->getInstanceMethod(MD
->getSelector())) {
2338 Ignore
= IMD
->isUnavailable();
2340 // Check the methods declared in the class extensions too.
2341 for (auto *Ext
: IFD
->visible_extensions())
2342 if (auto *IMD
= Ext
->getInstanceMethod(MD
->getSelector())) {
2343 Ignore
= IMD
->isUnavailable();
2348 Diag(ImplD
->getLocation(),
2349 diag::warn_objc_implementation_missing_designated_init_override
)
2350 << MD
->getSelector();
2351 Diag(MD
->getLocation(), diag::note_objc_designated_init_marked_here
);
2357 /// AddPropertyAttrs - Propagates attributes from a property to the
2358 /// implicitly-declared getter or setter for that property.
2359 static void AddPropertyAttrs(Sema
&S
, ObjCMethodDecl
*PropertyMethod
,
2360 ObjCPropertyDecl
*Property
) {
2361 // Should we just clone all attributes over?
2362 for (const auto *A
: Property
->attrs()) {
2363 if (isa
<DeprecatedAttr
>(A
) ||
2364 isa
<UnavailableAttr
>(A
) ||
2365 isa
<AvailabilityAttr
>(A
))
2366 PropertyMethod
->addAttr(A
->clone(S
.Context
));
2370 /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
2371 /// have the property type and issue diagnostics if they don't.
2372 /// Also synthesize a getter/setter method if none exist (and update the
2373 /// appropriate lookup tables.
2374 void Sema::ProcessPropertyDecl(ObjCPropertyDecl
*property
) {
2375 ObjCMethodDecl
*GetterMethod
, *SetterMethod
;
2376 ObjCContainerDecl
*CD
= cast
<ObjCContainerDecl
>(property
->getDeclContext());
2377 if (CD
->isInvalidDecl())
2380 bool IsClassProperty
= property
->isClassProperty();
2381 GetterMethod
= IsClassProperty
?
2382 CD
->getClassMethod(property
->getGetterName()) :
2383 CD
->getInstanceMethod(property
->getGetterName());
2385 // if setter or getter is not found in class extension, it might be
2386 // in the primary class.
2388 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2389 if (CatDecl
->IsClassExtension())
2390 GetterMethod
= IsClassProperty
? CatDecl
->getClassInterface()->
2391 getClassMethod(property
->getGetterName()) :
2392 CatDecl
->getClassInterface()->
2393 getInstanceMethod(property
->getGetterName());
2395 SetterMethod
= IsClassProperty
?
2396 CD
->getClassMethod(property
->getSetterName()) :
2397 CD
->getInstanceMethod(property
->getSetterName());
2399 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2400 if (CatDecl
->IsClassExtension())
2401 SetterMethod
= IsClassProperty
? CatDecl
->getClassInterface()->
2402 getClassMethod(property
->getSetterName()) :
2403 CatDecl
->getClassInterface()->
2404 getInstanceMethod(property
->getSetterName());
2405 DiagnosePropertyAccessorMismatch(property
, GetterMethod
,
2406 property
->getLocation());
2408 // synthesizing accessors must not result in a direct method that is not
2410 if (!GetterMethod
) {
2411 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
)) {
2412 auto *ExistingGetter
= CatDecl
->getClassInterface()->lookupMethod(
2413 property
->getGetterName(), !IsClassProperty
, true, false, CatDecl
);
2414 if (ExistingGetter
) {
2415 if (ExistingGetter
->isDirectMethod() || property
->isDirectProperty()) {
2416 Diag(property
->getLocation(), diag::err_objc_direct_duplicate_decl
)
2417 << property
->isDirectProperty() << 1 /* property */
2418 << ExistingGetter
->isDirectMethod()
2419 << ExistingGetter
->getDeclName();
2420 Diag(ExistingGetter
->getLocation(), diag::note_previous_declaration
);
2426 if (!property
->isReadOnly() && !SetterMethod
) {
2427 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
)) {
2428 auto *ExistingSetter
= CatDecl
->getClassInterface()->lookupMethod(
2429 property
->getSetterName(), !IsClassProperty
, true, false, CatDecl
);
2430 if (ExistingSetter
) {
2431 if (ExistingSetter
->isDirectMethod() || property
->isDirectProperty()) {
2432 Diag(property
->getLocation(), diag::err_objc_direct_duplicate_decl
)
2433 << property
->isDirectProperty() << 1 /* property */
2434 << ExistingSetter
->isDirectMethod()
2435 << ExistingSetter
->getDeclName();
2436 Diag(ExistingSetter
->getLocation(), diag::note_previous_declaration
);
2442 if (!property
->isReadOnly() && SetterMethod
) {
2443 if (Context
.getCanonicalType(SetterMethod
->getReturnType()) !=
2445 Diag(SetterMethod
->getLocation(), diag::err_setter_type_void
);
2446 if (SetterMethod
->param_size() != 1 ||
2447 !Context
.hasSameUnqualifiedType(
2448 (*SetterMethod
->param_begin())->getType().getNonReferenceType(),
2449 property
->getType().getNonReferenceType())) {
2450 Diag(property
->getLocation(),
2451 diag::warn_accessor_property_type_mismatch
)
2452 << property
->getDeclName()
2453 << SetterMethod
->getSelector();
2454 Diag(SetterMethod
->getLocation(), diag::note_declared_at
);
2458 // Synthesize getter/setter methods if none exist.
2459 // Find the default getter and if one not found, add one.
2460 // FIXME: The synthesized property we set here is misleading. We almost always
2461 // synthesize these methods unless the user explicitly provided prototypes
2462 // (which is odd, but allowed). Sema should be typechecking that the
2463 // declarations jive in that situation (which it is not currently).
2464 if (!GetterMethod
) {
2465 // No instance/class method of same name as property getter name was found.
2466 // Declare a getter method and add it to the list of methods
2468 SourceLocation Loc
= property
->getLocation();
2470 // The getter returns the declared property type with all qualifiers
2472 QualType resultTy
= property
->getType().getAtomicUnqualifiedType();
2474 // If the property is null_resettable, the getter returns nonnull.
2475 if (property
->getPropertyAttributes() &
2476 ObjCPropertyAttribute::kind_null_resettable
) {
2477 QualType modifiedTy
= resultTy
;
2478 if (auto nullability
= AttributedType::stripOuterNullability(modifiedTy
)) {
2479 if (*nullability
== NullabilityKind::Unspecified
)
2480 resultTy
= Context
.getAttributedType(attr::TypeNonNull
,
2481 modifiedTy
, modifiedTy
);
2485 GetterMethod
= ObjCMethodDecl::Create(
2486 Context
, Loc
, Loc
, property
->getGetterName(), resultTy
, nullptr, CD
,
2487 !IsClassProperty
, /*isVariadic=*/false,
2488 /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
2489 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
2490 (property
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
2491 ? ObjCImplementationControl::Optional
2492 : ObjCImplementationControl::Required
);
2493 CD
->addDecl(GetterMethod
);
2495 AddPropertyAttrs(*this, GetterMethod
, property
);
2497 if (property
->isDirectProperty())
2498 GetterMethod
->addAttr(ObjCDirectAttr::CreateImplicit(Context
, Loc
));
2500 if (property
->hasAttr
<NSReturnsNotRetainedAttr
>())
2501 GetterMethod
->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context
,
2504 if (property
->hasAttr
<ObjCReturnsInnerPointerAttr
>())
2505 GetterMethod
->addAttr(
2506 ObjCReturnsInnerPointerAttr::CreateImplicit(Context
, Loc
));
2508 if (const SectionAttr
*SA
= property
->getAttr
<SectionAttr
>())
2509 GetterMethod
->addAttr(SectionAttr::CreateImplicit(
2510 Context
, SA
->getName(), Loc
, SectionAttr::GNU_section
));
2512 if (getLangOpts().ObjCAutoRefCount
)
2513 CheckARCMethodDecl(GetterMethod
);
2515 // A user declared getter will be synthesize when @synthesize of
2516 // the property with the same name is seen in the @implementation
2517 GetterMethod
->setPropertyAccessor(true);
2519 GetterMethod
->createImplicitParams(Context
,
2520 GetterMethod
->getClassInterface());
2521 property
->setGetterMethodDecl(GetterMethod
);
2523 // Skip setter if property is read-only.
2524 if (!property
->isReadOnly()) {
2525 // Find the default setter and if one not found, add one.
2526 if (!SetterMethod
) {
2527 // No instance/class method of same name as property setter name was
2529 // Declare a setter method and add it to the list of methods
2531 SourceLocation Loc
= property
->getLocation();
2533 SetterMethod
= ObjCMethodDecl::Create(
2534 Context
, Loc
, Loc
, property
->getSetterName(), Context
.VoidTy
, nullptr,
2535 CD
, !IsClassProperty
,
2536 /*isVariadic=*/false,
2537 /*isPropertyAccessor=*/true,
2538 /*isSynthesizedAccessorStub=*/false,
2539 /*isImplicitlyDeclared=*/true,
2540 /*isDefined=*/false,
2541 (property
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
2542 ? ObjCImplementationControl::Optional
2543 : ObjCImplementationControl::Required
);
2545 // Remove all qualifiers from the setter's parameter type.
2547 property
->getType().getUnqualifiedType().getAtomicUnqualifiedType();
2549 // If the property is null_resettable, the setter accepts a
2551 if (property
->getPropertyAttributes() &
2552 ObjCPropertyAttribute::kind_null_resettable
) {
2553 QualType modifiedTy
= paramTy
;
2554 if (auto nullability
= AttributedType::stripOuterNullability(modifiedTy
)){
2555 if (*nullability
== NullabilityKind::Unspecified
)
2556 paramTy
= Context
.getAttributedType(attr::TypeNullable
,
2557 modifiedTy
, modifiedTy
);
2561 // Invent the arguments for the setter. We don't bother making a
2562 // nice name for the argument.
2563 ParmVarDecl
*Argument
= ParmVarDecl::Create(Context
, SetterMethod
,
2565 property
->getIdentifier(),
2570 SetterMethod
->setMethodParams(Context
, Argument
, std::nullopt
);
2572 AddPropertyAttrs(*this, SetterMethod
, property
);
2574 if (property
->isDirectProperty())
2575 SetterMethod
->addAttr(ObjCDirectAttr::CreateImplicit(Context
, Loc
));
2577 CD
->addDecl(SetterMethod
);
2578 if (const SectionAttr
*SA
= property
->getAttr
<SectionAttr
>())
2579 SetterMethod
->addAttr(SectionAttr::CreateImplicit(
2580 Context
, SA
->getName(), Loc
, SectionAttr::GNU_section
));
2581 // It's possible for the user to have set a very odd custom
2582 // setter selector that causes it to have a method family.
2583 if (getLangOpts().ObjCAutoRefCount
)
2584 CheckARCMethodDecl(SetterMethod
);
2586 // A user declared setter will be synthesize when @synthesize of
2587 // the property with the same name is seen in the @implementation
2588 SetterMethod
->setPropertyAccessor(true);
2590 SetterMethod
->createImplicitParams(Context
,
2591 SetterMethod
->getClassInterface());
2592 property
->setSetterMethodDecl(SetterMethod
);
2594 // Add any synthesized methods to the global pool. This allows us to
2595 // handle the following, which is supported by GCC (and part of the design).
2598 // @property double bar;
2601 // void thisIsUnfortunate() {
2603 // double bar = [foo bar];
2606 if (!IsClassProperty
) {
2608 AddInstanceMethodToGlobalPool(GetterMethod
);
2610 AddInstanceMethodToGlobalPool(SetterMethod
);
2613 AddFactoryMethodToGlobalPool(GetterMethod
);
2615 AddFactoryMethodToGlobalPool(SetterMethod
);
2618 ObjCInterfaceDecl
*CurrentClass
= dyn_cast
<ObjCInterfaceDecl
>(CD
);
2619 if (!CurrentClass
) {
2620 if (ObjCCategoryDecl
*Cat
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2621 CurrentClass
= Cat
->getClassInterface();
2622 else if (ObjCImplDecl
*Impl
= dyn_cast
<ObjCImplDecl
>(CD
))
2623 CurrentClass
= Impl
->getClassInterface();
2626 CheckObjCMethodOverrides(GetterMethod
, CurrentClass
, Sema::RTC_Unknown
);
2628 CheckObjCMethodOverrides(SetterMethod
, CurrentClass
, Sema::RTC_Unknown
);
2631 void Sema::CheckObjCPropertyAttributes(Decl
*PDecl
,
2633 unsigned &Attributes
,
2634 bool propertyInPrimaryClass
) {
2635 // FIXME: Improve the reported location.
2636 if (!PDecl
|| PDecl
->isInvalidDecl())
2639 if ((Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2640 (Attributes
& ObjCPropertyAttribute::kind_readwrite
))
2641 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2642 << "readonly" << "readwrite";
2644 ObjCPropertyDecl
*PropertyDecl
= cast
<ObjCPropertyDecl
>(PDecl
);
2645 QualType PropertyTy
= PropertyDecl
->getType();
2647 // Check for copy or retain on non-object types.
2649 (ObjCPropertyAttribute::kind_weak
| ObjCPropertyAttribute::kind_copy
|
2650 ObjCPropertyAttribute::kind_retain
|
2651 ObjCPropertyAttribute::kind_strong
)) &&
2652 !PropertyTy
->isObjCRetainableType() &&
2653 !PropertyDecl
->hasAttr
<ObjCNSObjectAttr
>()) {
2654 Diag(Loc
, diag::err_objc_property_requires_object
)
2655 << (Attributes
& ObjCPropertyAttribute::kind_weak
2657 : Attributes
& ObjCPropertyAttribute::kind_copy
2659 : "retain (or strong)");
2661 ~(ObjCPropertyAttribute::kind_weak
| ObjCPropertyAttribute::kind_copy
|
2662 ObjCPropertyAttribute::kind_retain
|
2663 ObjCPropertyAttribute::kind_strong
);
2664 PropertyDecl
->setInvalidDecl();
2667 // Check for assign on object types.
2668 if ((Attributes
& ObjCPropertyAttribute::kind_assign
) &&
2669 !(Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
) &&
2670 PropertyTy
->isObjCRetainableType() &&
2671 !PropertyTy
->isObjCARCImplicitlyUnretainedType()) {
2672 Diag(Loc
, diag::warn_objc_property_assign_on_object
);
2675 // Check for more than one of { assign, copy, retain }.
2676 if (Attributes
& ObjCPropertyAttribute::kind_assign
) {
2677 if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2678 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2679 << "assign" << "copy";
2680 Attributes
&= ~ObjCPropertyAttribute::kind_copy
;
2682 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2683 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2684 << "assign" << "retain";
2685 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2687 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2688 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2689 << "assign" << "strong";
2690 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2692 if (getLangOpts().ObjCAutoRefCount
&&
2693 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2694 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2695 << "assign" << "weak";
2696 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2698 if (PropertyDecl
->hasAttr
<IBOutletCollectionAttr
>())
2699 Diag(Loc
, diag::warn_iboutletcollection_property_assign
);
2700 } else if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
) {
2701 if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2702 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2703 << "unsafe_unretained" << "copy";
2704 Attributes
&= ~ObjCPropertyAttribute::kind_copy
;
2706 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2707 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2708 << "unsafe_unretained" << "retain";
2709 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2711 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2712 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2713 << "unsafe_unretained" << "strong";
2714 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2716 if (getLangOpts().ObjCAutoRefCount
&&
2717 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2718 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2719 << "unsafe_unretained" << "weak";
2720 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2722 } else if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2723 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2724 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2725 << "copy" << "retain";
2726 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2728 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2729 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2730 << "copy" << "strong";
2731 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2733 if (Attributes
& ObjCPropertyAttribute::kind_weak
) {
2734 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2735 << "copy" << "weak";
2736 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2738 } else if ((Attributes
& ObjCPropertyAttribute::kind_retain
) &&
2739 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2740 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "retain"
2742 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2743 } else if ((Attributes
& ObjCPropertyAttribute::kind_strong
) &&
2744 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2745 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "strong"
2747 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2750 if (Attributes
& ObjCPropertyAttribute::kind_weak
) {
2751 // 'weak' and 'nonnull' are mutually exclusive.
2752 if (auto nullability
= PropertyTy
->getNullability()) {
2753 if (*nullability
== NullabilityKind::NonNull
)
2754 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2755 << "nonnull" << "weak";
2759 if ((Attributes
& ObjCPropertyAttribute::kind_atomic
) &&
2760 (Attributes
& ObjCPropertyAttribute::kind_nonatomic
)) {
2761 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "atomic"
2763 Attributes
&= ~ObjCPropertyAttribute::kind_atomic
;
2766 // Warn if user supplied no assignment attribute, property is
2767 // readwrite, and this is an object type.
2768 if (!getOwnershipRule(Attributes
) && PropertyTy
->isObjCRetainableType()) {
2769 if (Attributes
& ObjCPropertyAttribute::kind_readonly
) {
2771 } else if (getLangOpts().ObjCAutoRefCount
) {
2772 // With arc, @property definitions should default to strong when
2774 PropertyDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
2775 } else if (PropertyTy
->isObjCObjectPointerType()) {
2776 bool isAnyClassTy
= (PropertyTy
->isObjCClassType() ||
2777 PropertyTy
->isObjCQualifiedClassType());
2778 // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
2779 // issue any warning.
2780 if (isAnyClassTy
&& getLangOpts().getGC() == LangOptions::NonGC
)
2782 else if (propertyInPrimaryClass
) {
2783 // Don't issue warning on property with no life time in class
2784 // extension as it is inherited from property in primary class.
2785 // Skip this warning in gc-only mode.
2786 if (getLangOpts().getGC() != LangOptions::GCOnly
)
2787 Diag(Loc
, diag::warn_objc_property_no_assignment_attribute
);
2789 // If non-gc code warn that this is likely inappropriate.
2790 if (getLangOpts().getGC() == LangOptions::NonGC
)
2791 Diag(Loc
, diag::warn_objc_property_default_assign_on_object
);
2795 // FIXME: Implement warning dependent on NSCopying being
2799 if (!(Attributes
& ObjCPropertyAttribute::kind_copy
) &&
2800 !(Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2801 getLangOpts().getGC() == LangOptions::GCOnly
&&
2802 PropertyTy
->isBlockPointerType())
2803 Diag(Loc
, diag::warn_objc_property_copy_missing_on_block
);
2804 else if ((Attributes
& ObjCPropertyAttribute::kind_retain
) &&
2805 !(Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2806 !(Attributes
& ObjCPropertyAttribute::kind_strong
) &&
2807 PropertyTy
->isBlockPointerType())
2808 Diag(Loc
, diag::warn_objc_property_retain_of_block
);
2810 if ((Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2811 (Attributes
& ObjCPropertyAttribute::kind_setter
))
2812 Diag(Loc
, diag::warn_objc_readonly_property_has_setter
);