Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

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