//===--- CallAndMessageChecker.cpp ------------------------------*- 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 defines CallAndMessageChecker, a builtin checker that checks for various
// errors of call and objc message expressions.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ExprCXX.h"
#include "clang/AST/ParentMap.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;
using namespace ento;

namespace {

class CallAndMessageChecker
    : public Checker<check::PreObjCMessage, check::ObjCMessageNil,
                     check::PreCall> {
  const BugType CallNullBug{
      this, "Called function pointer is null (null dereference)"};
  const BugType CallUndefBug{
      this, "Called function pointer is an uninitialized pointer value"};
  const BugType CXXCallNullBug{this, "Called C++ object pointer is null"};
  const BugType CXXCallUndefBug{this,
                                "Called C++ object pointer is uninitialized"};
  const BugType CallArgBug{this, "Uninitialized argument value"};
  const BugType CXXDeleteUndefBug{this, "Uninitialized argument value"};
  const BugType MsgUndefBug{
      this, "Receiver in message expression is an uninitialized value"};
  const BugType ObjCPropUndefBug{
      this, "Property access on an uninitialized object pointer"};
  const BugType ObjCSubscriptUndefBug{
      this, "Subscript access on an uninitialized object pointer"};
  const BugType MsgArgBug{this, "Uninitialized argument value"};
  const BugType MsgRetBug{this, "Receiver in message expression is 'nil'"};
  const BugType CallFewArgsBug{this, "Function call with too few arguments"};

public:
  // Like a checker family, CallAndMessageChecker can produce many kinds of
  // warnings which can be separately enabled or disabled. However, for
  // historical reasons these warning kinds are represented by checker options
  // (and not separate checker frontends with their own names) because
  // CallAndMessage is among the oldest checkers out there, and can
  // be responsible for the majority of the reports on any given project. This
  // is obviously not ideal, but changing checker name has the consequence of
  // changing the issue hashes associated with the reports, and databases
  // relying on this (CodeChecker, for instance) would suffer greatly.
  // If we ever end up making changes to the issue hash generation algorithm, or
  // the warning messages here, we should totally jump on the opportunity to
  // convert these to actual checker frontends.
  enum CheckKind {
    CK_FunctionPointer,
    CK_ParameterCount,
    CK_CXXThisMethodCall,
    CK_CXXDeallocationArg,
    CK_ArgInitializedness,
    CK_ArgPointeeInitializedness,
    CK_NilReceiver,
    CK_UndefReceiver,
    CK_NumCheckKinds
  };

  bool ChecksEnabled[CK_NumCheckKinds] = {false};

  /// When checking a struct value for uninitialized data and this setting is
  /// true, all members should be completely uninitialized to get a checker
  /// warning. When the value is false, the warning is emitted for partially
  // initialized structures too.
  bool ArgPointeeInitializednessComplete = true;

  void checkPreObjCMessage(const ObjCMethodCall &msg, CheckerContext &C) const;

  /// Fill in the return value that results from messaging nil based on the
  /// return type and architecture and diagnose if the return value will be
  /// garbage.
  void checkObjCMessageNil(const ObjCMethodCall &msg, CheckerContext &C) const;

  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;

  ProgramStateRef checkFunctionPointerCall(const CallExpr *CE,
                                           CheckerContext &C,
                                           ProgramStateRef State) const;

  ProgramStateRef checkCXXMethodCall(const CXXInstanceCall *CC,
                                     CheckerContext &C,
                                     ProgramStateRef State) const;

  ProgramStateRef checkParameterCount(const CallEvent &Call, CheckerContext &C,
                                      ProgramStateRef State) const;

  ProgramStateRef checkCXXDeallocation(const CXXDeallocatorCall *DC,
                                       CheckerContext &C,
                                       ProgramStateRef State) const;

  ProgramStateRef checkArgInitializedness(const CallEvent &Call,
                                          CheckerContext &C,
                                          ProgramStateRef State) const;

private:
  bool PreVisitProcessArg(CheckerContext &C, SVal V, SourceRange ArgRange,
                          const Expr *ArgEx, int ArgumentNumber,
                          bool CheckUninitFields, const CallEvent &Call,
                          const BugType &BT,
                          const ParmVarDecl *ParamDecl) const;

  static void emitBadCall(const BugType &BT, CheckerContext &C,
                          const Expr *BadE);
  void emitNilReceiverBug(CheckerContext &C, const ObjCMethodCall &msg,
                          ExplodedNode *N) const;

  void HandleNilReceiver(CheckerContext &C,
                         ProgramStateRef state,
                         const ObjCMethodCall &msg) const;

  bool uninitRefOrPointer(CheckerContext &C, SVal V, const CallEvent &Call,
                          const BugType &BT, const ParmVarDecl *ParamDecl,
                          int ArgumentNumber) const;

  // C library functions which have a pointer-to-struct parameter that should be
  // initialized (at least partially) before the call. The 'uninitRefOrPointer'
  // check uses this data.
  CallDescriptionMap<int> FunctionsWithInOutPtrParam = {
      {{CDM::CLibrary, {"mbrlen"}, 3}, 2},
      {{CDM::CLibrary, {"mbrtowc"}, 4}, 3},
      {{CDM::CLibrary, {"wcrtomb"}, 3}, 2},
      {{CDM::CLibrary, {"mbsrtowcs"}, 4}, 3},
      {{CDM::CLibrary, {"wcsrtombs"}, 4}, 3},
      {{CDM::CLibrary, {"mbsnrtowcs"}, 5}, 4},
      {{CDM::CLibrary, {"wcsnrtombs"}, 5}, 4},
      {{CDM::CLibrary, {"wcrtomb_s"}, 5}, 4},
      {{CDM::CLibrary, {"mbsrtowcs_s"}, 6}, 5},
      {{CDM::CLibrary, {"wcsrtombs_s"}, 6}, 5},

      {{CDM::CLibrary, {"mbrtoc8"}, 4}, 3},
      {{CDM::CLibrary, {"c8rtomb"}, 3}, 2},
      {{CDM::CLibrary, {"mbrtoc16"}, 4}, 3},
      {{CDM::CLibrary, {"c16rtomb"}, 3}, 2},
      {{CDM::CLibrary, {"mbrtoc32"}, 4}, 3},
      {{CDM::CLibrary, {"c32rtomb"}, 3}, 2},

      {{CDM::CLibrary, {"mktime"}, 1}, 0},
      {{CDM::CLibrary, {"timegm"}, 1}, 0},
  };
};
} // end anonymous namespace

