Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Analysis/RetainSummaryManager.h
Line
Count
Source (jump to first uncovered line)
1
//=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
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 defines summaries implementation for retain counting, which
10
//  implements a reference count checker for Core Foundation and Cocoa
11
//  on (Mac OS X).
12
//
13
//===----------------------------------------------------------------------===//
14
15
#ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_H
16
#define LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_H
17
18
#include "llvm/ADT/DenseMap.h"
19
#include "llvm/ADT/FoldingSet.h"
20
#include "llvm/ADT/ImmutableMap.h"
21
#include "clang/AST/Attr.h"
22
#include "clang/AST/DeclCXX.h"
23
#include "clang/AST/DeclObjC.h"
24
#include "clang/AST/ParentMap.h"
25
#include "clang/Analysis/AnyCall.h"
26
#include "clang/Analysis/SelectorExtras.h"
27
#include "llvm/ADT/STLExtras.h"
28
29
using namespace clang;
30
31
namespace clang {
32
namespace ento {
33
34
/// Determines the object kind of a tracked object.
35
enum class ObjKind {
36
  /// Indicates that the tracked object is a CF object.
37
  CF,
38
39
  /// Indicates that the tracked object is an Objective-C object.
40
  ObjC,
41
42
  /// Indicates that the tracked object could be a CF or Objective-C object.
43
  AnyObj,
44
45
  /// Indicates that the tracked object is a generalized object.
46
  Generalized,
47
48
  /// Indicates that the tracking object is a descendant of a
49
  /// referenced-counted OSObject, used in the Darwin kernel.
50
  OS
51
};
52
53
enum ArgEffectKind {
54
  /// There is no effect.
55
  DoNothing,
56
57
  /// The argument is treated as if an -autorelease message had been sent to
58
  /// the referenced object.
59
  Autorelease,
60
61
  /// The argument is treated as if the referenced object was deallocated.
62
  Dealloc,
63
64
  /// The argument has its reference count decreased by 1.
65
  DecRef,
66
67
  /// The argument has its reference count decreased by 1 to model
68
  /// a transferred bridge cast under ARC.
69
  DecRefBridgedTransferred,
70
71
  /// The argument has its reference count increased by 1.
72
  IncRef,
73
74
  /// The argument is a pointer to a retain-counted object; on exit, the new
75
  /// value of the pointer is a +0 value.
76
  UnretainedOutParameter,
77
78
  /// The argument is a pointer to a retain-counted object; on exit, the new
79
  /// value of the pointer is a +1 value.
80
  RetainedOutParameter,
81
82
  /// The argument is a pointer to a retain-counted object; on exit, the new
83
  /// value of the pointer is a +1 value iff the return code is zero.
84
  RetainedOutParameterOnZero,
85
86
  /// The argument is a pointer to a retain-counted object; on exit, the new
87
  /// value of the pointer is a +1 value iff the return code is non-zero.
88
  RetainedOutParameterOnNonZero,
89
90
  /// The argument is treated as potentially escaping, meaning that
91
  /// even when its reference count hits 0 it should be treated as still
92
  /// possibly being alive as someone else *may* be holding onto the object.
93
  MayEscape,
94
95
  /// All typestate tracking of the object ceases.  This is usually employed
96
  /// when the effect of the call is completely unknown.
97
  StopTracking,
98
99
  /// All typestate tracking of the object ceases.  Unlike StopTracking,
100
  /// this is also enforced when the method body is inlined.
101
  ///
102
  /// In some cases, we obtain a better summary for this checker
103
  /// by looking at the call site than by inlining the function.
104
  /// Signifies that we should stop tracking the symbol even if
105
  /// the function is inlined.
106
  StopTrackingHard,
107
108
  /// Performs the combined functionality of DecRef and StopTrackingHard.
109
  ///
110
  /// The models the effect that the called function decrements the reference
111
  /// count of the argument and all typestate tracking on that argument
112
  /// should cease.
113
  DecRefAndStopTrackingHard,
114
};
115
116
/// An ArgEffect summarizes the retain count behavior on an argument or receiver
117
/// to a function or method.
118
class ArgEffect {
119
  ArgEffectKind K;
120
  ObjKind O;
121
public:
122
  explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
123
12.1k
      : K(K), O(O) {}
124
125
31.4k
  ArgEffectKind getKind() const { return K; }
126
23.8k
  ObjKind getObjKind() const { return O; }
127
128
215
  ArgEffect withKind(ArgEffectKind NewK) {
129
215
    return ArgEffect(NewK, O);
130
215
  }
131
132
1.19k
  bool operator==(const ArgEffect &Other) const {
133
1.19k
    return K == Other.K && O == Other.O;
134
1.19k
  }
135
};
136
137
/// RetEffect summarizes a call's retain/release behavior with respect
138
/// to its return value.
139
class RetEffect {
140
public:
141
  enum Kind {
142
    /// Indicates that no retain count information is tracked for
143
    /// the return value.
144
    NoRet,
145
146
    /// Indicates that the returned value is an owned (+1) symbol.
147
    OwnedSymbol,
148
149
    /// Indicates that the returned value is an object with retain count
150
    /// semantics but that it is not owned (+0).  This is the default
151
    /// for getters, etc.
152
    NotOwnedSymbol,
153
154
    /// Indicates that the return value is an owned object when the
155
    /// receiver is also a tracked object.
156
    OwnedWhenTrackedReceiver,
157
158
    // Treat this function as returning a non-tracked symbol even if
159
    // the function has been inlined. This is used where the call
160
    // site summary is more precise than the summary indirectly produced
161
    // by inlining the function
162
    NoRetHard
163
  };
164
165
private:
166
  Kind K;
167
  ObjKind O;
168
169
4.08k
  RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}
170
171
public:
172
11.1k
  Kind getKind() const { return K; }
173
174
8.57k
  ObjKind getObjKind() const { return O; }
175
176
2.65k
  bool isOwned() const {
177
2.65k
    return K == OwnedSymbol || 
K == OwnedWhenTrackedReceiver1.21k
;
178
2.65k
  }
179
180
3.42k
  bool notOwned() const {
181
3.42k
    return K == NotOwnedSymbol;
182
3.42k
  }
183
184
9
  bool operator==(const RetEffect &Other) const {
185
9
    return K == Other.K && 
O == Other.O3
;
186
9
  }
187
188
67
  static RetEffect MakeOwnedWhenTrackedReceiver() {
189
67
    return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
190
67
  }
191
192
427
  static RetEffect MakeOwned(ObjKind o) {
193
427
    return RetEffect(OwnedSymbol, o);
194
427
  }
195
411
  static RetEffect MakeNotOwned(ObjKind o) {
196
411
    return RetEffect(NotOwnedSymbol, o);
197
411
  }
198
3.09k
  static RetEffect MakeNoRet() {
199
3.09k
    return RetEffect(NoRet);
200
3.09k
  }
201
85
  static RetEffect MakeNoRetHard() {
202
85
    return RetEffect(NoRetHard);
203
85
  }
204
};
205
206
/// A key identifying a summary.
207
class ObjCSummaryKey {
208
  IdentifierInfo* II;
209
  Selector S;
210
public:
211
  ObjCSummaryKey(IdentifierInfo* ii, Selector s)
212
19.4k
    : II(ii), S(s) {}
213
214
  ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
215
5.47k
    : II(d ? d->getIdentifier() : nullptr), S(s) {}
216
217
  ObjCSummaryKey(Selector s)
218
438
    : II(nullptr), S(s) {}
219
220
95.3k
  IdentifierInfo *getIdentifier() const { return II; }
221
44.7k
  Selector getSelector() const { return S; }
222
};
223
224
} // end namespace ento
225
} // end namespace clang
226
227
using namespace ento;
228
229
namespace llvm {
230
231
//===----------------------------------------------------------------------===//
232
// Adapters for FoldingSet.
233
//===----------------------------------------------------------------------===//
234
template <> struct FoldingSetTrait<ArgEffect> {
235
21.7k
static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
236
21.7k
  ID.AddInteger((unsigned) X.getKind());
237
21.7k
  ID.AddInteger((unsigned) X.getObjKind());
238
21.7k
}
239
};
240
template <> struct FoldingSetTrait<RetEffect> {
241
6.61k
  static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
242
6.61k
    ID.AddInteger((unsigned) X.getKind());
243
6.61k
    ID.AddInteger((unsigned) X.getObjKind());
244
6.61k
}
245
};
246
247
template <> struct DenseMapInfo<ObjCSummaryKey> {
248
10.5k
  static inline ObjCSummaryKey getEmptyKey() {
249
10.5k
    return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
250
10.5k
                          DenseMapInfo<Selector>::getEmptyKey());
251
10.5k
  }
