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_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 treated as potentially escaping, meaning that
     73   /// even when its reference count hits 0 it should be treated as still
     74   /// possibly being alive as someone else *may* be holding onto the object.
     75   MayEscape,
     76 
     77   /// All typestate tracking of the object ceases.  This is usually employed
     78   /// when the effect of the call is completely unknown.
     79   StopTracking,
     80 
     81   /// All typestate tracking of the object ceases.  Unlike StopTracking,
     82   /// this is also enforced when the method body is inlined.
     83   ///
     84   /// In some cases, we obtain a better summary for this checker
     85   /// by looking at the call site than by inlining the function.
     86   /// Signifies that we should stop tracking the symbol even if
     87   /// the function is inlined.
     88   StopTrackingHard,
     89 
     90   /// Performs the combined functionality of DecRef and StopTrackingHard.
     91   ///
     92   /// The models the effect that the called function decrements the reference
     93   /// count of the argument and all typestate tracking on that argument
     94   /// should cease.
     95   DecRefAndStopTrackingHard,
     96 
     97   /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
     98   ///
     99   /// The models the effect that the called function decrements the reference
    100   /// count of the argument and all typestate tracking on that argument
    101   /// should cease.
    102   DecRefMsgAndStopTrackingHard
    103 };
    104 
    105 /// RetEffect summarizes a call's retain/release behavior with respect
    106 /// to its return value.
    107 class RetEffect {
    108 public:
    109   enum Kind {
    110     /// Indicates that no retain count information is tracked for
    111     /// the return value.
    112     NoRet,
    113     /// Indicates that the returned value is an owned (+1) symbol.
    114     OwnedSymbol,
    115     /// Indicates that the returned value is an owned (+1) symbol and
    116     /// that it should be treated as freshly allocated.
    117     OwnedAllocatedSymbol,
    118     /// Indicates that the returned value is an object with retain count
    119     /// semantics but that it is not owned (+0).  This is the default
    120     /// for getters, etc.
    121     NotOwnedSymbol,
    122     /// Indicates that the object is not owned and controlled by the
    123     /// Garbage collector.
    124     GCNotOwnedSymbol,
    125     /// Indicates that the return value is an owned object when the
    126     /// receiver is also a tracked object.
    127     OwnedWhenTrackedReceiver,
    128     // Treat this function as returning a non-tracked symbol even if
    129     // the function has been inlined. This is used where the call
    130     // site summary is more presise than the summary indirectly produced
    131     // by inlining the function
    132     NoRetHard
    133   };
    134 
    135   /// Determines the object kind of a tracked object.
    136   enum ObjKind {
    137     /// Indicates that the tracked object is a CF object.  This is
    138     /// important between GC and non-GC code.
    139     CF,
    140     /// Indicates that the tracked object is an Objective-C object.
    141     ObjC,
    142     /// Indicates that the tracked object could be a CF or Objective-C object.
    143     AnyObj
    144   };
    145 
    146 private:
    147   Kind K;
    148   ObjKind O;
    149 
    150   RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
    151 
    152 public:
    153   Kind getKind() const { return K; }
    154 
    155   ObjKind getObjKind() const { return O; }
    156 
    157   bool isOwned() const {
    158     return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
    159     K == OwnedWhenTrackedReceiver;
    160   }
    161 
    162   bool notOwned() const {
    163     return K == NotOwnedSymbol;
    164   }
    165 
    166   bool operator==(const RetEffect &Other) const {
    167     return K == Other.K && O == Other.O;
    168   }
    169 
    170   static RetEffect MakeOwnedWhenTrackedReceiver() {
    171     return RetEffect(OwnedWhenTrackedReceiver, ObjC);
    172   }
    173 
    174   static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
    175     return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
    176   }
    177   static RetEffect MakeNotOwned(ObjKind o) {
    178     return RetEffect(NotOwnedSymbol, o);
    179   }
    180   static RetEffect MakeGCNotOwned() {
    181     return RetEffect(GCNotOwnedSymbol, ObjC);
    182   }
    183   static RetEffect MakeNoRet() {
    184     return RetEffect(NoRet);
    185   }
    186   static RetEffect MakeNoRetHard() {
    187     return RetEffect(NoRetHard);
    188   }
    189 };
    190 
    191 /// Encapsulates the retain count semantics on the arguments, return value,
    192 /// and receiver (if any) of a function/method call.
    193 ///
    194 /// Note that construction of these objects is not highly efficient.  That
    195 /// is okay for clients where creating these objects isn't really a bottleneck.
    196 /// The purpose of the API is to provide something simple.  The actual
    197 /// static analyzer checker that implements retain/release typestate
    198 /// tracking uses something more efficient.
    199 class CallEffects {
    200   llvm::SmallVector<ArgEffect, 10> Args;
    201   RetEffect Ret;
    202   ArgEffect Receiver;
    203 
    204   CallEffects(const RetEffect &R) : Ret(R) {}
    205 
    206 public:
    207   /// Returns the argument effects for a call.
    208   ArrayRef<ArgEffect> getArgs() const { return Args; }
    209 
    210   /// Returns the effects on the receiver.
    211   ArgEffect getReceiver() const { return Receiver; }
    212 
    213   /// Returns the effect on the return value.
    214   RetEffect getReturnValue() const { return Ret; }
    215 
    216   /// Return the CallEfect for a given Objective-C method.
    217   static CallEffects getEffect(const ObjCMethodDecl *MD);
    218 
    219   /// Return the CallEfect for a given C/C++ function.
    220   static CallEffects getEffect(const FunctionDecl *FD);
    221 };
    222 
    223 }}}
    224 
    225 #endif
    226 
    227