void CallAndMessageChecker::emitBadCall(const BugType &BT, CheckerContext &C,
                                        const Expr *BadE) {
  ExplodedNode *N = C.generateErrorNode();
  if (!N)
    return;

  auto R = std::make_unique<PathSensitiveBugReport>(BT, BT.getDescription(), N);
  if (BadE) {
    R->addRange(BadE->getSourceRange());
    if (BadE->isGLValue())
      BadE = bugreporter::getDerefExpr(BadE);
    bugreporter::trackExpressionValue(N, BadE, *R);
  }
  C.emitReport(std::move(R));
}

static void describeUninitializedArgumentInCall(const CallEvent &Call,
                                                int ArgumentNumber,
                                                llvm::raw_svector_ostream &Os) {
  switch (Call.getKind()) {
  case CE_ObjCMessage: {
    const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
    switch (Msg.getMessageKind()) {
    case OCM_Message:
      Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
         << " argument in message expression is an uninitialized value";
      return;
    case OCM_PropertyAccess:
      assert(Msg.isSetter() && "Getters have no args");
      Os << "Argument for property setter is an uninitialized value";
      return;
    case OCM_Subscript:
      if (Msg.isSetter() && (ArgumentNumber == 0))
        Os << "Argument for subscript setter is an uninitialized value";
      else
        Os << "Subscript index is an uninitialized value";
      return;
    }
    llvm_unreachable("Unknown message kind.");
  }
  case CE_Block:
    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
       << " block call argument is an uninitialized value";
    return;
  default:
    Os << (ArgumentNumber + 1) << llvm::getOrdinalSuffix(ArgumentNumber + 1)
       << " function call argument is an uninitialized value";
    return;
  }
}

