//===- IvarInvalidationChecker.cpp ------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This checker implements annotation driven invalidation checking. If a class
//  contains a method annotated with 'objc_instance_variable_invalidator',
//  - (void) foo
//           __attribute__((annotate("objc_instance_variable_invalidator")));
//  all the "ivalidatable" instance variables of this class should be
//  invalidated. We call an instance variable ivalidatable if it is an object of
//  a class which contains an invalidation method. There could be multiple
//  methods annotated with such annotations per class, either one can be used
//  to invalidate the ivar. An ivar or property are considered to be
//  invalidated if they are being assigned 'nil' or an invalidation method has
//  been called on them. An invalidation method should either invalidate all
//  the ivars or call another invalidation method (on self).
//
//  Partial invalidor annotation allows to addess cases when ivars are
//  invalidated by other methods, which might or might not be called from
//  the invalidation method. The checker checks that each invalidation
//  method and all the partial methods cumulatively invalidate all ivars.
//    __attribute__((annotate("objc_instance_variable_invalidator_partial")));
//
//===----------------------------------------------------------------------===//

#include "ClangSACheckers.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallString.h"

using namespace clang;
using namespace ento;

namespace {
struct ChecksFilter {
  /// Check for missing invalidation method declarations.
  DefaultBool check_MissingInvalidationMethod;
  /// Check that all ivars are invalidated.
  DefaultBool check_InstanceVariableInvalidation;

  CheckName checkName_MissingInvalidationMethod;
  CheckName checkName_InstanceVariableInvalidation;
};

class IvarInvalidationCheckerImpl {
  typedef llvm::SmallSetVector<const ObjCMethodDecl*, 2> MethodSet;
  typedef llvm::DenseMap<const ObjCMethodDecl*,
                         const ObjCIvarDecl*> MethToIvarMapTy;
  typedef llvm::DenseMap<const ObjCPropertyDecl*,
                         const ObjCIvarDecl*> PropToIvarMapTy;
  typedef llvm::DenseMap<const ObjCIvarDecl*,
                         const ObjCPropertyDecl*> IvarToPropMapTy;

  struct InvalidationInfo {
    /// Has the ivar been invalidated?
    bool IsInvalidated;

    /// The methods which can be used to invalidate the ivar.
    MethodSet InvalidationMethods;

    InvalidationInfo() : IsInvalidated(false) {}
    void addInvalidationMethod(const ObjCMethodDecl *MD) {
      InvalidationMethods.insert(MD);
    }

    bool needsInvalidation() const {
      return !InvalidationMethods.empty();
    }

    bool hasMethod(const ObjCMethodDecl *MD) {
      if (IsInvalidated)
        return true;
      for (MethodSet::iterator I = InvalidationMethods.begin(),
          E = InvalidationMethods.end(); I != E; ++I) {
        if (*I == MD) {
          IsInvalidated = true;
          return true;
        }
      }
      return false;
    }
  };

  typedef llvm::DenseMap<const ObjCIvarDecl*, InvalidationInfo> IvarSet;

  /// Statement visitor, which walks the method body and flags the ivars
  /// referenced in it (either directly or via property).
  class MethodCrawler : public ConstStmtVisitor<MethodCrawler> {
    /// The set of Ivars which need to be invalidated.
    IvarSet &IVars;

    /// Flag is set as the result of a message send to another
    /// invalidation method.
    bool &CalledAnotherInvalidationMethod;

    /// Property setter to ivar mapping.
    const MethToIvarMapTy &PropertySetterToIvarMap;

    /// Property getter to ivar mapping.
    const MethToIvarMapTy &PropertyGetterToIvarMap;

    /// Property to ivar mapping.
    const PropToIvarMapTy &PropertyToIvarMap;

    /// The invalidation method being currently processed.
    const ObjCMethodDecl *InvalidationMethod;

    ASTContext &Ctx;

    /// Peel off parens, casts, OpaqueValueExpr, and PseudoObjectExpr.
    const Expr *peel(const Expr *E) const;

    /// Does this expression represent zero: '0'?
    bool isZero(const Expr *E) const;

    /// Mark the given ivar as invalidated.
    void markInvalidated(const ObjCIvarDecl *Iv);

