//===- DirectIvarAssignment.cpp - Check rules on ObjC properties -*- C++ -*-==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  Check that Objective C properties are set with the setter, not though a
//      direct assignment.
//
//  Two versions of a checker exist: one that checks all methods and the other
//      that only checks the methods annotated with
//      __attribute__((annotate("objc_no_direct_instance_variable_assignment")))
//
//  The checker does not warn about assignments to Ivars, annotated with
//       __attribute__((objc_allow_direct_instance_variable_assignment"))). This
//      annotation serves as a false positive suppression mechanism for the
//      checker. The annotation is allowed on properties and Ivars.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.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"

using namespace clang;
using namespace ento;

namespace {

/// The default method filter, which is used to filter out the methods on which
/// the check should not be performed.
///
/// Checks for the init, dealloc, and any other functions that might be allowed
/// to perform direct instance variable assignment based on their name.
static bool DefaultMethodFilter(const ObjCMethodDecl *M) {
  return M->getMethodFamily() == OMF_init ||
         M->getMethodFamily() == OMF_dealloc ||
         M->getMethodFamily() == OMF_copy ||
         M->getMethodFamily() == OMF_mutableCopy ||
         M->getSelector().getNameForSlot(0).contains("init") ||
         M->getSelector().getNameForSlot(0).contains("Init");
}

class DirectIvarAssignment :
  public Checker<check::ASTDecl<ObjCImplementationDecl> > {

  typedef llvm::DenseMap<const ObjCIvarDecl*,
                         const ObjCPropertyDecl*> IvarToPropertyMapTy;

  /// A helper class, which walks the AST and locates all assignments to ivars
  /// in the given function.
  class MethodCrawler : public ConstStmtVisitor<MethodCrawler> {
    const IvarToPropertyMapTy &IvarToPropMap;
    const ObjCMethodDecl *MD;
    const ObjCInterfaceDecl *InterfD;
    BugReporter &BR;
    const CheckerBase *Checker;
    StackFrameOrAnalysisDeclContext DCtx;

  public:
    MethodCrawler(const IvarToPropertyMapTy &InMap, const ObjCMethodDecl *InMD,
                  const ObjCInterfaceDecl *InID, BugReporter &InBR,
                  const CheckerBase *Checker, AnalysisDeclContext *InDCtx)
        : IvarToPropMap(InMap), MD(InMD), InterfD(InID), BR(InBR),
          Checker(Checker), DCtx(InDCtx) {}

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

    void VisitBinaryOperator(const BinaryOperator *BO);

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

public:
  bool (*ShouldSkipMethod)(const ObjCMethodDecl *);

  DirectIvarAssignment() : ShouldSkipMethod(&DefaultMethodFilter) {}

  void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& Mgr,
                    BugReporter &BR) const;
};

static const ObjCIvarDecl *findPropertyBackingIvar(const ObjCPropertyDecl *PD,
                                               const ObjCInterfaceDecl *InterD,
                                               ASTContext &Ctx) {
  // Check for synthesized ivars.
  ObjCIvarDecl *ID = PD->getPropertyIvarDecl();
  if (ID)
    return ID;

  ObjCInterfaceDecl *NonConstInterD = const_cast<ObjCInterfaceDecl*>(InterD);

  // Check for existing "_PropName".
  ID = NonConstInterD->lookupInstanceVariable(PD->getDefaultSynthIvarName(Ctx));
  if (ID)
    return ID;

  // Check for existing "PropName".
  IdentifierInfo *PropIdent = PD->getIdentifier();
  ID = NonConstInterD->lookupInstanceVariable(PropIdent);

  return ID;
}

void DirectIvarAssignment::checkASTDecl(const ObjCImplementationDecl *D,
                                       AnalysisManager& Mgr,
                                       BugReporter &BR) const {
  const ObjCInterfaceDecl *InterD = D->getClassInterface();


  IvarToPropertyMapTy IvarToPropMap;

  // Find all properties for this class.
  for (const auto *PD : InterD->instance_properties()) {
    // Find the corresponding IVar.
    const ObjCIvarDecl *ID = findPropertyBackingIvar(PD, InterD,
                                                     Mgr.getASTContext());

    if (!ID)
      continue;

    // Store the IVar to property mapping.
    IvarToPropMap[ID] = PD;
  }

  if (IvarToPropMap.empty())
    return;

  for (const auto *M : D->instance_methods()) {
    AnalysisDeclContext *DCtx = Mgr.getAnalysisDeclContext(M);

    if ((*ShouldSkipMethod)(M))
      continue;

    const Stmt *Body = M->getBody();
    if (M->isSynthesizedAccessorStub())
      continue;
    assert(Body);

    MethodCrawler MC(IvarToPropMap, M->getCanonicalDecl(), InterD, BR, this,
                     DCtx);
    MC.VisitStmt(Body);
  }
}

static bool isAnnotatedToAllowDirectAssignment(const Decl *D) {
  for (const auto *Ann : D->specific_attrs<AnnotateAttr>())
    if (Ann->getAnnotation() ==
        "objc_allow_direct_instance_variable_assignment")
      return true;
  return false;
}

void DirectIvarAssignment::MethodCrawler::VisitBinaryOperator(
                                                    const BinaryOperator *BO) {
  if (!BO->isAssignmentOp())
    return;

  const ObjCIvarRefExpr *IvarRef =
          dyn_cast<ObjCIvarRefExpr>(BO->getLHS()->IgnoreParenCasts());

  if (!IvarRef)
    return;

  if (const ObjCIvarDecl *D = IvarRef->getDecl()) {
    IvarToPropertyMapTy::const_iterator I = IvarToPropMap.find(D);

    if (I != IvarToPropMap.end()) {
      const ObjCPropertyDecl *PD = I->second;
      // Skip warnings on Ivars, annotated with
      // objc_allow_direct_instance_variable_assignment. This annotation serves
      // as a false positive suppression mechanism for the checker. The
      // annotation is allowed on properties and ivars.
      if (isAnnotatedToAllowDirectAssignment(PD) ||
          isAnnotatedToAllowDirectAssignment(D))
        return;

      ObjCMethodDecl *GetterMethod =
          InterfD->getInstanceMethod(PD->getGetterName());
      ObjCMethodDecl *SetterMethod =
          InterfD->getInstanceMethod(PD->getSetterName());

      if (SetterMethod && SetterMethod->getCanonicalDecl() == MD)
        return;

      if (GetterMethod && GetterMethod->getCanonicalDecl() == MD)
        return;

      BR.EmitBasicReport(
          MD, Checker, "Property access", categories::CoreFoundationObjectiveC,
          "Direct assignment to an instance variable backing a property; "
          "use the setter instead",
          PathDiagnosticLocation(IvarRef, BR.getSourceManager(), DCtx));
    }
  }
}
}

// Register the checker that checks for direct accesses in functions annotated
// with __attribute__((annotate("objc_no_direct_instance_variable_assignment"))).
static bool AttrFilter(const ObjCMethodDecl *M) {
  for (const auto *Ann : M->specific_attrs<AnnotateAttr>())
    if (Ann->getAnnotation() == "objc_no_direct_instance_variable_assignment")
      return false;
  return true;
}

// Register the checker that checks for direct accesses in all functions,
// except for the initialization and copy routines.
void ento::registerDirectIvarAssignment(CheckerManager &mgr) {
  auto Chk = mgr.registerChecker<DirectIvarAssignment>();
  if (mgr.getAnalyzerOptions().getCheckerBooleanOption(Chk,
                                                       "AnnotatedFunctions"))
    Chk->ShouldSkipMethod = &AttrFilter;
}

bool ento::shouldRegisterDirectIvarAssignment(const CheckerManager &mgr) {
  return true;
}