namespace {
class FindUninitializedField {
public:
  using FieldChainTy = SmallVector<const FieldDecl *, 10>;
  FieldChainTy FieldChain;

private:
  StoreManager &StoreMgr;
  MemRegionManager &MrMgr;
  Store store;
  bool FindNotUninitialized;

public:
  FindUninitializedField(StoreManager &storeMgr, MemRegionManager &mrMgr,
                         Store s, bool FindNotUninitialized = false)
      : StoreMgr(storeMgr), MrMgr(mrMgr), store(s),
        FindNotUninitialized(FindNotUninitialized) {}

  bool Find(const TypedValueRegion *R) {
    QualType T = R->getValueType();
    if (const RecordType *RT = T->getAsStructureType()) {
      const RecordDecl *RD = RT->getDecl()->getDefinition();
      assert(RD && "Referred record has no definition");
      for (const auto *I : RD->fields()) {
        if (I->isUnnamedBitField())
          continue;
        const FieldRegion *FR = MrMgr.getFieldRegion(I, R);
        FieldChain.push_back(I);
        T = I->getType();
        if (T->isStructureType()) {
          if (FindNotUninitialized ? !Find(FR) : Find(FR))
            return !FindNotUninitialized;
        } else {
          SVal V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
          if (FindNotUninitialized ? !V.isUndef() : V.isUndef())
            return !FindNotUninitialized;
        }
        FieldChain.pop_back();
      }
    }

    return FindNotUninitialized;
  }
};
} // namespace

namespace llvm {
template <> struct format_provider<FindUninitializedField::FieldChainTy> {
  static void format(const FindUninitializedField::FieldChainTy &V,
                     raw_ostream &Stream, StringRef Style) {
    if (V.size() == 0)
      return;
    else if (V.size() == 1)
      Stream << " (e.g., field: '" << *V[0] << "')";
    else {
      Stream << " (e.g., via the field chain: '";
      interleave(
          V, Stream, [&Stream](const FieldDecl *FD) { Stream << *FD; }, ".");
      Stream << "')";
    }
  }
};
} // namespace llvm

bool CallAndMessageChecker::uninitRefOrPointer(CheckerContext &C, SVal V,
                                               const CallEvent &Call,
                                               const BugType &BT,
                                               const ParmVarDecl *ParamDecl,
                                               int ArgumentNumber) const {

  if (!ChecksEnabled[CK_ArgPointeeInitializedness])
    return false;

  // No parameter declaration available, i.e. variadic function argument.
  if (!ParamDecl)
    return false;

  QualType ParamT = ParamDecl->getType();
  if (!ParamT->isPointerOrReferenceType())
    return false;

  bool AllowPartialInitializedness = ArgPointeeInitializednessComplete;
  QualType PointeeT = ParamT->getPointeeType();
  if (!PointeeT.isConstQualified()) {
    if (const int *PI = FunctionsWithInOutPtrParam.lookup(Call)) {
      if (*PI != ArgumentNumber)
        return false;
      // At these functions always allow partial argument initializedness.
      AllowPartialInitializedness = true;
    } else {
      return false;
    }
  }

  const MemRegion *SValMemRegion = V.getAsRegion();
  if (!SValMemRegion)
    return false;

  // If parameter is declared as pointer to const in function declaration,
  // then check if corresponding argument in function call is
  // pointing to undefined symbol value (uninitialized memory).

  const ProgramStateRef State = C.getState();
  if (PointeeT->isVoidType())
    PointeeT = C.getASTContext().CharTy;
  const SVal PointeeV = State->getSVal(SValMemRegion, PointeeT);
  const Expr *ArgEx = Call.getArgExpr(ArgumentNumber);

  if (PointeeV.isUndef()) {
    if (ExplodedNode *N = C.generateErrorNode()) {
      std::string Msg = llvm::formatv(
          "{0}{1} function call argument is {2} uninitialized value",
          ArgumentNumber + 1, llvm::getOrdinalSuffix(ArgumentNumber + 1),
          ParamT->isPointerType() ? "a pointer to" : "an");
      auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
      R->addRange(Call.getArgSourceRange(ArgumentNumber));
      if (ArgEx)
        bugreporter::trackExpressionValue(N, ArgEx, *R);

      C.emitReport(std::move(R));
    }
    return true;
  }

  if (auto LV = PointeeV.getAs<nonloc::LazyCompoundVal>()) {
    const LazyCompoundValData *D = LV->getCVData();
    FindUninitializedField F(C.getState()->getStateManager().getStoreManager(),
                             C.getSValBuilder().getRegionManager(),
                             D->getStore(), AllowPartialInitializedness);

    if (F.Find(D->getRegion())) {
      if (ExplodedNode *N = C.generateErrorNode()) {
        std::string Msg = llvm::formatv(
            "{0}{1} function call argument {2} an uninitialized value{3}",
            (ArgumentNumber + 1), llvm::getOrdinalSuffix(ArgumentNumber + 1),
            ParamT->isPointerType() ? "points to" : "references", F.FieldChain);
        auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
        R->addRange(Call.getArgSourceRange(ArgumentNumber));
        if (ArgEx)
          bugreporter::trackExpressionValue(N, ArgEx, *R);

        C.emitReport(std::move(R));
      }
      return true;
    }
  }

  return false;
}