    /// Checks if IvarRef refers to the tracked IVar, if yes, marks it as
    /// invalidated.
    void checkObjCIvarRefExpr(const ObjCIvarRefExpr *IvarRef);

    /// Checks if ObjCPropertyRefExpr refers to the tracked IVar, if yes, marks
    /// it as invalidated.
    void checkObjCPropertyRefExpr(const ObjCPropertyRefExpr *PA);

    /// Checks if ObjCMessageExpr refers to (is a getter for) the tracked IVar,
    /// if yes, marks it as invalidated.
    void checkObjCMessageExpr(const ObjCMessageExpr *ME);

    /// Checks if the Expr refers to an ivar, if yes, marks it as invalidated.
    void check(const Expr *E);

  public:
    MethodCrawler(IvarSet &InIVars,
                  bool &InCalledAnotherInvalidationMethod,
                  const MethToIvarMapTy &InPropertySetterToIvarMap,
                  const MethToIvarMapTy &InPropertyGetterToIvarMap,
                  const PropToIvarMapTy &InPropertyToIvarMap,
                  ASTContext &InCtx)
    : IVars(InIVars),
      CalledAnotherInvalidationMethod(InCalledAnotherInvalidationMethod),
      PropertySetterToIvarMap(InPropertySetterToIvarMap),
      PropertyGetterToIvarMap(InPropertyGetterToIvarMap),
      PropertyToIvarMap(InPropertyToIvarMap),
      InvalidationMethod(nullptr),
      Ctx(InCtx) {}

    void VisitStmt(const Stmt *S) { VisitChildren(S); }

    void VisitBinaryOperator(const BinaryOperator *BO);

    void VisitObjCMessageExpr(const ObjCMessageExpr *ME);

    void VisitChildren(const Stmt *S) {
      for (const auto *Child : S->children()) {
        if (Child)
          this->Visit(Child);
        if (CalledAnotherInvalidationMethod)
          return;
      }
    }
  };

  /// Check if the any of the methods inside the interface are annotated with
  /// the invalidation annotation, update the IvarInfo accordingly.
  /// \param LookForPartial is set when we are searching for partial
  ///        invalidators.
  static void containsInvalidationMethod(const ObjCContainerDecl *D,
                                         InvalidationInfo &Out,
                                         bool LookForPartial);

  /// Check if ivar should be tracked and add to TrackedIvars if positive.
  /// Returns true if ivar should be tracked.
  static bool trackIvar(const ObjCIvarDecl *Iv, IvarSet &TrackedIvars,
                        const ObjCIvarDecl **FirstIvarDecl);

  /// Given the property declaration, and the list of tracked ivars, finds
  /// the ivar backing the property when possible. Returns '0' when no such
  /// ivar could be found.
  static const ObjCIvarDecl *findPropertyBackingIvar(
      const ObjCPropertyDecl *Prop,
      const ObjCInterfaceDecl *InterfaceD,
      IvarSet &TrackedIvars,
      const ObjCIvarDecl **FirstIvarDecl);

  /// Print ivar name or the property if the given ivar backs a property.
  static void printIvar(llvm::raw_svector_ostream &os,
                        const ObjCIvarDecl *IvarDecl,
                        const IvarToPropMapTy &IvarToPopertyMap);

  void reportNoInvalidationMethod(CheckName CheckName,
                                  const ObjCIvarDecl *FirstIvarDecl,
                                  const IvarToPropMapTy &IvarToPopertyMap,
                                  const ObjCInterfaceDecl *InterfaceD,
                                  bool MissingDeclaration) const;

  void reportIvarNeedsInvalidation(const ObjCIvarDecl *IvarD,
                                   const IvarToPropMapTy &IvarToPopertyMap,
                                   const ObjCMethodDecl *MethodD) const;

  AnalysisManager& Mgr;
  BugReporter &BR;
  /// Filter on the checks performed.
  const ChecksFilter &Filter;

public:
  IvarInvalidationCheckerImpl(AnalysisManager& InMgr,
                              BugReporter &InBR,
                              const ChecksFilter &InFilter) :
    Mgr (InMgr), BR(InBR), Filter(InFilter) {}