252
253
7.93k
  static inline ObjCSummaryKey getTombstoneKey() {
254
7.93k
    return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
255
7.93k
                          DenseMapInfo<Selector>::getTombstoneKey());
256
7.93k
  }
257
258
7.77k
  static unsigned getHashValue(const ObjCSummaryKey &V) {
259
7.77k
    typedef std::pair<IdentifierInfo*, Selector> PairTy;
260
7.77k
    return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
261
7.77k
                                                     V.getSelector()));
262
7.77k
  }
263
264
43.7k
  static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
265
43.7k
    return LHS.getIdentifier() == RHS.getIdentifier() &&
266
43.7k
           
LHS.getSelector() == RHS.getSelector()18.4k
;
267
43.7k
  }
268
269
};
270
271
} // end llvm namespace
272
273
274
namespace clang {
275
namespace ento {
276
277
/// ArgEffects summarizes the effects of a function/method call on all of
278
/// its arguments.
279
typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;
280
281
/// Summary for a function with respect to ownership changes.
282
class RetainSummary {
283
  /// Args - a map of (index, ArgEffect) pairs, where index
284
  ///  specifies the argument (starting from 0).  This can be sparsely
285
  ///  populated; arguments with no entry in Args use 'DefaultArgEffect'.
286
  ArgEffects Args;
287
288
  /// DefaultArgEffect - The default ArgEffect to apply to arguments that
289
  ///  do not have an entry in Args.
290
  ArgEffect DefaultArgEffect;
291
292
  /// Receiver - If this summary applies to an Objective-C message expression,
293
  ///  this is the effect applied to the state of the receiver.
294
  ArgEffect Receiver;
295
296
  /// Effect on "this" pointer - applicable only to C++ method calls.
297
  ArgEffect This;
298
299
  /// Ret - The effect on the return value.  Used to indicate if the
300
  ///  function/method call returns a new tracked symbol.
301
  RetEffect Ret;
302
303
public:
304
  RetainSummary(ArgEffects A,
305
                RetEffect R,
306
                ArgEffect defaultEff,
307
                ArgEffect ReceiverEff,
308
                ArgEffect ThisEff)
309
    : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
310
3.36k
      This(ThisEff), Ret(R) {}
311
312
  /// getArg - Return the argument effect on the argument specified by
313
  ///  idx (starting from 0).
314
5.38k
  ArgEffect getArg(unsigned idx) const {
315
5.38k
    if (const ArgEffect *AE = Args.lookup(idx))
316
2.46k
      return *AE;
317
2.91k
318
2.91k
    return DefaultArgEffect;
319
2.91k
  }
320
321
1.32k
  void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
322
1.32k
    Args = af.add(Args, idx, e);
323
1.32k
  }
324
325
  /// setDefaultArgEffect - Set the default argument effect.
326
0
  void setDefaultArgEffect(ArgEffect E) {
327
0
    DefaultArgEffect = E;
328
0
  }
329
330
  /// getRetEffect - Returns the effect on the return value of the call.
331
4.61k
  RetEffect getRetEffect() const { return Ret; }
332
333
  /// setRetEffect - Set the effect of the return value of the call.
334
109
  void setRetEffect(RetEffect E) { Ret = E; }
335
336
337
  /// Sets the effect on the receiver of the message.
338
14
  void setReceiverEffect(ArgEffect e) { Receiver = e; }
339
340
  /// getReceiverEffect - Returns the effect on the receiver of the call.
341
  ///  This is only meaningful if the summary applies to an ObjCMessageExpr*.
342
2.57k
  ArgEffect getReceiverEffect() const { return Receiver; }
343
344
  /// \return the effect on the "this" receiver of the method call.
345
  /// This is only meaningful if the summary applies to CXXMethodDecl*.
346
83
  ArgEffect getThisEffect() const { return This; }
347
348
0
  ArgEffect getDefaultEffect() const { return DefaultArgEffect; }
349
350
  /// Set the effect of the method on "this".
351
2
  void setThisEffect(ArgEffect e) { This = e; }
352
353
0
  bool isNoop() const {
354
0
    return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
355
0
      && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
356
0
      && Args.isEmpty();
357
0
  }
358
359
  /// Test if two retain summaries are identical. Note that merely equivalent
360
  /// summaries are not necessarily identical (for example, if an explicit
361
  /// argument effect matches the default effect).
362
0
  bool operator==(const RetainSummary &Other) const {
363
0
    return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
364
0
           Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret;
365
0
  }
366
367
  /// Profile this summary for inclusion in a FoldingSet.
368
6.61k
  void Profile(llvm::FoldingSetNodeID& ID) const {
369
6.61k
    ID.Add(Args);
370
6.61k
    ID.Add(DefaultArgEffect);
371
6.61k
    ID.Add(Receiver);
372
6.61k
    ID.Add(This);
373
6.61k
    ID.Add(Ret);
374
6.61k
  }
375
376
  /// A retain summary is simple if it has no ArgEffects other than the default.
377
4.52k
  bool isSimple() const {
378
4.52k
    return Args.isEmpty();
379
4.52k
  }
380
381
8.75k
  ArgEffects getArgEffects() const { return Args; }
382
383
private:
384
1.31k
  ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }
385
386
  friend class RetainSummaryManager;
387
};
388
389
class ObjCSummaryCache {
390
  typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
391
  MapTy M;
392
public:
393
146
  ObjCSummaryCache() {}
394
395
2.83k
  const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
396
2.83k
    // Do a lookup with the (D,S) pair.  If we find a match return
397
2.83k
    // the iterator.
398
2.83k
    ObjCSummaryKey K(D, S);
399
2.83k
    MapTy::iterator I = M.find(K);
400
2.83k
401
2.83k
    if (I != M.end())
402
1.73k
      return I->second;
403
1.10k
    if (!D)
404
7
      return nullptr;
405
1.09k
406
1.09k
    // Walk the super chain.  If we find a hit with a parent, we'll end
407
1.09k
    // up returning that summary.  We actually allow that key (null,S), as
408
1.09k
    // we cache summaries for the null ObjCInterfaceDecl* to allow us to
409
1.09k
    // generate initial summaries without having to worry about NSObject
410
1.09k
    // being declared.
411
1.09k
    // FIXME: We may change this at some point.
412
1.82k
    
for (ObjCInterfaceDecl *C=D->getSuperClass() ;; 1.09k
C=C->getSuperClass()734
) {
413
1.82k
      if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
414
294
        break;
415
1.53k
416
1.53k
      if (!C)
417
800
        return nullptr;
418
1.53k
    }
419
1.09k
420
1.09k
    // Cache the summary with original key to make the next lookup faster
421
1.09k
    // and return the iterator.
422
1.09k
    const RetainSummary *Summ = I->second;
423
294
    M[K] = Summ;
424
294
    return Summ;
425
1.09k
  }