bool CallAndMessageChecker::PreVisitProcessArg(
    CheckerContext &C, SVal V, SourceRange ArgRange, const Expr *ArgEx,
    int ArgumentNumber, bool CheckUninitFields, const CallEvent &Call,
    const BugType &BT, const ParmVarDecl *ParamDecl) const {
  if (uninitRefOrPointer(C, V, Call, BT, ParamDecl, ArgumentNumber))
    return true;

  if (V.isUndef()) {
    if (!ChecksEnabled[CK_ArgInitializedness]) {
      C.addSink();
      return true;
    }
    if (ExplodedNode *N = C.generateErrorNode()) {
      // Generate a report for this bug.
      SmallString<200> Buf;
      llvm::raw_svector_ostream Os(Buf);
      describeUninitializedArgumentInCall(Call, ArgumentNumber, Os);
      auto R = std::make_unique<PathSensitiveBugReport>(BT, Os.str(), N);

      R->addRange(ArgRange);
      if (ArgEx)
        bugreporter::trackExpressionValue(N, ArgEx, *R);
      C.emitReport(std::move(R));
    }
    return true;
  }

  if (!CheckUninitFields)
    return false;

  if (auto LV = V.getAs<nonloc::LazyCompoundVal>()) {
    const LazyCompoundValData *D = LV->getCVData();
    FindUninitializedField F(C.getState()->getStateManager().getStoreManager(),
                             C.getSValBuilder().getRegionManager(),
                             D->getStore());

    if (F.Find(D->getRegion())) {
      if (!ChecksEnabled[CK_ArgInitializedness]) {
        C.addSink();
        return true;
      }
      if (ExplodedNode *N = C.generateErrorNode()) {
        std::string Msg = llvm::formatv(
            "Passed-by-value struct argument contains uninitialized data{0}",
            F.FieldChain);

        // Generate a report for this bug.
        auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
        R->addRange(ArgRange);

        if (ArgEx)
          bugreporter::trackExpressionValue(N, ArgEx, *R);
        // FIXME: enhance track back for uninitialized value for arbitrary
        // memregions
        C.emitReport(std::move(R));
      }
      return true;
    }
  }

  return false;
}

