Clang Project

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