426
427
0
  const RetainSummary *find(IdentifierInfo* II, Selector S) {
428
0
    // FIXME: Class method lookup.  Right now we don't have a good way
429
0
    // of going between IdentifierInfo* and the class hierarchy.
430
0
    MapTy::iterator I = M.find(ObjCSummaryKey(II, S));
431
0
432
0
    if (I == M.end())
433
0
      I = M.find(ObjCSummaryKey(S));
434
0
435
0
    return I == M.end() ? nullptr : I->second;
436
0
  }
437
438
1.75k
  const RetainSummary *& operator[](ObjCSummaryKey K) {
439
1.75k
    return M[K];
440
1.75k
  }
441
442
438
  const RetainSummary *& operator[](Selector S) {
443
438
    return M[ ObjCSummaryKey(S) ];
444
438
  }
445
};
446
447
class RetainSummaryTemplate;
448
449
class RetainSummaryManager {
450
  typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
451
          FuncSummariesTy;
452
453
  typedef ObjCSummaryCache ObjCMethodSummariesTy;
454
455
  typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;
456
457
  /// Ctx - The ASTContext object for the analyzed ASTs.
458
  ASTContext &Ctx;
459
460
  /// Records whether or not the analyzed code runs in ARC mode.
461
  const bool ARCEnabled;
462
463
  /// Track Objective-C and CoreFoundation objects.
464
  const bool TrackObjCAndCFObjects;
465
466
  /// Track sublcasses of OSObject.
467
  const bool TrackOSObjects;
468
469
  /// FuncSummaries - A map from FunctionDecls to summaries.
470
  FuncSummariesTy FuncSummaries;
471
472
  /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
473
  ///  to summaries.
474
  ObjCMethodSummariesTy ObjCClassMethodSummaries;
475
476
  /// ObjCMethodSummaries - A map from selectors to summaries.
477
  ObjCMethodSummariesTy ObjCMethodSummaries;
478
479
  /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
480
  ///  and all other data used by the checker.
481
  llvm::BumpPtrAllocator BPAlloc;
482
483
  /// AF - A factory for ArgEffects objects.
484
  ArgEffects::Factory AF;
485
486
  /// ObjCAllocRetE - Default return effect for methods returning Objective-C
487
  ///  objects.
488
  RetEffect ObjCAllocRetE;
489
490
  /// ObjCInitRetE - Default return effect for init methods returning
491
  ///   Objective-C objects.
492
  RetEffect ObjCInitRetE;
493
494
  /// SimpleSummaries - Used for uniquing summaries that don't have special
495
  /// effects.
496
  llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;
497
498
  /// Create an OS object at +1.
499
  const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);
