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
))
1367 Context
.canAssignObjCInterfaces(
1368 PropertyIvarType
->getAs
<ObjCObjectPointerType
>(),
1369 IvarType
->getAs
<ObjCObjectPointerType
>());
1371 compat
= (CheckAssignmentConstraints(PropertyIvarLoc
, PropertyIvarType
,
1376 Diag(PropertyDiagLoc
, diag::err_property_ivar_type
)
1377 << property
->getDeclName() << PropType
1378 << Ivar
->getDeclName() << IvarType
;
1379 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1380 // Note! I deliberately want it to fall thru so, we have a
1381 // a property implementation and to avoid future warnings.
1384 // FIXME! Rules for properties are somewhat different that those
1385 // for assignments. Use a new routine to consolidate all cases;
1386 // specifically for property redeclarations as well as for ivars.
1387 QualType lhsType
=Context
.getCanonicalType(PropertyIvarType
).getUnqualifiedType();
1388 QualType rhsType
=Context
.getCanonicalType(IvarType
).getUnqualifiedType();
1389 if (lhsType
!= rhsType
&&
1390 lhsType
->isArithmeticType()) {
1391 Diag(PropertyDiagLoc
, diag::err_property_ivar_type
)
1392 << property
->getDeclName() << PropType
1393 << Ivar
->getDeclName() << IvarType
;
1394 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1395 // Fall thru - see previous comment
1398 // __weak is explicit. So it works on Canonical type.
1399 if ((PropType
.isObjCGCWeak() && !IvarType
.isObjCGCWeak() &&
1400 getLangOpts().getGC() != LangOptions::NonGC
)) {
1401 Diag(PropertyDiagLoc
, diag::err_weak_property
)
1402 << property
->getDeclName() << Ivar
->getDeclName();
1403 Diag(Ivar
->getLocation(), diag::note_ivar_decl
);
1404 // Fall thru - see previous comment
1406 // Fall thru - see previous comment
1407 if ((property
->getType()->isObjCObjectPointerType() ||
1408 PropType
.isObjCGCStrong()) && IvarType
.isObjCGCWeak() &&
1409 getLangOpts().getGC() != LangOptions::NonGC
) {
1410 Diag(PropertyDiagLoc
, diag::err_strong_property
)
1411 << property
->getDeclName() << Ivar
->getDeclName();
1412 // Fall thru - see previous comment
1415 if (getLangOpts().ObjCAutoRefCount
|| isARCWeak
||
1416 Ivar
->getType().getObjCLifetime())
1417 checkARCPropertyImpl(*this, PropertyLoc
, property
, Ivar
);
1418 } else if (PropertyIvar
)
1420 Diag(PropertyDiagLoc
, diag::err_dynamic_property_ivar_decl
);
1422 assert (property
&& "ActOnPropertyImplDecl - property declaration missing");
1423 ObjCPropertyImplDecl
*PIDecl
=
1424 ObjCPropertyImplDecl::Create(Context
, CurContext
, AtLoc
, PropertyLoc
,
1427 ObjCPropertyImplDecl::Synthesize
1428 : ObjCPropertyImplDecl::Dynamic
),
1429 Ivar
, PropertyIvarLoc
);
1431 if (CompleteTypeErr
|| !compat
)
1432 PIDecl
->setInvalidDecl();
1434 if (ObjCMethodDecl
*getterMethod
= property
->getGetterMethodDecl()) {
1435 getterMethod
->createImplicitParams(Context
, IDecl
);
1437 // Redeclare the getter within the implementation as DeclContext.
1439 // If the method hasn't been overridden, create a synthesized implementation.
1440 ObjCMethodDecl
*OMD
= ClassImpDecl
->getMethod(
1441 getterMethod
->getSelector(), getterMethod
->isInstanceMethod());
1443 OMD
= RedeclarePropertyAccessor(Context
, IC
, getterMethod
, AtLoc
,
1445 PIDecl
->setGetterMethodDecl(OMD
);
1448 if (getLangOpts().CPlusPlus
&& Synthesize
&& !CompleteTypeErr
&&
1449 Ivar
->getType()->isRecordType()) {
1450 // For Objective-C++, need to synthesize the AST for the IVAR object to be
1451 // returned by the getter as it must conform to C++'s copy-return rules.
1452 // FIXME. Eventually we want to do this for Objective-C as well.
1453 SynthesizedFunctionScope
Scope(*this, getterMethod
);
1454 ImplicitParamDecl
*SelfDecl
= getterMethod
->getSelfDecl();
1455 DeclRefExpr
*SelfExpr
= new (Context
)
1456 DeclRefExpr(Context
, SelfDecl
, false, SelfDecl
->getType(), VK_LValue
,
1458 MarkDeclRefReferenced(SelfExpr
);
1459 Expr
*LoadSelfExpr
= ImplicitCastExpr::Create(
1460 Context
, SelfDecl
->getType(), CK_LValueToRValue
, SelfExpr
, nullptr,
1461 VK_PRValue
, FPOptionsOverride());
1463 new (Context
) ObjCIvarRefExpr(Ivar
,
1464 Ivar
->getUsageType(SelfDecl
->getType()),
1466 Ivar
->getLocation(),
1467 LoadSelfExpr
, true, true);
1468 ExprResult Res
= PerformCopyInitialization(
1469 InitializedEntity::InitializeResult(PropertyDiagLoc
,
1470 getterMethod
->getReturnType()),
1471 PropertyDiagLoc
, IvarRefExpr
);
1472 if (!Res
.isInvalid()) {
1473 Expr
*ResExpr
= Res
.getAs
<Expr
>();
1475 ResExpr
= MaybeCreateExprWithCleanups(ResExpr
);
1476 PIDecl
->setGetterCXXConstructor(ResExpr
);
1479 if (property
->hasAttr
<NSReturnsNotRetainedAttr
>() &&
1480 !getterMethod
->hasAttr
<NSReturnsNotRetainedAttr
>()) {
1481 Diag(getterMethod
->getLocation(),
1482 diag::warn_property_getter_owning_mismatch
);
1483 Diag(property
->getLocation(), diag::note_property_declare
);
1485 if (getLangOpts().ObjCAutoRefCount
&& Synthesize
)
1486 switch (getterMethod
->getMethodFamily()) {
1488 case OMF_retainCount
:
1490 case OMF_autorelease
:
1491 Diag(getterMethod
->getLocation(), diag::err_arc_illegal_method_def
)
1492 << 1 << getterMethod
->getSelector();
1499 if (ObjCMethodDecl
*setterMethod
= property
->getSetterMethodDecl()) {
1500 setterMethod
->createImplicitParams(Context
, IDecl
);
1502 // Redeclare the setter within the implementation as DeclContext.
1504 ObjCMethodDecl
*OMD
= ClassImpDecl
->getMethod(
1505 setterMethod
->getSelector(), setterMethod
->isInstanceMethod());
1507 OMD
= RedeclarePropertyAccessor(Context
, IC
, setterMethod
,
1508 AtLoc
, PropertyLoc
);
1509 PIDecl
->setSetterMethodDecl(OMD
);
1512 if (getLangOpts().CPlusPlus
&& Synthesize
&& !CompleteTypeErr
&&
1513 Ivar
->getType()->isRecordType()) {
1514 // FIXME. Eventually we want to do this for Objective-C as well.
1515 SynthesizedFunctionScope
Scope(*this, setterMethod
);
1516 ImplicitParamDecl
*SelfDecl
= setterMethod
->getSelfDecl();
1517 DeclRefExpr
*SelfExpr
= new (Context
)
1518 DeclRefExpr(Context
, SelfDecl
, false, SelfDecl
->getType(), VK_LValue
,
1520 MarkDeclRefReferenced(SelfExpr
);
1521 Expr
*LoadSelfExpr
= ImplicitCastExpr::Create(
1522 Context
, SelfDecl
->getType(), CK_LValueToRValue
, SelfExpr
, nullptr,
1523 VK_PRValue
, FPOptionsOverride());
1525 new (Context
) ObjCIvarRefExpr(Ivar
,
1526 Ivar
->getUsageType(SelfDecl
->getType()),
1528 Ivar
->getLocation(),
1529 LoadSelfExpr
, true, true);
1530 ObjCMethodDecl::param_iterator P
= setterMethod
->param_begin();
1531 ParmVarDecl
*Param
= (*P
);
1532 QualType T
= Param
->getType().getNonReferenceType();
1533 DeclRefExpr
*rhs
= new (Context
)
1534 DeclRefExpr(Context
, Param
, false, T
, VK_LValue
, PropertyDiagLoc
);
1535 MarkDeclRefReferenced(rhs
);
1536 ExprResult Res
= BuildBinOp(S
, PropertyDiagLoc
,
1537 BO_Assign
, lhs
, rhs
);
1538 if (property
->getPropertyAttributes() &
1539 ObjCPropertyAttribute::kind_atomic
) {
1540 Expr
*callExpr
= Res
.getAs
<Expr
>();
1541 if (const CXXOperatorCallExpr
*CXXCE
=
1542 dyn_cast_or_null
<CXXOperatorCallExpr
>(callExpr
))
1543 if (const FunctionDecl
*FuncDecl
= CXXCE
->getDirectCallee())
1544 if (!FuncDecl
->isTrivial())
1545 if (property
->getType()->isReferenceType()) {
1546 Diag(PropertyDiagLoc
,
1547 diag::err_atomic_property_nontrivial_assign_op
)
1548 << property
->getType();
1549 Diag(FuncDecl
->getBeginLoc(), diag::note_callee_decl
)
1553 PIDecl
->setSetterCXXAssignment(Res
.getAs
<Expr
>());
1559 if (ObjCPropertyImplDecl
*PPIDecl
=
1560 IC
->FindPropertyImplIvarDecl(PropertyIvar
)) {
1561 Diag(PropertyLoc
, diag::err_duplicate_ivar_use
)
1562 << PropertyId
<< PPIDecl
->getPropertyDecl()->getIdentifier()
1564 Diag(PPIDecl
->getLocation(), diag::note_previous_use
);
1567 if (ObjCPropertyImplDecl
*PPIDecl
1568 = IC
->FindPropertyImplDecl(PropertyId
, QueryKind
)) {
1569 Diag(PropertyLoc
, diag::err_property_implemented
) << PropertyId
;
1570 Diag(PPIDecl
->getLocation(), diag::note_previous_declaration
);
1573 IC
->addPropertyImplementation(PIDecl
);
1574 if (getLangOpts().ObjCDefaultSynthProperties
&&
1575 getLangOpts().ObjCRuntime
.isNonFragile() &&
1576 !IDecl
->isObjCRequiresPropertyDefs()) {
1577 // Diagnose if an ivar was lazily synthesdized due to a previous
1578 // use and if 1) property is @dynamic or 2) property is synthesized
1579 // but it requires an ivar of different name.
1580 ObjCInterfaceDecl
*ClassDeclared
=nullptr;
1581 ObjCIvarDecl
*Ivar
= nullptr;
1583 Ivar
= IDecl
->lookupInstanceVariable(PropertyId
, ClassDeclared
);
1585 if (PropertyIvar
&& PropertyIvar
!= PropertyId
)
1586 Ivar
= IDecl
->lookupInstanceVariable(PropertyId
, ClassDeclared
);
1588 // Issue diagnostics only if Ivar belongs to current class.
1589 if (Ivar
&& Ivar
->getSynthesize() &&
1590 declaresSameEntity(IC
->getClassInterface(), ClassDeclared
)) {
1591 Diag(Ivar
->getLocation(), diag::err_undeclared_var_use
)
1593 Ivar
->setInvalidDecl();
1598 if (ObjCPropertyImplDecl
*PPIDecl
=
1599 CatImplClass
->FindPropertyImplIvarDecl(PropertyIvar
)) {
1600 Diag(PropertyDiagLoc
, diag::err_duplicate_ivar_use
)
1601 << PropertyId
<< PPIDecl
->getPropertyDecl()->getIdentifier()
1603 Diag(PPIDecl
->getLocation(), diag::note_previous_use
);
1606 if (ObjCPropertyImplDecl
*PPIDecl
=
1607 CatImplClass
->FindPropertyImplDecl(PropertyId
, QueryKind
)) {
1608 Diag(PropertyDiagLoc
, diag::err_property_implemented
) << PropertyId
;
1609 Diag(PPIDecl
->getLocation(), diag::note_previous_declaration
);
1612 CatImplClass
->addPropertyImplementation(PIDecl
);
1615 if (PIDecl
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
&&
1616 PIDecl
->getPropertyDecl() &&
1617 PIDecl
->getPropertyDecl()->isDirectProperty()) {
1618 Diag(PropertyLoc
, diag::err_objc_direct_dynamic_property
);
1619 Diag(PIDecl
->getPropertyDecl()->getLocation(),
1620 diag::note_previous_declaration
);
1627 //===----------------------------------------------------------------------===//
1629 //===----------------------------------------------------------------------===//
1631 /// DiagnosePropertyMismatch - Compares two properties for their
1632 /// attributes and types and warns on a variety of inconsistencies.
1635 Sema::DiagnosePropertyMismatch(ObjCPropertyDecl
*Property
,
1636 ObjCPropertyDecl
*SuperProperty
,
1637 const IdentifierInfo
*inheritedName
,
1638 bool OverridingProtocolProperty
) {
1639 ObjCPropertyAttribute::Kind CAttr
= Property
->getPropertyAttributes();
1640 ObjCPropertyAttribute::Kind SAttr
= SuperProperty
->getPropertyAttributes();
1642 // We allow readonly properties without an explicit ownership
1643 // (assign/unsafe_unretained/weak/retain/strong/copy) in super class
1644 // to be overridden by a property with any explicit ownership in the subclass.
1645 if (!OverridingProtocolProperty
&&
1646 !getOwnershipRule(SAttr
) && getOwnershipRule(CAttr
))
1649 if ((CAttr
& ObjCPropertyAttribute::kind_readonly
) &&
1650 (SAttr
& ObjCPropertyAttribute::kind_readwrite
))
1651 Diag(Property
->getLocation(), diag::warn_readonly_property
)
1652 << Property
->getDeclName() << inheritedName
;
1653 if ((CAttr
& ObjCPropertyAttribute::kind_copy
) !=
1654 (SAttr
& ObjCPropertyAttribute::kind_copy
))
1655 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1656 << Property
->getDeclName() << "copy" << inheritedName
;
1657 else if (!(SAttr
& ObjCPropertyAttribute::kind_readonly
)) {
1658 unsigned CAttrRetain
= (CAttr
& (ObjCPropertyAttribute::kind_retain
|
1659 ObjCPropertyAttribute::kind_strong
));
1660 unsigned SAttrRetain
= (SAttr
& (ObjCPropertyAttribute::kind_retain
|
1661 ObjCPropertyAttribute::kind_strong
));
1662 bool CStrong
= (CAttrRetain
!= 0);
1663 bool SStrong
= (SAttrRetain
!= 0);
1664 if (CStrong
!= SStrong
)
1665 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1666 << Property
->getDeclName() << "retain (or strong)" << inheritedName
;
1670 // Check for nonatomic; note that nonatomic is effectively
1671 // meaningless for readonly properties, so don't diagnose if the
1672 // atomic property is 'readonly'.
1673 checkAtomicPropertyMismatch(*this, SuperProperty
, Property
, false);
1674 // Readonly properties from protocols can be implemented as "readwrite"
1675 // with a custom setter name.
1676 if (Property
->getSetterName() != SuperProperty
->getSetterName() &&
1677 !(SuperProperty
->isReadOnly() &&
1678 isa
<ObjCProtocolDecl
>(SuperProperty
->getDeclContext()))) {
1679 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1680 << Property
->getDeclName() << "setter" << inheritedName
;
1681 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1683 if (Property
->getGetterName() != SuperProperty
->getGetterName()) {
1684 Diag(Property
->getLocation(), diag::warn_property_attribute
)
1685 << Property
->getDeclName() << "getter" << inheritedName
;
1686 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1690 Context
.getCanonicalType(SuperProperty
->getType());
1692 Context
.getCanonicalType(Property
->getType());
1694 if (!Context
.propertyTypesAreCompatible(LHSType
, RHSType
)) {
1695 // Do cases not handled in above.
1696 // FIXME. For future support of covariant property types, revisit this.
1697 bool IncompatibleObjC
= false;
1698 QualType ConvertedType
;
1699 if (!isObjCPointerConversion(RHSType
, LHSType
,
1700 ConvertedType
, IncompatibleObjC
) ||
1702 Diag(Property
->getLocation(), diag::warn_property_types_are_incompatible
)
1703 << Property
->getType() << SuperProperty
->getType() << inheritedName
;
1704 Diag(SuperProperty
->getLocation(), diag::note_property_declare
);
1709 bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl
*property
,
1710 ObjCMethodDecl
*GetterMethod
,
1711 SourceLocation Loc
) {
1714 QualType GetterType
= GetterMethod
->getReturnType().getNonReferenceType();
1715 QualType PropertyRValueType
=
1716 property
->getType().getNonReferenceType().getAtomicUnqualifiedType();
1717 bool compat
= Context
.hasSameType(PropertyRValueType
, GetterType
);
1719 const ObjCObjectPointerType
*propertyObjCPtr
= nullptr;
1720 const ObjCObjectPointerType
*getterObjCPtr
= nullptr;
1721 if ((propertyObjCPtr
=
1722 PropertyRValueType
->getAs
<ObjCObjectPointerType
>()) &&
1723 (getterObjCPtr
= GetterType
->getAs
<ObjCObjectPointerType
>()))
1724 compat
= Context
.canAssignObjCInterfaces(getterObjCPtr
, propertyObjCPtr
);
1725 else if (CheckAssignmentConstraints(Loc
, GetterType
, PropertyRValueType
)
1727 Diag(Loc
, diag::err_property_accessor_type
)
1728 << property
->getDeclName() << PropertyRValueType
1729 << GetterMethod
->getSelector() << GetterType
;
1730 Diag(GetterMethod
->getLocation(), diag::note_declared_at
);
1734 QualType lhsType
= Context
.getCanonicalType(PropertyRValueType
);
1735 QualType rhsType
=Context
.getCanonicalType(GetterType
).getUnqualifiedType();
1736 if (lhsType
!= rhsType
&& lhsType
->isArithmeticType())
1742 Diag(Loc
, diag::warn_accessor_property_type_mismatch
)
1743 << property
->getDeclName()
1744 << GetterMethod
->getSelector();
1745 Diag(GetterMethod
->getLocation(), diag::note_declared_at
);
1752 /// CollectImmediateProperties - This routine collects all properties in
1753 /// the class and its conforming protocols; but not those in its super class.
1755 CollectImmediateProperties(ObjCContainerDecl
*CDecl
,
1756 ObjCContainerDecl::PropertyMap
&PropMap
,
1757 ObjCContainerDecl::PropertyMap
&SuperPropMap
,
1758 bool CollectClassPropsOnly
= false,
1759 bool IncludeProtocols
= true) {
1760 if (ObjCInterfaceDecl
*IDecl
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
)) {
1761 for (auto *Prop
: IDecl
->properties()) {
1762 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1764 PropMap
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] =
1768 // Collect the properties from visible extensions.
1769 for (auto *Ext
: IDecl
->visible_extensions())
1770 CollectImmediateProperties(Ext
, PropMap
, SuperPropMap
,
1771 CollectClassPropsOnly
, IncludeProtocols
);
1773 if (IncludeProtocols
) {
1774 // Scan through class's protocols.
1775 for (auto *PI
: IDecl
->all_referenced_protocols())
1776 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1777 CollectClassPropsOnly
);
1780 if (ObjCCategoryDecl
*CATDecl
= dyn_cast
<ObjCCategoryDecl
>(CDecl
)) {
1781 for (auto *Prop
: CATDecl
->properties()) {
1782 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1784 PropMap
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] =
1787 if (IncludeProtocols
) {
1788 // Scan through class's protocols.
1789 for (auto *PI
: CATDecl
->protocols())
1790 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1791 CollectClassPropsOnly
);
1794 else if (ObjCProtocolDecl
*PDecl
= dyn_cast
<ObjCProtocolDecl
>(CDecl
)) {
1795 for (auto *Prop
: PDecl
->properties()) {
1796 if (CollectClassPropsOnly
&& !Prop
->isClassProperty())
1798 ObjCPropertyDecl
*PropertyFromSuper
=
1799 SuperPropMap
[std::make_pair(Prop
->getIdentifier(),
1800 Prop
->isClassProperty())];
1801 // Exclude property for protocols which conform to class's super-class,
1802 // as super-class has to implement the property.
1803 if (!PropertyFromSuper
||
1804 PropertyFromSuper
->getIdentifier() != Prop
->getIdentifier()) {
1805 ObjCPropertyDecl
*&PropEntry
=
1806 PropMap
[std::make_pair(Prop
->getIdentifier(),
1807 Prop
->isClassProperty())];
1812 // Scan through protocol's protocols.
1813 for (auto *PI
: PDecl
->protocols())
1814 CollectImmediateProperties(PI
, PropMap
, SuperPropMap
,
1815 CollectClassPropsOnly
);
1819 /// CollectSuperClassPropertyImplementations - This routine collects list of
1820 /// properties to be implemented in super class(s) and also coming from their
1821 /// conforming protocols.
1822 static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl
*CDecl
,
1823 ObjCInterfaceDecl::PropertyMap
&PropMap
) {
1824 if (ObjCInterfaceDecl
*SDecl
= CDecl
->getSuperClass()) {
1825 ObjCInterfaceDecl::PropertyDeclOrder PO
;
1827 SDecl
->collectPropertiesToImplement(PropMap
, PO
);
1828 SDecl
= SDecl
->getSuperClass();
1833 /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
1834 /// an ivar synthesized for 'Method' and 'Method' is a property accessor
1835 /// declared in class 'IFace'.
1837 Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl
*IFace
,
1838 ObjCMethodDecl
*Method
, ObjCIvarDecl
*IV
) {
1839 if (!IV
->getSynthesize())
1841 ObjCMethodDecl
*IMD
= IFace
->lookupMethod(Method
->getSelector(),
1842 Method
->isInstanceMethod());
1843 if (!IMD
|| !IMD
->isPropertyAccessor())
1846 // look up a property declaration whose one of its accessors is implemented
1848 for (const auto *Property
: IFace
->instance_properties()) {
1849 if ((Property
->getGetterName() == IMD
->getSelector() ||
1850 Property
->getSetterName() == IMD
->getSelector()) &&
1851 (Property
->getPropertyIvarDecl() == IV
))
1854 // Also look up property declaration in class extension whose one of its
1855 // accessors is implemented by this method.
1856 for (const auto *Ext
: IFace
->known_extensions())
1857 for (const auto *Property
: Ext
->instance_properties())
1858 if ((Property
->getGetterName() == IMD
->getSelector() ||
1859 Property
->getSetterName() == IMD
->getSelector()) &&
1860 (Property
->getPropertyIvarDecl() == IV
))
1865 static bool SuperClassImplementsProperty(ObjCInterfaceDecl
*IDecl
,
1866 ObjCPropertyDecl
*Prop
) {
1867 bool SuperClassImplementsGetter
= false;
1868 bool SuperClassImplementsSetter
= false;
1869 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly
)
1870 SuperClassImplementsSetter
= true;
1872 while (IDecl
->getSuperClass()) {
1873 ObjCInterfaceDecl
*SDecl
= IDecl
->getSuperClass();
1874 if (!SuperClassImplementsGetter
&& SDecl
->getInstanceMethod(Prop
->getGetterName()))
1875 SuperClassImplementsGetter
= true;
1877 if (!SuperClassImplementsSetter
&& SDecl
->getInstanceMethod(Prop
->getSetterName()))
1878 SuperClassImplementsSetter
= true;
1879 if (SuperClassImplementsGetter
&& SuperClassImplementsSetter
)
1881 IDecl
= IDecl
->getSuperClass();
1886 /// Default synthesizes all properties which must be synthesized
1887 /// in class's \@implementation.
1888 void Sema::DefaultSynthesizeProperties(Scope
*S
, ObjCImplDecl
*IMPDecl
,
1889 ObjCInterfaceDecl
*IDecl
,
1890 SourceLocation AtEnd
) {
1891 ObjCInterfaceDecl::PropertyMap PropMap
;
1892 ObjCInterfaceDecl::PropertyDeclOrder PropertyOrder
;
1893 IDecl
->collectPropertiesToImplement(PropMap
, PropertyOrder
);
1894 if (PropMap
.empty())
1896 ObjCInterfaceDecl::PropertyMap SuperPropMap
;
1897 CollectSuperClassPropertyImplementations(IDecl
, SuperPropMap
);
1899 for (unsigned i
= 0, e
= PropertyOrder
.size(); i
!= e
; i
++) {
1900 ObjCPropertyDecl
*Prop
= PropertyOrder
[i
];
1901 // Is there a matching property synthesize/dynamic?
1902 if (Prop
->isInvalidDecl() ||
1903 Prop
->isClassProperty() ||
1904 Prop
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
1906 // Property may have been synthesized by user.
1907 if (IMPDecl
->FindPropertyImplDecl(
1908 Prop
->getIdentifier(), Prop
->getQueryKind()))
1910 ObjCMethodDecl
*ImpMethod
= IMPDecl
->getInstanceMethod(Prop
->getGetterName());
1911 if (ImpMethod
&& !ImpMethod
->getBody()) {
1912 if (Prop
->getPropertyAttributes() & ObjCPropertyAttribute::kind_readonly
)
1914 ImpMethod
= IMPDecl
->getInstanceMethod(Prop
->getSetterName());
1915 if (ImpMethod
&& !ImpMethod
->getBody())
1918 if (ObjCPropertyImplDecl
*PID
=
1919 IMPDecl
->FindPropertyImplIvarDecl(Prop
->getIdentifier())) {
1920 Diag(Prop
->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property
)
1921 << Prop
->getIdentifier();
1922 if (PID
->getLocation().isValid())
1923 Diag(PID
->getLocation(), diag::note_property_synthesize
);
1926 ObjCPropertyDecl
*PropInSuperClass
=
1927 SuperPropMap
[std::make_pair(Prop
->getIdentifier(),
1928 Prop
->isClassProperty())];
1929 if (ObjCProtocolDecl
*Proto
=
1930 dyn_cast
<ObjCProtocolDecl
>(Prop
->getDeclContext())) {
1931 // We won't auto-synthesize properties declared in protocols.
1932 // Suppress the warning if class's superclass implements property's
1933 // getter and implements property's setter (if readwrite property).
1934 // Or, if property is going to be implemented in its super class.
1935 if (!SuperClassImplementsProperty(IDecl
, Prop
) && !PropInSuperClass
) {
1936 Diag(IMPDecl
->getLocation(),
1937 diag::warn_auto_synthesizing_protocol_property
)
1939 Diag(Prop
->getLocation(), diag::note_property_declare
);
1941 (Twine("@synthesize ") + Prop
->getName() + ";\n\n").str();
1942 Diag(AtEnd
, diag::note_add_synthesize_directive
)
1943 << FixItHint::CreateInsertion(AtEnd
, FixIt
);
1947 // If property to be implemented in the super class, ignore.
1948 if (PropInSuperClass
) {
1949 if ((Prop
->getPropertyAttributes() &
1950 ObjCPropertyAttribute::kind_readwrite
) &&
1951 (PropInSuperClass
->getPropertyAttributes() &
1952 ObjCPropertyAttribute::kind_readonly
) &&
1953 !IMPDecl
->getInstanceMethod(Prop
->getSetterName()) &&
1954 !IDecl
->HasUserDeclaredSetterMethod(Prop
)) {
1955 Diag(Prop
->getLocation(), diag::warn_no_autosynthesis_property
)
1956 << Prop
->getIdentifier();
1957 Diag(PropInSuperClass
->getLocation(), diag::note_property_declare
);
1959 Diag(Prop
->getLocation(), diag::warn_autosynthesis_property_in_superclass
)
1960 << Prop
->getIdentifier();
1961 Diag(PropInSuperClass
->getLocation(), diag::note_property_declare
);
1962 Diag(IMPDecl
->getLocation(), diag::note_while_in_implementation
);
1966 // We use invalid SourceLocations for the synthesized ivars since they
1967 // aren't really synthesized at a particular location; they just exist.
1968 // Saying that they are located at the @implementation isn't really going
1970 ObjCPropertyImplDecl
*PIDecl
= dyn_cast_or_null
<ObjCPropertyImplDecl
>(
1971 ActOnPropertyImplDecl(S
, SourceLocation(), SourceLocation(),
1973 /* property = */ Prop
->getIdentifier(),
1974 /* ivar = */ Prop
->getDefaultSynthIvarName(Context
),
1975 Prop
->getLocation(), Prop
->getQueryKind()));
1976 if (PIDecl
&& !Prop
->isUnavailable()) {
1977 Diag(Prop
->getLocation(), diag::warn_missing_explicit_synthesis
);
1978 Diag(IMPDecl
->getLocation(), diag::note_while_in_implementation
);
1983 void Sema::DefaultSynthesizeProperties(Scope
*S
, Decl
*D
,
1984 SourceLocation AtEnd
) {
1985 if (!LangOpts
.ObjCDefaultSynthProperties
|| LangOpts
.ObjCRuntime
.isFragile())
1987 ObjCImplementationDecl
*IC
=dyn_cast_or_null
<ObjCImplementationDecl
>(D
);
1990 if (ObjCInterfaceDecl
* IDecl
= IC
->getClassInterface())
1991 if (!IDecl
->isObjCRequiresPropertyDefs())
1992 DefaultSynthesizeProperties(S
, IC
, IDecl
, AtEnd
);
1995 static void DiagnoseUnimplementedAccessor(
1996 Sema
&S
, ObjCInterfaceDecl
*PrimaryClass
, Selector Method
,
1997 ObjCImplDecl
*IMPDecl
, ObjCContainerDecl
*CDecl
, ObjCCategoryDecl
*C
,
1998 ObjCPropertyDecl
*Prop
,
1999 llvm::SmallPtrSet
<const ObjCMethodDecl
*, 8> &SMap
) {
2000 // Check to see if we have a corresponding selector in SMap and with the
2001 // right method type.
2002 auto I
= llvm::find_if(SMap
, [&](const ObjCMethodDecl
*x
) {
2003 return x
->getSelector() == Method
&&
2004 x
->isClassMethod() == Prop
->isClassProperty();
2006 // When reporting on missing property setter/getter implementation in
2007 // categories, do not report when they are declared in primary class,
2008 // class's protocol, or one of it super classes. This is because,
2009 // the class is going to implement them.
2010 if (I
== SMap
.end() &&
2011 (PrimaryClass
== nullptr ||
2012 !PrimaryClass
->lookupPropertyAccessor(Method
, C
,
2013 Prop
->isClassProperty()))) {
2015 isa
<ObjCCategoryDecl
>(CDecl
)
2016 ? (Prop
->isClassProperty()
2017 ? diag::warn_impl_required_in_category_for_class_property
2018 : diag::warn_setter_getter_impl_required_in_category
)
2019 : (Prop
->isClassProperty()
2020 ? diag::warn_impl_required_for_class_property
2021 : diag::warn_setter_getter_impl_required
);
2022 S
.Diag(IMPDecl
->getLocation(), diag
) << Prop
->getDeclName() << Method
;
2023 S
.Diag(Prop
->getLocation(), diag::note_property_declare
);
2024 if (S
.LangOpts
.ObjCDefaultSynthProperties
&&
2025 S
.LangOpts
.ObjCRuntime
.isNonFragile())
2026 if (ObjCInterfaceDecl
*ID
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
))
2027 if (const ObjCInterfaceDecl
*RID
= ID
->isObjCRequiresPropertyDefs())
2028 S
.Diag(RID
->getLocation(), diag::note_suppressed_class_declare
);
2032 void Sema::DiagnoseUnimplementedProperties(Scope
*S
, ObjCImplDecl
* IMPDecl
,
2033 ObjCContainerDecl
*CDecl
,
2034 bool SynthesizeProperties
) {
2035 ObjCContainerDecl::PropertyMap PropMap
;
2036 ObjCInterfaceDecl
*IDecl
= dyn_cast
<ObjCInterfaceDecl
>(CDecl
);
2038 // Since we don't synthesize class properties, we should emit diagnose even
2039 // if SynthesizeProperties is true.
2040 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap
;
2041 // Gather properties which need not be implemented in this class
2044 if (ObjCCategoryDecl
*C
= dyn_cast
<ObjCCategoryDecl
>(CDecl
)) {
2045 // For categories, no need to implement properties declared in
2046 // its primary class (and its super classes) if property is
2047 // declared in one of those containers.
2048 if ((IDecl
= C
->getClassInterface())) {
2049 ObjCInterfaceDecl::PropertyDeclOrder PO
;
2050 IDecl
->collectPropertiesToImplement(NoNeedToImplPropMap
, PO
);
2054 CollectSuperClassPropertyImplementations(IDecl
, NoNeedToImplPropMap
);
2056 // When SynthesizeProperties is true, we only check class properties.
2057 CollectImmediateProperties(CDecl
, PropMap
, NoNeedToImplPropMap
,
2058 SynthesizeProperties
/*CollectClassPropsOnly*/);
2060 // Scan the @interface to see if any of the protocols it adopts
2061 // require an explicit implementation, via attribute
2062 // 'objc_protocol_requires_explicit_implementation'.
2064 std::unique_ptr
<ObjCContainerDecl::PropertyMap
> LazyMap
;
2066 for (auto *PDecl
: IDecl
->all_referenced_protocols()) {
2067 if (!PDecl
->hasAttr
<ObjCExplicitProtocolImplAttr
>())
2069 // Lazily construct a set of all the properties in the @interface
2070 // of the class, without looking at the superclass. We cannot
2071 // use the call to CollectImmediateProperties() above as that
2072 // utilizes information from the super class's properties as well
2073 // as scans the adopted protocols. This work only triggers for protocols
2074 // with the attribute, which is very rare, and only occurs when
2075 // analyzing the @implementation.
2077 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap
;
2078 LazyMap
.reset(new ObjCContainerDecl::PropertyMap());
2079 CollectImmediateProperties(CDecl
, *LazyMap
, NoNeedToImplPropMap
,
2080 /* CollectClassPropsOnly */ false,
2081 /* IncludeProtocols */ false);
2083 // Add the properties of 'PDecl' to the list of properties that
2084 // need to be implemented.
2085 for (auto *PropDecl
: PDecl
->properties()) {
2086 if ((*LazyMap
)[std::make_pair(PropDecl
->getIdentifier(),
2087 PropDecl
->isClassProperty())])
2089 PropMap
[std::make_pair(PropDecl
->getIdentifier(),
2090 PropDecl
->isClassProperty())] = PropDecl
;
2095 if (PropMap
.empty())
2098 llvm::DenseSet
<ObjCPropertyDecl
*> PropImplMap
;
2099 for (const auto *I
: IMPDecl
->property_impls())
2100 PropImplMap
.insert(I
->getPropertyDecl());
2102 llvm::SmallPtrSet
<const ObjCMethodDecl
*, 8> InsMap
;
2103 // Collect property accessors implemented in current implementation.
2104 for (const auto *I
: IMPDecl
->methods())
2107 ObjCCategoryDecl
*C
= dyn_cast
<ObjCCategoryDecl
>(CDecl
);
2108 ObjCInterfaceDecl
*PrimaryClass
= nullptr;
2109 if (C
&& !C
->IsClassExtension())
2110 if ((PrimaryClass
= C
->getClassInterface()))
2111 // Report unimplemented properties in the category as well.
2112 if (ObjCImplDecl
*IMP
= PrimaryClass
->getImplementation()) {
2113 // When reporting on missing setter/getters, do not report when
2114 // setter/getter is implemented in category's primary class
2116 for (const auto *I
: IMP
->methods())
2120 for (ObjCContainerDecl::PropertyMap::iterator
2121 P
= PropMap
.begin(), E
= PropMap
.end(); P
!= E
; ++P
) {
2122 ObjCPropertyDecl
*Prop
= P
->second
;
2123 // Is there a matching property synthesize/dynamic?
2124 if (Prop
->isInvalidDecl() ||
2125 Prop
->getPropertyImplementation() == ObjCPropertyDecl::Optional
||
2126 PropImplMap
.count(Prop
) ||
2127 Prop
->getAvailability() == AR_Unavailable
)
2130 // Diagnose unimplemented getters and setters.
2131 DiagnoseUnimplementedAccessor(*this,
2132 PrimaryClass
, Prop
->getGetterName(), IMPDecl
, CDecl
, C
, Prop
, InsMap
);
2133 if (!Prop
->isReadOnly())
2134 DiagnoseUnimplementedAccessor(*this,
2135 PrimaryClass
, Prop
->getSetterName(),
2136 IMPDecl
, CDecl
, C
, Prop
, InsMap
);
2140 void Sema::diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl
*impDecl
) {
2141 for (const auto *propertyImpl
: impDecl
->property_impls()) {
2142 const auto *property
= propertyImpl
->getPropertyDecl();
2143 // Warn about null_resettable properties with synthesized setters,
2144 // because the setter won't properly handle nil.
2145 if (propertyImpl
->getPropertyImplementation() ==
2146 ObjCPropertyImplDecl::Synthesize
&&
2147 (property
->getPropertyAttributes() &
2148 ObjCPropertyAttribute::kind_null_resettable
) &&
2149 property
->getGetterMethodDecl() && property
->getSetterMethodDecl()) {
2150 auto *getterImpl
= propertyImpl
->getGetterMethodDecl();
2151 auto *setterImpl
= propertyImpl
->getSetterMethodDecl();
2152 if ((!getterImpl
|| getterImpl
->isSynthesizedAccessorStub()) &&
2153 (!setterImpl
|| setterImpl
->isSynthesizedAccessorStub())) {
2154 SourceLocation loc
= propertyImpl
->getLocation();
2155 if (loc
.isInvalid())
2156 loc
= impDecl
->getBeginLoc();
2158 Diag(loc
, diag::warn_null_resettable_setter
)
2159 << setterImpl
->getSelector() << property
->getDeclName();
2166 Sema::AtomicPropertySetterGetterRules (ObjCImplDecl
* IMPDecl
,
2167 ObjCInterfaceDecl
* IDecl
) {
2168 // Rules apply in non-GC mode only
2169 if (getLangOpts().getGC() != LangOptions::NonGC
)
2171 ObjCContainerDecl::PropertyMap PM
;
2172 for (auto *Prop
: IDecl
->properties())
2173 PM
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] = Prop
;
2174 for (const auto *Ext
: IDecl
->known_extensions())
2175 for (auto *Prop
: Ext
->properties())
2176 PM
[std::make_pair(Prop
->getIdentifier(), Prop
->isClassProperty())] = Prop
;
2178 for (ObjCContainerDecl::PropertyMap::iterator I
= PM
.begin(), E
= PM
.end();
2180 const ObjCPropertyDecl
*Property
= I
->second
;
2181 ObjCMethodDecl
*GetterMethod
= nullptr;
2182 ObjCMethodDecl
*SetterMethod
= nullptr;
2184 unsigned Attributes
= Property
->getPropertyAttributes();
2185 unsigned AttributesAsWritten
= Property
->getPropertyAttributesAsWritten();
2187 if (!(AttributesAsWritten
& ObjCPropertyAttribute::kind_atomic
) &&
2188 !(AttributesAsWritten
& ObjCPropertyAttribute::kind_nonatomic
)) {
2189 GetterMethod
= Property
->isClassProperty() ?
2190 IMPDecl
->getClassMethod(Property
->getGetterName()) :
2191 IMPDecl
->getInstanceMethod(Property
->getGetterName());
2192 SetterMethod
= Property
->isClassProperty() ?
2193 IMPDecl
->getClassMethod(Property
->getSetterName()) :
2194 IMPDecl
->getInstanceMethod(Property
->getSetterName());
2195 if (GetterMethod
&& GetterMethod
->isSynthesizedAccessorStub())
2196 GetterMethod
= nullptr;
2197 if (SetterMethod
&& SetterMethod
->isSynthesizedAccessorStub())
2198 SetterMethod
= nullptr;
2200 Diag(GetterMethod
->getLocation(),
2201 diag::warn_default_atomic_custom_getter_setter
)
2202 << Property
->getIdentifier() << 0;
2203 Diag(Property
->getLocation(), diag::note_property_declare
);
2206 Diag(SetterMethod
->getLocation(),
2207 diag::warn_default_atomic_custom_getter_setter
)
2208 << Property
->getIdentifier() << 1;
2209 Diag(Property
->getLocation(), diag::note_property_declare
);
2213 // We only care about readwrite atomic property.
2214 if ((Attributes
& ObjCPropertyAttribute::kind_nonatomic
) ||
2215 !(Attributes
& ObjCPropertyAttribute::kind_readwrite
))
2217 if (const ObjCPropertyImplDecl
*PIDecl
= IMPDecl
->FindPropertyImplDecl(
2218 Property
->getIdentifier(), Property
->getQueryKind())) {
2219 if (PIDecl
->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic
)
2221 GetterMethod
= PIDecl
->getGetterMethodDecl();
2222 SetterMethod
= PIDecl
->getSetterMethodDecl();
2223 if (GetterMethod
&& GetterMethod
->isSynthesizedAccessorStub())
2224 GetterMethod
= nullptr;
2225 if (SetterMethod
&& SetterMethod
->isSynthesizedAccessorStub())
2226 SetterMethod
= nullptr;
2227 if ((bool)GetterMethod
^ (bool)SetterMethod
) {
2228 SourceLocation MethodLoc
=
2229 (GetterMethod
? GetterMethod
->getLocation()
2230 : SetterMethod
->getLocation());
2231 Diag(MethodLoc
, diag::warn_atomic_property_rule
)
2232 << Property
->getIdentifier() << (GetterMethod
!= nullptr)
2233 << (SetterMethod
!= nullptr);
2235 if (Property
->getLParenLoc().isValid() &&
2236 !(AttributesAsWritten
& ObjCPropertyAttribute::kind_atomic
)) {
2237 // @property () ... case.
2238 SourceLocation AfterLParen
=
2239 getLocForEndOfToken(Property
->getLParenLoc());
2240 StringRef NonatomicStr
= AttributesAsWritten
? "nonatomic, "
2242 Diag(Property
->getLocation(),
2243 diag::note_atomic_property_fixup_suggest
)
2244 << FixItHint::CreateInsertion(AfterLParen
, NonatomicStr
);
2245 } else if (Property
->getLParenLoc().isInvalid()) {
2247 SourceLocation startLoc
=
2248 Property
->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
2249 Diag(Property
->getLocation(),
2250 diag::note_atomic_property_fixup_suggest
)
2251 << FixItHint::CreateInsertion(startLoc
, "(nonatomic) ");
2253 Diag(MethodLoc
, diag::note_atomic_property_fixup_suggest
);
2254 Diag(Property
->getLocation(), diag::note_property_declare
);
2260 void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl
*D
) {
2261 if (getLangOpts().getGC() == LangOptions::GCOnly
)
2264 for (const auto *PID
: D
->property_impls()) {
2265 const ObjCPropertyDecl
*PD
= PID
->getPropertyDecl();
2266 if (PD
&& !PD
->hasAttr
<NSReturnsNotRetainedAttr
>() &&
2267 !PD
->isClassProperty()) {
2268 ObjCMethodDecl
*IM
= PID
->getGetterMethodDecl();
2269 if (IM
&& !IM
->isSynthesizedAccessorStub())
2271 ObjCMethodDecl
*method
= PD
->getGetterMethodDecl();
2274 ObjCMethodFamily family
= method
->getMethodFamily();
2275 if (family
== OMF_alloc
|| family
== OMF_copy
||
2276 family
== OMF_mutableCopy
|| family
== OMF_new
) {
2277 if (getLangOpts().ObjCAutoRefCount
)
2278 Diag(PD
->getLocation(), diag::err_cocoa_naming_owned_rule
);
2280 Diag(PD
->getLocation(), diag::warn_cocoa_naming_owned_rule
);
2282 // Look for a getter explicitly declared alongside the property.
2283 // If we find one, use its location for the note.
2284 SourceLocation noteLoc
= PD
->getLocation();
2285 SourceLocation fixItLoc
;
2286 for (auto *getterRedecl
: method
->redecls()) {
2287 if (getterRedecl
->isImplicit())
2289 if (getterRedecl
->getDeclContext() != PD
->getDeclContext())
2291 noteLoc
= getterRedecl
->getLocation();
2292 fixItLoc
= getterRedecl
->getEndLoc();
2295 Preprocessor
&PP
= getPreprocessor();
2296 TokenValue tokens
[] = {
2297 tok::kw___attribute
, tok::l_paren
, tok::l_paren
,
2298 PP
.getIdentifierInfo("objc_method_family"), tok::l_paren
,
2299 PP
.getIdentifierInfo("none"), tok::r_paren
,
2300 tok::r_paren
, tok::r_paren
2302 StringRef spelling
= "__attribute__((objc_method_family(none)))";
2303 StringRef macroName
= PP
.getLastMacroWithSpelling(noteLoc
, tokens
);
2304 if (!macroName
.empty())
2305 spelling
= macroName
;
2307 auto noteDiag
= Diag(noteLoc
, diag::note_cocoa_naming_declare_family
)
2308 << method
->getDeclName() << spelling
;
2309 if (fixItLoc
.isValid()) {
2310 SmallString
<64> fixItText(" ");
2311 fixItText
+= spelling
;
2312 noteDiag
<< FixItHint::CreateInsertion(fixItLoc
, fixItText
);
2319 void Sema::DiagnoseMissingDesignatedInitOverrides(
2320 const ObjCImplementationDecl
*ImplD
,
2321 const ObjCInterfaceDecl
*IFD
) {
2322 assert(IFD
->hasDesignatedInitializers());
2323 const ObjCInterfaceDecl
*SuperD
= IFD
->getSuperClass();
2327 SelectorSet InitSelSet
;
2328 for (const auto *I
: ImplD
->instance_methods())
2329 if (I
->getMethodFamily() == OMF_init
)
2330 InitSelSet
.insert(I
->getSelector());
2332 SmallVector
<const ObjCMethodDecl
*, 8> DesignatedInits
;
2333 SuperD
->getDesignatedInitializers(DesignatedInits
);
2334 for (SmallVector
<const ObjCMethodDecl
*, 8>::iterator
2335 I
= DesignatedInits
.begin(), E
= DesignatedInits
.end(); I
!= E
; ++I
) {
2336 const ObjCMethodDecl
*MD
= *I
;
2337 if (!InitSelSet
.count(MD
->getSelector())) {
2338 // Don't emit a diagnostic if the overriding method in the subclass is
2339 // marked as unavailable.
2340 bool Ignore
= false;
2341 if (auto *IMD
= IFD
->getInstanceMethod(MD
->getSelector())) {
2342 Ignore
= IMD
->isUnavailable();
2344 // Check the methods declared in the class extensions too.
2345 for (auto *Ext
: IFD
->visible_extensions())
2346 if (auto *IMD
= Ext
->getInstanceMethod(MD
->getSelector())) {
2347 Ignore
= IMD
->isUnavailable();
2352 Diag(ImplD
->getLocation(),
2353 diag::warn_objc_implementation_missing_designated_init_override
)
2354 << MD
->getSelector();
2355 Diag(MD
->getLocation(), diag::note_objc_designated_init_marked_here
);
2361 /// AddPropertyAttrs - Propagates attributes from a property to the
2362 /// implicitly-declared getter or setter for that property.
2363 static void AddPropertyAttrs(Sema
&S
, ObjCMethodDecl
*PropertyMethod
,
2364 ObjCPropertyDecl
*Property
) {
2365 // Should we just clone all attributes over?
2366 for (const auto *A
: Property
->attrs()) {
2367 if (isa
<DeprecatedAttr
>(A
) ||
2368 isa
<UnavailableAttr
>(A
) ||
2369 isa
<AvailabilityAttr
>(A
))
2370 PropertyMethod
->addAttr(A
->clone(S
.Context
));
2374 /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
2375 /// have the property type and issue diagnostics if they don't.
2376 /// Also synthesize a getter/setter method if none exist (and update the
2377 /// appropriate lookup tables.
2378 void Sema::ProcessPropertyDecl(ObjCPropertyDecl
*property
) {
2379 ObjCMethodDecl
*GetterMethod
, *SetterMethod
;
2380 ObjCContainerDecl
*CD
= cast
<ObjCContainerDecl
>(property
->getDeclContext());
2381 if (CD
->isInvalidDecl())
2384 bool IsClassProperty
= property
->isClassProperty();
2385 GetterMethod
= IsClassProperty
?
2386 CD
->getClassMethod(property
->getGetterName()) :
2387 CD
->getInstanceMethod(property
->getGetterName());
2389 // if setter or getter is not found in class extension, it might be
2390 // in the primary class.
2392 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2393 if (CatDecl
->IsClassExtension())
2394 GetterMethod
= IsClassProperty
? CatDecl
->getClassInterface()->
2395 getClassMethod(property
->getGetterName()) :
2396 CatDecl
->getClassInterface()->
2397 getInstanceMethod(property
->getGetterName());
2399 SetterMethod
= IsClassProperty
?
2400 CD
->getClassMethod(property
->getSetterName()) :
2401 CD
->getInstanceMethod(property
->getSetterName());
2403 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2404 if (CatDecl
->IsClassExtension())
2405 SetterMethod
= IsClassProperty
? CatDecl
->getClassInterface()->
2406 getClassMethod(property
->getSetterName()) :
2407 CatDecl
->getClassInterface()->
2408 getInstanceMethod(property
->getSetterName());
2409 DiagnosePropertyAccessorMismatch(property
, GetterMethod
,
2410 property
->getLocation());
2412 // synthesizing accessors must not result in a direct method that is not
2414 if (!GetterMethod
) {
2415 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
)) {
2416 auto *ExistingGetter
= CatDecl
->getClassInterface()->lookupMethod(
2417 property
->getGetterName(), !IsClassProperty
, true, false, CatDecl
);
2418 if (ExistingGetter
) {
2419 if (ExistingGetter
->isDirectMethod() || property
->isDirectProperty()) {
2420 Diag(property
->getLocation(), diag::err_objc_direct_duplicate_decl
)
2421 << property
->isDirectProperty() << 1 /* property */
2422 << ExistingGetter
->isDirectMethod()
2423 << ExistingGetter
->getDeclName();
2424 Diag(ExistingGetter
->getLocation(), diag::note_previous_declaration
);
2430 if (!property
->isReadOnly() && !SetterMethod
) {
2431 if (const ObjCCategoryDecl
*CatDecl
= dyn_cast
<ObjCCategoryDecl
>(CD
)) {
2432 auto *ExistingSetter
= CatDecl
->getClassInterface()->lookupMethod(
2433 property
->getSetterName(), !IsClassProperty
, true, false, CatDecl
);
2434 if (ExistingSetter
) {
2435 if (ExistingSetter
->isDirectMethod() || property
->isDirectProperty()) {
2436 Diag(property
->getLocation(), diag::err_objc_direct_duplicate_decl
)
2437 << property
->isDirectProperty() << 1 /* property */
2438 << ExistingSetter
->isDirectMethod()
2439 << ExistingSetter
->getDeclName();
2440 Diag(ExistingSetter
->getLocation(), diag::note_previous_declaration
);
2446 if (!property
->isReadOnly() && SetterMethod
) {
2447 if (Context
.getCanonicalType(SetterMethod
->getReturnType()) !=
2449 Diag(SetterMethod
->getLocation(), diag::err_setter_type_void
);
2450 if (SetterMethod
->param_size() != 1 ||
2451 !Context
.hasSameUnqualifiedType(
2452 (*SetterMethod
->param_begin())->getType().getNonReferenceType(),
2453 property
->getType().getNonReferenceType())) {
2454 Diag(property
->getLocation(),
2455 diag::warn_accessor_property_type_mismatch
)
2456 << property
->getDeclName()
2457 << SetterMethod
->getSelector();
2458 Diag(SetterMethod
->getLocation(), diag::note_declared_at
);
2462 // Synthesize getter/setter methods if none exist.
2463 // Find the default getter and if one not found, add one.
2464 // FIXME: The synthesized property we set here is misleading. We almost always
2465 // synthesize these methods unless the user explicitly provided prototypes
2466 // (which is odd, but allowed). Sema should be typechecking that the
2467 // declarations jive in that situation (which it is not currently).
2468 if (!GetterMethod
) {
2469 // No instance/class method of same name as property getter name was found.
2470 // Declare a getter method and add it to the list of methods
2472 SourceLocation Loc
= property
->getLocation();
2474 // The getter returns the declared property type with all qualifiers
2476 QualType resultTy
= property
->getType().getAtomicUnqualifiedType();
2478 // If the property is null_resettable, the getter returns nonnull.
2479 if (property
->getPropertyAttributes() &
2480 ObjCPropertyAttribute::kind_null_resettable
) {
2481 QualType modifiedTy
= resultTy
;
2482 if (auto nullability
= AttributedType::stripOuterNullability(modifiedTy
)) {
2483 if (*nullability
== NullabilityKind::Unspecified
)
2484 resultTy
= Context
.getAttributedType(attr::TypeNonNull
,
2485 modifiedTy
, modifiedTy
);
2489 GetterMethod
= ObjCMethodDecl::Create(
2490 Context
, Loc
, Loc
, property
->getGetterName(), resultTy
, nullptr, CD
,
2491 !IsClassProperty
, /*isVariadic=*/false,
2492 /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
2493 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
2494 (property
->getPropertyImplementation() == ObjCPropertyDecl::Optional
)
2495 ? ObjCMethodDecl::Optional
2496 : ObjCMethodDecl::Required
);
2497 CD
->addDecl(GetterMethod
);
2499 AddPropertyAttrs(*this, GetterMethod
, property
);
2501 if (property
->isDirectProperty())
2502 GetterMethod
->addAttr(ObjCDirectAttr::CreateImplicit(Context
, Loc
));
2504 if (property
->hasAttr
<NSReturnsNotRetainedAttr
>())
2505 GetterMethod
->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context
,
2508 if (property
->hasAttr
<ObjCReturnsInnerPointerAttr
>())
2509 GetterMethod
->addAttr(
2510 ObjCReturnsInnerPointerAttr::CreateImplicit(Context
, Loc
));
2512 if (const SectionAttr
*SA
= property
->getAttr
<SectionAttr
>())
2513 GetterMethod
->addAttr(SectionAttr::CreateImplicit(
2514 Context
, SA
->getName(), Loc
, AttributeCommonInfo::AS_GNU
,
2515 SectionAttr::GNU_section
));
2517 if (getLangOpts().ObjCAutoRefCount
)
2518 CheckARCMethodDecl(GetterMethod
);
2520 // A user declared getter will be synthesize when @synthesize of
2521 // the property with the same name is seen in the @implementation
2522 GetterMethod
->setPropertyAccessor(true);
2524 GetterMethod
->createImplicitParams(Context
,
2525 GetterMethod
->getClassInterface());
2526 property
->setGetterMethodDecl(GetterMethod
);
2528 // Skip setter if property is read-only.
2529 if (!property
->isReadOnly()) {
2530 // Find the default setter and if one not found, add one.
2531 if (!SetterMethod
) {
2532 // No instance/class method of same name as property setter name was
2534 // Declare a setter method and add it to the list of methods
2536 SourceLocation Loc
= property
->getLocation();
2539 ObjCMethodDecl::Create(Context
, Loc
, Loc
,
2540 property
->getSetterName(), Context
.VoidTy
,
2541 nullptr, CD
, !IsClassProperty
,
2542 /*isVariadic=*/false,
2543 /*isPropertyAccessor=*/true,
2544 /*isSynthesizedAccessorStub=*/false,
2545 /*isImplicitlyDeclared=*/true,
2546 /*isDefined=*/false,
2547 (property
->getPropertyImplementation() ==
2548 ObjCPropertyDecl::Optional
) ?
2549 ObjCMethodDecl::Optional
:
2550 ObjCMethodDecl::Required
);
2552 // Remove all qualifiers from the setter's parameter type.
2554 property
->getType().getUnqualifiedType().getAtomicUnqualifiedType();
2556 // If the property is null_resettable, the setter accepts a
2558 if (property
->getPropertyAttributes() &
2559 ObjCPropertyAttribute::kind_null_resettable
) {
2560 QualType modifiedTy
= paramTy
;
2561 if (auto nullability
= AttributedType::stripOuterNullability(modifiedTy
)){
2562 if (*nullability
== NullabilityKind::Unspecified
)
2563 paramTy
= Context
.getAttributedType(attr::TypeNullable
,
2564 modifiedTy
, modifiedTy
);
2568 // Invent the arguments for the setter. We don't bother making a
2569 // nice name for the argument.
2570 ParmVarDecl
*Argument
= ParmVarDecl::Create(Context
, SetterMethod
,
2572 property
->getIdentifier(),
2577 SetterMethod
->setMethodParams(Context
, Argument
, None
);
2579 AddPropertyAttrs(*this, SetterMethod
, property
);
2581 if (property
->isDirectProperty())
2582 SetterMethod
->addAttr(ObjCDirectAttr::CreateImplicit(Context
, Loc
));
2584 CD
->addDecl(SetterMethod
);
2585 if (const SectionAttr
*SA
= property
->getAttr
<SectionAttr
>())
2586 SetterMethod
->addAttr(SectionAttr::CreateImplicit(
2587 Context
, SA
->getName(), Loc
, AttributeCommonInfo::AS_GNU
,
2588 SectionAttr::GNU_section
));
2589 // It's possible for the user to have set a very odd custom
2590 // setter selector that causes it to have a method family.
2591 if (getLangOpts().ObjCAutoRefCount
)
2592 CheckARCMethodDecl(SetterMethod
);
2594 // A user declared setter will be synthesize when @synthesize of
2595 // the property with the same name is seen in the @implementation
2596 SetterMethod
->setPropertyAccessor(true);
2598 SetterMethod
->createImplicitParams(Context
,
2599 SetterMethod
->getClassInterface());
2600 property
->setSetterMethodDecl(SetterMethod
);
2602 // Add any synthesized methods to the global pool. This allows us to
2603 // handle the following, which is supported by GCC (and part of the design).
2606 // @property double bar;
2609 // void thisIsUnfortunate() {
2611 // double bar = [foo bar];
2614 if (!IsClassProperty
) {
2616 AddInstanceMethodToGlobalPool(GetterMethod
);
2618 AddInstanceMethodToGlobalPool(SetterMethod
);
2621 AddFactoryMethodToGlobalPool(GetterMethod
);
2623 AddFactoryMethodToGlobalPool(SetterMethod
);
2626 ObjCInterfaceDecl
*CurrentClass
= dyn_cast
<ObjCInterfaceDecl
>(CD
);
2627 if (!CurrentClass
) {
2628 if (ObjCCategoryDecl
*Cat
= dyn_cast
<ObjCCategoryDecl
>(CD
))
2629 CurrentClass
= Cat
->getClassInterface();
2630 else if (ObjCImplDecl
*Impl
= dyn_cast
<ObjCImplDecl
>(CD
))
2631 CurrentClass
= Impl
->getClassInterface();
2634 CheckObjCMethodOverrides(GetterMethod
, CurrentClass
, Sema::RTC_Unknown
);
2636 CheckObjCMethodOverrides(SetterMethod
, CurrentClass
, Sema::RTC_Unknown
);
2639 void Sema::CheckObjCPropertyAttributes(Decl
*PDecl
,
2641 unsigned &Attributes
,
2642 bool propertyInPrimaryClass
) {
2643 // FIXME: Improve the reported location.
2644 if (!PDecl
|| PDecl
->isInvalidDecl())
2647 if ((Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2648 (Attributes
& ObjCPropertyAttribute::kind_readwrite
))
2649 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2650 << "readonly" << "readwrite";
2652 ObjCPropertyDecl
*PropertyDecl
= cast
<ObjCPropertyDecl
>(PDecl
);
2653 QualType PropertyTy
= PropertyDecl
->getType();
2655 // Check for copy or retain on non-object types.
2657 (ObjCPropertyAttribute::kind_weak
| ObjCPropertyAttribute::kind_copy
|
2658 ObjCPropertyAttribute::kind_retain
|
2659 ObjCPropertyAttribute::kind_strong
)) &&
2660 !PropertyTy
->isObjCRetainableType() &&
2661 !PropertyDecl
->hasAttr
<ObjCNSObjectAttr
>()) {
2662 Diag(Loc
, diag::err_objc_property_requires_object
)
2663 << (Attributes
& ObjCPropertyAttribute::kind_weak
2665 : Attributes
& ObjCPropertyAttribute::kind_copy
2667 : "retain (or strong)");
2669 ~(ObjCPropertyAttribute::kind_weak
| ObjCPropertyAttribute::kind_copy
|
2670 ObjCPropertyAttribute::kind_retain
|
2671 ObjCPropertyAttribute::kind_strong
);
2672 PropertyDecl
->setInvalidDecl();
2675 // Check for assign on object types.
2676 if ((Attributes
& ObjCPropertyAttribute::kind_assign
) &&
2677 !(Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
) &&
2678 PropertyTy
->isObjCRetainableType() &&
2679 !PropertyTy
->isObjCARCImplicitlyUnretainedType()) {
2680 Diag(Loc
, diag::warn_objc_property_assign_on_object
);
2683 // Check for more than one of { assign, copy, retain }.
2684 if (Attributes
& ObjCPropertyAttribute::kind_assign
) {
2685 if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2686 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2687 << "assign" << "copy";
2688 Attributes
&= ~ObjCPropertyAttribute::kind_copy
;
2690 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2691 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2692 << "assign" << "retain";
2693 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2695 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2696 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2697 << "assign" << "strong";
2698 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2700 if (getLangOpts().ObjCAutoRefCount
&&
2701 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2702 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2703 << "assign" << "weak";
2704 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2706 if (PropertyDecl
->hasAttr
<IBOutletCollectionAttr
>())
2707 Diag(Loc
, diag::warn_iboutletcollection_property_assign
);
2708 } else if (Attributes
& ObjCPropertyAttribute::kind_unsafe_unretained
) {
2709 if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2710 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2711 << "unsafe_unretained" << "copy";
2712 Attributes
&= ~ObjCPropertyAttribute::kind_copy
;
2714 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2715 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2716 << "unsafe_unretained" << "retain";
2717 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2719 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2720 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2721 << "unsafe_unretained" << "strong";
2722 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2724 if (getLangOpts().ObjCAutoRefCount
&&
2725 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2726 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2727 << "unsafe_unretained" << "weak";
2728 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2730 } else if (Attributes
& ObjCPropertyAttribute::kind_copy
) {
2731 if (Attributes
& ObjCPropertyAttribute::kind_retain
) {
2732 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2733 << "copy" << "retain";
2734 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2736 if (Attributes
& ObjCPropertyAttribute::kind_strong
) {
2737 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2738 << "copy" << "strong";
2739 Attributes
&= ~ObjCPropertyAttribute::kind_strong
;
2741 if (Attributes
& ObjCPropertyAttribute::kind_weak
) {
2742 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2743 << "copy" << "weak";
2744 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2746 } else if ((Attributes
& ObjCPropertyAttribute::kind_retain
) &&
2747 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2748 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "retain"
2750 Attributes
&= ~ObjCPropertyAttribute::kind_retain
;
2751 } else if ((Attributes
& ObjCPropertyAttribute::kind_strong
) &&
2752 (Attributes
& ObjCPropertyAttribute::kind_weak
)) {
2753 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "strong"
2755 Attributes
&= ~ObjCPropertyAttribute::kind_weak
;
2758 if (Attributes
& ObjCPropertyAttribute::kind_weak
) {
2759 // 'weak' and 'nonnull' are mutually exclusive.
2760 if (auto nullability
= PropertyTy
->getNullability(Context
)) {
2761 if (*nullability
== NullabilityKind::NonNull
)
2762 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
)
2763 << "nonnull" << "weak";
2767 if ((Attributes
& ObjCPropertyAttribute::kind_atomic
) &&
2768 (Attributes
& ObjCPropertyAttribute::kind_nonatomic
)) {
2769 Diag(Loc
, diag::err_objc_property_attr_mutually_exclusive
) << "atomic"
2771 Attributes
&= ~ObjCPropertyAttribute::kind_atomic
;
2774 // Warn if user supplied no assignment attribute, property is
2775 // readwrite, and this is an object type.
2776 if (!getOwnershipRule(Attributes
) && PropertyTy
->isObjCRetainableType()) {
2777 if (Attributes
& ObjCPropertyAttribute::kind_readonly
) {
2779 } else if (getLangOpts().ObjCAutoRefCount
) {
2780 // With arc, @property definitions should default to strong when
2782 PropertyDecl
->setPropertyAttributes(ObjCPropertyAttribute::kind_strong
);
2783 } else if (PropertyTy
->isObjCObjectPointerType()) {
2784 bool isAnyClassTy
= (PropertyTy
->isObjCClassType() ||
2785 PropertyTy
->isObjCQualifiedClassType());
2786 // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
2787 // issue any warning.
2788 if (isAnyClassTy
&& getLangOpts().getGC() == LangOptions::NonGC
)
2790 else if (propertyInPrimaryClass
) {
2791 // Don't issue warning on property with no life time in class
2792 // extension as it is inherited from property in primary class.
2793 // Skip this warning in gc-only mode.
2794 if (getLangOpts().getGC() != LangOptions::GCOnly
)
2795 Diag(Loc
, diag::warn_objc_property_no_assignment_attribute
);
2797 // If non-gc code warn that this is likely inappropriate.
2798 if (getLangOpts().getGC() == LangOptions::NonGC
)
2799 Diag(Loc
, diag::warn_objc_property_default_assign_on_object
);
2803 // FIXME: Implement warning dependent on NSCopying being
2804 // implemented. See also:
2805 // <rdar://5168496&4855821&5607453&5096644&4947311&5698469&4947014&5168496>
2806 // (please trim this list while you are at it).
2809 if (!(Attributes
& ObjCPropertyAttribute::kind_copy
) &&
2810 !(Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2811 getLangOpts().getGC() == LangOptions::GCOnly
&&
2812 PropertyTy
->isBlockPointerType())
2813 Diag(Loc
, diag::warn_objc_property_copy_missing_on_block
);
2814 else if ((Attributes
& ObjCPropertyAttribute::kind_retain
) &&
2815 !(Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2816 !(Attributes
& ObjCPropertyAttribute::kind_strong
) &&
2817 PropertyTy
->isBlockPointerType())
2818 Diag(Loc
, diag::warn_objc_property_retain_of_block
);
2820 if ((Attributes
& ObjCPropertyAttribute::kind_readonly
) &&
2821 (Attributes
& ObjCPropertyAttribute::kind_setter
))
2822 Diag(Loc
, diag::warn_objc_readonly_property_has_setter
);