• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  //==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- C++ -*--//
2  //
3  //                     The LLVM Compiler Infrastructure
4  //
5  // This file is distributed under the University of Illinois Open Source
6  // License. See LICENSE.TXT for details.
7  //
8  //===----------------------------------------------------------------------===//
9  //
10  //  This file defines the core data structures for retain count "summaries"
11  //  for Objective-C and Core Foundation APIs.  These summaries are used
12  //  by the static analyzer to summarize the retain/release effects of
13  //  function and method calls.  This drives a path-sensitive typestate
14  //  analysis in the static analyzer, but can also potentially be used by
15  //  other clients.
16  //
17  //===----------------------------------------------------------------------===//
18  
19  #ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
20  #define LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
21  
22  #include "clang/Basic/LLVM.h"
23  #include "llvm/ADT/ArrayRef.h"
24  #include "llvm/ADT/SmallVector.h"
25  
26  namespace clang {
27  class FunctionDecl;
28  class ObjCMethodDecl;
29  
30  namespace ento { namespace objc_retain {
31  
32  /// An ArgEffect summarizes the retain count behavior on an argument or receiver
33  /// to a function or method.
34  enum ArgEffect {
35    /// There is no effect.
36    DoNothing,
37  
38    /// The argument is treated as if an -autorelease message had been sent to
39    /// the referenced object.
40    Autorelease,
41  
42    /// The argument is treated as if an -dealloc message had been sent to
43    /// the referenced object.
44    Dealloc,
45  
46    /// The argument has its reference count decreased by 1.  This is as
47    /// if CFRelease has been called on the argument.
48    DecRef,
49  
50    /// The argument has its reference count decreased by 1.  This is as
51    /// if a -release message has been sent to the argument.  This differs
52    /// in behavior from DecRef when GC is enabled.
53    DecRefMsg,
54  
55    /// The argument has its reference count decreased by 1 to model
56    /// a transferred bridge cast under ARC.
57    DecRefBridgedTransferred,
58  
59    /// The argument has its reference count increased by 1.  This is as
60    /// if a -retain message has been sent to the argument.  This differs
61    /// in behavior from IncRef when GC is enabled.
62    IncRefMsg,
63  
64    /// The argument has its reference count increased by 1.  This is as
65    /// if CFRetain has been called on the argument.
66    IncRef,
67  
68    /// The argument acts as if has been passed to CFMakeCollectable, which
69    /// transfers the object to the Garbage Collector under GC.
70    MakeCollectable,
71  
72    /// The argument is a pointer to a retain-counted object; on exit, the new
73    /// value of the pointer is a +0 value or NULL.
74    UnretainedOutParameter,
75  
76    /// The argument is a pointer to a retain-counted object; on exit, the new
77    /// value of the pointer is a +1 value or NULL.
78    RetainedOutParameter,
79  
80    /// The argument is treated as potentially escaping, meaning that
81    /// even when its reference count hits 0 it should be treated as still
82    /// possibly being alive as someone else *may* be holding onto the object.
83    MayEscape,
84  
85    /// All typestate tracking of the object ceases.  This is usually employed
86    /// when the effect of the call is completely unknown.
87    StopTracking,
88  
89    /// All typestate tracking of the object ceases.  Unlike StopTracking,
90    /// this is also enforced when the method body is inlined.
91    ///
92    /// In some cases, we obtain a better summary for this checker
93    /// by looking at the call site than by inlining the function.
94    /// Signifies that we should stop tracking the symbol even if
95    /// the function is inlined.
96    StopTrackingHard,
97  
98    /// Performs the combined functionality of DecRef and StopTrackingHard.
99    ///
100    /// The models the effect that the called function decrements the reference
101    /// count of the argument and all typestate tracking on that argument
102    /// should cease.
103    DecRefAndStopTrackingHard,
104  
105    /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
106    ///
107    /// The models the effect that the called function decrements the reference
108    /// count of the argument and all typestate tracking on that argument
109    /// should cease.
110    DecRefMsgAndStopTrackingHard
111  };
112  
113  /// RetEffect summarizes a call's retain/release behavior with respect
114  /// to its return value.
115  class RetEffect {
116  public:
117    enum Kind {
118      /// Indicates that no retain count information is tracked for
119      /// the return value.
120      NoRet,
121      /// Indicates that the returned value is an owned (+1) symbol.
122      OwnedSymbol,
123      /// Indicates that the returned value is an owned (+1) symbol and
124      /// that it should be treated as freshly allocated.
125      OwnedAllocatedSymbol,
126      /// Indicates that the returned value is an object with retain count
127      /// semantics but that it is not owned (+0).  This is the default
128      /// for getters, etc.
129      NotOwnedSymbol,
130      /// Indicates that the object is not owned and controlled by the
131      /// Garbage collector.
132      GCNotOwnedSymbol,
133      /// Indicates that the return value is an owned object when the
134      /// receiver is also a tracked object.
135      OwnedWhenTrackedReceiver,
136      // Treat this function as returning a non-tracked symbol even if
137      // the function has been inlined. This is used where the call
138      // site summary is more presise than the summary indirectly produced
139      // by inlining the function
140      NoRetHard
141    };
142  
143    /// Determines the object kind of a tracked object.
144    enum ObjKind {
145      /// Indicates that the tracked object is a CF object.  This is
146      /// important between GC and non-GC code.
147      CF,
148      /// Indicates that the tracked object is an Objective-C object.
149      ObjC,
150      /// Indicates that the tracked object could be a CF or Objective-C object.
151      AnyObj
152    };
153  
154  private:
155    Kind K;
156    ObjKind O;
157  
K(k)158    RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
159  
160  public:
getKind()161    Kind getKind() const { return K; }
162  
getObjKind()163    ObjKind getObjKind() const { return O; }
164  
isOwned()165    bool isOwned() const {
166      return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
167      K == OwnedWhenTrackedReceiver;
168    }
169  
notOwned()170    bool notOwned() const {
171      return K == NotOwnedSymbol;
172    }
173  
174    bool operator==(const RetEffect &Other) const {
175      return K == Other.K && O == Other.O;
176    }
177  
MakeOwnedWhenTrackedReceiver()178    static RetEffect MakeOwnedWhenTrackedReceiver() {
179      return RetEffect(OwnedWhenTrackedReceiver, ObjC);
180    }
181  
182    static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
183      return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
184    }
MakeNotOwned(ObjKind o)185    static RetEffect MakeNotOwned(ObjKind o) {
186      return RetEffect(NotOwnedSymbol, o);
187    }
MakeGCNotOwned()188    static RetEffect MakeGCNotOwned() {
189      return RetEffect(GCNotOwnedSymbol, ObjC);
190    }
MakeNoRet()191    static RetEffect MakeNoRet() {
192      return RetEffect(NoRet);
193    }
MakeNoRetHard()194    static RetEffect MakeNoRetHard() {
195      return RetEffect(NoRetHard);
196    }
197  };
198  
199  /// Encapsulates the retain count semantics on the arguments, return value,
200  /// and receiver (if any) of a function/method call.
201  ///
202  /// Note that construction of these objects is not highly efficient.  That
203  /// is okay for clients where creating these objects isn't really a bottleneck.
204  /// The purpose of the API is to provide something simple.  The actual
205  /// static analyzer checker that implements retain/release typestate
206  /// tracking uses something more efficient.
207  class CallEffects {
208    llvm::SmallVector<ArgEffect, 10> Args;
209    RetEffect Ret;
210    ArgEffect Receiver;
211  
CallEffects(const RetEffect & R)212    CallEffects(const RetEffect &R) : Ret(R) {}
213  
214  public:
215    /// Returns the argument effects for a call.
getArgs()216    ArrayRef<ArgEffect> getArgs() const { return Args; }
217  
218    /// Returns the effects on the receiver.
getReceiver()219    ArgEffect getReceiver() const { return Receiver; }
220  
221    /// Returns the effect on the return value.
getReturnValue()222    RetEffect getReturnValue() const { return Ret; }
223  
224    /// Return the CallEfect for a given Objective-C method.
225    static CallEffects getEffect(const ObjCMethodDecl *MD);
226  
227    /// Return the CallEfect for a given C/C++ function.
228    static CallEffects getEffect(const FunctionDecl *FD);
229  };
230  
231  }}}
232  
233  #endif
234  
235