500
501
  /// Get an OS object at +0.
502
  const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);
503
504
  /// Increment the reference count on OS object.
505
  const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);
506
507
  /// Decrement the reference count on OS object.
508
  const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);
509
510
  /// Free the OS object.
511
  const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);
512
513
  const RetainSummary *getUnarySummary(const FunctionType* FT,
514
                                       ArgEffectKind AE);
515
516
  const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
517
  const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
518
  const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);
519
520
  const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
521
522
  const RetainSummary *
523
  getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
524
                       ArgEffect ReceiverEff = ArgEffect(DoNothing),
525
                       ArgEffect DefaultEff = ArgEffect(MayEscape),
526
3.36k
                       ArgEffect ThisEff = ArgEffect(DoNothing)) {
527
3.36k
    RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
528
3.36k
    return getPersistentSummary(Summ);
529
3.36k
  }
530
531
8
  const RetainSummary *getDoNothingSummary() {
532
8
    return getPersistentSummary(RetEffect::MakeNoRet(),
533
8
                                ArgEffects(AF.getEmptyMap()),
534
8
                                ArgEffect(DoNothing), ArgEffect(DoNothing));
535
8
  }
536
537
1.48k
  const RetainSummary *getDefaultSummary() {
538
1.48k
    return getPersistentSummary(RetEffect::MakeNoRet(),
539
1.48k
                                ArgEffects(AF.getEmptyMap()),
540
1.48k
                                ArgEffect(DoNothing), ArgEffect(MayEscape));
541
1.48k
  }
