// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "nullability/pointer_nullability_diagnosis.h"

#include <optional>
#include <string>

#include "nullability/pointer_nullability.h"
#include "nullability/pointer_nullability_matchers.h"
#include "nullability/type_nullability.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Stmt.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Basic/Specifiers.h"

namespace clang::tidy::nullability {

using ast_matchers::MatchFinder;
using dataflow::CFGMatchSwitchBuilder;
using dataflow::Environment;
using dataflow::TransferStateForDiagnostics;

namespace {

// Returns true if `Expr` is uninterpreted or known to be nullable.
bool isNullableOrUntracked(const Expr *E, const Environment &Env) {
  auto *ActualVal = getPointerValueFromExpr(E, Env);
  if (ActualVal == nullptr) {
    llvm::dbgs()
        << "The dataflow analysis framework does not model a PointerValue for "
           "the following Expr, and thus its dereference is marked as "
           "unsafe:\n";
    E->dump();
  }
  return !ActualVal || isNullable(*ActualVal, Env);
}

// Returns true if an uninterpreted or nullable `Expr` was assigned to a
// construct with a non-null `DeclaredType`.
bool isIncompatibleAssignment(QualType DeclaredType, const Expr *E,
                              const Environment &Env, ASTContext &Ctx) {
  CHECK(DeclaredType->isAnyPointerType());
  return getNullabilityKind(DeclaredType, Ctx) == NullabilityKind::NonNull &&
         isNullableOrUntracked(E, Env);
}

std::optional<CFGElement> diagnoseDereference(
    const UnaryOperator *UnaryOp, const MatchFinder::MatchResult &,
    const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
  if (isNullableOrUntracked(UnaryOp->getSubExpr(), State.Env)) {
    return std::optional<CFGElement>(CFGStmt(UnaryOp));
  }
  return std::nullopt;
}

std::optional<CFGElement> diagnoseArrow(
    const MemberExpr *MemberExpr, const MatchFinder::MatchResult &Result,
    const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
  if (isNullableOrUntracked(MemberExpr->getBase(), State.Env)) {
    return std::optional<CFGElement>(CFGStmt(MemberExpr));
  }
  return std::nullopt;
}

bool isIncompatibleArgumentList(const FunctionProtoType &CalleeFPT,
                                ArrayRef<const Expr *> Args,
                                const Environment &Env, ASTContext &Ctx) {
  auto ParamTypes = CalleeFPT.getParamTypes();
  // C-style varargs cannot be annotated and therefore are unchecked.
  if (CalleeFPT.isVariadic()) {
    CHECK_GE(Args.size(), ParamTypes.size());
    Args = Args.take_front(ParamTypes.size());
  }
  CHECK_EQ(ParamTypes.size(), Args.size());
  for (unsigned int I = 0; I < Args.size(); ++I) {
    auto ParamType = ParamTypes[I].getNonReferenceType();
    if (!ParamType->isAnyPointerType()) {
      continue;
    }
    if (isIncompatibleAssignment(ParamType, Args[I], Env, Ctx)) {
      return true;
    }
  }
  return false;
}

NullabilityKind parseNullabilityKind(StringRef EnumName) {
  return llvm::StringSwitch<NullabilityKind>(EnumName)
      .Case("NK_nonnull", NullabilityKind::NonNull)
      .Case("NK_nullable", NullabilityKind::Nullable)
      .Case("NK_unspecified", NullabilityKind::Unspecified)
      .Default(NullabilityKind::Unspecified);
}

/// Evaluates the `__assert_nullability` call by comparing the expected
/// nullability to the nullability computed by the dataflow analysis.
///
/// If the function being diagnosed is called `__assert_nullability`, we assume
/// it is a call of the shape __assert_nullability<a, b, c, ...>(p), where `p`
/// is an expression that contains pointers and a, b, c ... represent each of
/// the NullabilityKinds in `p`'s expected nullability. An expression's
/// nullability can be expressed as a vector of NullabilityKinds, where each
/// vector element corresponds to one of the pointers contained in the
/// expression.
///
/// For example:
/// \code
///    enum NullabilityKind {
///      NK_nonnull,
///      NK_nullable,
///      NK_unspecified,
///    };
///
///    template<NullabilityKind ...NK, typename T>
///    void __assert_nullability(T&);
///
///    template<typename T0, typename T1>
///    struct Struct2Arg {
///      T0 arg0;
///      T1 arg1;
///    };
///
///    void target(Struct2Arg<int *, int * _Nullable> p) {
///      __assert_nullability<NK_unspecified, NK_nullable>(p);
///    }
/// \endcode
bool diagnoseAssertNullabilityCall(
    const CallExpr *CE,
    const TransferStateForDiagnostics<PointerNullabilityLattice> &State,
    ASTContext &Ctx) {
  auto *DRE = cast<DeclRefExpr>(CE->getCallee()->IgnoreImpCasts());

  // Extract the expected nullability from the template parameter pack.
  TypeNullability Expected;
  for (auto P : DRE->template_arguments()) {
    if (P.getArgument().getKind() == TemplateArgument::Expression) {
      if (auto *EnumDRE = dyn_cast<DeclRefExpr>(P.getSourceExpression())) {
        Expected.push_back(parseNullabilityKind(EnumDRE->getDecl()->getName()));
      }
    }
  }

  // Compare the nullability computed by nullability analysis with the
  // expected one.
  const Expr *GivenExpr = CE->getArg(0);
  const TypeNullability *MaybeComputed =
      State.Lattice.getExprNullability(GivenExpr);
  if (MaybeComputed == nullptr) {
    llvm::dbgs()
        << "Could not evaluate __assert_nullability. Could not find the "
           "nullability of the argument expression: ";
    CE->dump();
    return false;
  }
  if (*MaybeComputed == Expected) return true;
  // The computed and expected nullabilities differ. Print both to aid
  // debugging.
  llvm::dbgs() << "__assert_nullability failed at location: ";
  CE->getExprLoc().print(llvm::dbgs(), Ctx.getSourceManager());
  llvm::dbgs() << "\nExpression:\n";
  GivenExpr->dump();
  llvm::dbgs() << "Expected nullability: ";
  llvm::dbgs() << nullabilityToString(Expected) << "\n";
  llvm::dbgs() << "Computed nullability: ";
  llvm::dbgs() << nullabilityToString(*MaybeComputed) << "\n";
  return false;
}

std::optional<CFGElement> diagnoseCallExpr(
    const CallExpr *CE, const MatchFinder::MatchResult &Result,
    const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
  // Check whether the callee is null.
  // - Skip direct callees to avoid handling builtin functions, which don't
  //   decay to pointer.
  // - Skip member callees, as they are not pointers at all (rather "bound
  //   member function type").
  //   Note that in `(obj.*nullable_pmf)()` the deref is *before* the call.
  if (!CE->getDirectCallee() && !isa<CXXMemberCallExpr>(CE) &&
      isNullableOrUntracked(CE->getCallee(), State.Env)) {
    return std::optional<CFGElement>(CFGStmt(CE->getCallee()));
  }

  if (auto *FD = CE->getDirectCallee()) {
    if (FD->getDeclName().isIdentifier() &&
        FD->getName() == "__assert_nullability" &&
        !diagnoseAssertNullabilityCall(CE, State, *Result.Context)) {
      // TODO: Handle __assert_nullability failures differently from regular
      // diagnostic ([[unsafe]]) failures.
      return std::optional<CFGElement>(CFGStmt(CE));
    }
  }

  auto *Callee = CE->getCalleeDecl();
  // TODO(mboehme): Retrieve the nullability directly from the callee using
  // `getNullabilityForChild(CE->getCallee())`, as what we have here now
  // doesn't work for callees that don't have a decl.
  if (!Callee) return std::nullopt;

  auto *CalleeType = Callee->getFunctionType();
  if (!CalleeType) return std::nullopt;

  // TODO(mboehme): We're only looking at the nullability spelled on the
  // `FunctionProtoType`, but there could be extra information in the callee.
  // An example (due to sammccall@):
  //
  // template <typename T> struct Sink {
  //   static void eat(T) { ... }
  // }
  // void target(Sink<Nonnull<int*>> &S) {
  //   S<Nonnull<int*>>::eat(nullptr); // no warning
  //   // callee is instantiated Sink<int*>::eat(int*)
  //   // however nullability vector of DRE S::eat should be [Nonnull]
  //   // (not sure if it is today)
  // }
  auto *CalleeFPT = CalleeType->getAs<FunctionProtoType>();
  if (!CalleeFPT) return std::nullopt;

  ArrayRef<const Expr *> Args(CE->getArgs(), CE->getNumArgs());
  // The first argument of an member operator call expression is the implicit
  // object argument, which does not appear in the list of parameter types.
  // Note that operator calls always have a direct callee.
  if (isa<CXXOperatorCallExpr>(CE) &&
      isa<CXXMethodDecl>(CE->getDirectCallee())) {
    Args = Args.drop_front();
  }
  return isIncompatibleArgumentList(*CalleeFPT, Args, State.Env,
                                    *Result.Context)
             ? std::optional<CFGElement>(CFGStmt(CE))
             : std::nullopt;
}

std::optional<CFGElement> diagnoseConstructExpr(
    const CXXConstructExpr *CE, const MatchFinder::MatchResult &Result,
    const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
  auto *CalleeFPT = CE->getConstructor()->getType()->getAs<FunctionProtoType>();
  if (!CalleeFPT) return std::nullopt;
  ArrayRef<const Expr *> ConstructorArgs(CE->getArgs(), CE->getNumArgs());
  return isIncompatibleArgumentList(*CalleeFPT, ConstructorArgs, State.Env,
                                    *Result.Context)
             ? std::optional<CFGElement>(CFGStmt(CE))
             : std::nullopt;
}

std::optional<CFGElement> diagnoseReturn(
    const ReturnStmt *RS, const MatchFinder::MatchResult &Result,
    const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
  auto ReturnType = cast<FunctionDecl>(State.Env.getDeclCtx())->getReturnType();

  // TODO: Handle non-pointer return types.
  if (!ReturnType->isPointerType()) {
    return std::nullopt;
  }

  auto *ReturnExpr = RS->getRetValue();
  CHECK(ReturnExpr->getType()->isPointerType());

  return isIncompatibleAssignment(ReturnType, ReturnExpr, State.Env,
                                  *Result.Context)
             ? std::optional<CFGElement>(CFGStmt(RS))
             : std::nullopt;
}

std::optional<CFGElement> diagnoseMemberInitializer(
    const CXXCtorInitializer *CI, const MatchFinder::MatchResult &Result,
    const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
  CHECK(CI->isAnyMemberInitializer());
  auto MemberType = CI->getAnyMember()->getType();
  if (!MemberType->isAnyPointerType()) {
    return std::nullopt;
  }
  auto MemberInitExpr = CI->getInit();
  return isIncompatibleAssignment(MemberType, MemberInitExpr, State.Env,
                                  *Result.Context)
             ? std::optional<CFGElement>(CFGInitializer(CI))
             : std::nullopt;
}

auto buildDiagnoser() {
  return CFGMatchSwitchBuilder<const dataflow::TransferStateForDiagnostics<
                                   PointerNullabilityLattice>,
                               std::optional<CFGElement>>()
      // (*)
      .CaseOfCFGStmt<UnaryOperator>(isPointerDereference(), diagnoseDereference)
      // (->)
      .CaseOfCFGStmt<MemberExpr>(isPointerArrow(), diagnoseArrow)
      // Check compatibility of parameter assignments
      .CaseOfCFGStmt<CallExpr>(isCallExpr(), diagnoseCallExpr)
      .CaseOfCFGStmt<ReturnStmt>(isPointerReturn(), diagnoseReturn)
      .CaseOfCFGStmt<CXXConstructExpr>(isConstructExpr(), diagnoseConstructExpr)
      .CaseOfCFGInit<CXXCtorInitializer>(isCtorMemberInitializer(),
                                         diagnoseMemberInitializer)
      .Build();
}

}  // namespace

PointerNullabilityDiagnoser::PointerNullabilityDiagnoser()
    : Diagnoser(buildDiagnoser()) {}

}  // namespace clang::tidy::nullability