ProgramStateRef CallAndMessageChecker::checkFunctionPointerCall(
    const CallExpr *CE, CheckerContext &C, ProgramStateRef State) const {

  const Expr *Callee = CE->getCallee()->IgnoreParens();
  const LocationContext *LCtx = C.getLocationContext();
  SVal L = State->getSVal(Callee, LCtx);

  if (L.isUndef()) {
    if (!ChecksEnabled[CK_FunctionPointer]) {
      C.addSink(State);
      return nullptr;
    }
    emitBadCall(CallUndefBug, C, Callee);
    return nullptr;
  }

  ProgramStateRef StNonNull, StNull;
  std::tie(StNonNull, StNull) = State->assume(L.castAs<DefinedOrUnknownSVal>());

  if (StNull && !StNonNull) {
    if (!ChecksEnabled[CK_FunctionPointer]) {
      C.addSink(StNull);
      return nullptr;
    }
    emitBadCall(CallNullBug, C, Callee);
    return nullptr;
  }

  return StNonNull;
}

ProgramStateRef CallAndMessageChecker::checkParameterCount(
    const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {

  // If we have a function or block declaration, we can make sure we pass
  // enough parameters.
  unsigned Params = Call.parameters().size();
  if (Call.getNumArgs() >= Params)
    return State;

  if (!ChecksEnabled[CK_ParameterCount]) {
    C.addSink(State);
    return nullptr;
  }

  ExplodedNode *N = C.generateErrorNode();
  if (!N)
    return nullptr;

  SmallString<512> Str;
  llvm::raw_svector_ostream os(Str);
  if (isa<AnyFunctionCall>(Call)) {
    os << "Function ";
  } else {
    assert(isa<BlockCall>(Call));
    os << "Block ";
  }
  os << "taking " << Params << " argument" << (Params == 1 ? "" : "s")
     << " is called with fewer (" << Call.getNumArgs() << ")";

  C.emitReport(
      std::make_unique<PathSensitiveBugReport>(CallFewArgsBug, os.str(), N));
  return nullptr;
}

ProgramStateRef CallAndMessageChecker::checkCXXMethodCall(
    const CXXInstanceCall *CC, CheckerContext &C, ProgramStateRef State) const {

  SVal V = CC->getCXXThisVal();
  if (V.isUndef()) {
    if (!ChecksEnabled[CK_CXXThisMethodCall]) {
      C.addSink(State);
      return nullptr;
    }
    emitBadCall(CXXCallUndefBug, C, CC->getCXXThisExpr());
    return nullptr;
  }

  ProgramStateRef StNonNull, StNull;
  std::tie(StNonNull, StNull) = State->assume(V.castAs<DefinedOrUnknownSVal>());

  if (StNull && !StNonNull) {
    if (!ChecksEnabled[CK_CXXThisMethodCall]) {
      C.addSink(StNull);
      return nullptr;
    }
    emitBadCall(CXXCallNullBug, C, CC->getCXXThisExpr());
    return nullptr;
  }

  return StNonNull;
}

ProgramStateRef
CallAndMessageChecker::checkCXXDeallocation(const CXXDeallocatorCall *DC,
                                            CheckerContext &C,
                                            ProgramStateRef State) const {
  const CXXDeleteExpr *DE = DC->getOriginExpr();
  assert(DE);
  SVal Arg = C.getSVal(DE->getArgument());
  if (!Arg.isUndef())
    return State;

  if (!ChecksEnabled[CK_CXXDeallocationArg]) {
    C.addSink(State);
    return nullptr;
  }

  StringRef Desc;
  ExplodedNode *N = C.generateErrorNode();
  if (!N)
    return nullptr;
  if (DE->isArrayFormAsWritten())
    Desc = "Argument to 'delete[]' is uninitialized";
  else
    Desc = "Argument to 'delete' is uninitialized";
  auto R = std::make_unique<PathSensitiveBugReport>(CXXDeleteUndefBug, Desc, N);
  bugreporter::trackExpressionValue(N, DE, *R);
  C.emitReport(std::move(R));
  return nullptr;
}

ProgramStateRef CallAndMessageChecker::checkArgInitializedness(
    const CallEvent &Call, CheckerContext &C, ProgramStateRef State) const {

  const Decl *D = Call.getDecl();

  // Don't check for uninitialized field values in arguments if the
  // caller has a body that is available and we have the chance to inline it.
  // This is a hack, but is a reasonable compromise betweens sometimes warning
  // and sometimes not depending on if we decide to inline a function.
  const bool checkUninitFields =
      !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));

  const BugType &BT = isa<ObjCMethodCall>(Call) ? MsgArgBug : CallArgBug;

  const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D);
  for (unsigned i = 0, e = Call.getNumArgs(); i != e; ++i) {
    const ParmVarDecl *ParamDecl = nullptr;
    if (FD && i < FD->getNumParams())
      ParamDecl = FD->getParamDecl(i);
    if (PreVisitProcessArg(C, Call.getArgSVal(i), Call.getArgSourceRange(i),
                           Call.getArgExpr(i), i, checkUninitFields, Call, BT,
                           ParamDecl))
      return nullptr;
  }
  return State;
}