542
543
106
  const RetainSummary *getPersistentStopSummary() {
544
106
    return getPersistentSummary(
545
106
        RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
546
106
        ArgEffect(StopTracking), ArgEffect(StopTracking));
547
106
  }
548
549
  void InitializeClassMethodSummaries();
550
  void InitializeMethodSummaries();
551
552
0
  void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
553
0
    ObjCClassMethodSummaries[S] = Summ;
554
0
  }
555
556
438
  void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
557
438
    ObjCMethodSummaries[S] = Summ;
558
438
  }
559
560
  void addClassMethSummary(const char* Cls, const char* name,
561
584
                           const RetainSummary *Summ, bool isNullary = true) {
562
584
    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
563
584
    Selector S = isNullary ? 
GetNullarySelector(name, Ctx)511
564
584
                           : 
GetUnarySelector(name, Ctx)73
;
565
584
    ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
566
584
  }
567
568
  void addInstMethSummary(const char* Cls, const char* nullaryName,
569
0
                          const RetainSummary *Summ) {
570
0
    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
571
0
    Selector S = GetNullarySelector(nullaryName, Ctx);
572
0
    ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
573
0
  }
574
575
  template <typename... Keywords>
576
  void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
577
365
                        const RetainSummary *Summ, Keywords *... Kws) {
578
365
    Selector S = getKeywordSelector(Ctx, Kws...);
579
365
    Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
580
365
  }
