clang 23.0.0git
SemaObjCProperty.cpp
Go to the documentation of this file.
1//===--- SemaObjCProperty.cpp - Semantic Analysis for ObjC @property ------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements semantic analysis for Objective C @property and
10// @synthesize declarations.
11//
12//===----------------------------------------------------------------------===//
13
15#include "clang/AST/DeclObjC.h"
16#include "clang/AST/ExprCXX.h"
17#include "clang/AST/ExprObjC.h"
19#include "clang/Lex/Lexer.h"
22#include "clang/Sema/SemaObjC.h"
23#include "llvm/ADT/DenseSet.h"
24
25using namespace clang;
26
27//===----------------------------------------------------------------------===//
28// Grammar actions.
29//===----------------------------------------------------------------------===//
30
31/// getImpliedARCOwnership - Given a set of property attributes and a
32/// type, infer an expected lifetime. The type's ownership qualification
33/// is not considered.
34///
35/// Returns OCL_None if the attributes as stated do not imply an ownership.
36/// Never returns OCL_Autoreleasing.
39 // retain, strong, copy, weak, and unsafe_unretained are only legal
40 // on properties of retainable pointer type.
41 if (attrs &
45 } else if (attrs & ObjCPropertyAttribute::kind_weak) {
49 }
50
51 // assign can appear on other types, so we have to check the
52 // property type.
54 type->isObjCRetainableType()) {
56 }
57
59}
60
61/// Check the internal consistency of a property declaration with
62/// an explicit ownership qualifier.
64 ObjCPropertyDecl *property) {
65 if (property->isInvalidDecl()) return;
66
67 ObjCPropertyAttribute::Kind propertyKind = property->getPropertyAttributes();
68 Qualifiers::ObjCLifetime propertyLifetime
69 = property->getType().getObjCLifetime();
70
71 assert(propertyLifetime != Qualifiers::OCL_None);
72
73 Qualifiers::ObjCLifetime expectedLifetime
74 = getImpliedARCOwnership(propertyKind, property->getType());
75 if (!expectedLifetime) {
76 // We have a lifetime qualifier but no dominating property
77 // attribute. That's okay, but restore reasonable invariants by
78 // setting the property attribute according to the lifetime
79 // qualifier.
81 if (propertyLifetime == Qualifiers::OCL_Strong) {
83 } else if (propertyLifetime == Qualifiers::OCL_Weak) {
85 } else {
86 assert(propertyLifetime == Qualifiers::OCL_ExplicitNone);
88 }
89 property->setPropertyAttributes(attr);
90 return;
91 }
92
93 if (propertyLifetime == expectedLifetime) return;
94
95 property->setInvalidDecl();
96 S.Diag(property->getLocation(),
97 diag::err_arc_inconsistent_property_ownership)
98 << property->getDeclName()
99 << expectedLifetime
100 << propertyLifetime;
101}
102
103/// Check this Objective-C property against a property declared in the
104/// given protocol.
105static void
107 ObjCProtocolDecl *Proto,
108 llvm::SmallPtrSetImpl<ObjCProtocolDecl *> &Known) {
109 // Have we seen this protocol before?
110 if (!Known.insert(Proto).second)
111 return;
112
113 // Look for a property with the same name.
114 if (ObjCPropertyDecl *ProtoProp = Proto->getProperty(
115 Prop->getIdentifier(), Prop->isInstanceProperty())) {
116 S.ObjC().DiagnosePropertyMismatch(Prop, ProtoProp, Proto->getIdentifier(),
117 true);
118 return;
119 }
120
121 // Check this property against any protocols we inherit.
122 for (auto *P : Proto->protocols())
123 CheckPropertyAgainstProtocol(S, Prop, P, Known);
124}
125
127 // In GC mode, just look for the __weak qualifier.
128 if (S.getLangOpts().getGC() != LangOptions::NonGC) {
129 if (T.isObjCGCWeak())
131
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()) {
135 switch (ownership) {
144 return 0;
145 }
146 llvm_unreachable("bad qualifier");
147 }
148
149 return 0;
150}
151
152static const unsigned OwnershipMask =
157
158static unsigned getOwnershipRule(unsigned attr) {
159 unsigned result = attr & OwnershipMask;
160
161 // From an ownership perspective, assign and unsafe_unretained are
162 // identical; make sure one also implies the other.
167 }
168
169 return result;
170}
171
173 SourceLocation LParenLoc, FieldDeclarator &FD,
174 ObjCDeclSpec &ODS, Selector GetterSel,
175 Selector SetterSel,
176 tok::ObjCKeywordKind MethodImplKind,
177 DeclContext *lexicalDC) {
178 unsigned Attributes = ODS.getPropertyAttributes();
180 0);
181 TypeSourceInfo *TSI = SemaRef.GetTypeForDeclarator(FD.D);
182 QualType T = TSI->getType();
183 if (T.getPointerAuth().isPresent()) {
184 Diag(AtLoc, diag::err_ptrauth_qualifier_invalid) << T << 2;
185 }
186 if (!getOwnershipRule(Attributes)) {
188 }
189 bool isReadWrite = ((Attributes & ObjCPropertyAttribute::kind_readwrite) ||
190 // default is readwrite!
192
193 // Proceed with constructing the ObjCPropertyDecls.
194 ObjCContainerDecl *ClassDecl = cast<ObjCContainerDecl>(SemaRef.CurContext);
195 ObjCPropertyDecl *Res = nullptr;
196 if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
197 if (CDecl->IsClassExtension()) {
198 Res = HandlePropertyInClassExtension(S, AtLoc, LParenLoc,
199 FD,
200 GetterSel, ODS.getGetterNameLoc(),
201 SetterSel, ODS.getSetterNameLoc(),
202 isReadWrite, Attributes,
204 T, TSI, MethodImplKind);
205 if (!Res)
206 return nullptr;
207 }
208 }
209
210 if (!Res) {
211 Res = CreatePropertyDecl(S, ClassDecl, AtLoc, LParenLoc, FD,
212 GetterSel, ODS.getGetterNameLoc(), SetterSel,
213 ODS.getSetterNameLoc(), isReadWrite, Attributes,
214 ODS.getPropertyAttributes(), T, TSI,
215 MethodImplKind);
216 if (lexicalDC)
217 Res->setLexicalDeclContext(lexicalDC);
218 }
219
220 // Validate the attributes on the @property.
221 CheckObjCPropertyAttributes(Res, AtLoc, Attributes,
222 (isa<ObjCInterfaceDecl>(ClassDecl) ||
223 isa<ObjCProtocolDecl>(ClassDecl)));
224
225 // Check consistency if the type has explicit ownership qualification.
226 if (Res->getType().getObjCLifetime())
228
230 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
231 // For a class, compare the property against a property in our superclass.
232 bool FoundInSuper = false;
233 ObjCInterfaceDecl *CurrentInterfaceDecl = IFace;
234 while (ObjCInterfaceDecl *Super = CurrentInterfaceDecl->getSuperClass()) {
235 if (ObjCPropertyDecl *SuperProp = Super->getProperty(
236 Res->getIdentifier(), Res->isInstanceProperty())) {
237 DiagnosePropertyMismatch(Res, SuperProp, Super->getIdentifier(), false);
238 FoundInSuper = true;
239 break;
240 }
241 CurrentInterfaceDecl = Super;
242 }
243
244 if (FoundInSuper) {
245 // Also compare the property against a property in our protocols.
246 for (auto *P : CurrentInterfaceDecl->protocols()) {
247 CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos);
248 }
249 } else {
250 // Slower path: look in all protocols we referenced.
251 for (auto *P : IFace->all_referenced_protocols()) {
252 CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos);
253 }
254 }
255 } else if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
256 // We don't check if class extension. Because properties in class extension
257 // are meant to override some of the attributes and checking has already done
258 // when property in class extension is constructed.
259 if (!Cat->IsClassExtension())
260 for (auto *P : Cat->protocols())
261 CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos);
262 } else {
263 ObjCProtocolDecl *Proto = cast<ObjCProtocolDecl>(ClassDecl);
264 for (auto *P : Proto->protocols())
265 CheckPropertyAgainstProtocol(SemaRef, Res, P, KnownProtos);
266 }
267
268 SemaRef.ActOnDocumentableDecl(Res);
269 return Res;
270}
271
272static bool LocPropertyAttribute( ASTContext &Context, const char *attrName,
273 SourceLocation LParenLoc, SourceLocation &Loc) {
274 if (LParenLoc.isMacroID())
275 return false;
276
277 SourceManager &SM = Context.getSourceManager();
278 FileIDAndOffset locInfo = SM.getDecomposedLoc(LParenLoc);
279 // Try to load the file buffer.
280 bool invalidTemp = false;
281 StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
282 if (invalidTemp)
283 return false;
284 const char *tokenBegin = file.data() + locInfo.second;
285
286 // Lex from the start of the given location.
287 Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
288 Context.getLangOpts(),
289 file.begin(), tokenBegin, file.end());
290 Token Tok;
291 do {
292 lexer.LexFromRawLexer(Tok);
293 if (Tok.is(tok::raw_identifier) && Tok.getRawIdentifier() == attrName) {
294 Loc = Tok.getLocation();
295 return true;
296 }
297 } while (Tok.isNot(tok::r_paren));
298 return false;
299}
300
301/// Check for a mismatch in the atomicity of the given properties.
303 ObjCPropertyDecl *OldProperty,
304 ObjCPropertyDecl *NewProperty,
305 bool PropagateAtomicity) {
306 // If the atomicity of both matches, we're done.
307 bool OldIsAtomic = (OldProperty->getPropertyAttributes() &
309 bool NewIsAtomic = (NewProperty->getPropertyAttributes() &
311 if (OldIsAtomic == NewIsAtomic) return;
312
313 // Determine whether the given property is readonly and implicitly
314 // atomic.
315 auto isImplicitlyReadonlyAtomic = [](ObjCPropertyDecl *Property) -> bool {
316 // Is it readonly?
317 auto Attrs = Property->getPropertyAttributes();
318 if ((Attrs & ObjCPropertyAttribute::kind_readonly) == 0)
319 return false;
320
321 // Is it nonatomic?
323 return false;
324
325 // Was 'atomic' specified directly?
326 if (Property->getPropertyAttributesAsWritten() &
328 return false;
329
330 return true;
331 };
332
333 // If we're allowed to propagate atomicity, and the new property did
334 // not specify atomicity at all, propagate.
335 const unsigned AtomicityMask = (ObjCPropertyAttribute::kind_atomic |
337 if (PropagateAtomicity &&
338 ((NewProperty->getPropertyAttributesAsWritten() & AtomicityMask) == 0)) {
339 unsigned Attrs = NewProperty->getPropertyAttributes();
340 Attrs = Attrs & ~AtomicityMask;
341 if (OldIsAtomic)
343 else
345
346 NewProperty->overwritePropertyAttributes(Attrs);
347 return;
348 }
349
350 // One of the properties is atomic; if it's a readonly property, and
351 // 'atomic' wasn't explicitly specified, we're okay.
352 if ((OldIsAtomic && isImplicitlyReadonlyAtomic(OldProperty)) ||
353 (NewIsAtomic && isImplicitlyReadonlyAtomic(NewProperty)))
354 return;
355
356 // Diagnose the conflict.
357 const IdentifierInfo *OldContextName;
358 auto *OldDC = OldProperty->getDeclContext();
359 if (auto Category = dyn_cast<ObjCCategoryDecl>(OldDC))
360 OldContextName = Category->getClassInterface()->getIdentifier();
361 else
362 OldContextName = cast<ObjCContainerDecl>(OldDC)->getIdentifier();
363
364 S.Diag(NewProperty->getLocation(), diag::warn_property_attribute)
365 << NewProperty->getDeclName() << "atomic"
366 << OldContextName;
367 S.Diag(OldProperty->getLocation(), diag::note_property_declare);
368}
369
371 Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc,
372 FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc,
373 Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite,
374 unsigned &Attributes, const unsigned AttributesAsWritten, QualType T,
375 TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind) {
377 // Diagnose if this property is already in continuation class.
378 DeclContext *DC = SemaRef.CurContext;
379 const IdentifierInfo *PropertyId = FD.D.getIdentifier();
380 ObjCInterfaceDecl *CCPrimary = CDecl->getClassInterface();
381
382 // We need to look in the @interface to see if the @property was
383 // already declared.
384 if (!CCPrimary) {
385 Diag(CDecl->getLocation(), diag::err_continuation_class);
386 return nullptr;
387 }
388
389 bool isClassProperty =
390 (AttributesAsWritten & ObjCPropertyAttribute::kind_class) ||
392
393 // Find the property in the extended class's primary class or
394 // extensions.
396 PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty));
397
398 // If we found a property in an extension, complain.
399 if (PIDecl && isa<ObjCCategoryDecl>(PIDecl->getDeclContext())) {
400 Diag(AtLoc, diag::err_duplicate_property);
401 Diag(PIDecl->getLocation(), diag::note_property_declare);
402 return nullptr;
403 }
404
405 // Check for consistency with the previous declaration, if there is one.
406 if (PIDecl) {
407 // A readonly property declared in the primary class can be refined
408 // by adding a readwrite property within an extension.
409 // Anything else is an error.
410 if (!(PIDecl->isReadOnly() && isReadWrite)) {
411 // Tailor the diagnostics for the common case where a readwrite
412 // property is declared both in the @interface and the continuation.
413 // This is a common error where the user often intended the original
414 // declaration to be readonly.
415 unsigned diag =
419 ? diag::err_use_continuation_class_redeclaration_readwrite
420 : diag::err_use_continuation_class;
421 Diag(AtLoc, diag)
422 << CCPrimary->getDeclName();
423 Diag(PIDecl->getLocation(), diag::note_property_declare);
424 return nullptr;
425 }
426
427 // Check for consistency of getters.
428 if (PIDecl->getGetterName() != GetterSel) {
429 // If the getter was written explicitly, complain.
430 if (AttributesAsWritten & ObjCPropertyAttribute::kind_getter) {
431 Diag(AtLoc, diag::warn_property_redecl_getter_mismatch)
432 << PIDecl->getGetterName() << GetterSel;
433 Diag(PIDecl->getLocation(), diag::note_property_declare);
434 }
435
436 // Always adopt the getter from the original declaration.
437 GetterSel = PIDecl->getGetterName();
439 }
440
441 // Check consistency of ownership.
442 unsigned ExistingOwnership
444 unsigned NewOwnership = getOwnershipRule(Attributes);
445 if (ExistingOwnership && NewOwnership != ExistingOwnership) {
446 // If the ownership was written explicitly, complain.
447 if (getOwnershipRule(AttributesAsWritten)) {
448 Diag(AtLoc, diag::warn_property_attr_mismatch);
449 Diag(PIDecl->getLocation(), diag::note_property_declare);
450 }
451
452 // Take the ownership from the original property.
453 Attributes = (Attributes & ~OwnershipMask) | ExistingOwnership;
454 }
455
456 // If the redeclaration is 'weak' but the original property is not,
457 if ((Attributes & ObjCPropertyAttribute::kind_weak) &&
460 PIDecl->getType()->getAs<ObjCObjectPointerType>() &&
462 Diag(AtLoc, diag::warn_property_implicitly_mismatched);
463 Diag(PIDecl->getLocation(), diag::note_property_declare);
464 }
465 }
466
467 // Create a new ObjCPropertyDecl with the DeclContext being
468 // the class extension.
469 ObjCPropertyDecl *PDecl = CreatePropertyDecl(S, CDecl, AtLoc, LParenLoc,
470 FD, GetterSel, GetterNameLoc,
471 SetterSel, SetterNameLoc,
472 isReadWrite,
473 Attributes, AttributesAsWritten,
474 T, TSI, MethodImplKind, DC);
475 ASTContext &Context = getASTContext();
476 // If there was no declaration of a property with the same name in
477 // the primary class, we're done.
478 if (!PIDecl) {
479 ProcessPropertyDecl(PDecl);
480 return PDecl;
481 }
482
483 if (!Context.hasSameType(PIDecl->getType(), PDecl->getType())) {
484 bool IncompatibleObjC = false;
485 QualType ConvertedType;
486 // Relax the strict type matching for property type in continuation class.
487 // Allow property object type of continuation class to be different as long
488 // as it narrows the object type in its primary class property. Note that
489 // this conversion is safe only because the wider type is for a 'readonly'
490 // property in primary class and 'narrowed' type for a 'readwrite' property
491 // in continuation class.
492 QualType PrimaryClassPropertyT = Context.getCanonicalType(PIDecl->getType());
493 QualType ClassExtPropertyT = Context.getCanonicalType(PDecl->getType());
494 if (!isa<ObjCObjectPointerType>(PrimaryClassPropertyT) ||
495 !isa<ObjCObjectPointerType>(ClassExtPropertyT) ||
496 (!SemaRef.isObjCPointerConversion(ClassExtPropertyT,
497 PrimaryClassPropertyT, ConvertedType,
498 IncompatibleObjC)) ||
499 IncompatibleObjC) {
500 Diag(AtLoc,
501 diag::err_type_mismatch_continuation_class) << PDecl->getType();
502 Diag(PIDecl->getLocation(), diag::note_property_declare);
503 return nullptr;
504 }
505 }
506
507 // Check that atomicity of property in class extension matches the previous
508 // declaration.
509 checkAtomicPropertyMismatch(SemaRef, PIDecl, PDecl, true);
510
511 // Make sure getter/setter are appropriately synthesized.
512 ProcessPropertyDecl(PDecl);
513 return PDecl;
514}
515
517 Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc,
518 SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel,
519 SourceLocation GetterNameLoc, Selector SetterSel,
520 SourceLocation SetterNameLoc, const bool isReadWrite,
521 const unsigned Attributes, const unsigned AttributesAsWritten, QualType T,
522 TypeSourceInfo *TInfo, tok::ObjCKeywordKind MethodImplKind,
523 DeclContext *lexicalDC) {
524 ASTContext &Context = getASTContext();
525 const IdentifierInfo *PropertyId = FD.D.getIdentifier();
526
527 // Property defaults to 'assign' if it is readwrite, unless this is ARC
528 // and the type is retainable.
529 bool isAssign;
530 if (Attributes & (ObjCPropertyAttribute::kind_assign |
532 isAssign = true;
533 } else if (getOwnershipRule(Attributes) || !isReadWrite) {
534 isAssign = false;
535 } else {
536 isAssign = (!getLangOpts().ObjCAutoRefCount ||
537 !T->isObjCRetainableType());
538 }
539
540 // Issue a warning if property is 'assign' as default and its
541 // object, which is gc'able conforms to NSCopying protocol
542 if (getLangOpts().getGC() != LangOptions::NonGC && isAssign &&
543 !(Attributes & ObjCPropertyAttribute::kind_assign)) {
544 if (const ObjCObjectPointerType *ObjPtrTy =
546 ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface();
547 if (IDecl)
548 if (ObjCProtocolDecl* PNSCopying =
549 LookupProtocol(&Context.Idents.get("NSCopying"), AtLoc))
550 if (IDecl->ClassImplementsProtocol(PNSCopying, true))
551 Diag(AtLoc, diag::warn_implements_nscopying) << PropertyId;
552 }
553 }
554
555 if (T->isObjCObjectType()) {
556 SourceLocation StarLoc = TInfo->getTypeLoc().getEndLoc();
557 StarLoc = SemaRef.getLocForEndOfToken(StarLoc);
558 Diag(FD.D.getIdentifierLoc(), diag::err_statically_allocated_object)
559 << FixItHint::CreateInsertion(StarLoc, "*");
560 T = Context.getObjCObjectPointerType(T);
561 SourceLocation TLoc = TInfo->getTypeLoc().getBeginLoc();
562 TInfo = Context.getTrivialTypeSourceInfo(T, TLoc);
563 }
564
565 DeclContext *DC = CDecl;
566 ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC,
567 FD.D.getIdentifierLoc(),
568 PropertyId, AtLoc,
569 LParenLoc, T, TInfo);
570
571 bool isClassProperty =
572 (AttributesAsWritten & ObjCPropertyAttribute::kind_class) ||
574 // Class property and instance property can have the same name.
576 DC, PropertyId, ObjCPropertyDecl::getQueryKind(isClassProperty))) {
577 Diag(PDecl->getLocation(), diag::err_duplicate_property);
578 Diag(prevDecl->getLocation(), diag::note_property_declare);
579 PDecl->setInvalidDecl();
580 }
581 else {
582 DC->addDecl(PDecl);
583 if (lexicalDC)
584 PDecl->setLexicalDeclContext(lexicalDC);
585 }
586
587 if (T->isArrayType() || T->isFunctionType()) {
588 Diag(AtLoc, diag::err_property_type) << T;
589 PDecl->setInvalidDecl();
590 }
591
592 // Regardless of setter/getter attribute, we save the default getter/setter
593 // selector names in anticipation of declaration of setter/getter methods.
594 PDecl->setGetterName(GetterSel, GetterNameLoc);
595 PDecl->setSetterName(SetterSel, SetterNameLoc);
597 static_cast<ObjCPropertyAttribute::Kind>(AttributesAsWritten));
598
599 SemaRef.ProcessDeclAttributes(S, PDecl, FD.D);
600
603
604 if (Attributes & ObjCPropertyAttribute::kind_getter)
606
607 if (Attributes & ObjCPropertyAttribute::kind_setter)
609
610 if (isReadWrite)
612
613 if (Attributes & ObjCPropertyAttribute::kind_retain)
615
616 if (Attributes & ObjCPropertyAttribute::kind_strong)
618
619 if (Attributes & ObjCPropertyAttribute::kind_weak)
621
622 if (Attributes & ObjCPropertyAttribute::kind_copy)
624
627
628 if (isAssign)
630
631 // In the semantic attributes, one of nonatomic or atomic is always set.
634 else
636
637 // 'unsafe_unretained' is alias for 'assign'.
640 if (isAssign)
642
643 if (MethodImplKind == tok::objc_required)
645 else if (MethodImplKind == tok::objc_optional)
647
650
653
654 if (Attributes & ObjCPropertyAttribute::kind_class)
656
657 if ((Attributes & ObjCPropertyAttribute::kind_direct) ||
658 CDecl->hasAttr<ObjCDirectMembersAttr>()) {
659 if (isa<ObjCProtocolDecl>(CDecl)) {
660 Diag(PDecl->getLocation(), diag::err_objc_direct_on_protocol) << true;
663 } else {
664 Diag(PDecl->getLocation(), diag::warn_objc_direct_property_ignored)
665 << PDecl->getDeclName();
666 }
667 }
668
669 return PDecl;
670}
671
672static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc,
673 ObjCPropertyDecl *property,
674 ObjCIvarDecl *ivar) {
675 if (property->isInvalidDecl() || ivar->isInvalidDecl()) return;
676
677 QualType ivarType = ivar->getType();
678 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
679
680 // The lifetime implied by the property's attributes.
681 Qualifiers::ObjCLifetime propertyLifetime =
683 property->getType());
684
685 // We're fine if they match.
686 if (propertyLifetime == ivarLifetime) return;
687
688 // None isn't a valid lifetime for an object ivar in ARC, and
689 // __autoreleasing is never valid; don't diagnose twice.
690 if ((ivarLifetime == Qualifiers::OCL_None &&
691 S.getLangOpts().ObjCAutoRefCount) ||
692 ivarLifetime == Qualifiers::OCL_Autoreleasing)
693 return;
694
695 // If the ivar is private, and it's implicitly __unsafe_unretained
696 // because of its type, then pretend it was actually implicitly
697 // __strong. This is only sound because we're processing the
698 // property implementation before parsing any method bodies.
699 if (ivarLifetime == Qualifiers::OCL_ExplicitNone &&
700 propertyLifetime == Qualifiers::OCL_Strong &&
702 SplitQualType split = ivarType.split();
703 if (split.Quals.hasObjCLifetime()) {
704 assert(ivarType->isObjCARCImplicitlyUnretainedType());
706 ivarType = S.Context.getQualifiedType(split);
707 ivar->setType(ivarType);
708 return;
709 }
710 }
711
712 switch (propertyLifetime) {
714 S.Diag(ivar->getLocation(), diag::err_arc_strong_property_ownership)
715 << property->getDeclName()
716 << ivar->getDeclName()
717 << ivarLifetime;
718 break;
719
721 S.Diag(ivar->getLocation(), diag::err_weak_property)
722 << property->getDeclName()
723 << ivar->getDeclName();
724 break;
725
727 S.Diag(ivar->getLocation(), diag::err_arc_assign_property_ownership)
728 << property->getDeclName() << ivar->getDeclName()
729 << ((property->getPropertyAttributesAsWritten() &
731 break;
732
734 llvm_unreachable("properties cannot be autoreleasing");
735
737 // Any other property should be ignored.
738 return;
739 }
740
741 S.Diag(property->getLocation(), diag::note_property_declare);
742 if (propertyImplLoc.isValid())
743 S.Diag(propertyImplLoc, diag::note_property_synthesize);
744}
745
746/// setImpliedPropertyAttributeForReadOnlyProperty -
747/// This routine evaludates life-time attributes for a 'readonly'
748/// property with no known lifetime of its own, using backing
749/// 'ivar's attribute, if any. If no backing 'ivar', property's
750/// life-time is assumed 'strong'.
752 ObjCPropertyDecl *property, ObjCIvarDecl *ivar) {
753 Qualifiers::ObjCLifetime propertyLifetime =
755 property->getType());
756 if (propertyLifetime != Qualifiers::OCL_None)
757 return;
758
759 if (!ivar) {
760 // if no backing ivar, make property 'strong'.
761 property->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
762 return;
763 }
764 // property assumes owenership of backing ivar.
765 QualType ivarType = ivar->getType();
766 Qualifiers::ObjCLifetime ivarLifetime = ivarType.getObjCLifetime();
767 if (ivarLifetime == Qualifiers::OCL_Strong)
768 property->setPropertyAttributes(ObjCPropertyAttribute::kind_strong);
769 else if (ivarLifetime == Qualifiers::OCL_Weak)
770 property->setPropertyAttributes(ObjCPropertyAttribute::kind_weak);
771}
772
773static bool isIncompatiblePropertyAttribute(unsigned Attr1, unsigned Attr2,
775 return (Attr1 & Kind) != (Attr2 & Kind);
776}
777
778static bool areIncompatiblePropertyAttributes(unsigned Attr1, unsigned Attr2,
779 unsigned Kinds) {
780 return ((Attr1 & Kinds) != 0) != ((Attr2 & Kinds) != 0);
781}
782
783/// SelectPropertyForSynthesisFromProtocols - Finds the most appropriate
784/// property declaration that should be synthesised in all of the inherited
785/// protocols. It also diagnoses properties declared in inherited protocols with
786/// mismatched types or attributes, since any of them can be candidate for
787/// synthesis.
788static ObjCPropertyDecl *
790 ObjCInterfaceDecl *ClassDecl,
791 ObjCPropertyDecl *Property) {
792 assert(isa<ObjCProtocolDecl>(Property->getDeclContext()) &&
793 "Expected a property from a protocol");
796 for (const auto *PI : ClassDecl->all_referenced_protocols()) {
797 if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
798 PDecl->collectInheritedProtocolProperties(Property, ProtocolSet,
799 Properties);
800 }
801 if (ObjCInterfaceDecl *SDecl = ClassDecl->getSuperClass()) {
802 while (SDecl) {
803 for (const auto *PI : SDecl->all_referenced_protocols()) {
804 if (const ObjCProtocolDecl *PDecl = PI->getDefinition())
805 PDecl->collectInheritedProtocolProperties(Property, ProtocolSet,
806 Properties);
807 }
808 SDecl = SDecl->getSuperClass();
809 }
810 }
811
812 if (Properties.empty())
813 return Property;
814
815 ObjCPropertyDecl *OriginalProperty = Property;
816 size_t SelectedIndex = 0;
817 for (const auto &Prop : llvm::enumerate(Properties)) {
818 // Select the 'readwrite' property if such property exists.
819 if (Property->isReadOnly() && !Prop.value()->isReadOnly()) {
820 Property = Prop.value();
821 SelectedIndex = Prop.index();
822 }
823 }
824 if (Property != OriginalProperty) {
825 // Check that the old property is compatible with the new one.
826 Properties[SelectedIndex] = OriginalProperty;
827 }
828
829 QualType RHSType = S.Context.getCanonicalType(Property->getType());
830 unsigned OriginalAttributes = Property->getPropertyAttributesAsWritten();
831 enum MismatchKind {
832 IncompatibleType = 0,
833 HasNoExpectedAttribute,
834 HasUnexpectedAttribute,
835 DifferentGetter,
836 DifferentSetter
837 };
838 // Represents a property from another protocol that conflicts with the
839 // selected declaration.
840 struct MismatchingProperty {
841 const ObjCPropertyDecl *Prop;
842 MismatchKind Kind;
843 StringRef AttributeName;
844 };
846 for (ObjCPropertyDecl *Prop : Properties) {
847 // Verify the property attributes.
848 unsigned Attr = Prop->getPropertyAttributesAsWritten();
849 if (Attr != OriginalAttributes) {
850 auto Diag = [&](bool OriginalHasAttribute, StringRef AttributeName) {
851 MismatchKind Kind = OriginalHasAttribute ? HasNoExpectedAttribute
852 : HasUnexpectedAttribute;
853 Mismatches.push_back({Prop, Kind, AttributeName});
854 };
855 // The ownership might be incompatible unless the property has no explicit
856 // ownership.
857 bool HasOwnership =
864 if (HasOwnership &&
865 isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
867 Diag(OriginalAttributes & ObjCPropertyAttribute::kind_copy, "copy");
868 continue;
869 }
870 if (HasOwnership && areIncompatiblePropertyAttributes(
871 OriginalAttributes, Attr,
874 Diag(OriginalAttributes & (ObjCPropertyAttribute::kind_retain |
876 "retain (or strong)");
877 continue;
878 }
879 if (isIncompatiblePropertyAttribute(OriginalAttributes, Attr,
881 Diag(OriginalAttributes & ObjCPropertyAttribute::kind_atomic, "atomic");
882 continue;
883 }
884 }
885 if (Property->getGetterName() != Prop->getGetterName()) {
886 Mismatches.push_back({Prop, DifferentGetter, ""});
887 continue;
888 }
889 if (!Property->isReadOnly() && !Prop->isReadOnly() &&
890 Property->getSetterName() != Prop->getSetterName()) {
891 Mismatches.push_back({Prop, DifferentSetter, ""});
892 continue;
893 }
894 QualType LHSType = S.Context.getCanonicalType(Prop->getType());
895 if (!S.Context.propertyTypesAreCompatible(LHSType, RHSType)) {
896 bool IncompatibleObjC = false;
897 QualType ConvertedType;
898 if (!S.isObjCPointerConversion(RHSType, LHSType, ConvertedType, IncompatibleObjC)
899 || IncompatibleObjC) {
900 Mismatches.push_back({Prop, IncompatibleType, ""});
901 continue;
902 }
903 }
904 }
905
906 if (Mismatches.empty())
907 return Property;
908
909 // Diagnose incompability.
910 {
911 bool HasIncompatibleAttributes = false;
912 for (const auto &Note : Mismatches)
913 HasIncompatibleAttributes =
914 Note.Kind != IncompatibleType ? true : HasIncompatibleAttributes;
915 // Promote the warning to an error if there are incompatible attributes or
916 // incompatible types together with readwrite/readonly incompatibility.
917 auto Diag = S.Diag(Property->getLocation(),
918 Property != OriginalProperty || HasIncompatibleAttributes
919 ? diag::err_protocol_property_mismatch
920 : diag::warn_protocol_property_mismatch);
921 Diag << Mismatches[0].Kind;
922 switch (Mismatches[0].Kind) {
923 case IncompatibleType:
924 Diag << Property->getType();
925 break;
926 case HasNoExpectedAttribute:
927 case HasUnexpectedAttribute:
928 Diag << Mismatches[0].AttributeName;
929 break;
930 case DifferentGetter:
931 Diag << Property->getGetterName();
932 break;
933 case DifferentSetter:
934 Diag << Property->getSetterName();
935 break;
936 }
937 }
938 for (const auto &Note : Mismatches) {
939 auto Diag =
940 S.Diag(Note.Prop->getLocation(), diag::note_protocol_property_declare)
941 << Note.Kind;
942 switch (Note.Kind) {
943 case IncompatibleType:
944 Diag << Note.Prop->getType();
945 break;
946 case HasNoExpectedAttribute:
947 case HasUnexpectedAttribute:
948 Diag << Note.AttributeName;
949 break;
950 case DifferentGetter:
951 Diag << Note.Prop->getGetterName();
952 break;
953 case DifferentSetter:
954 Diag << Note.Prop->getSetterName();
955 break;
956 }
957 }
958 if (AtLoc.isValid())
959 S.Diag(AtLoc, diag::note_property_synthesize);
960
961 return Property;
962}
963
964/// Determine whether any storage attributes were written on the property.
966 ObjCPropertyQueryKind QueryKind) {
967 if (Prop->getPropertyAttributesAsWritten() & OwnershipMask) return true;
968
969 // If this is a readwrite property in a class extension that refines
970 // a readonly property in the original class definition, check it as
971 // well.
972
973 // If it's a readonly property, we're not interested.
974 if (Prop->isReadOnly()) return false;
975
976 // Is it declared in an extension?
977 auto Category = dyn_cast<ObjCCategoryDecl>(Prop->getDeclContext());
978 if (!Category || !Category->IsClassExtension()) return false;
979
980 // Find the corresponding property in the primary class definition.
981 auto OrigClass = Category->getClassInterface();
982 for (auto *Found : OrigClass->lookup(Prop->getDeclName())) {
983 if (ObjCPropertyDecl *OrigProp = dyn_cast<ObjCPropertyDecl>(Found))
984 return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
985 }
986
987 // Look through all of the protocols.
988 for (const auto *Proto : OrigClass->all_referenced_protocols()) {
989 if (ObjCPropertyDecl *OrigProp = Proto->FindPropertyDeclaration(
990 Prop->getIdentifier(), QueryKind))
991 return OrigProp->getPropertyAttributesAsWritten() & OwnershipMask;
992 }
993
994 return false;
995}
996
997/// Create a synthesized property accessor stub inside the \@implementation.
998static ObjCMethodDecl *
1000 ObjCMethodDecl *AccessorDecl, SourceLocation AtLoc,
1001 SourceLocation PropertyLoc) {
1002 ObjCMethodDecl *Decl = AccessorDecl;
1004 Context, AtLoc.isValid() ? AtLoc : Decl->getBeginLoc(),
1005 PropertyLoc.isValid() ? PropertyLoc : Decl->getEndLoc(),
1006 Decl->getSelector(), Decl->getReturnType(),
1007 Decl->getReturnTypeSourceInfo(), Impl, Decl->isInstanceMethod(),
1008 Decl->isVariadic(), Decl->isPropertyAccessor(),
1009 /*isSynthesizedAccessorStub=*/true, Decl->isImplicit(), Decl->isDefined(),
1010 Decl->getImplementationControl(), Decl->hasRelatedResultType());
1011 ImplDecl->getMethodFamily();
1012 if (Decl->hasAttrs())
1013 ImplDecl->setAttrs(Decl->getAttrs());
1014 ImplDecl->setSelfDecl(Decl->getSelfDecl());
1015 ImplDecl->setCmdDecl(Decl->getCmdDecl());
1017 Decl->getSelectorLocs(SelLocs);
1018 ImplDecl->setMethodParams(Context, Decl->parameters(), SelLocs);
1019 ImplDecl->setLexicalDeclContext(Impl);
1020 ImplDecl->setDefined(false);
1021 return ImplDecl;
1022}
1023
1024/// ActOnPropertyImplDecl - This routine performs semantic checks and
1025/// builds the AST node for a property implementation declaration; declared
1026/// as \@synthesize or \@dynamic.
1027///
1029 Scope *S, SourceLocation AtLoc, SourceLocation PropertyLoc, bool Synthesize,
1030 IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar,
1031 SourceLocation PropertyIvarLoc, ObjCPropertyQueryKind QueryKind) {
1032 ASTContext &Context = getASTContext();
1033 ObjCContainerDecl *ClassImpDecl =
1034 dyn_cast<ObjCContainerDecl>(SemaRef.CurContext);
1035 // Make sure we have a context for the property implementation declaration.
1036 if (!ClassImpDecl) {
1037 Diag(AtLoc, diag::err_missing_property_context);
1038 return nullptr;
1039 }
1040 if (PropertyIvarLoc.isInvalid())
1041 PropertyIvarLoc = PropertyLoc;
1042 SourceLocation PropertyDiagLoc = PropertyLoc;
1043 if (PropertyDiagLoc.isInvalid())
1044 PropertyDiagLoc = ClassImpDecl->getBeginLoc();
1045 ObjCPropertyDecl *property = nullptr;
1046 ObjCInterfaceDecl *IDecl = nullptr;
1047 // Find the class or category class where this property must have
1048 // a declaration.
1049 ObjCImplementationDecl *IC = nullptr;
1050 ObjCCategoryImplDecl *CatImplClass = nullptr;
1051 if ((IC = dyn_cast<ObjCImplementationDecl>(ClassImpDecl))) {
1052 IDecl = IC->getClassInterface();
1053 // We always synthesize an interface for an implementation
1054 // without an interface decl. So, IDecl is always non-zero.
1055 assert(IDecl &&
1056 "ActOnPropertyImplDecl - @implementation without @interface");
1057
1058 // Look for this property declaration in the @implementation's @interface
1059 property = IDecl->FindPropertyDeclaration(PropertyId, QueryKind);
1060 if (!property) {
1061 Diag(PropertyLoc, diag::err_bad_property_decl) << IDecl->getDeclName();
1062 return nullptr;
1063 }
1064 if (property->isClassProperty() && Synthesize) {
1065 Diag(PropertyLoc, diag::err_synthesize_on_class_property) << PropertyId;
1066 return nullptr;
1067 }
1068 unsigned PIkind = property->getPropertyAttributesAsWritten();
1069 if ((PIkind & (ObjCPropertyAttribute::kind_atomic |
1071 if (AtLoc.isValid())
1072 Diag(AtLoc, diag::warn_implicit_atomic_property);
1073 else
1074 Diag(IC->getLocation(), diag::warn_auto_implicit_atomic_property);
1075 Diag(property->getLocation(), diag::note_property_declare);
1076 }
1077
1078 if (const ObjCCategoryDecl *CD =
1079 dyn_cast<ObjCCategoryDecl>(property->getDeclContext())) {
1080 if (!CD->IsClassExtension()) {
1081 Diag(PropertyLoc, diag::err_category_property) << CD->getDeclName();
1082 Diag(property->getLocation(), diag::note_property_declare);
1083 return nullptr;
1084 }
1085 }
1086 if (Synthesize && (PIkind & ObjCPropertyAttribute::kind_readonly) &&
1087 property->hasAttr<IBOutletAttr>() && !AtLoc.isValid()) {
1088 bool ReadWriteProperty = false;
1089 // Search into the class extensions and see if 'readonly property is
1090 // redeclared 'readwrite', then no warning is to be issued.
1091 for (auto *Ext : IDecl->known_extensions()) {
1092 DeclContext::lookup_result R = Ext->lookup(property->getDeclName());
1093 if (auto *ExtProp = R.find_first<ObjCPropertyDecl>()) {
1094 PIkind = ExtProp->getPropertyAttributesAsWritten();
1096 ReadWriteProperty = true;
1097 break;
1098 }
1099 }
1100 }
1101
1102 if (!ReadWriteProperty) {
1103 Diag(property->getLocation(), diag::warn_auto_readonly_iboutlet_property)
1104 << property;
1105 SourceLocation readonlyLoc;
1106 if (LocPropertyAttribute(Context, "readonly",
1107 property->getLParenLoc(), readonlyLoc)) {
1108 SourceLocation endLoc =
1109 readonlyLoc.getLocWithOffset(strlen("readonly")-1);
1110 SourceRange ReadonlySourceRange(readonlyLoc, endLoc);
1111 Diag(property->getLocation(),
1112 diag::note_auto_readonly_iboutlet_fixup_suggest) <<
1113 FixItHint::CreateReplacement(ReadonlySourceRange, "readwrite");
1114 }
1115 }
1116 }
1117 if (Synthesize && isa<ObjCProtocolDecl>(property->getDeclContext()))
1118 property = SelectPropertyForSynthesisFromProtocols(SemaRef, AtLoc, IDecl,
1119 property);
1120
1121 } else if ((CatImplClass = dyn_cast<ObjCCategoryImplDecl>(ClassImpDecl))) {
1122 if (Synthesize) {
1123 Diag(AtLoc, diag::err_synthesize_category_decl);
1124 return nullptr;
1125 }
1126 IDecl = CatImplClass->getClassInterface();
1127 if (!IDecl) {
1128 Diag(AtLoc, diag::err_missing_property_interface);
1129 return nullptr;
1130 }
1131 ObjCCategoryDecl *Category =
1132 IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier());
1133
1134 // If category for this implementation not found, it is an error which
1135 // has already been reported eralier.
1136 if (!Category)
1137 return nullptr;
1138 // Look for this property declaration in @implementation's category
1139 property = Category->FindPropertyDeclaration(PropertyId, QueryKind);
1140 if (!property) {
1141 Diag(PropertyLoc, diag::err_bad_category_property_decl)
1142 << Category->getDeclName();
1143 return nullptr;
1144 }
1145 } else {
1146 Diag(AtLoc, diag::err_bad_property_context);
1147 return nullptr;
1148 }
1149 ObjCIvarDecl *Ivar = nullptr;
1150 bool CompleteTypeErr = false;
1151 bool compat = true;
1152 // Check that we have a valid, previously declared ivar for @synthesize
1153 if (Synthesize) {
1154 // @synthesize
1155 if (!PropertyIvar)
1156 PropertyIvar = PropertyId;
1157 // Check that this is a previously declared 'ivar' in 'IDecl' interface
1158 ObjCInterfaceDecl *ClassDeclared;
1159 Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared);
1160 QualType PropType = property->getType();
1161 QualType PropertyIvarType = PropType.getNonReferenceType();
1162
1163 if (SemaRef.RequireCompleteType(PropertyDiagLoc, PropertyIvarType,
1164 diag::err_incomplete_synthesized_property,
1165 property->getDeclName())) {
1166 Diag(property->getLocation(), diag::note_property_declare);
1167 CompleteTypeErr = true;
1168 }
1169
1170 if (getLangOpts().ObjCAutoRefCount &&
1171 (property->getPropertyAttributesAsWritten() &
1173 PropertyIvarType->isObjCRetainableType()) {
1175 }
1176
1177 ObjCPropertyAttribute::Kind kind = property->getPropertyAttributes();
1178
1179 bool isARCWeak = false;
1181 // Add GC __weak to the ivar type if the property is weak.
1182 if (getLangOpts().getGC() != LangOptions::NonGC) {
1183 assert(!getLangOpts().ObjCAutoRefCount);
1184 if (PropertyIvarType.isObjCGCStrong()) {
1185 Diag(PropertyDiagLoc, diag::err_gc_weak_property_strong_type);
1186 Diag(property->getLocation(), diag::note_property_declare);
1187 } else {
1188 PropertyIvarType =
1189 Context.getObjCGCQualType(PropertyIvarType, Qualifiers::Weak);
1190 }
1191
1192 // Otherwise, check whether ARC __weak is enabled and works with
1193 // the property type.
1194 } else {
1195 if (!getLangOpts().ObjCWeak) {
1196 // Only complain here when synthesizing an ivar.
1197 if (!Ivar) {
1198 Diag(PropertyDiagLoc,
1199 getLangOpts().ObjCWeakRuntime
1200 ? diag::err_synthesizing_arc_weak_property_disabled
1201 : diag::err_synthesizing_arc_weak_property_no_runtime);
1202 Diag(property->getLocation(), diag::note_property_declare);
1203 }
1204 CompleteTypeErr = true; // suppress later diagnostics about the ivar
1205 } else {
1206 isARCWeak = true;
1207 if (const ObjCObjectPointerType *ObjT =
1208 PropertyIvarType->getAs<ObjCObjectPointerType>()) {
1209 const ObjCInterfaceDecl *ObjI = ObjT->getInterfaceDecl();
1210 if (ObjI && ObjI->isArcWeakrefUnavailable()) {
1211 Diag(property->getLocation(),
1212 diag::err_arc_weak_unavailable_property)
1213 << PropertyIvarType;
1214 Diag(ClassImpDecl->getLocation(), diag::note_implemented_by_class)
1215 << ClassImpDecl->getName();
1216 }
1217 }
1218 }
1219 }
1220 }
1221
1222 if (AtLoc.isInvalid()) {
1223 // Check when default synthesizing a property that there is
1224 // an ivar matching property name and issue warning; since this
1225 // is the most common case of not using an ivar used for backing
1226 // property in non-default synthesis case.
1227 ObjCInterfaceDecl *ClassDeclared=nullptr;
1228 ObjCIvarDecl *originalIvar =
1229 IDecl->lookupInstanceVariable(property->getIdentifier(),
1230 ClassDeclared);
1231 if (originalIvar) {
1232 Diag(PropertyDiagLoc,
1233 diag::warn_autosynthesis_property_ivar_match)
1234 << PropertyId << (Ivar == nullptr) << PropertyIvar
1235 << originalIvar->getIdentifier();
1236 Diag(property->getLocation(), diag::note_property_declare);
1237 Diag(originalIvar->getLocation(), diag::note_ivar_decl);
1238 }
1239 }
1240
1241 if (!Ivar) {
1242 // In ARC, give the ivar a lifetime qualifier based on the
1243 // property attributes.
1244 if ((getLangOpts().ObjCAutoRefCount || isARCWeak) &&
1245 !PropertyIvarType.getObjCLifetime() &&
1246 PropertyIvarType->isObjCRetainableType()) {
1247
1248 // It's an error if we have to do this and the user didn't
1249 // explicitly write an ownership attribute on the property.
1250 if (!hasWrittenStorageAttribute(property, QueryKind) &&
1252 Diag(PropertyDiagLoc,
1253 diag::err_arc_objc_property_default_assign_on_object);
1254 Diag(property->getLocation(), diag::note_property_declare);
1255 } else {
1256 Qualifiers::ObjCLifetime lifetime =
1257 getImpliedARCOwnership(kind, PropertyIvarType);
1258 assert(lifetime && "no lifetime for property?");
1259
1260 Qualifiers qs;
1261 qs.addObjCLifetime(lifetime);
1262 PropertyIvarType = Context.getQualifiedType(PropertyIvarType, qs);
1263 }
1264 }
1265
1266 if (Context.getLangOpts().PointerAuthObjcInterfaceSel &&
1267 !PropertyIvarType.getPointerAuth()) {
1268 if (Context.isObjCSelType(QualType(PropertyIvarType.getTypePtr(), 0))) {
1269 if (auto PAQ = Context.getObjCMemberSelTypePtrAuth())
1270 PropertyIvarType =
1271 Context.getPointerAuthType(PropertyIvarType, PAQ);
1272 }
1273 }
1274
1275 Ivar = ObjCIvarDecl::Create(Context, ClassImpDecl,
1276 PropertyIvarLoc,PropertyIvarLoc, PropertyIvar,
1277 PropertyIvarType, /*TInfo=*/nullptr,
1279 (Expr *)nullptr, true);
1280 if (SemaRef.RequireNonAbstractType(PropertyIvarLoc, PropertyIvarType,
1281 diag::err_abstract_type_in_decl,
1283 Diag(property->getLocation(), diag::note_property_declare);
1284 // An abstract type is as bad as an incomplete type.
1285 CompleteTypeErr = true;
1286 }
1287 if (!CompleteTypeErr) {
1288 if (const auto *RD = PropertyIvarType->getAsRecordDecl();
1289 RD && RD->hasFlexibleArrayMember()) {
1290 Diag(PropertyIvarLoc, diag::err_synthesize_variable_sized_ivar)
1291 << PropertyIvarType;
1292 CompleteTypeErr = true; // suppress later diagnostics about the ivar
1293 }
1294 }
1295 if (CompleteTypeErr)
1296 Ivar->setInvalidDecl();
1297 ClassImpDecl->addDecl(Ivar);
1298 IDecl->makeDeclVisibleInContext(Ivar);
1299
1301 Diag(PropertyDiagLoc, diag::err_missing_property_ivar_decl)
1302 << PropertyId;
1303 // Note! I deliberately want it to fall thru so, we have a
1304 // a property implementation and to avoid future warnings.
1305 } else if (getLangOpts().ObjCRuntime.isNonFragile() &&
1306 !declaresSameEntity(ClassDeclared, IDecl)) {
1307 Diag(PropertyDiagLoc, diag::err_ivar_in_superclass_use)
1308 << property->getDeclName() << Ivar->getDeclName()
1309 << ClassDeclared->getDeclName();
1310 Diag(Ivar->getLocation(), diag::note_previous_access_declaration)
1311 << Ivar << Ivar->getName();
1312 // Note! I deliberately want it to fall thru so more errors are caught.
1313 }
1314 property->setPropertyIvarDecl(Ivar);
1315
1316 QualType IvarType = Context.getCanonicalType(Ivar->getType());
1317
1318 // Check that type of property and its ivar are type compatible.
1319 if (!Context.hasSameType(PropertyIvarType, IvarType)) {
1320 if (isa<ObjCObjectPointerType>(PropertyIvarType)
1321 && isa<ObjCObjectPointerType>(IvarType))
1322 compat = Context.canAssignObjCInterfaces(
1323 PropertyIvarType->castAs<ObjCObjectPointerType>(),
1324 IvarType->castAs<ObjCObjectPointerType>());
1325 else {
1326 compat = SemaRef.IsAssignConvertCompatible(
1327 SemaRef.CheckAssignmentConstraints(PropertyIvarLoc,
1328 PropertyIvarType, IvarType));
1329 }
1330 if (!compat) {
1331 Diag(PropertyDiagLoc, diag::err_property_ivar_type)
1332 << property->getDeclName() << PropType
1333 << Ivar->getDeclName() << IvarType;
1334 Diag(Ivar->getLocation(), diag::note_ivar_decl);
1335 // Note! I deliberately want it to fall thru so, we have a
1336 // a property implementation and to avoid future warnings.
1337 }
1338 else {
1339 // FIXME! Rules for properties are somewhat different that those
1340 // for assignments. Use a new routine to consolidate all cases;
1341 // specifically for property redeclarations as well as for ivars.
1342 QualType lhsType =Context.getCanonicalType(PropertyIvarType).getUnqualifiedType();
1343 QualType rhsType =Context.getCanonicalType(IvarType).getUnqualifiedType();
1344 if (lhsType != rhsType &&
1345 lhsType->isArithmeticType()) {
1346 Diag(PropertyDiagLoc, diag::err_property_ivar_type)
1347 << property->getDeclName() << PropType
1348 << Ivar->getDeclName() << IvarType;
1349 Diag(Ivar->getLocation(), diag::note_ivar_decl);
1350 // Fall thru - see previous comment
1351 }
1352 }
1353 // __weak is explicit. So it works on Canonical type.
1354 if ((PropType.isObjCGCWeak() && !IvarType.isObjCGCWeak() &&
1355 getLangOpts().getGC() != LangOptions::NonGC)) {
1356 Diag(PropertyDiagLoc, diag::err_weak_property)
1357 << property->getDeclName() << Ivar->getDeclName();
1358 Diag(Ivar->getLocation(), diag::note_ivar_decl);
1359 // Fall thru - see previous comment
1360 }
1361 // Fall thru - see previous comment
1362 if ((property->getType()->isObjCObjectPointerType() ||
1363 PropType.isObjCGCStrong()) && IvarType.isObjCGCWeak() &&
1364 getLangOpts().getGC() != LangOptions::NonGC) {
1365 Diag(PropertyDiagLoc, diag::err_strong_property)
1366 << property->getDeclName() << Ivar->getDeclName();
1367 // Fall thru - see previous comment
1368 }
1369 }
1370 if (getLangOpts().ObjCAutoRefCount || isARCWeak ||
1371 Ivar->getType().getObjCLifetime())
1372 checkARCPropertyImpl(SemaRef, PropertyLoc, property, Ivar);
1373 } else if (PropertyIvar)
1374 // @dynamic
1375 Diag(PropertyDiagLoc, diag::err_dynamic_property_ivar_decl);
1376
1377 assert (property && "ActOnPropertyImplDecl - property declaration missing");
1379 Context, SemaRef.CurContext, AtLoc, PropertyLoc, property,
1382 Ivar, PropertyIvarLoc);
1383
1384 if (CompleteTypeErr || !compat)
1385 PIDecl->setInvalidDecl();
1386
1387 if (ObjCMethodDecl *getterMethod = property->getGetterMethodDecl()) {
1388 getterMethod->createImplicitParams(Context, IDecl);
1389
1390 // Redeclare the getter within the implementation as DeclContext.
1391 if (Synthesize) {
1392 // If the method hasn't been overridden, create a synthesized implementation.
1393 ObjCMethodDecl *OMD = ClassImpDecl->getMethod(
1394 getterMethod->getSelector(), getterMethod->isInstanceMethod());
1395 if (!OMD)
1396 OMD = RedeclarePropertyAccessor(Context, IC, getterMethod, AtLoc,
1397 PropertyLoc);
1398 PIDecl->setGetterMethodDecl(OMD);
1399 }
1400
1401 if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
1402 Ivar->getType()->isRecordType()) {
1403 // For Objective-C++, need to synthesize the AST for the IVAR object to be
1404 // returned by the getter as it must conform to C++'s copy-return rules.
1405 // FIXME. Eventually we want to do this for Objective-C as well.
1407 ImplicitParamDecl *SelfDecl = getterMethod->getSelfDecl();
1408 DeclRefExpr *SelfExpr = new (Context)
1409 DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
1410 PropertyDiagLoc);
1411 SemaRef.MarkDeclRefReferenced(SelfExpr);
1412 Expr *LoadSelfExpr = ImplicitCastExpr::Create(
1413 Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
1415 Expr *IvarRefExpr =
1416 new (Context) ObjCIvarRefExpr(Ivar,
1417 Ivar->getUsageType(SelfDecl->getType()),
1418 PropertyDiagLoc,
1419 Ivar->getLocation(),
1420 LoadSelfExpr, true, true);
1421 ExprResult Res = SemaRef.PerformCopyInitialization(
1423 getterMethod->getReturnType()),
1424 PropertyDiagLoc, IvarRefExpr);
1425 if (!Res.isInvalid()) {
1426 Expr *ResExpr = Res.getAs<Expr>();
1427 if (ResExpr)
1428 ResExpr = SemaRef.MaybeCreateExprWithCleanups(ResExpr);
1429 PIDecl->setGetterCXXConstructor(ResExpr);
1430 }
1431 }
1432 if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
1433 !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
1434 Diag(getterMethod->getLocation(),
1435 diag::warn_property_getter_owning_mismatch);
1436 Diag(property->getLocation(), diag::note_property_declare);
1437 }
1438 if (getLangOpts().ObjCAutoRefCount && Synthesize)
1439 switch (getterMethod->getMethodFamily()) {
1440 case OMF_retain:
1441 case OMF_retainCount:
1442 case OMF_release:
1443 case OMF_autorelease:
1444 Diag(getterMethod->getLocation(), diag::err_arc_illegal_method_def)
1445 << 1 << getterMethod->getSelector();
1446 break;
1447 default:
1448 break;
1449 }
1450 }
1451
1452 if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
1453 setterMethod->createImplicitParams(Context, IDecl);
1454
1455 // Redeclare the setter within the implementation as DeclContext.
1456 if (Synthesize) {
1457 ObjCMethodDecl *OMD = ClassImpDecl->getMethod(
1458 setterMethod->getSelector(), setterMethod->isInstanceMethod());
1459 if (!OMD)
1460 OMD = RedeclarePropertyAccessor(Context, IC, setterMethod,
1461 AtLoc, PropertyLoc);
1462 PIDecl->setSetterMethodDecl(OMD);
1463 }
1464
1465 if (getLangOpts().CPlusPlus && Synthesize && !CompleteTypeErr &&
1466 Ivar->getType()->isRecordType()) {
1467 // FIXME. Eventually we want to do this for Objective-C as well.
1469 ImplicitParamDecl *SelfDecl = setterMethod->getSelfDecl();
1470 DeclRefExpr *SelfExpr = new (Context)
1471 DeclRefExpr(Context, SelfDecl, false, SelfDecl->getType(), VK_LValue,
1472 PropertyDiagLoc);
1473 SemaRef.MarkDeclRefReferenced(SelfExpr);
1474 Expr *LoadSelfExpr = ImplicitCastExpr::Create(
1475 Context, SelfDecl->getType(), CK_LValueToRValue, SelfExpr, nullptr,
1477 Expr *lhs =
1478 new (Context) ObjCIvarRefExpr(Ivar,
1479 Ivar->getUsageType(SelfDecl->getType()),
1480 PropertyDiagLoc,
1481 Ivar->getLocation(),
1482 LoadSelfExpr, true, true);
1483 ObjCMethodDecl::param_iterator P = setterMethod->param_begin();
1484 ParmVarDecl *Param = (*P);
1485 QualType T = Param->getType().getNonReferenceType();
1486 DeclRefExpr *rhs = new (Context)
1487 DeclRefExpr(Context, Param, false, T, VK_LValue, PropertyDiagLoc);
1488 SemaRef.MarkDeclRefReferenced(rhs);
1489 ExprResult Res =
1490 SemaRef.BuildBinOp(S, PropertyDiagLoc, BO_Assign, lhs, rhs);
1491 if (property->getPropertyAttributes() &
1493 Expr *callExpr = Res.getAs<Expr>();
1494 if (const CXXOperatorCallExpr *CXXCE =
1495 dyn_cast_or_null<CXXOperatorCallExpr>(callExpr))
1496 if (const FunctionDecl *FuncDecl = CXXCE->getDirectCallee())
1497 if (!FuncDecl->isTrivial())
1498 if (property->getType()->isReferenceType()) {
1499 Diag(PropertyDiagLoc,
1500 diag::err_atomic_property_nontrivial_assign_op)
1501 << property->getType();
1502 Diag(FuncDecl->getBeginLoc(), diag::note_callee_decl)
1503 << FuncDecl;
1504 }
1505 }
1506 PIDecl->setSetterCXXAssignment(Res.getAs<Expr>());
1507 }
1508 }
1509
1510 if (IC) {
1511 if (Synthesize)
1512 if (ObjCPropertyImplDecl *PPIDecl =
1513 IC->FindPropertyImplIvarDecl(PropertyIvar)) {
1514 Diag(PropertyLoc, diag::err_duplicate_ivar_use)
1515 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
1516 << PropertyIvar;
1517 Diag(PPIDecl->getLocation(), diag::note_previous_use);
1518 }
1519
1520 if (ObjCPropertyImplDecl *PPIDecl
1521 = IC->FindPropertyImplDecl(PropertyId, QueryKind)) {
1522 Diag(PropertyLoc, diag::err_property_implemented) << PropertyId;
1523 Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
1524 return nullptr;
1525 }
1526 IC->addPropertyImplementation(PIDecl);
1527 if (getLangOpts().ObjCDefaultSynthProperties &&
1529 !IDecl->isObjCRequiresPropertyDefs()) {
1530 // Diagnose if an ivar was lazily synthesdized due to a previous
1531 // use and if 1) property is @dynamic or 2) property is synthesized
1532 // but it requires an ivar of different name.
1533 ObjCInterfaceDecl *ClassDeclared=nullptr;
1534 ObjCIvarDecl *Ivar = nullptr;
1535 if (!Synthesize)
1536 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
1537 else {
1538 if (PropertyIvar && PropertyIvar != PropertyId)
1539 Ivar = IDecl->lookupInstanceVariable(PropertyId, ClassDeclared);
1540 }
1541 // Issue diagnostics only if Ivar belongs to current class.
1542 if (Ivar && Ivar->getSynthesize() &&
1543 declaresSameEntity(IC->getClassInterface(), ClassDeclared)) {
1544 Diag(Ivar->getLocation(), diag::err_undeclared_var_use)
1545 << PropertyId;
1546 Ivar->setInvalidDecl();
1547 }
1548 }
1549 } else {
1550 if (Synthesize)
1551 if (ObjCPropertyImplDecl *PPIDecl =
1552 CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) {
1553 Diag(PropertyDiagLoc, diag::err_duplicate_ivar_use)
1554 << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier()
1555 << PropertyIvar;
1556 Diag(PPIDecl->getLocation(), diag::note_previous_use);
1557 }
1558
1559 if (ObjCPropertyImplDecl *PPIDecl =
1560 CatImplClass->FindPropertyImplDecl(PropertyId, QueryKind)) {
1561 Diag(PropertyDiagLoc, diag::err_property_implemented) << PropertyId;
1562 Diag(PPIDecl->getLocation(), diag::note_previous_declaration);
1563 return nullptr;
1564 }
1565 CatImplClass->addPropertyImplementation(PIDecl);
1566 }
1567
1569 PIDecl->getPropertyDecl() &&
1570 PIDecl->getPropertyDecl()->isDirectProperty()) {
1571 Diag(PropertyLoc, diag::err_objc_direct_dynamic_property);
1572 Diag(PIDecl->getPropertyDecl()->getLocation(),
1573 diag::note_previous_declaration);
1574 return nullptr;
1575 }
1576
1577 return PIDecl;
1578}
1579
1580//===----------------------------------------------------------------------===//
1581// Helper methods.
1582//===----------------------------------------------------------------------===//
1583
1584/// DiagnosePropertyMismatch - Compares two properties for their
1585/// attributes and types and warns on a variety of inconsistencies.
1586///
1588 ObjCPropertyDecl *SuperProperty,
1589 const IdentifierInfo *inheritedName,
1590 bool OverridingProtocolProperty) {
1591 ASTContext &Context = getASTContext();
1592 ObjCPropertyAttribute::Kind CAttr = Property->getPropertyAttributes();
1593 ObjCPropertyAttribute::Kind SAttr = SuperProperty->getPropertyAttributes();
1594
1595 // We allow readonly properties without an explicit ownership
1596 // (assign/unsafe_unretained/weak/retain/strong/copy) in super class
1597 // to be overridden by a property with any explicit ownership in the subclass.
1598 if (!OverridingProtocolProperty &&
1599 !getOwnershipRule(SAttr) && getOwnershipRule(CAttr))
1600 ;
1601 else {
1604 Diag(Property->getLocation(), diag::warn_readonly_property)
1605 << Property->getDeclName() << inheritedName;
1606 if ((CAttr & ObjCPropertyAttribute::kind_copy) !=
1608 Diag(Property->getLocation(), diag::warn_property_attribute)
1609 << Property->getDeclName() << "copy" << inheritedName;
1610 else if (!(SAttr & ObjCPropertyAttribute::kind_readonly)) {
1611 unsigned CAttrRetain = (CAttr & (ObjCPropertyAttribute::kind_retain |
1613 unsigned SAttrRetain = (SAttr & (ObjCPropertyAttribute::kind_retain |
1615 bool CStrong = (CAttrRetain != 0);
1616 bool SStrong = (SAttrRetain != 0);
1617 if (CStrong != SStrong)
1618 Diag(Property->getLocation(), diag::warn_property_attribute)
1619 << Property->getDeclName() << "retain (or strong)" << inheritedName;
1620 }
1621 }
1622
1623 // Check for nonatomic; note that nonatomic is effectively
1624 // meaningless for readonly properties, so don't diagnose if the
1625 // atomic property is 'readonly'.
1626 checkAtomicPropertyMismatch(SemaRef, SuperProperty, Property, false);
1627 // Readonly properties from protocols can be implemented as "readwrite"
1628 // with a custom setter name.
1629 if (Property->getSetterName() != SuperProperty->getSetterName() &&
1630 !(SuperProperty->isReadOnly() &&
1631 isa<ObjCProtocolDecl>(SuperProperty->getDeclContext()))) {
1632 Diag(Property->getLocation(), diag::warn_property_attribute)
1633 << Property->getDeclName() << "setter" << inheritedName;
1634 Diag(SuperProperty->getLocation(), diag::note_property_declare);
1635 }
1636 if (Property->getGetterName() != SuperProperty->getGetterName()) {
1637 Diag(Property->getLocation(), diag::warn_property_attribute)
1638 << Property->getDeclName() << "getter" << inheritedName;
1639 Diag(SuperProperty->getLocation(), diag::note_property_declare);
1640 }
1641
1642 QualType LHSType =
1643 Context.getCanonicalType(SuperProperty->getType());
1644 QualType RHSType =
1645 Context.getCanonicalType(Property->getType());
1646
1647 if (!Context.propertyTypesAreCompatible(LHSType, RHSType)) {
1648 // Do cases not handled in above.
1649 // FIXME. For future support of covariant property types, revisit this.
1650 bool IncompatibleObjC = false;
1651 QualType ConvertedType;
1652 if (!SemaRef.isObjCPointerConversion(RHSType, LHSType, ConvertedType,
1653 IncompatibleObjC) ||
1654 IncompatibleObjC) {
1655 Diag(Property->getLocation(), diag::warn_property_types_are_incompatible)
1656 << Property->getType() << SuperProperty->getType() << inheritedName;
1657 Diag(SuperProperty->getLocation(), diag::note_property_declare);
1658 }
1659 }
1660}
1661
1663 ObjCMethodDecl *GetterMethod,
1664 SourceLocation Loc) {
1665 ASTContext &Context = getASTContext();
1666 if (!GetterMethod)
1667 return false;
1668 QualType GetterType = GetterMethod->getReturnType().getNonReferenceType();
1669 QualType PropertyRValueType =
1670 property->getType().getNonReferenceType().getAtomicUnqualifiedType();
1671 bool compat = Context.hasSameType(PropertyRValueType, GetterType);
1672 if (!compat) {
1673 const ObjCObjectPointerType *propertyObjCPtr = nullptr;
1674 const ObjCObjectPointerType *getterObjCPtr = nullptr;
1675 if ((propertyObjCPtr =
1676 PropertyRValueType->getAs<ObjCObjectPointerType>()) &&
1677 (getterObjCPtr = GetterType->getAs<ObjCObjectPointerType>()))
1678 compat = Context.canAssignObjCInterfaces(getterObjCPtr, propertyObjCPtr);
1679 else if (!SemaRef.IsAssignConvertCompatible(
1680 SemaRef.CheckAssignmentConstraints(Loc, GetterType,
1681 PropertyRValueType))) {
1682 Diag(Loc, diag::err_property_accessor_type)
1683 << property->getDeclName() << PropertyRValueType
1684 << GetterMethod->getSelector() << GetterType;
1685 Diag(GetterMethod->getLocation(), diag::note_declared_at);
1686 return true;
1687 } else {
1688 compat = true;
1689 QualType lhsType = Context.getCanonicalType(PropertyRValueType);
1690 QualType rhsType =Context.getCanonicalType(GetterType).getUnqualifiedType();
1691 if (lhsType != rhsType && lhsType->isArithmeticType())
1692 compat = false;
1693 }
1694 }
1695
1696 if (!compat) {
1697 Diag(Loc, diag::warn_accessor_property_type_mismatch)
1698 << property->getDeclName()
1699 << GetterMethod->getSelector();
1700 Diag(GetterMethod->getLocation(), diag::note_declared_at);
1701 return true;
1702 }
1703
1704 return false;
1705}
1706
1707/// CollectImmediateProperties - This routine collects all properties in
1708/// the class and its conforming protocols; but not those in its super class.
1709static void
1712 ObjCContainerDecl::PropertyMap &SuperPropMap,
1713 bool CollectClassPropsOnly = false,
1714 bool IncludeProtocols = true) {
1715 if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
1716 for (auto *Prop : IDecl->properties()) {
1717 if (CollectClassPropsOnly && !Prop->isClassProperty())
1718 continue;
1719 PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] =
1720 Prop;
1721 }
1722
1723 // Collect the properties from visible extensions.
1724 for (auto *Ext : IDecl->visible_extensions())
1725 CollectImmediateProperties(Ext, PropMap, SuperPropMap,
1726 CollectClassPropsOnly, IncludeProtocols);
1727
1728 if (IncludeProtocols) {
1729 // Scan through class's protocols.
1730 for (auto *PI : IDecl->all_referenced_protocols())
1731 CollectImmediateProperties(PI, PropMap, SuperPropMap,
1732 CollectClassPropsOnly);
1733 }
1734 }
1735 if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {
1736 for (auto *Prop : CATDecl->properties()) {
1737 if (CollectClassPropsOnly && !Prop->isClassProperty())
1738 continue;
1739 PropMap[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] =
1740 Prop;
1741 }
1742 if (IncludeProtocols) {
1743 // Scan through class's protocols.
1744 for (auto *PI : CATDecl->protocols())
1745 CollectImmediateProperties(PI, PropMap, SuperPropMap,
1746 CollectClassPropsOnly);
1747 }
1748 }
1749 else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
1750 for (auto *Prop : PDecl->properties()) {
1751 if (CollectClassPropsOnly && !Prop->isClassProperty())
1752 continue;
1753 ObjCPropertyDecl *PropertyFromSuper =
1754 SuperPropMap[std::make_pair(Prop->getIdentifier(),
1755 Prop->isClassProperty())];
1756 // Exclude property for protocols which conform to class's super-class,
1757 // as super-class has to implement the property.
1758 if (!PropertyFromSuper ||
1759 PropertyFromSuper->getIdentifier() != Prop->getIdentifier()) {
1760 ObjCPropertyDecl *&PropEntry =
1761 PropMap[std::make_pair(Prop->getIdentifier(),
1762 Prop->isClassProperty())];
1763 if (!PropEntry)
1764 PropEntry = Prop;
1765 }
1766 }
1767 // Scan through protocol's protocols.
1768 for (auto *PI : PDecl->protocols())
1769 CollectImmediateProperties(PI, PropMap, SuperPropMap,
1770 CollectClassPropsOnly);
1771 }
1772}
1773
1774/// CollectSuperClassPropertyImplementations - This routine collects list of
1775/// properties to be implemented in super class(s) and also coming from their
1776/// conforming protocols.
1779 if (ObjCInterfaceDecl *SDecl = CDecl->getSuperClass()) {
1780 while (SDecl) {
1781 SDecl->collectPropertiesToImplement(PropMap);
1782 SDecl = SDecl->getSuperClass();
1783 }
1784 }
1785}
1786
1787/// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
1788/// an ivar synthesized for 'Method' and 'Method' is a property accessor
1789/// declared in class 'IFace'.
1792 ObjCIvarDecl *IV) {
1793 if (!IV->getSynthesize())
1794 return false;
1795 ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(),
1796 Method->isInstanceMethod());
1797 if (!IMD || !IMD->isPropertyAccessor())
1798 return false;
1799
1800 // look up a property declaration whose one of its accessors is implemented
1801 // by this method.
1802 for (const auto *Property : IFace->instance_properties()) {
1803 if ((Property->getGetterName() == IMD->getSelector() ||
1804 Property->getSetterName() == IMD->getSelector()) &&
1805 (Property->getPropertyIvarDecl() == IV))
1806 return true;
1807 }
1808 // Also look up property declaration in class extension whose one of its
1809 // accessors is implemented by this method.
1810 for (const auto *Ext : IFace->known_extensions())
1811 for (const auto *Property : Ext->instance_properties())
1812 if ((Property->getGetterName() == IMD->getSelector() ||
1813 Property->getSetterName() == IMD->getSelector()) &&
1814 (Property->getPropertyIvarDecl() == IV))
1815 return true;
1816 return false;
1817}
1818
1820 ObjCPropertyDecl *Prop) {
1821 bool SuperClassImplementsGetter = false;
1822 bool SuperClassImplementsSetter = false;
1824 SuperClassImplementsSetter = true;
1825
1826 while (IDecl->getSuperClass()) {
1827 ObjCInterfaceDecl *SDecl = IDecl->getSuperClass();
1828 if (!SuperClassImplementsGetter && SDecl->getInstanceMethod(Prop->getGetterName()))
1829 SuperClassImplementsGetter = true;
1830
1831 if (!SuperClassImplementsSetter && SDecl->getInstanceMethod(Prop->getSetterName()))
1832 SuperClassImplementsSetter = true;
1833 if (SuperClassImplementsGetter && SuperClassImplementsSetter)
1834 return true;
1835 IDecl = IDecl->getSuperClass();
1836 }
1837 return false;
1838}
1839
1840/// Default synthesizes all properties which must be synthesized
1841/// in class's \@implementation.
1843 ObjCInterfaceDecl *IDecl,
1844 SourceLocation AtEnd) {
1845 ASTContext &Context = getASTContext();
1847 IDecl->collectPropertiesToImplement(PropMap);
1848 if (PropMap.empty())
1849 return;
1850 ObjCInterfaceDecl::PropertyMap SuperPropMap;
1851 CollectSuperClassPropertyImplementations(IDecl, SuperPropMap);
1852
1853 for (const auto &PropEntry : PropMap) {
1854 ObjCPropertyDecl *Prop = PropEntry.second;
1855 // Is there a matching property synthesize/dynamic?
1856 if (Prop->isInvalidDecl() ||
1857 Prop->isClassProperty() ||
1859 continue;
1860 // Property may have been synthesized by user.
1861 if (IMPDecl->FindPropertyImplDecl(
1862 Prop->getIdentifier(), Prop->getQueryKind()))
1863 continue;
1864 ObjCMethodDecl *ImpMethod = IMPDecl->getInstanceMethod(Prop->getGetterName());
1865 if (ImpMethod && !ImpMethod->getBody()) {
1867 continue;
1868 ImpMethod = IMPDecl->getInstanceMethod(Prop->getSetterName());
1869 if (ImpMethod && !ImpMethod->getBody())
1870 continue;
1871 }
1872 if (ObjCPropertyImplDecl *PID =
1873 IMPDecl->FindPropertyImplIvarDecl(Prop->getIdentifier())) {
1874 Diag(Prop->getLocation(), diag::warn_no_autosynthesis_shared_ivar_property)
1875 << Prop->getIdentifier();
1876 if (PID->getLocation().isValid())
1877 Diag(PID->getLocation(), diag::note_property_synthesize);
1878 continue;
1879 }
1880 ObjCPropertyDecl *PropInSuperClass =
1881 SuperPropMap[std::make_pair(Prop->getIdentifier(),
1882 Prop->isClassProperty())];
1883 if (ObjCProtocolDecl *Proto =
1884 dyn_cast<ObjCProtocolDecl>(Prop->getDeclContext())) {
1885 // We won't auto-synthesize properties declared in protocols.
1886 // Suppress the warning if class's superclass implements property's
1887 // getter and implements property's setter (if readwrite property).
1888 // Or, if property is going to be implemented in its super class.
1889 if (!SuperClassImplementsProperty(IDecl, Prop) && !PropInSuperClass) {
1890 Diag(IMPDecl->getLocation(),
1891 diag::warn_auto_synthesizing_protocol_property)
1892 << Prop << Proto;
1893 Diag(Prop->getLocation(), diag::note_property_declare);
1894 std::string FixIt =
1895 (Twine("@synthesize ") + Prop->getName() + ";\n\n").str();
1896 Diag(AtEnd, diag::note_add_synthesize_directive)
1897 << FixItHint::CreateInsertion(AtEnd, FixIt);
1898 }
1899 continue;
1900 }
1901 // If property to be implemented in the super class, ignore.
1902 if (PropInSuperClass) {
1903 if ((Prop->getPropertyAttributes() &
1905 (PropInSuperClass->getPropertyAttributes() &
1907 !IMPDecl->getInstanceMethod(Prop->getSetterName()) &&
1908 !IDecl->HasUserDeclaredSetterMethod(Prop)) {
1909 Diag(Prop->getLocation(), diag::warn_no_autosynthesis_property)
1910 << Prop->getIdentifier();
1911 Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
1912 } else {
1913 Diag(Prop->getLocation(), diag::warn_autosynthesis_property_in_superclass)
1914 << Prop->getIdentifier();
1915 Diag(PropInSuperClass->getLocation(), diag::note_property_declare);
1916 Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
1917 }
1918 continue;
1919 }
1920 // We use invalid SourceLocations for the synthesized ivars since they
1921 // aren't really synthesized at a particular location; they just exist.
1922 // Saying that they are located at the @implementation isn't really going
1923 // to help users.
1924 ObjCPropertyImplDecl *PIDecl = dyn_cast_or_null<ObjCPropertyImplDecl>(
1926 true,
1927 /* property = */ Prop->getIdentifier(),
1928 /* ivar = */ Prop->getDefaultSynthIvarName(Context),
1929 Prop->getLocation(), Prop->getQueryKind()));
1930 if (PIDecl && !Prop->isUnavailable()) {
1931 Diag(Prop->getLocation(), diag::warn_missing_explicit_synthesis);
1932 Diag(IMPDecl->getLocation(), diag::note_while_in_implementation);
1933 }
1934 }
1935}
1936
1938 SourceLocation AtEnd) {
1939 if (!getLangOpts().ObjCDefaultSynthProperties ||
1941 return;
1942 ObjCImplementationDecl *IC=dyn_cast_or_null<ObjCImplementationDecl>(D);
1943 if (!IC)
1944 return;
1945 if (ObjCInterfaceDecl* IDecl = IC->getClassInterface())
1946 if (!IDecl->isObjCRequiresPropertyDefs())
1947 DefaultSynthesizeProperties(S, IC, IDecl, AtEnd);
1948}
1949
1951 Sema &S, ObjCInterfaceDecl *PrimaryClass, Selector Method,
1953 ObjCPropertyDecl *Prop,
1955 // Check to see if we have a corresponding selector in SMap and with the
1956 // right method type.
1957 auto I = llvm::find_if(SMap, [&](const ObjCMethodDecl *x) {
1958 return x->getSelector() == Method &&
1959 x->isClassMethod() == Prop->isClassProperty();
1960 });
1961 // When reporting on missing property setter/getter implementation in
1962 // categories, do not report when they are declared in primary class,
1963 // class's protocol, or one of it super classes. This is because,
1964 // the class is going to implement them.
1965 if (I == SMap.end() &&
1966 (PrimaryClass == nullptr ||
1967 !PrimaryClass->lookupPropertyAccessor(Method, C,
1968 Prop->isClassProperty()))) {
1969 unsigned diag =
1971 ? (Prop->isClassProperty()
1972 ? diag::warn_impl_required_in_category_for_class_property
1973 : diag::warn_setter_getter_impl_required_in_category)
1974 : (Prop->isClassProperty()
1975 ? diag::warn_impl_required_for_class_property
1976 : diag::warn_setter_getter_impl_required);
1977 S.Diag(IMPDecl->getLocation(), diag) << Prop->getDeclName() << Method;
1978 S.Diag(Prop->getLocation(), diag::note_property_declare);
1979 if (S.LangOpts.ObjCDefaultSynthProperties &&
1981 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CDecl))
1982 if (const ObjCInterfaceDecl *RID = ID->isObjCRequiresPropertyDefs())
1983 S.Diag(RID->getLocation(), diag::note_suppressed_class_declare);
1984 }
1985}
1986
1988 ObjCContainerDecl *CDecl,
1989 bool SynthesizeProperties) {
1991 ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl);
1992
1993 // Since we don't synthesize class properties, we should emit diagnose even
1994 // if SynthesizeProperties is true.
1995 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
1996 // Gather properties which need not be implemented in this class
1997 // or category.
1998 if (!IDecl)
1999 if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
2000 // For categories, no need to implement properties declared in
2001 // its primary class (and its super classes) if property is
2002 // declared in one of those containers.
2003 if ((IDecl = C->getClassInterface())) {
2004 IDecl->collectPropertiesToImplement(NoNeedToImplPropMap);
2005 }
2006 }
2007 if (IDecl)
2008 CollectSuperClassPropertyImplementations(IDecl, NoNeedToImplPropMap);
2009
2010 // When SynthesizeProperties is true, we only check class properties.
2011 CollectImmediateProperties(CDecl, PropMap, NoNeedToImplPropMap,
2012 SynthesizeProperties/*CollectClassPropsOnly*/);
2013
2014 // Scan the @interface to see if any of the protocols it adopts
2015 // require an explicit implementation, via attribute
2016 // 'objc_protocol_requires_explicit_implementation'.
2017 if (IDecl) {
2018 std::unique_ptr<ObjCContainerDecl::PropertyMap> LazyMap;
2019
2020 for (auto *PDecl : IDecl->all_referenced_protocols()) {
2021 if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
2022 continue;
2023 // Lazily construct a set of all the properties in the @interface
2024 // of the class, without looking at the superclass. We cannot
2025 // use the call to CollectImmediateProperties() above as that
2026 // utilizes information from the super class's properties as well
2027 // as scans the adopted protocols. This work only triggers for protocols
2028 // with the attribute, which is very rare, and only occurs when
2029 // analyzing the @implementation.
2030 if (!LazyMap) {
2031 ObjCContainerDecl::PropertyMap NoNeedToImplPropMap;
2032 LazyMap.reset(new ObjCContainerDecl::PropertyMap());
2033 CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap,
2034 /* CollectClassPropsOnly */ false,
2035 /* IncludeProtocols */ false);
2036 }
2037 // Add the properties of 'PDecl' to the list of properties that
2038 // need to be implemented.
2039 for (auto *PropDecl : PDecl->properties()) {
2040 if ((*LazyMap)[std::make_pair(PropDecl->getIdentifier(),
2041 PropDecl->isClassProperty())])
2042 continue;
2043 PropMap[std::make_pair(PropDecl->getIdentifier(),
2044 PropDecl->isClassProperty())] = PropDecl;
2045 }
2046 }
2047 }
2048
2049 if (PropMap.empty())
2050 return;
2051
2052 llvm::DenseSet<ObjCPropertyDecl *> PropImplMap;
2053 for (const auto *I : IMPDecl->property_impls())
2054 PropImplMap.insert(I->getPropertyDecl());
2055
2056 // Collect property accessors implemented in current implementation.
2057 llvm::SmallPtrSet<const ObjCMethodDecl *, 8> InsMap(llvm::from_range,
2058 IMPDecl->methods());
2059
2060 ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
2061 ObjCInterfaceDecl *PrimaryClass = nullptr;
2062 if (C && !C->IsClassExtension())
2063 if ((PrimaryClass = C->getClassInterface()))
2064 // Report unimplemented properties in the category as well.
2065 if (ObjCImplDecl *IMP = PrimaryClass->getImplementation()) {
2066 // When reporting on missing setter/getters, do not report when
2067 // setter/getter is implemented in category's primary class
2068 // implementation.
2069 InsMap.insert_range(IMP->methods());
2070 }
2071
2072 for (ObjCContainerDecl::PropertyMap::iterator
2073 P = PropMap.begin(), E = PropMap.end(); P != E; ++P) {
2074 ObjCPropertyDecl *Prop = P->second;
2075 // Is there a matching property synthesize/dynamic?
2076 if (Prop->isInvalidDecl() ||
2078 PropImplMap.count(Prop) ||
2080 continue;
2081
2082 // Diagnose unimplemented getters and setters.
2084 IMPDecl, CDecl, C, Prop, InsMap);
2085 if (!Prop->isReadOnly())
2087 Prop->getSetterName(), IMPDecl, CDecl, C,
2088 Prop, InsMap);
2089 }
2090}
2091
2093 const ObjCImplDecl *impDecl) {
2094 for (const auto *propertyImpl : impDecl->property_impls()) {
2095 const auto *property = propertyImpl->getPropertyDecl();
2096 // Warn about null_resettable properties with synthesized setters,
2097 // because the setter won't properly handle nil.
2098 if (propertyImpl->getPropertyImplementation() ==
2100 (property->getPropertyAttributes() &
2102 property->getGetterMethodDecl() && property->getSetterMethodDecl()) {
2103 auto *getterImpl = propertyImpl->getGetterMethodDecl();
2104 auto *setterImpl = propertyImpl->getSetterMethodDecl();
2105 if ((!getterImpl || getterImpl->isSynthesizedAccessorStub()) &&
2106 (!setterImpl || setterImpl->isSynthesizedAccessorStub())) {
2107 SourceLocation loc = propertyImpl->getLocation();
2108 if (loc.isInvalid())
2109 loc = impDecl->getBeginLoc();
2110
2111 Diag(loc, diag::warn_null_resettable_setter)
2112 << setterImpl->getSelector() << property->getDeclName();
2113 }
2114 }
2115 }
2116}
2117
2119 ObjCInterfaceDecl *IDecl) {
2120 // Rules apply in non-GC mode only
2121 if (getLangOpts().getGC() != LangOptions::NonGC)
2122 return;
2124 for (auto *Prop : IDecl->properties())
2125 PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
2126 for (const auto *Ext : IDecl->known_extensions())
2127 for (auto *Prop : Ext->properties())
2128 PM[std::make_pair(Prop->getIdentifier(), Prop->isClassProperty())] = Prop;
2129
2130 for (ObjCContainerDecl::PropertyMap::iterator I = PM.begin(), E = PM.end();
2131 I != E; ++I) {
2132 const ObjCPropertyDecl *Property = I->second;
2133 ObjCMethodDecl *GetterMethod = nullptr;
2134 ObjCMethodDecl *SetterMethod = nullptr;
2135
2136 unsigned Attributes = Property->getPropertyAttributes();
2137 unsigned AttributesAsWritten = Property->getPropertyAttributesAsWritten();
2138
2139 if (!(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic) &&
2140 !(AttributesAsWritten & ObjCPropertyAttribute::kind_nonatomic)) {
2141 GetterMethod = Property->isClassProperty() ?
2142 IMPDecl->getClassMethod(Property->getGetterName()) :
2143 IMPDecl->getInstanceMethod(Property->getGetterName());
2144 SetterMethod = Property->isClassProperty() ?
2145 IMPDecl->getClassMethod(Property->getSetterName()) :
2146 IMPDecl->getInstanceMethod(Property->getSetterName());
2147 if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
2148 GetterMethod = nullptr;
2149 if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
2150 SetterMethod = nullptr;
2151 if (GetterMethod) {
2152 Diag(GetterMethod->getLocation(),
2153 diag::warn_default_atomic_custom_getter_setter)
2154 << Property->getIdentifier() << 0;
2155 Diag(Property->getLocation(), diag::note_property_declare);
2156 }
2157 if (SetterMethod) {
2158 Diag(SetterMethod->getLocation(),
2159 diag::warn_default_atomic_custom_getter_setter)
2160 << Property->getIdentifier() << 1;
2161 Diag(Property->getLocation(), diag::note_property_declare);
2162 }
2163 }
2164
2165 // We only care about readwrite atomic property.
2166 if ((Attributes & ObjCPropertyAttribute::kind_nonatomic) ||
2168 continue;
2169 if (const ObjCPropertyImplDecl *PIDecl = IMPDecl->FindPropertyImplDecl(
2170 Property->getIdentifier(), Property->getQueryKind())) {
2171 if (PIDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
2172 continue;
2173 GetterMethod = PIDecl->getGetterMethodDecl();
2174 SetterMethod = PIDecl->getSetterMethodDecl();
2175 if (GetterMethod && GetterMethod->isSynthesizedAccessorStub())
2176 GetterMethod = nullptr;
2177 if (SetterMethod && SetterMethod->isSynthesizedAccessorStub())
2178 SetterMethod = nullptr;
2179 if ((bool)GetterMethod ^ (bool)SetterMethod) {
2180 SourceLocation MethodLoc =
2181 (GetterMethod ? GetterMethod->getLocation()
2182 : SetterMethod->getLocation());
2183 Diag(MethodLoc, diag::warn_atomic_property_rule)
2184 << Property->getIdentifier() << (GetterMethod != nullptr)
2185 << (SetterMethod != nullptr);
2186 // fixit stuff.
2187 if (Property->getLParenLoc().isValid() &&
2188 !(AttributesAsWritten & ObjCPropertyAttribute::kind_atomic)) {
2189 // @property () ... case.
2190 SourceLocation AfterLParen =
2191 SemaRef.getLocForEndOfToken(Property->getLParenLoc());
2192 StringRef NonatomicStr = AttributesAsWritten? "nonatomic, "
2193 : "nonatomic";
2194 Diag(Property->getLocation(),
2195 diag::note_atomic_property_fixup_suggest)
2196 << FixItHint::CreateInsertion(AfterLParen, NonatomicStr);
2197 } else if (Property->getLParenLoc().isInvalid()) {
2198 //@property id etc.
2199 SourceLocation startLoc =
2200 Property->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
2201 Diag(Property->getLocation(),
2202 diag::note_atomic_property_fixup_suggest)
2203 << FixItHint::CreateInsertion(startLoc, "(nonatomic) ");
2204 } else
2205 Diag(MethodLoc, diag::note_atomic_property_fixup_suggest);
2206 Diag(Property->getLocation(), diag::note_property_declare);
2207 }
2208 }
2209 }
2210}
2211
2213 const ObjCImplementationDecl *D) {
2214 if (getLangOpts().getGC() == LangOptions::GCOnly)
2215 return;
2216
2217 for (const auto *PID : D->property_impls()) {
2218 const ObjCPropertyDecl *PD = PID->getPropertyDecl();
2219 if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
2220 !PD->isClassProperty()) {
2221 ObjCMethodDecl *IM = PID->getGetterMethodDecl();
2222 if (IM && !IM->isSynthesizedAccessorStub())
2223 continue;
2224 ObjCMethodDecl *method = PD->getGetterMethodDecl();
2225 if (!method)
2226 continue;
2227 ObjCMethodFamily family = method->getMethodFamily();
2228 if (family == OMF_alloc || family == OMF_copy ||
2229 family == OMF_mutableCopy || family == OMF_new) {
2230 if (getLangOpts().ObjCAutoRefCount)
2231 Diag(PD->getLocation(), diag::err_cocoa_naming_owned_rule);
2232 else
2233 Diag(PD->getLocation(), diag::warn_cocoa_naming_owned_rule);
2234
2235 // Look for a getter explicitly declared alongside the property.
2236 // If we find one, use its location for the note.
2237 SourceLocation noteLoc = PD->getLocation();
2238 SourceLocation fixItLoc;
2239 for (auto *getterRedecl : method->redecls()) {
2240 if (getterRedecl->isImplicit())
2241 continue;
2242 if (getterRedecl->getDeclContext() != PD->getDeclContext())
2243 continue;
2244 noteLoc = getterRedecl->getLocation();
2245 fixItLoc = getterRedecl->getEndLoc();
2246 }
2247
2248 Preprocessor &PP = SemaRef.getPreprocessor();
2249 TokenValue tokens[] = {
2250 tok::kw___attribute, tok::l_paren, tok::l_paren,
2251 PP.getIdentifierInfo("objc_method_family"), tok::l_paren,
2252 PP.getIdentifierInfo("none"), tok::r_paren,
2253 tok::r_paren, tok::r_paren
2254 };
2255 StringRef spelling = "__attribute__((objc_method_family(none)))";
2256 StringRef macroName = PP.getLastMacroWithSpelling(noteLoc, tokens);
2257 if (!macroName.empty())
2258 spelling = macroName;
2259
2260 auto noteDiag = Diag(noteLoc, diag::note_cocoa_naming_declare_family)
2261 << method->getDeclName() << spelling;
2262 if (fixItLoc.isValid()) {
2263 SmallString<64> fixItText(" ");
2264 fixItText += spelling;
2265 noteDiag << FixItHint::CreateInsertion(fixItLoc, fixItText);
2266 }
2267 }
2268 }
2269 }
2270}
2271
2273 const ObjCImplementationDecl *ImplD, const ObjCInterfaceDecl *IFD) {
2274 assert(IFD->hasDesignatedInitializers());
2275 const ObjCInterfaceDecl *SuperD = IFD->getSuperClass();
2276 if (!SuperD)
2277 return;
2278
2279 SelectorSet InitSelSet;
2280 for (const auto *I : ImplD->instance_methods())
2281 if (I->getMethodFamily() == OMF_init)
2282 InitSelSet.insert(I->getSelector());
2283
2285 SuperD->getDesignatedInitializers(DesignatedInits);
2287 I = DesignatedInits.begin(), E = DesignatedInits.end(); I != E; ++I) {
2288 const ObjCMethodDecl *MD = *I;
2289 if (!InitSelSet.count(MD->getSelector())) {
2290 // Don't emit a diagnostic if the overriding method in the subclass is
2291 // marked as unavailable.
2292 bool Ignore = false;
2293 if (auto *IMD = IFD->getInstanceMethod(MD->getSelector())) {
2294 Ignore = IMD->isUnavailable();
2295 } else {
2296 // Check the methods declared in the class extensions too.
2297 for (auto *Ext : IFD->visible_extensions())
2298 if (auto *IMD = Ext->getInstanceMethod(MD->getSelector())) {
2299 Ignore = IMD->isUnavailable();
2300 break;
2301 }
2302 }
2303 if (!Ignore) {
2304 Diag(ImplD->getLocation(),
2305 diag::warn_objc_implementation_missing_designated_init_override)
2306 << MD->getSelector();
2307 Diag(MD->getLocation(), diag::note_objc_designated_init_marked_here);
2308 }
2309 }
2310 }
2311}
2312
2313/// AddPropertyAttrs - Propagates attributes from a property to the
2314/// implicitly-declared getter or setter for that property.
2315static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod,
2316 ObjCPropertyDecl *Property) {
2317 // Should we just clone all attributes over?
2318 for (const auto *A : Property->attrs()) {
2319 if (isa<DeprecatedAttr>(A) ||
2322 PropertyMethod->addAttr(A->clone(S.Context));
2323 }
2324}
2325
2326/// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods
2327/// have the property type and issue diagnostics if they don't.
2328/// Also synthesize a getter/setter method if none exist (and update the
2329/// appropriate lookup tables.
2331 ASTContext &Context = getASTContext();
2332 ObjCMethodDecl *GetterMethod, *SetterMethod;
2334 if (CD->isInvalidDecl())
2335 return;
2336
2337 bool IsClassProperty = property->isClassProperty();
2338 GetterMethod = IsClassProperty ?
2339 CD->getClassMethod(property->getGetterName()) :
2340 CD->getInstanceMethod(property->getGetterName());
2341
2342 // if setter or getter is not found in class extension, it might be
2343 // in the primary class.
2344 if (!GetterMethod)
2345 if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
2346 if (CatDecl->IsClassExtension())
2347 GetterMethod = IsClassProperty ? CatDecl->getClassInterface()->
2348 getClassMethod(property->getGetterName()) :
2349 CatDecl->getClassInterface()->
2350 getInstanceMethod(property->getGetterName());
2351
2352 SetterMethod = IsClassProperty ?
2353 CD->getClassMethod(property->getSetterName()) :
2354 CD->getInstanceMethod(property->getSetterName());
2355 if (!SetterMethod)
2356 if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD))
2357 if (CatDecl->IsClassExtension())
2358 SetterMethod = IsClassProperty ? CatDecl->getClassInterface()->
2359 getClassMethod(property->getSetterName()) :
2360 CatDecl->getClassInterface()->
2361 getInstanceMethod(property->getSetterName());
2362 DiagnosePropertyAccessorMismatch(property, GetterMethod,
2363 property->getLocation());
2364
2365 // synthesizing accessors must not result in a direct method that is not
2366 // monomorphic
2367 if (!GetterMethod) {
2368 if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) {
2369 auto *ExistingGetter = CatDecl->getClassInterface()->lookupMethod(
2370 property->getGetterName(), !IsClassProperty, true, false, CatDecl);
2371 if (ExistingGetter) {
2372 if (ExistingGetter->isDirectMethod() || property->isDirectProperty()) {
2373 Diag(property->getLocation(), diag::err_objc_direct_duplicate_decl)
2374 << property->isDirectProperty() << 1 /* property */
2375 << ExistingGetter->isDirectMethod()
2376 << ExistingGetter->getDeclName();
2377 Diag(ExistingGetter->getLocation(), diag::note_previous_declaration);
2378 }
2379 }
2380 }
2381 }
2382
2383 if (!property->isReadOnly() && !SetterMethod) {
2384 if (const ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(CD)) {
2385 auto *ExistingSetter = CatDecl->getClassInterface()->lookupMethod(
2386 property->getSetterName(), !IsClassProperty, true, false, CatDecl);
2387 if (ExistingSetter) {
2388 if (ExistingSetter->isDirectMethod() || property->isDirectProperty()) {
2389 Diag(property->getLocation(), diag::err_objc_direct_duplicate_decl)
2390 << property->isDirectProperty() << 1 /* property */
2391 << ExistingSetter->isDirectMethod()
2392 << ExistingSetter->getDeclName();
2393 Diag(ExistingSetter->getLocation(), diag::note_previous_declaration);
2394 }
2395 }
2396 }
2397 }
2398
2399 if (!property->isReadOnly() && SetterMethod) {
2400 if (Context.getCanonicalType(SetterMethod->getReturnType()) !=
2401 Context.VoidTy)
2402 Diag(SetterMethod->getLocation(), diag::err_setter_type_void);
2403 if (SetterMethod->param_size() != 1 ||
2404 !Context.hasSameUnqualifiedType(
2405 (*SetterMethod->param_begin())->getType().getNonReferenceType(),
2406 property->getType().getNonReferenceType())) {
2407 Diag(property->getLocation(),
2408 diag::warn_accessor_property_type_mismatch)
2409 << property->getDeclName()
2410 << SetterMethod->getSelector();
2411 Diag(SetterMethod->getLocation(), diag::note_declared_at);
2412 }
2413 }
2414
2415 // Synthesize getter/setter methods if none exist.
2416 // Find the default getter and if one not found, add one.
2417 // FIXME: The synthesized property we set here is misleading. We almost always
2418 // synthesize these methods unless the user explicitly provided prototypes
2419 // (which is odd, but allowed). Sema should be typechecking that the
2420 // declarations jive in that situation (which it is not currently).
2421 if (!GetterMethod) {
2422 // No instance/class method of same name as property getter name was found.
2423 // Declare a getter method and add it to the list of methods
2424 // for this class.
2425 SourceLocation Loc = property->getLocation();
2426
2427 // The getter returns the declared property type with all qualifiers
2428 // removed.
2429 QualType resultTy = property->getType().getAtomicUnqualifiedType();
2430
2431 // If the property is null_resettable, the getter returns nonnull.
2432 if (property->getPropertyAttributes() &
2434 QualType modifiedTy = resultTy;
2435 if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)) {
2436 if (*nullability == NullabilityKind::Unspecified)
2437 resultTy = Context.getAttributedType(NullabilityKind::NonNull,
2438 modifiedTy, modifiedTy);
2439 }
2440 }
2441
2442 GetterMethod = ObjCMethodDecl::Create(
2443 Context, Loc, Loc, property->getGetterName(), resultTy, nullptr, CD,
2444 !IsClassProperty, /*isVariadic=*/false,
2445 /*isPropertyAccessor=*/true, /*isSynthesizedAccessorStub=*/false,
2446 /*isImplicitlyDeclared=*/true, /*isDefined=*/false,
2450 CD->addDecl(GetterMethod);
2451
2452 AddPropertyAttrs(SemaRef, GetterMethod, property);
2453
2454 if (property->isDirectProperty())
2455 GetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc));
2456
2457 if (property->hasAttr<NSReturnsNotRetainedAttr>())
2458 GetterMethod->addAttr(NSReturnsNotRetainedAttr::CreateImplicit(Context,
2459 Loc));
2460
2461 if (property->hasAttr<ObjCReturnsInnerPointerAttr>())
2462 GetterMethod->addAttr(
2463 ObjCReturnsInnerPointerAttr::CreateImplicit(Context, Loc));
2464
2465 if (const SectionAttr *SA = property->getAttr<SectionAttr>())
2466 GetterMethod->addAttr(SectionAttr::CreateImplicit(
2467 Context, SA->getName(), Loc, SectionAttr::GNU_section));
2468
2469 SemaRef.ProcessAPINotes(GetterMethod);
2470
2471 if (getLangOpts().ObjCAutoRefCount)
2472 CheckARCMethodDecl(GetterMethod);
2473 } else
2474 // A user declared getter will be synthesize when @synthesize of
2475 // the property with the same name is seen in the @implementation
2476 GetterMethod->setPropertyAccessor(true);
2477
2478 GetterMethod->createImplicitParams(Context,
2479 GetterMethod->getClassInterface());
2480 property->setGetterMethodDecl(GetterMethod);
2481
2482 // Skip setter if property is read-only.
2483 if (!property->isReadOnly()) {
2484 // Find the default setter and if one not found, add one.
2485 if (!SetterMethod) {
2486 // No instance/class method of same name as property setter name was
2487 // found.
2488 // Declare a setter method and add it to the list of methods
2489 // for this class.
2490 SourceLocation Loc = property->getLocation();
2491
2492 SetterMethod = ObjCMethodDecl::Create(
2493 Context, Loc, Loc, property->getSetterName(), Context.VoidTy, nullptr,
2494 CD, !IsClassProperty,
2495 /*isVariadic=*/false,
2496 /*isPropertyAccessor=*/true,
2497 /*isSynthesizedAccessorStub=*/false,
2498 /*isImplicitlyDeclared=*/true,
2499 /*isDefined=*/false,
2503
2504 // Remove all qualifiers from the setter's parameter type.
2505 QualType paramTy =
2506 property->getType().getUnqualifiedType().getAtomicUnqualifiedType();
2507
2508 // If the property is null_resettable, the setter accepts a
2509 // nullable value.
2510 if (property->getPropertyAttributes() &
2512 QualType modifiedTy = paramTy;
2513 if (auto nullability = AttributedType::stripOuterNullability(modifiedTy)){
2514 if (*nullability == NullabilityKind::Unspecified)
2515 paramTy = Context.getAttributedType(NullabilityKind::Nullable,
2516 modifiedTy, modifiedTy);
2517 }
2518 }
2519
2520 // Invent the arguments for the setter. We don't bother making a
2521 // nice name for the argument.
2522 ParmVarDecl *Argument = ParmVarDecl::Create(Context, SetterMethod,
2523 Loc, Loc,
2524 property->getIdentifier(),
2525 paramTy,
2526 /*TInfo=*/nullptr,
2527 SC_None,
2528 nullptr);
2529 SetterMethod->setMethodParams(Context, Argument, {});
2530
2531 AddPropertyAttrs(SemaRef, SetterMethod, property);
2532
2533 if (property->isDirectProperty())
2534 SetterMethod->addAttr(ObjCDirectAttr::CreateImplicit(Context, Loc));
2535
2536 CD->addDecl(SetterMethod);
2537 if (const SectionAttr *SA = property->getAttr<SectionAttr>())
2538 SetterMethod->addAttr(SectionAttr::CreateImplicit(
2539 Context, SA->getName(), Loc, SectionAttr::GNU_section));
2540
2541 SemaRef.ProcessAPINotes(SetterMethod);
2542
2543 // It's possible for the user to have set a very odd custom
2544 // setter selector that causes it to have a method family.
2545 if (getLangOpts().ObjCAutoRefCount)
2546 CheckARCMethodDecl(SetterMethod);
2547 } else
2548 // A user declared setter will be synthesize when @synthesize of
2549 // the property with the same name is seen in the @implementation
2550 SetterMethod->setPropertyAccessor(true);
2551
2552 SetterMethod->createImplicitParams(Context,
2553 SetterMethod->getClassInterface());
2554 property->setSetterMethodDecl(SetterMethod);
2555 }
2556 // Add any synthesized methods to the global pool. This allows us to
2557 // handle the following, which is supported by GCC (and part of the design).
2558 //
2559 // @interface Foo
2560 // @property double bar;
2561 // @end
2562 //
2563 // void thisIsUnfortunate() {
2564 // id foo;
2565 // double bar = [foo bar];
2566 // }
2567 //
2568 if (!IsClassProperty) {
2569 if (GetterMethod)
2570 AddInstanceMethodToGlobalPool(GetterMethod);
2571 if (SetterMethod)
2572 AddInstanceMethodToGlobalPool(SetterMethod);
2573 } else {
2574 if (GetterMethod)
2575 AddFactoryMethodToGlobalPool(GetterMethod);
2576 if (SetterMethod)
2577 AddFactoryMethodToGlobalPool(SetterMethod);
2578 }
2579
2580 ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(CD);
2581 if (!CurrentClass) {
2582 if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(CD))
2583 CurrentClass = Cat->getClassInterface();
2584 else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(CD))
2585 CurrentClass = Impl->getClassInterface();
2586 }
2587 if (GetterMethod)
2588 CheckObjCMethodOverrides(GetterMethod, CurrentClass, SemaObjC::RTC_Unknown);
2589 if (SetterMethod)
2590 CheckObjCMethodOverrides(SetterMethod, CurrentClass, SemaObjC::RTC_Unknown);
2591}
2592
2594 unsigned &Attributes,
2595 bool propertyInPrimaryClass) {
2596 // FIXME: Improve the reported location.
2597 if (!PDecl || PDecl->isInvalidDecl())
2598 return;
2599
2600 if ((Attributes & ObjCPropertyAttribute::kind_readonly) &&
2602 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2603 << "readonly" << "readwrite";
2604
2605 ObjCPropertyDecl *PropertyDecl = cast<ObjCPropertyDecl>(PDecl);
2606 QualType PropertyTy = PropertyDecl->getType();
2607
2608 // Check for copy or retain on non-object types.
2609 if ((Attributes &
2613 !PropertyTy->isObjCRetainableType() &&
2614 !PropertyDecl->hasAttr<ObjCNSObjectAttr>()) {
2615 Diag(Loc, diag::err_objc_property_requires_object)
2616 << (Attributes & ObjCPropertyAttribute::kind_weak
2617 ? "weak"
2619 ? "copy"
2620 : "retain (or strong)");
2621 Attributes &=
2625 PropertyDecl->setInvalidDecl();
2626 }
2627
2628 // Check for assign on object types.
2629 if ((Attributes & ObjCPropertyAttribute::kind_assign) &&
2631 PropertyTy->isObjCRetainableType() &&
2632 !PropertyTy->isObjCARCImplicitlyUnretainedType()) {
2633 Diag(Loc, diag::warn_objc_property_assign_on_object);
2634 }
2635
2636 // Check for more than one of { assign, copy, retain }.
2637 if (Attributes & ObjCPropertyAttribute::kind_assign) {
2638 if (Attributes & ObjCPropertyAttribute::kind_copy) {
2639 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2640 << "assign" << "copy";
2641 Attributes &= ~ObjCPropertyAttribute::kind_copy;
2642 }
2643 if (Attributes & ObjCPropertyAttribute::kind_retain) {
2644 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2645 << "assign" << "retain";
2646 Attributes &= ~ObjCPropertyAttribute::kind_retain;
2647 }
2648 if (Attributes & ObjCPropertyAttribute::kind_strong) {
2649 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2650 << "assign" << "strong";
2651 Attributes &= ~ObjCPropertyAttribute::kind_strong;
2652 }
2653 if (getLangOpts().ObjCAutoRefCount &&
2654 (Attributes & ObjCPropertyAttribute::kind_weak)) {
2655 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2656 << "assign" << "weak";
2657 Attributes &= ~ObjCPropertyAttribute::kind_weak;
2658 }
2659 if (PropertyDecl->hasAttr<IBOutletCollectionAttr>())
2660 Diag(Loc, diag::warn_iboutletcollection_property_assign);
2661 } else if (Attributes & ObjCPropertyAttribute::kind_unsafe_unretained) {
2662 if (Attributes & ObjCPropertyAttribute::kind_copy) {
2663 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2664 << "unsafe_unretained" << "copy";
2665 Attributes &= ~ObjCPropertyAttribute::kind_copy;
2666 }
2667 if (Attributes & ObjCPropertyAttribute::kind_retain) {
2668 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2669 << "unsafe_unretained" << "retain";
2670 Attributes &= ~ObjCPropertyAttribute::kind_retain;
2671 }
2672 if (Attributes & ObjCPropertyAttribute::kind_strong) {
2673 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2674 << "unsafe_unretained" << "strong";
2675 Attributes &= ~ObjCPropertyAttribute::kind_strong;
2676 }
2677 if (getLangOpts().ObjCAutoRefCount &&
2678 (Attributes & ObjCPropertyAttribute::kind_weak)) {
2679 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2680 << "unsafe_unretained" << "weak";
2681 Attributes &= ~ObjCPropertyAttribute::kind_weak;
2682 }
2683 } else if (Attributes & ObjCPropertyAttribute::kind_copy) {
2684 if (Attributes & ObjCPropertyAttribute::kind_retain) {
2685 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2686 << "copy" << "retain";
2687 Attributes &= ~ObjCPropertyAttribute::kind_retain;
2688 }
2689 if (Attributes & ObjCPropertyAttribute::kind_strong) {
2690 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2691 << "copy" << "strong";
2692 Attributes &= ~ObjCPropertyAttribute::kind_strong;
2693 }
2694 if (Attributes & ObjCPropertyAttribute::kind_weak) {
2695 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2696 << "copy" << "weak";
2697 Attributes &= ~ObjCPropertyAttribute::kind_weak;
2698 }
2699 } else if ((Attributes & ObjCPropertyAttribute::kind_retain) &&
2700 (Attributes & ObjCPropertyAttribute::kind_weak)) {
2701 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "retain"
2702 << "weak";
2703 Attributes &= ~ObjCPropertyAttribute::kind_retain;
2704 } else if ((Attributes & ObjCPropertyAttribute::kind_strong) &&
2705 (Attributes & ObjCPropertyAttribute::kind_weak)) {
2706 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "strong"
2707 << "weak";
2708 Attributes &= ~ObjCPropertyAttribute::kind_weak;
2709 }
2710
2711 if (Attributes & ObjCPropertyAttribute::kind_weak) {
2712 // 'weak' and 'nonnull' are mutually exclusive.
2713 if (auto nullability = PropertyTy->getNullability()) {
2714 if (*nullability == NullabilityKind::NonNull)
2715 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive)
2716 << "nonnull" << "weak";
2717 }
2718 }
2719
2720 if ((Attributes & ObjCPropertyAttribute::kind_atomic) &&
2722 Diag(Loc, diag::err_objc_property_attr_mutually_exclusive) << "atomic"
2723 << "nonatomic";
2724 Attributes &= ~ObjCPropertyAttribute::kind_atomic;
2725 }
2726
2727 // Warn if user supplied no assignment attribute, property is
2728 // readwrite, and this is an object type.
2729 if (!getOwnershipRule(Attributes) && PropertyTy->isObjCRetainableType()) {
2730 if (Attributes & ObjCPropertyAttribute::kind_readonly) {
2731 // do nothing
2732 } else if (getLangOpts().ObjCAutoRefCount) {
2733 // With arc, @property definitions should default to strong when
2734 // not specified.
2736 } else if (PropertyTy->isObjCObjectPointerType()) {
2737 bool isAnyClassTy = (PropertyTy->isObjCClassType() ||
2738 PropertyTy->isObjCQualifiedClassType());
2739 // In non-gc, non-arc mode, 'Class' is treated as a 'void *' no need to
2740 // issue any warning.
2741 if (isAnyClassTy && getLangOpts().getGC() == LangOptions::NonGC)
2742 ;
2743 else if (propertyInPrimaryClass) {
2744 // Don't issue warning on property with no life time in class
2745 // extension as it is inherited from property in primary class.
2746 // Skip this warning in gc-only mode.
2747 if (getLangOpts().getGC() != LangOptions::GCOnly)
2748 Diag(Loc, diag::warn_objc_property_no_assignment_attribute);
2749
2750 // If non-gc code warn that this is likely inappropriate.
2751 if (getLangOpts().getGC() == LangOptions::NonGC)
2752 Diag(Loc, diag::warn_objc_property_default_assign_on_object);
2753 }
2754 }
2755
2756 // FIXME: Implement warning dependent on NSCopying being
2757 // implemented.
2758 }
2759
2760 if (!(Attributes & ObjCPropertyAttribute::kind_copy) &&
2761 !(Attributes & ObjCPropertyAttribute::kind_readonly) &&
2762 getLangOpts().getGC() == LangOptions::GCOnly &&
2763 PropertyTy->isBlockPointerType())
2764 Diag(Loc, diag::warn_objc_property_copy_missing_on_block);
2765 else if ((Attributes & ObjCPropertyAttribute::kind_retain) &&
2766 !(Attributes & ObjCPropertyAttribute::kind_readonly) &&
2767 !(Attributes & ObjCPropertyAttribute::kind_strong) &&
2768 PropertyTy->isBlockPointerType())
2769 Diag(Loc, diag::warn_objc_property_retain_of_block);
2770
2771 if ((Attributes & ObjCPropertyAttribute::kind_readonly) &&
2773 Diag(Loc, diag::warn_objc_readonly_property_has_setter);
2774}
Defines the clang::Expr interface and subclasses for C++ expressions.
Token Tok
The Token.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
#define SM(sm)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
Defines the clang::Preprocessor interface.
static bool SuperClassImplementsProperty(ObjCInterfaceDecl *IDecl, ObjCPropertyDecl *Prop)
static bool areIncompatiblePropertyAttributes(unsigned Attr1, unsigned Attr2, unsigned Kinds)
static Qualifiers::ObjCLifetime getImpliedARCOwnership(ObjCPropertyAttribute::Kind attrs, QualType type)
getImpliedARCOwnership - Given a set of property attributes and a type, infer an expected lifetime.
static void checkARCPropertyImpl(Sema &S, SourceLocation propertyImplLoc, ObjCPropertyDecl *property, ObjCIvarDecl *ivar)
static bool LocPropertyAttribute(ASTContext &Context, const char *attrName, SourceLocation LParenLoc, SourceLocation &Loc)
static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, ObjCPropertyDecl *Property)
AddPropertyAttrs - Propagates attributes from a property to the implicitly-declared getter or setter ...
static void checkPropertyDeclWithOwnership(Sema &S, ObjCPropertyDecl *property)
Check the internal consistency of a property declaration with an explicit ownership qualifier.
static unsigned deducePropertyOwnershipFromType(Sema &S, QualType T)
static void CollectImmediateProperties(ObjCContainerDecl *CDecl, ObjCContainerDecl::PropertyMap &PropMap, ObjCContainerDecl::PropertyMap &SuperPropMap, bool CollectClassPropsOnly=false, bool IncludeProtocols=true)
CollectImmediateProperties - This routine collects all properties in the class and its conforming pro...
static void checkAtomicPropertyMismatch(Sema &S, ObjCPropertyDecl *OldProperty, ObjCPropertyDecl *NewProperty, bool PropagateAtomicity)
Check for a mismatch in the atomicity of the given properties.
static void setImpliedPropertyAttributeForReadOnlyProperty(ObjCPropertyDecl *property, ObjCIvarDecl *ivar)
setImpliedPropertyAttributeForReadOnlyProperty - This routine evaludates life-time attributes for a '...
static unsigned getOwnershipRule(unsigned attr)
static ObjCMethodDecl * RedeclarePropertyAccessor(ASTContext &Context, ObjCImplementationDecl *Impl, ObjCMethodDecl *AccessorDecl, SourceLocation AtLoc, SourceLocation PropertyLoc)
Create a synthesized property accessor stub inside the @implementation.
static bool hasWrittenStorageAttribute(ObjCPropertyDecl *Prop, ObjCPropertyQueryKind QueryKind)
Determine whether any storage attributes were written on the property.
static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl, ObjCInterfaceDecl::PropertyMap &PropMap)
CollectSuperClassPropertyImplementations - This routine collects list of properties to be implemented...
static const unsigned OwnershipMask
static void DiagnoseUnimplementedAccessor(Sema &S, ObjCInterfaceDecl *PrimaryClass, Selector Method, ObjCImplDecl *IMPDecl, ObjCContainerDecl *CDecl, ObjCCategoryDecl *C, ObjCPropertyDecl *Prop, llvm::SmallPtrSet< const ObjCMethodDecl *, 8 > &SMap)
static ObjCPropertyDecl * SelectPropertyForSynthesisFromProtocols(Sema &S, SourceLocation AtLoc, ObjCInterfaceDecl *ClassDecl, ObjCPropertyDecl *Property)
SelectPropertyForSynthesisFromProtocols - Finds the most appropriate property declaration that should...
static void CheckPropertyAgainstProtocol(Sema &S, ObjCPropertyDecl *Prop, ObjCProtocolDecl *Proto, llvm::SmallPtrSetImpl< ObjCProtocolDecl * > &Known)
Check this Objective-C property against a property declared in the given protocol.
static bool isIncompatiblePropertyAttribute(unsigned Attr1, unsigned Attr2, ObjCPropertyAttribute::Kind Kind)
This file declares semantic analysis for Objective-C.
Defines the SourceManager interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
bool propertyTypesAreCompatible(QualType, QualType)
QualType getQualifiedType(SplitQualType split) const
Un-split a SplitQualType.
bool isInvalid() const
Definition Ownership.h:167
Attr - This represents one attribute.
Definition Attr.h:46
A call to an overloaded operator written using operator syntax.
Definition ExprCXX.h:85
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
void makeDeclVisibleInContext(NamedDecl *D)
Makes a declaration visible within this context.
DeclContextLookupResult lookup_result
Definition DeclBase.h:2577
void addDecl(Decl *D)
Add the declaration D into this context.
A reference to a declared variable, function, enum, etc.
Definition Expr.h:1273
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
SourceLocation getEndLoc() const LLVM_READONLY
Definition DeclBase.h:435
T * getAttr() const
Definition DeclBase.h:573
bool hasAttrs() const
Definition DeclBase.h:518
void addAttr(Attr *A)
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
Definition DeclBase.h:593
void setAttrs(const AttrVec &Attrs)
Definition DeclBase.h:520
bool isUnavailable(std::string *Message=nullptr) const
Determine whether this declaration is marked 'unavailable'.
Definition DeclBase.h:771
AvailabilityResult getAvailability(std::string *Message=nullptr, VersionTuple EnclosingVersion=VersionTuple(), StringRef *RealizedPlatform=nullptr) const
Determine the availability of the given declaration.
Definition DeclBase.cpp:775
void setInvalidDecl(bool Invalid=true)
setInvalidDecl - Indicates the Decl had a semantic error.
Definition DeclBase.cpp:178
bool isInvalidDecl() const
Definition DeclBase.h:588
SourceLocation getLocation() const
Definition DeclBase.h:439
redecl_range redecls() const
Returns an iterator range for all the redeclarations of the same decl.
Definition DeclBase.h:1049
DeclContext * getDeclContext()
Definition DeclBase.h:448
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:431
AttrVec & getAttrs()
Definition DeclBase.h:524
bool hasAttr() const
Definition DeclBase.h:577
void setLexicalDeclContext(DeclContext *DC)
Definition DeclBase.cpp:386
SourceLocation getIdentifierLoc() const
Definition DeclSpec.h:2357
void setObjCWeakProperty(bool Val=true)
Definition DeclSpec.h:2731
const IdentifierInfo * getIdentifier() const
Definition DeclSpec.h:2351
This represents one expression.
Definition Expr.h:112
Represents difference between two FPOptions values.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string.
Definition Diagnostic.h:140
static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, bool BeforePreviousInsertions=false)
Create a code modification hint that inserts the given code string at a specific location.
Definition Diagnostic.h:103
Represents a function declaration or definition.
Definition Decl.h:2000
One of these records is kept for each identifier that is lexed.
static ImplicitCastExpr * Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat, FPOptionsOverride FPO)
Definition Expr.cpp:2073
static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type)
Create the initialization entity for the result of a function.
clang::ObjCRuntime ObjCRuntime
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
Definition Lexer.h:78
bool LexFromRawLexer(Token &Result)
LexFromRawLexer - Lex a token from a designated raw lexer (one with no associated preprocessor object...
Definition Lexer.h:236
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
ObjCCategoryDecl - Represents a category declaration.
Definition DeclObjC.h:2329
ObjCInterfaceDecl * getClassInterface()
Definition DeclObjC.h:2372
ObjCCategoryImplDecl - An object of this class encapsulates a category @implementation declaration.
Definition DeclObjC.h:2545
ObjCContainerDecl - Represents a container for method declarations.
Definition DeclObjC.h:948
ObjCMethodDecl * getMethod(Selector Sel, bool isInstance, bool AllowHidden=false) const
Definition DeclObjC.cpp:90
method_range methods() const
Definition DeclObjC.h:1016
instmeth_range instance_methods() const
Definition DeclObjC.h:1033
llvm::SmallDenseSet< const ObjCProtocolDecl *, 8 > ProtocolPropertySet
Definition DeclObjC.h:1088
ObjCPropertyDecl * getProperty(const IdentifierInfo *Id, bool IsInstance) const
Definition DeclObjC.cpp:233
instprop_range instance_properties() const
Definition DeclObjC.h:982
llvm::MapVector< std::pair< IdentifierInfo *, unsigned >, ObjCPropertyDecl * > PropertyMap
Definition DeclObjC.h:1085
ObjCPropertyDecl * FindPropertyDeclaration(const IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const
FindPropertyDeclaration - Finds declaration of the property given its name in 'PropertyId' and return...
Definition DeclObjC.cpp:247
llvm::SmallVector< ObjCPropertyDecl *, 8 > PropertyDeclOrder
Definition DeclObjC.h:1089
ObjCMethodDecl * getClassMethod(Selector Sel, bool AllowHidden=false) const
Definition DeclObjC.h:1071
prop_range properties() const
Definition DeclObjC.h:967
ObjCMethodDecl * getInstanceMethod(Selector Sel, bool AllowHidden=false) const
Definition DeclObjC.h:1066
bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const
This routine returns 'true' if a user declared setter method was found in the class,...
Definition DeclObjC.cpp:122
Captures information about "declaration specifiers" specific to Objective-C.
Definition DeclSpec.h:905
ObjCPropertyAttribute::Kind getPropertyAttributes() const
Definition DeclSpec.h:939
SourceLocation getGetterNameLoc() const
Definition DeclSpec.h:974
SourceLocation getSetterNameLoc() const
Definition DeclSpec.h:982
void addPropertyImplementation(ObjCPropertyImplDecl *property)
propimpl_range property_impls() const
Definition DeclObjC.h:2513
ObjCPropertyImplDecl * FindPropertyImplDecl(IdentifierInfo *propertyId, ObjCPropertyQueryKind queryKind) const
FindPropertyImplDecl - This method looks up a previous ObjCPropertyImplDecl added to the list of thos...
const ObjCInterfaceDecl * getClassInterface() const
Definition DeclObjC.h:2486
ObjCPropertyImplDecl * FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const
FindPropertyImplIvarDecl - This method lookup the ivar in the list of properties implemented in this ...
ObjCImplementationDecl - Represents a class definition - this is where method definitions are specifi...
Definition DeclObjC.h:2597
Represents an ObjC class declaration.
Definition DeclObjC.h:1154
ObjCPropertyDecl * FindPropertyVisibleInPrimaryClass(const IdentifierInfo *PropertyId, ObjCPropertyQueryKind QueryKind) const
FindPropertyVisibleInPrimaryClass - Finds declaration of the property with name 'PropertyId' in the p...
Definition DeclObjC.cpp:379
ObjCIvarDecl * lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared)
Definition DeclObjC.cpp:634
all_protocol_range all_referenced_protocols() const
Definition DeclObjC.h:1417
visible_extensions_range visible_extensions() const
Definition DeclObjC.h:1723
ObjCCategoryDecl * FindCategoryDeclaration(const IdentifierInfo *CategoryId) const
FindCategoryDeclaration - Finds category declaration in the list of categories for this class and ret...
protocol_range protocols() const
Definition DeclObjC.h:1359
const ObjCInterfaceDecl * isObjCRequiresPropertyDefs() const
isObjCRequiresPropertyDefs - Checks that a class or one of its super classes must not be auto-synthes...
Definition DeclObjC.cpp:429
ObjCMethodDecl * lookupPropertyAccessor(const Selector Sel, const ObjCCategoryDecl *Cat, bool IsClassProperty) const
Lookup a setter or getter in the class hierarchy, including in all categories except for category pas...
Definition DeclObjC.h:1869
ObjCMethodDecl * lookupMethod(Selector Sel, bool isInstance, bool shallowCategoryLookup=false, bool followSuper=true, const ObjCCategoryDecl *C=nullptr) const
lookupMethod - This method returns an instance/class method by looking in the class,...
Definition DeclObjC.cpp:696
bool ClassImplementsProtocol(ObjCProtocolDecl *lProto, bool lookupCategory, bool RHSIsQualifiedID=false)
ClassImplementsProtocol - Checks that 'lProto' protocol has been implemented in IDecl class,...
ObjCImplementationDecl * getImplementation() const
bool hasDesignatedInitializers() const
Returns true if this interface decl contains at least one initializer marked with the 'objc_designate...
void getDesignatedInitializers(llvm::SmallVectorImpl< const ObjCMethodDecl * > &Methods) const
Returns the designated initializers for the interface.
Definition DeclObjC.cpp:545
void collectPropertiesToImplement(PropertyMap &PM) const override
This routine collects list of properties to be implemented in the class.
Definition DeclObjC.cpp:402
bool isArcWeakrefUnavailable() const
isArcWeakrefUnavailable - Checks for a class or one of its super classes to be incompatible with __we...
Definition DeclObjC.cpp:419
ObjCInterfaceDecl * getSuperClass() const
Definition DeclObjC.cpp:349
known_extensions_range known_extensions() const
Definition DeclObjC.h:1762
ObjCIvarDecl - Represents an ObjC instance variable.
Definition DeclObjC.h:1952
AccessControl getAccessControl() const
Definition DeclObjC.h:2000
bool getSynthesize() const
Definition DeclObjC.h:2007
static ObjCIvarDecl * Create(ASTContext &C, ObjCContainerDecl *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW=nullptr, bool synthesized=false)
QualType getUsageType(QualType objectType) const
Retrieve the type of this instance variable when viewed as a member of a specific object type.
ObjCIvarRefExpr - A reference to an ObjC instance variable.
Definition ExprObjC.h:546
ObjCMethodDecl - Represents an instance or class method declaration.
Definition DeclObjC.h:140
void setDefined(bool isDefined)
Definition DeclObjC.h:453
unsigned param_size() const
Definition DeclObjC.h:347
void setSelfDecl(ImplicitParamDecl *SD)
Definition DeclObjC.h:419
bool isPropertyAccessor() const
Definition DeclObjC.h:436
static ObjCMethodDecl * Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc, Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo, DeclContext *contextDecl, bool isInstance=true, bool isVariadic=false, bool isPropertyAccessor=false, bool isSynthesizedAccessorStub=false, bool isImplicitlyDeclared=false, bool isDefined=false, ObjCImplementationControl impControl=ObjCImplementationControl::None, bool HasRelatedResultType=false)
Definition DeclObjC.cpp:849
param_const_iterator param_begin() const
Definition DeclObjC.h:354
void setCmdDecl(ImplicitParamDecl *CD)
Definition DeclObjC.h:421
Stmt * getBody() const override
Retrieve the body of this method, if it has one.
Definition DeclObjC.cpp:906
void setMethodParams(ASTContext &C, ArrayRef< ParmVarDecl * > Params, ArrayRef< SourceLocation > SelLocs={})
Sets the method's parameters and selector source locations.
Definition DeclObjC.cpp:941
bool isSynthesizedAccessorStub() const
Definition DeclObjC.h:444
void setPropertyAccessor(bool isAccessor)
Definition DeclObjC.h:440
Selector getSelector() const
Definition DeclObjC.h:327
ObjCMethodFamily getMethodFamily() const
Determines the family of this method.
void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID)
createImplicitParams - Used to lazily create the self and cmd implicit parameters.
QualType getReturnType() const
Definition DeclObjC.h:329
ParmVarDecl *const * param_iterator
Definition DeclObjC.h:350
bool isClassMethod() const
Definition DeclObjC.h:434
ObjCInterfaceDecl * getClassInterface()
Represents a pointer to an Objective C object.
Definition TypeBase.h:8006
Represents one property declaration in an Objective-C interface.
Definition DeclObjC.h:731
ObjCPropertyQueryKind getQueryKind() const
Definition DeclObjC.h:860
bool isClassProperty() const
Definition DeclObjC.h:855
void setPropertyImplementation(PropertyControl pc)
Definition DeclObjC.h:908
void setSetterName(Selector Sel, SourceLocation Loc=SourceLocation())
Definition DeclObjC.h:896
ObjCMethodDecl * getGetterMethodDecl() const
Definition DeclObjC.h:901
bool isInstanceProperty() const
Definition DeclObjC.h:854
void setPropertyAttributes(ObjCPropertyAttribute::Kind PRVal)
Definition DeclObjC.h:819
bool isReadOnly() const
isReadOnly - Return true iff the property has a setter.
Definition DeclObjC.h:838
static ObjCPropertyDecl * findPropertyDecl(const DeclContext *DC, const IdentifierInfo *propertyID, ObjCPropertyQueryKind queryKind)
Lookup a property by name in the specified DeclContext.
Definition DeclObjC.cpp:176
bool isDirectProperty() const
Selector getSetterName() const
Definition DeclObjC.h:893
QualType getType() const
Definition DeclObjC.h:804
void setPropertyAttributesAsWritten(ObjCPropertyAttribute::Kind PRVal)
Definition DeclObjC.h:831
void overwritePropertyAttributes(unsigned PRVal)
Definition DeclObjC.h:823
Selector getGetterName() const
Definition DeclObjC.h:885
ObjCPropertyAttribute::Kind getPropertyAttributesAsWritten() const
Definition DeclObjC.h:827
IdentifierInfo * getDefaultSynthIvarName(ASTContext &Ctx) const
Get the default name of the synthesized ivar.
Definition DeclObjC.cpp:224
ObjCPropertyAttribute::Kind getPropertyAttributes() const
Definition DeclObjC.h:815
static ObjCPropertyDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, const IdentifierInfo *Id, SourceLocation AtLocation, SourceLocation LParenLocation, QualType T, TypeSourceInfo *TSI, PropertyControl propControl=None)
void setGetterName(Selector Sel, SourceLocation Loc=SourceLocation())
Definition DeclObjC.h:888
PropertyControl getPropertyImplementation() const
Definition DeclObjC.h:912
ObjCPropertyImplDecl - Represents implementation declaration of a property in a class or category imp...
Definition DeclObjC.h:2805
Kind getPropertyImplementation() const
Definition DeclObjC.h:2875
void setSetterMethodDecl(ObjCMethodDecl *MD)
Definition DeclObjC.h:2905
ObjCPropertyDecl * getPropertyDecl() const
Definition DeclObjC.h:2870
void setSetterCXXAssignment(Expr *setterCXXAssignment)
Definition DeclObjC.h:2919
static ObjCPropertyImplDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation atLoc, SourceLocation L, ObjCPropertyDecl *property, Kind PK, ObjCIvarDecl *ivarDecl, SourceLocation ivarLoc)
void setGetterMethodDecl(ObjCMethodDecl *MD)
Definition DeclObjC.h:2902
void setGetterCXXConstructor(Expr *getterCXXConstructor)
Definition DeclObjC.h:2911
Represents an Objective-C protocol declaration.
Definition DeclObjC.h:2084
ObjCProtocolDecl * getDefinition()
Retrieve the definition of this protocol, if any.
Definition DeclObjC.h:2250
protocol_range protocols() const
Definition DeclObjC.h:2161
The basic abstraction for the target Objective-C runtime.
Definition ObjCRuntime.h:28
bool isNonFragile() const
Does this runtime follow the set of implied behaviors for a "non-fragile" ABI?
Definition ObjCRuntime.h:82
bool allowsDirectDispatch() const
Does this runtime supports direct dispatch.
bool isFragile() const
The inverse of isNonFragile(): does this runtime follow the set of implied behaviors for a "fragile" ...
Definition ObjCRuntime.h:97
Represents a parameter to a function.
Definition Decl.h:1790
static ParmVarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg)
Definition Decl.cpp:2958
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
IdentifierInfo * getIdentifierInfo(StringRef Name) const
Return information about the specified preprocessor identifier token.
StringRef getLastMacroWithSpelling(SourceLocation Loc, ArrayRef< TokenValue > Tokens) const
Return the name of the macro defined before Loc that has spelling Tokens.
A (possibly-)qualified type.
Definition TypeBase.h:937
PointerAuthQualifier getPointerAuth() const
Definition TypeBase.h:1459
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8388
Qualifiers::ObjCLifetime getObjCLifetime() const
Returns lifetime attribute of this type.
Definition TypeBase.h:1444
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8573
QualType getCanonicalType() const
Definition TypeBase.h:8440
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition TypeBase.h:8482
SplitQualType split() const
Divides a QualType into its unqualified type and a set of local qualifiers.
Definition TypeBase.h:8409
bool isObjCGCStrong() const
true when Type is objc's strong.
Definition TypeBase.h:1439
bool isObjCGCWeak() const
true when Type is objc's weak.
Definition TypeBase.h:1434
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
Definition TypeBase.h:361
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
Definition TypeBase.h:354
@ OCL_None
There is no lifetime qualification on this type.
Definition TypeBase.h:350
@ OCL_Weak
Reading or writing from this object requires a barrier call.
Definition TypeBase.h:364
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
Definition TypeBase.h:367
bool hasObjCLifetime() const
Definition TypeBase.h:544
void addObjCLifetime(ObjCLifetime type)
Definition TypeBase.h:552
void setObjCLifetime(ObjCLifetime type)
Definition TypeBase.h:548
bool hasFlexibleArrayMember() const
Definition Decl.h:4360
Scope - A scope is a transient data structure that is used while parsing the program.
Definition Scope.h:41
Smart pointer class that efficiently represents Objective-C method names.
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
Sema & SemaRef
Definition SemaBase.h:40
const LangOptions & getLangOpts() const
Definition SemaBase.cpp:11
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
void DefaultSynthesizeProperties(Scope *S, ObjCImplDecl *IMPDecl, ObjCInterfaceDecl *IDecl, SourceLocation AtEnd)
DefaultSynthesizeProperties - This routine default synthesizes all properties which must be synthesiz...
bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, ObjCMethodDecl *Getter, SourceLocation Loc)
void ProcessPropertyDecl(ObjCPropertyDecl *property)
Process the specified property declaration and create decls for the setters and getters as needed.
ObjCPropertyDecl * HandlePropertyInClassExtension(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc, Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite, unsigned &Attributes, const unsigned AttributesAsWritten, QualType T, TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind)
Called by ActOnProperty to handle @property declarations in class extensions.
void diagnoseNullResettableSynthesizedSetters(const ObjCImplDecl *impDecl)
Diagnose any null-resettable synthesized setters.
llvm::SmallPtrSet< Selector, 8 > SelectorSet
Definition SemaObjC.h:222
ObjCPropertyDecl * CreatePropertyDecl(Scope *S, ObjCContainerDecl *CDecl, SourceLocation AtLoc, SourceLocation LParenLoc, FieldDeclarator &FD, Selector GetterSel, SourceLocation GetterNameLoc, Selector SetterSel, SourceLocation SetterNameLoc, const bool isReadWrite, const unsigned Attributes, const unsigned AttributesAsWritten, QualType T, TypeSourceInfo *TSI, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC=nullptr)
Called by ActOnProperty and HandlePropertyInClassExtension to handle creating the ObjcPropertyDecl fo...
bool CheckARCMethodDecl(ObjCMethodDecl *method)
Check a method declaration for compatibility with the Objective-C ARC conventions.
bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace, ObjCMethodDecl *Method, ObjCIvarDecl *IV)
IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is an ivar synthesized for 'Meth...
void DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D)
Decl * ActOnProperty(Scope *S, SourceLocation AtLoc, SourceLocation LParenLoc, FieldDeclarator &FD, ObjCDeclSpec &ODS, Selector GetterSel, Selector SetterSel, tok::ObjCKeywordKind MethodImplKind, DeclContext *lexicalDC=nullptr)
void DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl *IMPDecl, ObjCContainerDecl *CDecl, bool SynthesizeProperties)
DiagnoseUnimplementedProperties - This routine warns on those properties which must be implemented by...
void AtomicPropertySetterGetterRules(ObjCImplDecl *IMPDecl, ObjCInterfaceDecl *IDecl)
AtomicPropertySetterGetterRules - This routine enforces the rule (via warning) when atomic property h...
Decl * ActOnPropertyImplDecl(Scope *S, SourceLocation AtLoc, SourceLocation PropertyLoc, bool ImplKind, IdentifierInfo *PropertyId, IdentifierInfo *PropertyIvar, SourceLocation PropertyIvarLoc, ObjCPropertyQueryKind QueryKind)
ActOnPropertyImplDecl - This routine performs semantic checks and builds the AST node for a property ...
void DiagnoseMissingDesignatedInitOverrides(const ObjCImplementationDecl *ImplD, const ObjCInterfaceDecl *IFD)
ObjCProtocolDecl * LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, RedeclarationKind Redecl=RedeclarationKind::NotForRedeclaration)
Find the protocol with the given name, if any.
void CheckObjCPropertyAttributes(Decl *PropertyPtrTy, SourceLocation Loc, unsigned &Attributes, bool propertyInPrimaryClass)
Ensure attributes are consistent with type.
void AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false)
AddFactoryMethodToGlobalPool - Same as above, but for factory methods.
Definition SemaObjC.h:530
void DiagnosePropertyMismatch(ObjCPropertyDecl *Property, ObjCPropertyDecl *SuperProperty, const IdentifierInfo *Name, bool OverridingProtocolProperty)
DiagnosePropertyMismatch - Compares two properties for their attributes and types and warns on a vari...
void CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, ObjCInterfaceDecl *CurrentClass, ResultTypeCompatibilityKind RTC)
void AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl=false)
AddInstanceMethodToGlobalPool - All instance methods in a translation unit are added to a global pool...
Definition SemaObjC.h:524
RAII object to handle the state changes required to synthesize a function body.
Definition Sema.h:13587
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:868
ASTContext & Context
Definition Sema.h:1300
bool isObjCPointerConversion(QualType FromType, QualType ToType, QualType &ConvertedType, bool &IncompatibleObjC)
isObjCPointerConversion - Determines whether this is an Objective-C pointer conversion.
SemaObjC & ObjC()
Definition Sema.h:1509
const LangOptions & getLangOpts() const
Definition Sema.h:932
const LangOptions & LangOpts
Definition Sema.h:1298
@ AbstractSynthesizedIvarType
Definition Sema.h:6282
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getLocWithOffset(IntTy Offset) const
Return a source location with the specified offset from this SourceLocation.
This class handles loading and caching of source files into memory.
A trivial tuple used to represent a source range.
Stores token information for comparing actual tokens with predefined values.
Token - This structure provides full information about a lexed token.
Definition Token.h:36
SourceLocation getEndLoc() const
Get the end source location.
Definition TypeLoc.cpp:227
SourceLocation getBeginLoc() const
Get the begin source location.
Definition TypeLoc.cpp:193
A container of type source information.
Definition TypeBase.h:8359
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
Definition TypeLoc.h:267
QualType getType() const
Return the type wrapped by this type source info.
Definition TypeBase.h:8370
bool isBlockPointerType() const
Definition TypeBase.h:8645
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isArithmeticType() const
Definition Type.cpp:2374
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9285
bool isObjCObjectPointerType() const
Definition TypeBase.h:8804
bool isObjCQualifiedClassType() const
Definition TypeBase.h:8831
bool isObjCClassType() const
Definition TypeBase.h:8843
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9218
bool isObjCARCImplicitlyUnretainedType() const
Determines if this type, which must satisfy isObjCLifetimeType(), is implicitly __unsafe_unretained r...
Definition Type.cpp:5329
bool isRecordType() const
Definition TypeBase.h:8752
bool isObjCRetainableType() const
Definition Type.cpp:5360
std::optional< NullabilityKind > getNullability() const
Determine the nullability of the given type.
Definition Type.cpp:5090
void setType(QualType newType)
Definition Decl.h:724
QualType getType() const
Definition Decl.h:723
ObjCPropertyAttribute::Kind - list of property attributes.
@ kind_nullability
Indicates that the nullability of the type was spelled with a property attribute rather than a type q...
const internal::VariadicDynCastAllOfMatcher< Stmt, CallExpr > callExpr
Matches call expressions.
const internal::VariadicAllOfMatcher< Type > type
Matches Types in the clang AST.
ObjCKeywordKind
Provides a namespace for Objective-C keywords which start with an '@'.
Definition TokenKinds.h:41
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
@ CPlusPlus
ObjCPropertyQueryKind
Definition DeclObjC.h:719
@ Nullable
Values of this type can be null.
Definition Specifiers.h:352
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
Definition Specifiers.h:357
@ NonNull
Values of this type can never be null.
Definition Specifiers.h:350
std::pair< FileID, unsigned > FileIDAndOffset
@ SC_None
Definition Specifiers.h:250
ObjCMethodFamily
A family of Objective-C methods.
@ Property
The type of a property.
Definition TypeBase.h:911
@ AR_Unavailable
Definition DeclBase.h:76
@ VK_PRValue
A pr-value expression (in the C++11 taxonomy) produces a temporary value.
Definition Specifiers.h:135
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition Specifiers.h:139
bool declaresSameEntity(const Decl *D1, const Decl *D2)
Determine whether two declarations declare the same entity.
Definition DeclBase.h:1288
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
#define true
Definition stdbool.h:25
This little struct is used to capture information about structure field declarators,...
Definition DeclSpec.h:2791
A std::pair-like structure for storing a qualified type split into its local qualifiers and its local...
Definition TypeBase.h:870
Qualifiers Quals
The local qualifiers.
Definition TypeBase.h:875