  void visit(const ObjCImplementationDecl *D) const;
};

static bool isInvalidationMethod(const ObjCMethodDecl *M, bool LookForPartial) {
  for (const auto *Ann : M->specific_attrs<AnnotateAttr>()) {
    if (!LookForPartial &&
        Ann->getAnnotation() == "objc_instance_variable_invalidator")
      return true;
    if (LookForPartial &&
        Ann->getAnnotation() == "objc_instance_variable_invalidator_partial")
      return true;
  }
  return false;
}

void IvarInvalidationCheckerImpl::containsInvalidationMethod(
    const ObjCContainerDecl *D, InvalidationInfo &OutInfo, bool Partial) {

  if (!D)
    return;

  assert(!isa<ObjCImplementationDecl>(D));
  // TODO: Cache the results.

  // Check all methods.
  for (const auto *MDI : D->methods())
    if (isInvalidationMethod(MDI, Partial))
      OutInfo.addInvalidationMethod(
          cast<ObjCMethodDecl>(MDI->getCanonicalDecl()));

  // If interface, check all parent protocols and super.
  if (const ObjCInterfaceDecl *InterfD = dyn_cast<ObjCInterfaceDecl>(D)) {

    // Visit all protocols.
    for (const auto *I : InterfD->protocols())
      containsInvalidationMethod(I->getDefinition(), OutInfo, Partial);

    // Visit all categories in case the invalidation method is declared in
    // a category.
    for (const auto *Ext : InterfD->visible_extensions())
      containsInvalidationMethod(Ext, OutInfo, Partial);

    containsInvalidationMethod(InterfD->getSuperClass(), OutInfo, Partial);
    return;
  }

  // If protocol, check all parent protocols.
  if (const ObjCProtocolDecl *ProtD = dyn_cast<ObjCProtocolDecl>(D)) {
    for (const auto *I : ProtD->protocols()) {
      containsInvalidationMethod(I->getDefinition(), OutInfo, Partial);
    }
    return;
  }
}

bool IvarInvalidationCheckerImpl::trackIvar(const ObjCIvarDecl *Iv,
                                        IvarSet &TrackedIvars,
                                        const ObjCIvarDecl **FirstIvarDecl) {
  QualType IvQTy = Iv->getType();
  const ObjCObjectPointerType *IvTy = IvQTy->getAs<ObjCObjectPointerType>();
  if (!IvTy)
    return false;
  const ObjCInterfaceDecl *IvInterf = IvTy->getInterfaceDecl();

  InvalidationInfo Info;
  containsInvalidationMethod(IvInterf, Info, /*LookForPartial*/ false);
  if (Info.needsInvalidation()) {
    const ObjCIvarDecl *I = cast<ObjCIvarDecl>(Iv->getCanonicalDecl());
    TrackedIvars[I] = Info;
    if (!*FirstIvarDecl)
      *FirstIvarDecl = I;
    return true;
  }
  return false;
}

const ObjCIvarDecl *IvarInvalidationCheckerImpl::findPropertyBackingIvar(
                        const ObjCPropertyDecl *Prop,
                        const ObjCInterfaceDecl *InterfaceD,
                        IvarSet &TrackedIvars,
                        const ObjCIvarDecl **FirstIvarDecl) {
  const ObjCIvarDecl *IvarD = nullptr;

  // Lookup for the synthesized case.
  IvarD = Prop->getPropertyIvarDecl();
  // We only track the ivars/properties that are defined in the current
  // class (not the parent).
  if (IvarD && IvarD->getContainingInterface() == InterfaceD) {
    if (TrackedIvars.count(IvarD)) {
      return IvarD;
    }
    // If the ivar is synthesized we still want to track it.
    if (trackIvar(IvarD, TrackedIvars, FirstIvarDecl))
      return IvarD;
  }

  // Lookup IVars named "_PropName"or "PropName" among the tracked Ivars.
  StringRef PropName = Prop->getIdentifier()->getName();
  for (IvarSet::const_iterator I = TrackedIvars.begin(),
                               E = TrackedIvars.end(); I != E; ++I) {
    const ObjCIvarDecl *Iv = I->first;
    StringRef IvarName = Iv->getName();

    if (IvarName == PropName)
      return Iv;

    SmallString<128> PropNameWithUnderscore;
    {
      llvm::raw_svector_ostream os(PropNameWithUnderscore);
      os << '_' << PropName;
    }
    if (IvarName == PropNameWithUnderscore)
      return Iv;
  }

  // Note, this is a possible source of false positives. We could look at the
  // getter implementation to find the ivar when its name is not derived from
  // the property name.
  return nullptr;
}

void IvarInvalidationCheckerImpl::printIvar(llvm::raw_svector_ostream &os,
                                      const ObjCIvarDecl *IvarDecl,
                                      const IvarToPropMapTy &IvarToPopertyMap) {
  if (IvarDecl->getSynthesize()) {
    const ObjCPropertyDecl *PD = IvarToPopertyMap.lookup(IvarDecl);
    assert(PD &&"Do we synthesize ivars for something other than properties?");
    os << "Property "<< PD->getName() << " ";
  } else {
    os << "Instance variable "<< IvarDecl->getName() << " ";
  }
}

// Check that the invalidatable interfaces with ivars/properties implement the
// invalidation methods.
void IvarInvalidationCheckerImpl::
visit(const ObjCImplementationDecl *ImplD) const {
  // Collect all ivars that need cleanup.
  IvarSet Ivars;
  // Record the first Ivar needing invalidation; used in reporting when only
  // one ivar is sufficient. Cannot grab the first on the Ivars set to ensure
  // deterministic output.
  const ObjCIvarDecl *FirstIvarDecl = nullptr;
  const ObjCInterfaceDecl *InterfaceD = ImplD->getClassInterface();

  // Collect ivars declared in this class, its extensions and its implementation
  ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(InterfaceD);
  for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv;
       Iv= Iv->getNextIvar())
    trackIvar(Iv, Ivars, &FirstIvarDecl);