void clang::ento::RetainSummaryManager::addMethodSummary<char const>(clang::IdentifierInfo*, clang::ento::ObjCSummaryCache&, clang::ento::RetainSummary const*, char const*)
Line
Count
Source
577
146
                        const RetainSummary *Summ, Keywords *... Kws) {
578
146
    Selector S = getKeywordSelector(Ctx, Kws...);
579
146
    Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
580
146
  }
void clang::ento::RetainSummaryManager::addMethodSummary<char const, char const>(clang::IdentifierInfo*, clang::ento::ObjCSummaryCache&, clang::ento::RetainSummary const*, char const*, char const*)
Line
Count
Source
577
146
                        const RetainSummary *Summ, Keywords *... Kws) {
578
146
    Selector S = getKeywordSelector(Ctx, Kws...);
579
146
    Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
580
146
  }
void clang::ento::RetainSummaryManager::addMethodSummary<char const, char const, char const, char const>(clang::IdentifierInfo*, clang::ento::ObjCSummaryCache&, clang::ento::RetainSummary const*, char const*, char const*, char const*, char const*)
Line
Count
Source
577
73
                        const RetainSummary *Summ, Keywords *... Kws) {
578
73
    Selector S = getKeywordSelector(Ctx, Kws...);
579
73
    Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
580
73
  }
581
582
  template <typename... Keywords>
583
  void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
584
365
                          Keywords *... Kws) {
585
365
    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
586
365
  }
void clang::ento::RetainSummaryManager::addInstMethSummary<char const>(char const*, clang::ento::RetainSummary const*, char const*)
Line
Count
Source
584
146
                          Keywords *... Kws) {
585
146
    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
586
146
  }
void clang::ento::RetainSummaryManager::addInstMethSummary<char const, char const>(char const*, clang::ento::RetainSummary const*, char const*, char const*)
Line
Count
Source
584
146
                          Keywords *... Kws) {
585
146
    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
586
146
  }
void clang::ento::RetainSummaryManager::addInstMethSummary<char const, char const, char const, char const>(char const*, clang::ento::RetainSummary const*, char const*, char const*, char const*, char const*)
Line
Count
Source
584
73
                          Keywords *... Kws) {
585
73
    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
586
73
  }
587
588
  template <typename... Keywords>
589
  void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
590
                         Keywords *... Kws) {
591
    addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
592
                     Kws...);
593
  }
594
595
  template <typename... Keywords>
596
  void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
597
                         Keywords *... Kws) {
598
    addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
599
  }
600
601
  const RetainSummary * generateSummary(const FunctionDecl *FD,
602
                                        bool &AllowAnnotations);
603
604
  /// Return a summary for OSObject, or nullptr if not found.
605
  const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
606
                                             StringRef FName, QualType RetTy);
607
608
  /// Return a summary for Objective-C or CF object, or nullptr if not found.
609
  const RetainSummary *getSummaryForObjCOrCFObject(
610
    const FunctionDecl *FD,
611
    StringRef FName,
612
    QualType RetTy,
613
    const FunctionType *FT,
614
    bool &AllowAnnotations);
615
616
  /// Apply the annotation of {@code pd} in function {@code FD}
617
  /// to the resulting summary stored in out-parameter {@code Template}.
618
  /// \return whether an annotation was applied.
619
  bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx,
620
                                  const NamedDecl *FD,
621
                                  RetainSummaryTemplate &Template);
622
623
public:
624
  RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects,
625
                       bool trackOSObjects)
626
      : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount),
627
        TrackObjCAndCFObjects(trackObjCAndCFObjects),
628
        TrackOSObjects(trackOSObjects), AF(BPAlloc),
629
        ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
630
                                 : RetEffect::MakeOwned(ObjKind::ObjC)),
631
        ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
632
73
                                : RetEffect::MakeOwnedWhenTrackedReceiver()) {
633
73
    InitializeClassMethodSummaries();
634
73
    InitializeMethodSummaries();
635
73
  }
636
637
  enum class BehaviorSummary {
638
    // Function does not return.
639
    NoOp,
640
641
    // Function returns the first argument.
642
    Identity,
643
644
    // Function returns "this" argument.
645
    IdentityThis,
646
647
    // Function either returns zero, or the input parameter.
648
    IdentityOrZero
649
  };