void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
                                         CheckerContext &C) const {
  ProgramStateRef State = C.getState();

  if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr()))
    State = checkFunctionPointerCall(CE, C, State);

  if (!State)
    return;

  if (Call.getDecl())
    State = checkParameterCount(Call, C, State);

  if (!State)
    return;

  if (const auto *CC = dyn_cast<CXXInstanceCall>(&Call))
    State = checkCXXMethodCall(CC, C, State);

  if (!State)
    return;

  if (const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call))
    State = checkCXXDeallocation(DC, C, State);

  if (!State)
    return;

  State = checkArgInitializedness(Call, C, State);

  // If we make it here, record our assumptions about the callee.
  C.addTransition(State);
}

void CallAndMessageChecker::checkPreObjCMessage(const ObjCMethodCall &msg,
                                                CheckerContext &C) const {
  SVal recVal = msg.getReceiverSVal();
  if (recVal.isUndef()) {
    if (!ChecksEnabled[CK_UndefReceiver]) {
      C.addSink();
      return;
    }
    if (ExplodedNode *N = C.generateErrorNode()) {
      const BugType *BT = nullptr;
      switch (msg.getMessageKind()) {
      case OCM_Message:
        BT = &MsgUndefBug;
        break;
      case OCM_PropertyAccess:
        BT = &ObjCPropUndefBug;
        break;
      case OCM_Subscript:
        BT = &ObjCSubscriptUndefBug;
        break;
      }
      assert(BT && "Unknown message kind.");

      auto R = std::make_unique<PathSensitiveBugReport>(*BT, BT->getDescription(), N);
      const ObjCMessageExpr *ME = msg.getOriginExpr();
      R->addRange(ME->getReceiverRange());

      // FIXME: getTrackNullOrUndefValueVisitor can't handle "super" yet.
      if (const Expr *ReceiverE = ME->getInstanceReceiver())
        bugreporter::trackExpressionValue(N, ReceiverE, *R);
      C.emitReport(std::move(R));
    }
    return;
  }
}

void CallAndMessageChecker::checkObjCMessageNil(const ObjCMethodCall &msg,
                                                CheckerContext &C) const {
  HandleNilReceiver(C, C.getState(), msg);
}

void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C,
                                               const ObjCMethodCall &msg,
                                               ExplodedNode *N) const {
  if (!ChecksEnabled[CK_NilReceiver]) {
    C.addSink();
    return;
  }

  const ObjCMessageExpr *ME = msg.getOriginExpr();

  QualType ResTy = msg.getResultType();

  SmallString<200> buf;
  llvm::raw_svector_ostream os(buf);
  os << "The receiver of message '";
  ME->getSelector().print(os);
  os << "' is nil";
  if (ResTy->isReferenceType()) {
    os << ", which results in forming a null reference";
  } else {
    os << " and returns a value of type '";
    msg.getResultType().print(os, C.getLangOpts());
    os << "' that will be garbage";
  }

  auto report =
      std::make_unique<PathSensitiveBugReport>(MsgRetBug, os.str(), N);
  report->addRange(ME->getReceiverRange());
  // FIXME: This won't track "self" in messages to super.
  if (const Expr *receiver = ME->getInstanceReceiver()) {
    bugreporter::trackExpressionValue(N, receiver, *report);
  }
  C.emitReport(std::move(report));
}