  // Construct Property/Property Accessor to Ivar maps to assist checking if an
  // ivar which is backing a property has been reset.
  MethToIvarMapTy PropSetterToIvarMap;
  MethToIvarMapTy PropGetterToIvarMap;
  PropToIvarMapTy PropertyToIvarMap;
  IvarToPropMapTy IvarToPopertyMap;

  ObjCInterfaceDecl::PropertyMap PropMap;
  ObjCInterfaceDecl::PropertyDeclOrder PropOrder;
  InterfaceD->collectPropertiesToImplement(PropMap, PropOrder);

  for (ObjCInterfaceDecl::PropertyMap::iterator
      I = PropMap.begin(), E = PropMap.end(); I != E; ++I) {
    const ObjCPropertyDecl *PD = I->second;
    if (PD->isClassProperty())
      continue;

    const ObjCIvarDecl *ID = findPropertyBackingIvar(PD, InterfaceD, Ivars,
                                                     &FirstIvarDecl);
    if (!ID)
      continue;

    // Store the mappings.
    PD = cast<ObjCPropertyDecl>(PD->getCanonicalDecl());
    PropertyToIvarMap[PD] = ID;
    IvarToPopertyMap[ID] = PD;

    // Find the setter and the getter.
    const ObjCMethodDecl *SetterD = PD->getSetterMethodDecl();
    if (SetterD) {
      SetterD = cast<ObjCMethodDecl>(SetterD->getCanonicalDecl());
      PropSetterToIvarMap[SetterD] = ID;
    }

    const ObjCMethodDecl *GetterD = PD->getGetterMethodDecl();
    if (GetterD) {
      GetterD = cast<ObjCMethodDecl>(GetterD->getCanonicalDecl());
      PropGetterToIvarMap[GetterD] = ID;
    }
  }

  // If no ivars need invalidation, there is nothing to check here.
  if (Ivars.empty())
    return;

  // Find all partial invalidation methods.
  InvalidationInfo PartialInfo;
  containsInvalidationMethod(InterfaceD, PartialInfo, /*LookForPartial*/ true);