650
651
  Optional<BehaviorSummary> canEval(const CallExpr *CE, const FunctionDecl *FD,
652
                                    bool &hasTrustedImplementationAnnotation);
653
654
  /// \return Whether the type corresponds to a known smart pointer
655
  /// implementation (that is, everything about it is inlineable).
656
  static bool isKnownSmartPointer(QualType QT);
657
658
  bool isTrustedReferenceCountImplementation(const Decl *FD);
659
660
  const RetainSummary *getSummary(AnyCall C,
661
                                  bool HasNonZeroCallbackArg=false,
662
                                  bool IsReceiverUnconsumedSelf=false,
663
                                  QualType ReceiverType={});
664
665
381
  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
666
667
private:
668
669
  /// getMethodSummary - This version of getMethodSummary is used to query
670
  ///  the summary for the current method being analyzed.
671
  const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD);
672
673
  const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
674
675
  const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
676
                                        const ObjCMethodDecl *MD,
677
                                        QualType RetTy,
678
                                        ObjCMethodSummariesTy &CachedSummaries);
679
680
  const RetainSummary *
681
  getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType);
682
683
  const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME);
684
685
  const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
686
                                                Selector S, QualType RetTy);
687
688
  /// Determine if there is a special return effect for this function or method.
689
  Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
690
                                                  const Decl *D);
691
692
  void updateSummaryFromAnnotations(const RetainSummary *&Summ,
693
                                    const ObjCMethodDecl *MD);
694
695
  void updateSummaryFromAnnotations(const RetainSummary *&Summ,
696
                                    const FunctionDecl *FD);
697
698
  const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
699
                                                          AnyCall &C);
700
701
  /// Special case '[super init];' and '[self init];'
702
  ///
703
  /// Even though calling '[super init]' without assigning the result to self
704
  /// and checking if the parent returns 'nil' is a bad pattern, it is common.
705
  /// Additionally, our Self Init checker already warns about it. To avoid
706
  /// overwhelming the user with messages from both checkers, we model the case
707
  /// of '[super init]' in cases when it is not consumed by another expression
708
  /// as if the call preserves the value of 'self'; essentially, assuming it can
709
  /// never fail and return 'nil'.
710
  /// Note, we don't want to just stop tracking the value since we want the
711
  /// RetainCount checker to report leaks and use-after-free if SelfInit checker
712
  /// is turned off.
713
  void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S);
714
715
  /// Set argument types for arguments which are not doing anything.
716
  void updateSummaryForArgumentTypes(const AnyCall &C, const RetainSummary *&RS);
717
718
  /// Determine whether a declaration {@code D} of correspondent type (return
719
  /// type for functions/methods) {@code QT} has any of the given attributes,
720
  /// provided they pass necessary validation checks AND tracking the given
721
  /// attribute is enabled.
722
  /// Returns the object kind corresponding to the present attribute, or None,
723
  /// if none of the specified attributes are present.
724
  /// Crashes if passed an attribute which is not explicitly handled.
725
  template <class T>
726
  Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
727
728
  template <class T1, class T2, class... Others>
729
  Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);
730
731
  friend class RetainSummaryTemplate;
732
};
733
734
735
// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
736
// summaries. If a function or method looks like it has a default summary, but
737
// it has annotations, the annotations are added to the stack-based template
738
// and then copied into managed memory.
739
class RetainSummaryTemplate {
740
  RetainSummaryManager &Manager;
741
  const RetainSummary *&RealSummary;
742
  RetainSummary ScratchSummary;
743
  bool Accessed;
744
public:
745
  RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
746
8.31k
    : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}
747
748
8.31k
  ~RetainSummaryTemplate() {
749
8.31k
    if (Accessed)
750
1.16k
      RealSummary = Manager.getPersistentSummary(ScratchSummary);
751
8.31k
  }
752
753
0
  RetainSummary &operator*() {
754
0
    Accessed = true;
755
0
    return ScratchSummary;
756
0
  }
757
758
1.44k
  RetainSummary *operator->() {
759
1.44k
    Accessed = true;
760
1.44k
    return &ScratchSummary;
761
1.44k
  }
762
};
763
764
} // end namespace ento
765
} // end namespace clang
766
767
#endif