static bool supportsNilWithFloatRet(const llvm::Triple &triple) {
  return (triple.getVendor() == llvm::Triple::Apple &&
          (triple.isiOS() || triple.isWatchOS() ||
           !triple.isMacOSXVersionLT(10,5)));
}

void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C,
                                              ProgramStateRef state,
                                              const ObjCMethodCall &Msg) const {
  ASTContext &Ctx = C.getASTContext();

  // Check the return type of the message expression.  A message to nil will
  // return different values depending on the return type and the architecture.
  QualType RetTy = Msg.getResultType();
  CanQualType CanRetTy = Ctx.getCanonicalType(RetTy);
  const LocationContext *LCtx = C.getLocationContext();

  if (CanRetTy->isStructureOrClassType()) {
    // Structure returns are safe since the compiler zeroes them out.
    SVal V = C.getSValBuilder().makeZeroVal(RetTy);
    C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
    return;
  }

  // Other cases: check if sizeof(return type) > sizeof(void*)
  if (CanRetTy != Ctx.VoidTy && C.getLocationContext()->getParentMap()
                                  .isConsumedExpr(Msg.getOriginExpr())) {
    // Compute: sizeof(void *) and sizeof(return type)
    const uint64_t voidPtrSize = Ctx.getTypeSize(Ctx.VoidPtrTy);
    const uint64_t returnTypeSize = Ctx.getTypeSize(CanRetTy);

    if (CanRetTy.getTypePtr()->isReferenceType()||
        (voidPtrSize < returnTypeSize &&
         !(supportsNilWithFloatRet(Ctx.getTargetInfo().getTriple()) &&
           (Ctx.FloatTy == CanRetTy ||
            Ctx.DoubleTy == CanRetTy ||
            Ctx.LongDoubleTy == CanRetTy ||
            Ctx.LongLongTy == CanRetTy ||
            Ctx.UnsignedLongLongTy == CanRetTy)))) {
      if (ExplodedNode *N = C.generateErrorNode(state))
        emitNilReceiverBug(C, Msg, N);
      return;
    }

    // Handle the safe cases where the return value is 0 if the
    // receiver is nil.
    //
    // FIXME: For now take the conservative approach that we only
    // return null values if we *know* that the receiver is nil.
    // This is because we can have surprises like:
    //
    //   ... = [[NSScreens screens] objectAtIndex:0];
    //
    // What can happen is that [... screens] could return nil, but
    // it most likely isn't nil.  We should assume the semantics
    // of this case unless we have *a lot* more knowledge.
    //
    SVal V = C.getSValBuilder().makeZeroVal(RetTy);
    C.addTransition(state->BindExpr(Msg.getOriginExpr(), LCtx, V));
    return;
  }

  C.addTransition(state);
}

void ento::registerCallAndMessageChecker(CheckerManager &Mgr) {
  CallAndMessageChecker *Chk = Mgr.registerChecker<CallAndMessageChecker>();

#define QUERY_CHECKER_OPTION(OPTION)                                           \
  Chk->ChecksEnabled[CallAndMessageChecker::CK_##OPTION] =                     \
      Mgr.getAnalyzerOptions().getCheckerBooleanOption(                        \
          Mgr.getCurrentCheckerName(), #OPTION);

  QUERY_CHECKER_OPTION(FunctionPointer)
  QUERY_CHECKER_OPTION(ParameterCount)
  QUERY_CHECKER_OPTION(CXXThisMethodCall)
  QUERY_CHECKER_OPTION(CXXDeallocationArg)
  QUERY_CHECKER_OPTION(ArgInitializedness)
  QUERY_CHECKER_OPTION(ArgPointeeInitializedness)
  QUERY_CHECKER_OPTION(NilReceiver)
  QUERY_CHECKER_OPTION(UndefReceiver)

  Chk->ArgPointeeInitializednessComplete =
      Mgr.getAnalyzerOptions().getCheckerBooleanOption(
          Mgr.getCurrentCheckerName(), "ArgPointeeInitializednessComplete");
}

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