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