15774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- C++ -*--// 25774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// 35774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// The LLVM Compiler Infrastructure 45774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// 55774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// This file is distributed under the University of Illinois Open Source 65774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// License. See LICENSE.TXT for details. 75774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// 85774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek//===----------------------------------------------------------------------===// 95774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// 105774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// This file defines the core data structures for retain count "summaries" 115774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// for Objective-C and Core Foundation APIs. These summaries are used 125774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// by the static analyzer to summarize the retain/release effects of 135774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// function and method calls. This drives a path-sensitive typestate 145774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// analysis in the static analyzer, but can also potentially be used by 155774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// other clients. 165774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek// 175774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek//===----------------------------------------------------------------------===// 185774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 195774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek#ifndef LLVM_CLANG_OBJCRETAINCOUNT_H 205774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek#define LLVM_CLANG_OBJCRETAINCOUNT_H 215774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 225774e390199a572d10b22c78a80ed2cdde94304dTed Kremeneknamespace clang { namespace ento { namespace objc_retain { 235774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 245774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek/// An ArgEffect summarizes the retain count behavior on an argument or receiver 255774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek/// to a function or method. 265774e390199a572d10b22c78a80ed2cdde94304dTed Kremenekenum ArgEffect { 275774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// There is no effect. 285774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek DoNothing, 295774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 305774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument is treated as if an -autorelease message had been sent to 315774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// the referenced object. 325774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek Autorelease, 335774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 345774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument is treated as if an -dealloc message had been sent to 355774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// the referenced object. 365774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek Dealloc, 375774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 385774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument has its reference count decreased by 1. This is as 395774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// if CFRelease has been called on the argument. 405774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek DecRef, 415774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 425774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument has its reference count decreased by 1. This is as 435774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// if a -release message has been sent to the argument. This differs 445774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// in behavior from DecRef when GC is enabled. 455774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek DecRefMsg, 465774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 475774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument has its reference count decreased by 1 to model 485774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// a transferred bridge cast under ARC. 49063820655db8121f0022a7c51458463c7250324cBenjamin Kramer DecRefBridgedTransferred, 505774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 515774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument has its reference count increased by 1. This is as 525774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// if a -retain message has been sent to the argument. This differs 535774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// in behavior from IncRef when GC is enabled. 545774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek IncRefMsg, 555774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 565774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument has its reference count increased by 1. This is as 575774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// if CFRetain has been called on the argument. 585774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek IncRef, 595774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 605774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument acts as if has been passed to CFMakeCollectable, which 615774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// transfers the object to the Garbage Collector under GC. 625774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek MakeCollectable, 635774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 645774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The argument is treated as potentially escaping, meaning that 655774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// even when its reference count hits 0 it should be treated as still 665774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// possibly being alive as someone else *may* be holding onto the object. 675774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek MayEscape, 685774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 695774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// All typestate tracking of the object ceases. This is usually employed 705774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// when the effect of the call is completely unknown. 715774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek StopTracking, 725774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 735774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// All typestate tracking of the object ceases. Unlike StopTracking, 74c79ce4214cf4f81ae31146731ceb5d01cfcceb96Ted Kremenek /// this is also enforced when the method body is inlined. 755774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// 765774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// In some cases, we obtain a better summary for this checker 775774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// by looking at the call site than by inlining the function. 785774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Signifies that we should stop tracking the symbol even if 795774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// the function is inlined. 805774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek StopTrackingHard, 815774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 825774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Performs the combined functionality of DecRef and StopTrackingHard. 835774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// 845774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The models the effect that the called function decrements the reference 855774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// count of the argument and all typestate tracking on that argument 865774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// should cease. 875774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek DecRefAndStopTrackingHard, 885774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 895774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Performs the combined functionality of DecRefMsg and StopTrackingHard. 905774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// 915774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// The models the effect that the called function decrements the reference 925774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// count of the argument and all typestate tracking on that argument 935774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// should cease. 945774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek DecRefMsgAndStopTrackingHard 955774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek}; 965774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 975774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek/// RetEffect summarizes a call's retain/release behavior with respect 985774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek/// to its return value. 995774e390199a572d10b22c78a80ed2cdde94304dTed Kremenekclass RetEffect { 1005774e390199a572d10b22c78a80ed2cdde94304dTed Kremenekpublic: 1015774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek enum Kind { 1025774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that no retain count information is tracked for 1035774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// the return value. 1045774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek NoRet, 1055774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that the returned value is an owned (+1) symbol. 1065774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek OwnedSymbol, 1075774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that the returned value is an owned (+1) symbol and 1085774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// that it should be treated as freshly allocated. 1095774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek OwnedAllocatedSymbol, 1105774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that the returned value is an object with retain count 1115774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// semantics but that it is not owned (+0). This is the default 1125774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// for getters, etc. 1135774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek NotOwnedSymbol, 1145774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that the object is not owned and controlled by the 1155774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Garbage collector. 1165774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek GCNotOwnedSymbol, 1175774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that the return value is an owned object when the 1185774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// receiver is also a tracked object. 1195774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek OwnedWhenTrackedReceiver, 1205774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek // Treat this function as returning a non-tracked symbol even if 1215774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek // the function has been inlined. This is used where the call 1225774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek // site summary is more presise than the summary indirectly produced 1235774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek // by inlining the function 1245774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek NoRetHard 1255774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek }; 1265774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1275774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Determines the object kind of a tracked object. 1285774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek enum ObjKind { 1295774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that the tracked object is a CF object. This is 1305774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// important between GC and non-GC code. 1315774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek CF, 1325774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that the tracked object is an Objective-C object. 1335774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek ObjC, 1345774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek /// Indicates that the tracked object could be a CF or Objective-C object. 1355774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek AnyObj 1365774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek }; 1375774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1385774e390199a572d10b22c78a80ed2cdde94304dTed Kremenekprivate: 1395774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek Kind K; 1405774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek ObjKind O; 1415774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1425774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {} 1435774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1445774e390199a572d10b22c78a80ed2cdde94304dTed Kremenekpublic: 1455774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek Kind getKind() const { return K; } 1465774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1475774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek ObjKind getObjKind() const { return O; } 1485774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1495774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek bool isOwned() const { 1505774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek return K == OwnedSymbol || K == OwnedAllocatedSymbol || 1515774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek K == OwnedWhenTrackedReceiver; 1525774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek } 1535774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1545f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian bool notOwned() const { 155651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return K == NotOwnedSymbol; 1565f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian } 1575f7ac67c84e7b9a04fa4c5065e384f928c8f812fFariborz Jahanian 1585774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek bool operator==(const RetEffect &Other) const { 1595774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek return K == Other.K && O == Other.O; 1605774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek } 1615774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1625774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek static RetEffect MakeOwnedWhenTrackedReceiver() { 1635774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek return RetEffect(OwnedWhenTrackedReceiver, ObjC); 1645774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek } 1655774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 1665774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) { 1675774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o); 1685774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek } 1695774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek static RetEffect MakeNotOwned(ObjKind o) { 1705774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek return RetEffect(NotOwnedSymbol, o); 1715774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek } 1725774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek static RetEffect MakeGCNotOwned() { 1735774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek return RetEffect(GCNotOwnedSymbol, ObjC); 1745774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek } 1755774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek static RetEffect MakeNoRet() { 1765774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek return RetEffect(NoRet); 1775774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek } 1785774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek static RetEffect MakeNoRetHard() { 1795774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek return RetEffect(NoRetHard); 1805774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek } 1815774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek}; 18253c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek 18353c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek/// Encapsulates the retain count semantics on the arguments, return value, 18453c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek/// and receiver (if any) of a function/method call. 18553c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek/// 18653c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek/// Note that construction of these objects is not highly efficient. That 18753c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek/// is okay for clients where creating these objects isn't really a bottleneck. 18853c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek/// The purpose of the API is to provide something simple. The actual 18953c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek/// static analyzer checker that implements retain/release typestate 19053c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek/// tracking uses something more efficient. 19153c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenekclass CallEffects { 19253c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek llvm::SmallVector<ArgEffect, 10> Args; 19353c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek RetEffect Ret; 19453c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek ArgEffect Receiver; 19553c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek 19653c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek CallEffects(const RetEffect &R) : Ret(R) {} 19753c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek 19853c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenekpublic: 19953c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek /// Returns the argument effects for a call. 200ef8225444452a1486bd721f3285301fe84643b00Stephen Hines ArrayRef<ArgEffect> getArgs() const { return Args; } 20153c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek 20253c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek /// Returns the effects on the receiver. 20353c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek ArgEffect getReceiver() const { return Receiver; } 20453c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek 20553c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek /// Returns the effect on the return value. 20653c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek RetEffect getReturnValue() const { return Ret; } 20753c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek 20853c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek /// Return the CallEfect for a given Objective-C method. 20953c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek static CallEffects getEffect(const ObjCMethodDecl *MD); 21053c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek 21153c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek /// Return the CallEfect for a given C/C++ function. 21253c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek static CallEffects getEffect(const FunctionDecl *FD); 21353c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek}; 21453c7ea1517fc9080b30b054c578cb407de12d5b5Ted Kremenek 2155774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek}}} 2165774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 2175774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek#endif 2185774e390199a572d10b22c78a80ed2cdde94304dTed Kremenek 219