Coverage Report

Created: 2024-01-17 10:31

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