Coverage Report

Created: 2019-07-24 05:18

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