Home | History | Annotate | Download | only in Checkers
      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 
    142   RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
    143 
    144 public:
    145   Kind getKind() const { return K; }
    146 
    147   ObjKind getObjKind() const { return O; }
    148 
    149   bool isOwned() const {
    150     return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
    151     K == OwnedWhenTrackedReceiver;
    152   }
    153 
    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 
    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   }
    169   static RetEffect MakeNotOwned(ObjKind o) {
    170     return RetEffect(NotOwnedSymbol, o);
    171   }
    172   static RetEffect MakeGCNotOwned() {
    173     return RetEffect(GCNotOwnedSymbol, ObjC);
    174   }
    175   static RetEffect MakeNoRet() {
    176     return RetEffect(NoRet);
    177   }
    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 
    196   CallEffects(const RetEffect &R) : Ret(R) {}
    197 
    198 public:
    199   /// Returns the argument effects for a call.
    200   ArrayRef<ArgEffect> getArgs() const { return Args; }
    201 
    202   /// Returns the effects on the receiver.
    203   ArgEffect getReceiver() const { return Receiver; }
    204 
    205   /// Returns the effect on the return value.
    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