  // Remove ivars invalidated by the partial invalidation methods. They do not
  // need to be invalidated in the regular invalidation methods.
  bool AtImplementationContainsAtLeastOnePartialInvalidationMethod = false;
  for (MethodSet::iterator
      I = PartialInfo.InvalidationMethods.begin(),
      E = PartialInfo.InvalidationMethods.end(); I != E; ++I) {
    const ObjCMethodDecl *InterfD = *I;

    // Get the corresponding method in the @implementation.
    const ObjCMethodDecl *D = ImplD->getMethod(InterfD->getSelector(),
                                               InterfD->isInstanceMethod());
    if (D && D->hasBody()) {
      AtImplementationContainsAtLeastOnePartialInvalidationMethod = true;

      bool CalledAnotherInvalidationMethod = false;
      // The MethodCrowler is going to remove the invalidated ivars.
      MethodCrawler(Ivars,
                    CalledAnotherInvalidationMethod,
                    PropSetterToIvarMap,
                    PropGetterToIvarMap,
                    PropertyToIvarMap,
                    BR.getContext()).VisitStmt(D->getBody());
      // If another invalidation method was called, trust that full invalidation
      // has occurred.
      if (CalledAnotherInvalidationMethod)
        Ivars.clear();
    }
  }

  // If all ivars have been invalidated by partial invalidators, there is
  // nothing to check here.
  if (Ivars.empty())
    return;

  // Find all invalidation methods in this @interface declaration and parents.
  InvalidationInfo Info;
  containsInvalidationMethod(InterfaceD, Info, /*LookForPartial*/ false);

  // Report an error in case none of the invalidation methods are declared.
  if (!Info.needsInvalidation() && !PartialInfo.needsInvalidation()) {
    if (Filter.check_MissingInvalidationMethod)
      reportNoInvalidationMethod(Filter.checkName_MissingInvalidationMethod,
                                 FirstIvarDecl, IvarToPopertyMap, InterfaceD,
                                 /*MissingDeclaration*/ true);
    // If there are no invalidation methods, there is no ivar validation work
    // to be done.
    return;
  }

  // Only check if Ivars are invalidated when InstanceVariableInvalidation
  // has been requested.
  if (!Filter.check_InstanceVariableInvalidation)
    return;

  // Check that all ivars are invalidated by the invalidation methods.
  bool AtImplementationContainsAtLeastOneInvalidationMethod = false;
  for (MethodSet::iterator I = Info.InvalidationMethods.begin(),
                           E = Info.InvalidationMethods.end(); I != E; ++I) {
    const ObjCMethodDecl *InterfD = *I;

    // Get the corresponding method in the @implementation.
    const ObjCMethodDecl *D = ImplD->getMethod(InterfD->getSelector(),
                                               InterfD->isInstanceMethod());
    if (D && D->hasBody()) {
      AtImplementationContainsAtLeastOneInvalidationMethod = true;

      // Get a copy of ivars needing invalidation.
      IvarSet IvarsI = Ivars;

      bool CalledAnotherInvalidationMethod = false;
      MethodCrawler(IvarsI,
                    CalledAnotherInvalidationMethod,
                    PropSetterToIvarMap,
                    PropGetterToIvarMap,
                    PropertyToIvarMap,
                    BR.getContext()).VisitStmt(D->getBody());
      // If another invalidation method was called, trust that full invalidation
      // has occurred.
      if (CalledAnotherInvalidationMethod)
        continue;

      // Warn on the ivars that were not invalidated by the method.
      for (IvarSet::const_iterator
          I = IvarsI.begin(), E = IvarsI.end(); I != E; ++I)
        reportIvarNeedsInvalidation(I->first, IvarToPopertyMap, D);
    }
  }

  // Report an error in case none of the invalidation methods are implemented.
  if (!AtImplementationContainsAtLeastOneInvalidationMethod) {
    if (AtImplementationContainsAtLeastOnePartialInvalidationMethod) {
      // Warn on the ivars that were not invalidated by the prrtial
      // invalidation methods.
      for (IvarSet::const_iterator
           I = Ivars.begin(), E = Ivars.end(); I != E; ++I)
        reportIvarNeedsInvalidation(I->first, IvarToPopertyMap, nullptr);
    } else {
      // Otherwise, no invalidation methods were implemented.
      reportNoInvalidationMethod(Filter.checkName_InstanceVariableInvalidation,
                                 FirstIvarDecl, IvarToPopertyMap, InterfaceD,
                                 /*MissingDeclaration*/ false);
    }
  }
}

