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