//== TrustNonnullChecker.cpp --------- API nullability modeling -*- 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
//
//===----------------------------------------------------------------------===//
//
// This checker adds nullability-related assumptions:
//
// 1. Methods annotated with _Nonnull
// which come from system headers actually return a non-null pointer.
//
// 2. NSDictionary key is non-null after the keyword subscript operation
// on read if and only if the resulting expression is non-null.
//
// 3. NSMutableDictionary index is non-null after a write operation.
//
//===----------------------------------------------------------------------===//

#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Analysis/SelectorExtras.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"

using namespace clang;
using namespace ento;

/// Records implications between symbols.
/// The semantics is:
///    (antecedent != 0) => (consequent != 0)
/// These implications are then read during the evaluation of the assumption,
/// and the appropriate antecedents are applied.
REGISTER_MAP_WITH_PROGRAMSTATE(NonNullImplicationMap, SymbolRef, SymbolRef)

/// The semantics is:
///    (antecedent == 0) => (consequent == 0)
REGISTER_MAP_WITH_PROGRAMSTATE(NullImplicationMap, SymbolRef, SymbolRef)

namespace {

class TrustNonnullChecker : public Checker<check::PostCall,
                                           check::PostObjCMessage,
                                           check::DeadSymbols,
                                           eval::Assume> {
  // Do not try to iterate over symbols with higher complexity.
  static unsigned constexpr ComplexityThreshold = 10;
  Selector ObjectForKeyedSubscriptSel;
  Selector ObjectForKeySel;
  Selector SetObjectForKeyedSubscriptSel;
  Selector SetObjectForKeySel;

public:
  TrustNonnullChecker(ASTContext &Ctx)
      : ObjectForKeyedSubscriptSel(
            getKeywordSelector(Ctx, "objectForKeyedSubscript")),
        ObjectForKeySel(getKeywordSelector(Ctx, "objectForKey")),
        SetObjectForKeyedSubscriptSel(
            getKeywordSelector(Ctx, "setObject", "forKeyedSubscript")),
        SetObjectForKeySel(getKeywordSelector(Ctx, "setObject", "forKey")) {}

  ProgramStateRef evalAssume(ProgramStateRef State,
                             SVal Cond,
                             bool Assumption) const {
    const SymbolRef CondS = Cond.getAsSymbol();
    if (!CondS || CondS->computeComplexity() > ComplexityThreshold)
      return State;

    for (SymbolRef Antecedent : CondS->symbols()) {
      State = addImplication(Antecedent, State, true);
      State = addImplication(Antecedent, State, false);
    }

    return State;
  }

  void checkPostCall(const CallEvent &Call, CheckerContext &C) const {
    // Only trust annotations for system headers for non-protocols.
    if (!Call.isInSystemHeader())
      return;

    ProgramStateRef State = C.getState();

    if (isNonNullPtr(Call, C))
      if (auto L = Call.getReturnValue().getAs<Loc>())
        State = State->assume(*L, /*assumption=*/true);

    C.addTransition(State);
  }

  void checkPostObjCMessage(const ObjCMethodCall &Msg,
                            CheckerContext &C) const {
    const ObjCInterfaceDecl *ID = Msg.getReceiverInterface();
    if (!ID)
      return;

    ProgramStateRef State = C.getState();

    // Index to setter for NSMutableDictionary is assumed to be non-null,
    // as an exception is thrown otherwise.
    if (interfaceHasSuperclass(ID, "NSMutableDictionary") &&
        (Msg.getSelector() == SetObjectForKeyedSubscriptSel ||
         Msg.getSelector() == SetObjectForKeySel)) {
      if (auto L = Msg.getArgSVal(1).getAs<Loc>())
        State = State->assume(*L, /*assumption=*/true);
    }

    // Record an implication: index is non-null if the output is non-null.
    if (interfaceHasSuperclass(ID, "NSDictionary") &&
        (Msg.getSelector() == ObjectForKeyedSubscriptSel ||
         Msg.getSelector() == ObjectForKeySel)) {
      SymbolRef ArgS = Msg.getArgSVal(0).getAsSymbol();
      SymbolRef RetS = Msg.getReturnValue().getAsSymbol();

      if (ArgS && RetS) {
        // Emulate an implication: the argument is non-null if
        // the return value is non-null.
        State = State->set<NonNullImplicationMap>(RetS, ArgS);

        // Conversely, when the argument is null, the return value
        // is definitely null.
        State = State->set<NullImplicationMap>(ArgS, RetS);
      }
    }

    C.addTransition(State);
  }

  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const {
    ProgramStateRef State = C.getState();

    State = dropDeadFromGDM<NullImplicationMap>(SymReaper, State);
    State = dropDeadFromGDM<NonNullImplicationMap>(SymReaper, State);

    C.addTransition(State);
  }

private:

  /// \returns State with GDM \p MapName where all dead symbols were
  // removed.
  template <typename MapName>
  ProgramStateRef dropDeadFromGDM(SymbolReaper &SymReaper,
                                  ProgramStateRef State) const {
    for (const std::pair<SymbolRef, SymbolRef> &P : State->get<MapName>())
      if (!SymReaper.isLive(P.first) || !SymReaper.isLive(P.second))
        State = State->remove<MapName>(P.first);
    return State;
  }

  /// \returns Whether we trust the result of the method call to be
  /// a non-null pointer.
  bool isNonNullPtr(const CallEvent &Call, CheckerContext &C) const {
    QualType ExprRetType = Call.getResultType();
    if (!ExprRetType->isAnyPointerType())
      return false;

    if (getNullabilityAnnotation(ExprRetType) == Nullability::Nonnull)
      return true;

    // The logic for ObjC instance method calls is more complicated,
    // as the return value is nil when the receiver is nil.
    if (!isa<ObjCMethodCall>(&Call))
      return false;

    const auto *MCall = cast<ObjCMethodCall>(&Call);
    const ObjCMethodDecl *MD = MCall->getDecl();

    // Distrust protocols.
    if (isa<ObjCProtocolDecl>(MD->getDeclContext()))
      return false;

    QualType DeclRetType = MD->getReturnType();
    if (getNullabilityAnnotation(DeclRetType) != Nullability::Nonnull)
      return false;

    // For class messages it is sufficient for the declaration to be
    // annotated _Nonnull.
    if (!MCall->isInstanceMessage())
      return true;

    // Alternatively, the analyzer could know that the receiver is not null.
    SVal Receiver = MCall->getReceiverSVal();
    ConditionTruthVal TV = C.getState()->isNonNull(Receiver);
    if (TV.isConstrainedTrue())
      return true;

    return false;
  }

  /// \return Whether \p ID has a superclass by the name \p ClassName.
  bool interfaceHasSuperclass(const ObjCInterfaceDecl *ID,
                         StringRef ClassName) const {
    if (ID->getIdentifier()->getName() == ClassName)
      return true;

    if (const ObjCInterfaceDecl *Super = ID->getSuperClass())
      return interfaceHasSuperclass(Super, ClassName);

    return false;
  }


  /// \return a state with an optional implication added (if exists)
  /// from a map of recorded implications.
  /// If \p Negated is true, checks NullImplicationMap, and assumes
  /// the negation of \p Antecedent.
  /// Checks NonNullImplicationMap and assumes \p Antecedent otherwise.
  ProgramStateRef addImplication(SymbolRef Antecedent,
                                 ProgramStateRef InputState,
                                 bool Negated) const {
    if (!InputState)
      return nullptr;
    SValBuilder &SVB = InputState->getStateManager().getSValBuilder();
    const SymbolRef *Consequent =
        Negated ? InputState->get<NonNullImplicationMap>(Antecedent)
                : InputState->get<NullImplicationMap>(Antecedent);
    if (!Consequent)
      return InputState;

    SVal AntecedentV = SVB.makeSymbolVal(Antecedent);
    ProgramStateRef State = InputState;

    if ((Negated && InputState->isNonNull(AntecedentV).isConstrainedTrue())
        || (!Negated && InputState->isNull(AntecedentV).isConstrainedTrue())) {
      SVal ConsequentS = SVB.makeSymbolVal(*Consequent);
      State = InputState->assume(ConsequentS.castAs<DefinedSVal>(), Negated);
      if (!State)
        return nullptr;

      // Drop implications from the map.
      if (Negated) {
        State = State->remove<NonNullImplicationMap>(Antecedent);
        State = State->remove<NullImplicationMap>(*Consequent);
      } else {
        State = State->remove<NullImplicationMap>(Antecedent);
        State = State->remove<NonNullImplicationMap>(*Consequent);
      }
    }

    return State;
  }
};

} // end empty namespace

void ento::registerTrustNonnullChecker(CheckerManager &Mgr) {
  Mgr.registerChecker<TrustNonnullChecker>(Mgr.getASTContext());
}

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