void IvarInvalidationCheckerImpl::reportNoInvalidationMethod(
    CheckName CheckName, const ObjCIvarDecl *FirstIvarDecl,
    const IvarToPropMapTy &IvarToPopertyMap,
    const ObjCInterfaceDecl *InterfaceD, bool MissingDeclaration) const {
  SmallString<128> sbuf;
  llvm::raw_svector_ostream os(sbuf);
  assert(FirstIvarDecl);
  printIvar(os, FirstIvarDecl, IvarToPopertyMap);
  os << "needs to be invalidated; ";
  if (MissingDeclaration)
    os << "no invalidation method is declared for ";
  else
    os << "no invalidation method is defined in the @implementation for ";
  os << InterfaceD->getName();

  PathDiagnosticLocation IvarDecLocation =
    PathDiagnosticLocation::createBegin(FirstIvarDecl, BR.getSourceManager());

  BR.EmitBasicReport(FirstIvarDecl, CheckName, "Incomplete invalidation",
                     categories::CoreFoundationObjectiveC, os.str(),
                     IvarDecLocation);
}

void IvarInvalidationCheckerImpl::
reportIvarNeedsInvalidation(const ObjCIvarDecl *IvarD,
                            const IvarToPropMapTy &IvarToPopertyMap,
                            const ObjCMethodDecl *MethodD) const {
  SmallString<128> sbuf;
  llvm::raw_svector_ostream os(sbuf);
  printIvar(os, IvarD, IvarToPopertyMap);
  os << "needs to be invalidated or set to nil";
  if (MethodD) {
    PathDiagnosticLocation MethodDecLocation =
                           PathDiagnosticLocation::createEnd(MethodD->getBody(),
                           BR.getSourceManager(),
                           Mgr.getAnalysisDeclContext(MethodD));
    BR.EmitBasicReport(MethodD, Filter.checkName_InstanceVariableInvalidation,
                       "Incomplete invalidation",
                       categories::CoreFoundationObjectiveC, os.str(),
                       MethodDecLocation);
  } else {
    BR.EmitBasicReport(
        IvarD, Filter.checkName_InstanceVariableInvalidation,
        "Incomplete invalidation", categories::CoreFoundationObjectiveC,
        os.str(),
        PathDiagnosticLocation::createBegin(IvarD, BR.getSourceManager()));
  }
}

void IvarInvalidationCheckerImpl::MethodCrawler::markInvalidated(
    const ObjCIvarDecl *Iv) {
  IvarSet::iterator I = IVars.find(Iv);
  if (I != IVars.end()) {
    // If InvalidationMethod is present, we are processing the message send and
    // should ensure we are invalidating with the appropriate method,
    // otherwise, we are processing setting to 'nil'.
    if (!InvalidationMethod || I->second.hasMethod(InvalidationMethod))
      IVars.erase(I);
  }
}

const Expr *IvarInvalidationCheckerImpl::MethodCrawler::peel(const Expr *E) const {
  E = E->IgnoreParenCasts();
  if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E))
    E = POE->getSyntacticForm()->IgnoreParenCasts();
  if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
    E = OVE->getSourceExpr()->IgnoreParenCasts();
  return E;
}

void IvarInvalidationCheckerImpl::MethodCrawler::checkObjCIvarRefExpr(
    const ObjCIvarRefExpr *IvarRef) {
  if (const Decl *D = IvarRef->getDecl())
    markInvalidated(cast<ObjCIvarDecl>(D->getCanonicalDecl()));
}

void IvarInvalidationCheckerImpl::MethodCrawler::checkObjCMessageExpr(
    const ObjCMessageExpr *ME) {
  const ObjCMethodDecl *MD = ME->getMethodDecl();
  if (MD) {
    MD = cast<ObjCMethodDecl>(MD->getCanonicalDecl());
    MethToIvarMapTy::const_iterator IvI = PropertyGetterToIvarMap.find(MD);
    if (IvI != PropertyGetterToIvarMap.end())
      markInvalidated(IvI->second);
  }
}

void IvarInvalidationCheckerImpl::MethodCrawler::checkObjCPropertyRefExpr(
    const ObjCPropertyRefExpr *PA) {

  if (PA->isExplicitProperty()) {
    const ObjCPropertyDecl *PD = PA->getExplicitProperty();
    if (PD) {
      PD = cast<ObjCPropertyDecl>(PD->getCanonicalDecl());
      PropToIvarMapTy::const_iterator IvI = PropertyToIvarMap.find(PD);
      if (IvI != PropertyToIvarMap.end())
        markInvalidated(IvI->second);
      return;
    }
  }

  if (PA->isImplicitProperty()) {
    const ObjCMethodDecl *MD = PA->getImplicitPropertySetter();
    if (MD) {
      MD = cast<ObjCMethodDecl>(MD->getCanonicalDecl());
      MethToIvarMapTy::const_iterator IvI =PropertyGetterToIvarMap.find(MD);
      if (IvI != PropertyGetterToIvarMap.end())
        markInvalidated(IvI->second);
      return;
    }
  }
}

bool IvarInvalidationCheckerImpl::MethodCrawler::isZero(const Expr *E) const {
  E = peel(E);

  return (E->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull)
           != Expr::NPCK_NotNull);
}

void IvarInvalidationCheckerImpl::MethodCrawler::check(const Expr *E) {
  E = peel(E);

  if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) {
    checkObjCIvarRefExpr(IvarRef);
    return;
  }

  if (const ObjCPropertyRefExpr *PropRef = dyn_cast<ObjCPropertyRefExpr>(E)) {
    checkObjCPropertyRefExpr(PropRef);
    return;
  }

  if (const ObjCMessageExpr *MsgExpr = dyn_cast<ObjCMessageExpr>(E)) {
    checkObjCMessageExpr(MsgExpr);
    return;
  }
}

void IvarInvalidationCheckerImpl::MethodCrawler::VisitBinaryOperator(
    const BinaryOperator *BO) {
  VisitStmt(BO);

  // Do we assign/compare against zero? If yes, check the variable we are
  // assigning to.
  BinaryOperatorKind Opcode = BO->getOpcode();
  if (Opcode != BO_Assign &&
      Opcode != BO_EQ &&
      Opcode != BO_NE)
    return;

  if (isZero(BO->getRHS())) {
      check(BO->getLHS());
      return;
  }

  if (Opcode != BO_Assign && isZero(BO->getLHS())) {
    check(BO->getRHS());
    return;
  }
}

void IvarInvalidationCheckerImpl::MethodCrawler::VisitObjCMessageExpr(
  const ObjCMessageExpr *ME) {
  const ObjCMethodDecl *MD = ME->getMethodDecl();
  const Expr *Receiver = ME->getInstanceReceiver();

  // Stop if we are calling '[self invalidate]'.
  if (Receiver && isInvalidationMethod(MD, /*LookForPartial*/ false))
    if (Receiver->isObjCSelfExpr()) {
      CalledAnotherInvalidationMethod = true;
      return;
    }

  // Check if we call a setter and set the property to 'nil'.
  if (MD && (ME->getNumArgs() == 1) && isZero(ME->getArg(0))) {
    MD = cast<ObjCMethodDecl>(MD->getCanonicalDecl());
    MethToIvarMapTy::const_iterator IvI = PropertySetterToIvarMap.find(MD);
    if (IvI != PropertySetterToIvarMap.end()) {
      markInvalidated(IvI->second);
      return;
    }
  }

  // Check if we call the 'invalidation' routine on the ivar.
  if (Receiver) {
    InvalidationMethod = MD;
    check(Receiver->IgnoreParenCasts());
    InvalidationMethod = nullptr;
  }

  VisitStmt(ME);
}
} // end anonymous namespace

// Register the checkers.
namespace {
class IvarInvalidationChecker :
  public Checker<check::ASTDecl<ObjCImplementationDecl> > {
public:
  ChecksFilter Filter;
public:
  void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& Mgr,
                    BugReporter &BR) const {
    IvarInvalidationCheckerImpl Walker(Mgr, BR, Filter);
    Walker.visit(D);
  }
};
} // end anonymous namespace

#define REGISTER_CHECKER(name)                                                 \
  void ento::register##name(CheckerManager &mgr) {                             \
    IvarInvalidationChecker *checker =                                         \
        mgr.registerChecker<IvarInvalidationChecker>();                        \
    checker->Filter.check_##name = true;                                       \
    checker->Filter.checkName_##name = mgr.getCurrentCheckName();              \
  }

REGISTER_CHECKER(InstanceVariableInvalidation)
REGISTER_CHECKER(MissingInvalidationMethod)
