//===--- UseNullptrCheck.cpp - clang-tidy----------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "UseNullptrCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"

using namespace clang;
using namespace clang::ast_matchers;
using namespace llvm;

namespace clang {
namespace tidy {
namespace modernize {
namespace {

const char CastSequence[] = "sequence";

AST_MATCHER(Type, sugaredNullptrType) {
  const Type *DesugaredType = Node.getUnqualifiedDesugaredType();
  if (const auto *BT = dyn_cast<BuiltinType>(DesugaredType))
    return BT->getKind() == BuiltinType::NullPtr;
  return false;
}

/// \brief Create a matcher that finds implicit casts as well as the head of a
/// sequence of zero or more nested explicit casts that have an implicit cast
/// to null within.
/// Finding sequences of explict casts is necessary so that an entire sequence
/// can be replaced instead of just the inner-most implicit cast.
StatementMatcher makeCastSequenceMatcher() {
  StatementMatcher ImplicitCastToNull = implicitCastExpr(
      anyOf(hasCastKind(CK_NullToPointer), hasCastKind(CK_NullToMemberPointer)),
      unless(hasImplicitDestinationType(qualType(substTemplateTypeParmType()))),
      unless(hasSourceExpression(hasType(sugaredNullptrType()))));

  return castExpr(anyOf(ImplicitCastToNull,
                        explicitCastExpr(hasDescendant(ImplicitCastToNull))),
                  unless(hasAncestor(explicitCastExpr())))
      .bind(CastSequence);
}

bool isReplaceableRange(SourceLocation StartLoc, SourceLocation EndLoc,
                        const SourceManager &SM) {
  return SM.isWrittenInSameFile(StartLoc, EndLoc);
}

/// \brief Replaces the provided range with the text "nullptr", but only if
/// the start and end location are both in main file.
/// Returns true if and only if a replacement was made.
void replaceWithNullptr(ClangTidyCheck &Check, SourceManager &SM,
                        SourceLocation StartLoc, SourceLocation EndLoc) {
  CharSourceRange Range(SourceRange(StartLoc, EndLoc), true);
  // Add a space if nullptr follows an alphanumeric character. This happens
  // whenever there is an c-style explicit cast to nullptr not surrounded by
  // parentheses and right beside a return statement.
  SourceLocation PreviousLocation = StartLoc.getLocWithOffset(-1);
  bool NeedsSpace = isAlphanumeric(*SM.getCharacterData(PreviousLocation));
  Check.diag(Range.getBegin(), "use nullptr") << FixItHint::CreateReplacement(
      Range, NeedsSpace ? " nullptr" : "nullptr");
}

/// \brief Returns the name of the outermost macro.
///
/// Given
/// \code
/// #define MY_NULL NULL
/// \endcode
/// If \p Loc points to NULL, this function will return the name MY_NULL.
StringRef getOutermostMacroName(SourceLocation Loc, const SourceManager &SM,
                                const LangOptions &LO) {
  assert(Loc.isMacroID());
  SourceLocation OutermostMacroLoc;

  while (Loc.isMacroID()) {
    OutermostMacroLoc = Loc;
    Loc = SM.getImmediateMacroCallerLoc(Loc);
  }

  return Lexer::getImmediateMacroName(OutermostMacroLoc, SM, LO);
}

/// \brief RecursiveASTVisitor for ensuring all nodes rooted at a given AST
/// subtree that have file-level source locations corresponding to a macro
/// argument have implicit NullTo(Member)Pointer nodes as ancestors.
class MacroArgUsageVisitor : public RecursiveASTVisitor<MacroArgUsageVisitor> {
public:
  MacroArgUsageVisitor(SourceLocation CastLoc, const SourceManager &SM)
      : CastLoc(CastLoc), SM(SM), Visited(false), CastFound(false),
        InvalidFound(false) {
    assert(CastLoc.isFileID());
  }

  bool TraverseStmt(Stmt *S) {
    bool VisitedPreviously = Visited;

    if (!RecursiveASTVisitor<MacroArgUsageVisitor>::TraverseStmt(S))
      return false;

    // The point at which VisitedPreviously is false and Visited is true is the
    // root of a subtree containing nodes whose locations match CastLoc. It's
    // at this point we test that the Implicit NullTo(Member)Pointer cast was
    // found or not.
    if (!VisitedPreviously) {
      if (Visited && !CastFound) {
        // Found nodes with matching SourceLocations but didn't come across a
        // cast. This is an invalid macro arg use. Can stop traversal
        // completely now.
        InvalidFound = true;
        return false;
      }
      // Reset state as we unwind back up the tree.
      CastFound = false;
      Visited = false;
    }
    return true;
  }

  bool VisitStmt(Stmt *S) {
    if (SM.getFileLoc(S->getLocStart()) != CastLoc)
      return true;
    Visited = true;

    const ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(S);
    if (Cast && (Cast->getCastKind() == CK_NullToPointer ||
                 Cast->getCastKind() == CK_NullToMemberPointer))
      CastFound = true;

    return true;
  }

  bool TraverseInitListExpr(InitListExpr *S) {
    // Only go through the semantic form of the InitListExpr, because
    // ImplicitCast might not appear in the syntactic form, and this results in
    // finding usages of the macro argument that don't have a ImplicitCast as an
    // ancestor (thus invalidating the replacement) when they actually have.
    return RecursiveASTVisitor<MacroArgUsageVisitor>::
        TraverseSynOrSemInitListExpr(
            S->isSemanticForm() ? S : S->getSemanticForm());
  }

  bool foundInvalid() const { return InvalidFound; }

private:
  SourceLocation CastLoc;
  const SourceManager &SM;

  bool Visited;
  bool CastFound;
  bool InvalidFound;
};

/// \brief Looks for implicit casts as well as sequences of 0 or more explicit
/// casts with an implicit null-to-pointer cast within.
///
/// The matcher this visitor is used with will find a single implicit cast or a
/// top-most explicit cast (i.e. it has no explicit casts as an ancestor) where
/// an implicit cast is nested within. However, there is no guarantee that only
/// explicit casts exist between the found top-most explicit cast and the
/// possibly more than one nested implicit cast. This visitor finds all cast
/// sequences with an implicit cast to null within and creates a replacement
/// leaving the outermost explicit cast unchanged to avoid introducing
/// ambiguities.
class CastSequenceVisitor : public RecursiveASTVisitor<CastSequenceVisitor> {
public:
  CastSequenceVisitor(ASTContext &Context, ArrayRef<StringRef> NullMacros,
                      ClangTidyCheck &check)
      : SM(Context.getSourceManager()), Context(Context),
        NullMacros(NullMacros), Check(check), FirstSubExpr(nullptr),
        PruneSubtree(false) {}

  bool TraverseStmt(Stmt *S) {
    // Stop traversing down the tree if requested.
    if (PruneSubtree) {
      PruneSubtree = false;
      return true;
    }
    return RecursiveASTVisitor<CastSequenceVisitor>::TraverseStmt(S);
  }

  // Only VisitStmt is overridden as we shouldn't find other base AST types
  // within a cast expression.
  bool VisitStmt(Stmt *S) {
    auto *C = dyn_cast<CastExpr>(S);
    // Catch the castExpr inside cxxDefaultArgExpr.
    if (auto *E = dyn_cast<CXXDefaultArgExpr>(S)) {
      C = dyn_cast<CastExpr>(E->getExpr());
      FirstSubExpr = nullptr;
    }
    if (!C) {
      FirstSubExpr = nullptr;
      return true;
    }

    auto* CastSubExpr = C->getSubExpr()->IgnoreParens();
    // Ignore cast expressions which cast nullptr literal.
    if (isa<CXXNullPtrLiteralExpr>(CastSubExpr)) {
      return true;
    }

    if (!FirstSubExpr)
      FirstSubExpr = CastSubExpr;

    if (C->getCastKind() != CK_NullToPointer &&
        C->getCastKind() != CK_NullToMemberPointer) {
      return true;
    }

    SourceLocation StartLoc = FirstSubExpr->getLocStart();
    SourceLocation EndLoc = FirstSubExpr->getLocEnd();

    // If the location comes from a macro arg expansion, *all* uses of that
    // arg must be checked to result in NullTo(Member)Pointer casts.
    //
    // If the location comes from a macro body expansion, check to see if its
    // coming from one of the allowed 'NULL' macros.
    if (SM.isMacroArgExpansion(StartLoc) && SM.isMacroArgExpansion(EndLoc)) {
      SourceLocation FileLocStart = SM.getFileLoc(StartLoc),
                     FileLocEnd = SM.getFileLoc(EndLoc);
      SourceLocation ImmediateMacroArgLoc, MacroLoc;
      // Skip NULL macros used in macro.
      if (!getMacroAndArgLocations(StartLoc, ImmediateMacroArgLoc, MacroLoc) ||
          ImmediateMacroArgLoc != FileLocStart)
        return skipSubTree();

      if (isReplaceableRange(FileLocStart, FileLocEnd, SM) &&
          allArgUsesValid(C)) {
        replaceWithNullptr(Check, SM, FileLocStart, FileLocEnd);
      }
      return true;
    }

    if (SM.isMacroBodyExpansion(StartLoc) && SM.isMacroBodyExpansion(EndLoc)) {
      StringRef OutermostMacroName =
          getOutermostMacroName(StartLoc, SM, Context.getLangOpts());

      // Check to see if the user wants to replace the macro being expanded.
      if (std::find(NullMacros.begin(), NullMacros.end(), OutermostMacroName) ==
          NullMacros.end()) {
        return skipSubTree();
      }

      StartLoc = SM.getFileLoc(StartLoc);
      EndLoc = SM.getFileLoc(EndLoc);
    }

    if (!isReplaceableRange(StartLoc, EndLoc, SM)) {
      return skipSubTree();
    }
    replaceWithNullptr(Check, SM, StartLoc, EndLoc);

    return true;
  }

private:
  bool skipSubTree() {
    PruneSubtree = true;
    return true;
  }

  /// \brief Tests that all expansions of a macro arg, one of which expands to
  /// result in \p CE, yield NullTo(Member)Pointer casts.
  bool allArgUsesValid(const CastExpr *CE) {
    SourceLocation CastLoc = CE->getLocStart();

    // Step 1: Get location of macro arg and location of the macro the arg was
    // provided to.
    SourceLocation ArgLoc, MacroLoc;
    if (!getMacroAndArgLocations(CastLoc, ArgLoc, MacroLoc))
      return false;

    // Step 2: Find the first ancestor that doesn't expand from this macro.
    ast_type_traits::DynTypedNode ContainingAncestor;
    if (!findContainingAncestor(
            ast_type_traits::DynTypedNode::create<Stmt>(*CE), MacroLoc,
            ContainingAncestor))
      return false;

    // Step 3:
    // Visit children of this containing parent looking for the least-descended
    // nodes of the containing parent which are macro arg expansions that expand
    // from the given arg location.
    // Visitor needs: arg loc.
    MacroArgUsageVisitor ArgUsageVisitor(SM.getFileLoc(CastLoc), SM);
    if (const auto *D = ContainingAncestor.get<Decl>())
      ArgUsageVisitor.TraverseDecl(const_cast<Decl *>(D));
    else if (const auto *S = ContainingAncestor.get<Stmt>())
      ArgUsageVisitor.TraverseStmt(const_cast<Stmt *>(S));
    else
      llvm_unreachable("Unhandled ContainingAncestor node type");

    return !ArgUsageVisitor.foundInvalid();
  }

  /// \brief Given the SourceLocation for a macro arg expansion, finds the
  /// non-macro SourceLocation of the macro the arg was passed to and the
  /// non-macro SourceLocation of the argument in the arg list to that macro.
  /// These results are returned via \c MacroLoc and \c ArgLoc respectively.
  /// These values are undefined if the return value is false.
  ///
  /// \returns false if one of the returned SourceLocations would be a
  /// SourceLocation pointing within the definition of another macro.
  bool getMacroAndArgLocations(SourceLocation Loc, SourceLocation &ArgLoc,
                               SourceLocation &MacroLoc) {
    assert(Loc.isMacroID() && "Only reasonble to call this on macros");

    ArgLoc = Loc;

    // Find the location of the immediate macro expansion.
    while (true) {
      std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(ArgLoc);
      const SrcMgr::SLocEntry *E = &SM.getSLocEntry(LocInfo.first);
      const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();

      SourceLocation OldArgLoc = ArgLoc;
      ArgLoc = Expansion.getExpansionLocStart();
      if (!Expansion.isMacroArgExpansion()) {
        if (!MacroLoc.isFileID())
          return false;

        StringRef Name =
            Lexer::getImmediateMacroName(OldArgLoc, SM, Context.getLangOpts());
        return std::find(NullMacros.begin(), NullMacros.end(), Name) !=
               NullMacros.end();
      }

      MacroLoc = SM.getExpansionRange(ArgLoc).getBegin();

      ArgLoc = Expansion.getSpellingLoc().getLocWithOffset(LocInfo.second);
      if (ArgLoc.isFileID())
        return true;

      // If spelling location resides in the same FileID as macro expansion
      // location, it means there is no inner macro.
      FileID MacroFID = SM.getFileID(MacroLoc);
      if (SM.isInFileID(ArgLoc, MacroFID)) {
        // Don't transform this case. If the characters that caused the
        // null-conversion come from within a macro, they can't be changed.
        return false;
      }
    }

    llvm_unreachable("getMacroAndArgLocations");
  }

  /// \brief Tests if TestMacroLoc is found while recursively unravelling
  /// expansions starting at TestLoc. TestMacroLoc.isFileID() must be true.
  /// Implementation is very similar to getMacroAndArgLocations() except in this
  /// case, it's not assumed that TestLoc is expanded from a macro argument.
  /// While unravelling expansions macro arguments are handled as with
  /// getMacroAndArgLocations() but in this function macro body expansions are
  /// also handled.
  ///
  /// False means either:
  /// - TestLoc is not from a macro expansion.
  /// - TestLoc is from a different macro expansion.
  bool expandsFrom(SourceLocation TestLoc, SourceLocation TestMacroLoc) {
    if (TestLoc.isFileID()) {
      return false;
    }

    SourceLocation Loc = TestLoc, MacroLoc;

    while (true) {
      std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
      const SrcMgr::SLocEntry *E = &SM.getSLocEntry(LocInfo.first);
      const SrcMgr::ExpansionInfo &Expansion = E->getExpansion();

      Loc = Expansion.getExpansionLocStart();

      if (!Expansion.isMacroArgExpansion()) {
        if (Loc.isFileID()) {
          return Loc == TestMacroLoc;
        }
        // Since Loc is still a macro ID and it's not an argument expansion, we
        // don't need to do the work of handling an argument expansion. Simply
        // keep recursively expanding until we hit a FileID or a macro arg
        // expansion or a macro arg expansion.
        continue;
      }

      MacroLoc = SM.getImmediateExpansionRange(Loc).getBegin();
      if (MacroLoc.isFileID() && MacroLoc == TestMacroLoc) {
        // Match made.
        return true;
      }

      Loc = Expansion.getSpellingLoc().getLocWithOffset(LocInfo.second);
      if (Loc.isFileID()) {
        // If we made it this far without finding a match, there is no match to
        // be made.
        return false;
      }
    }

    llvm_unreachable("expandsFrom");
  }

  /// \brief Given a starting point \c Start in the AST, find an ancestor that
  /// doesn't expand from the macro called at file location \c MacroLoc.
  ///
  /// \pre MacroLoc.isFileID()
  /// \returns true if such an ancestor was found, false otherwise.
  bool findContainingAncestor(ast_type_traits::DynTypedNode Start,
                              SourceLocation MacroLoc,
                              ast_type_traits::DynTypedNode &Result) {
    // Below we're only following the first parent back up the AST. This should
    // be fine since for the statements we care about there should only be one
    // parent, except for the case specified below.

    assert(MacroLoc.isFileID());

    while (true) {
      const auto &Parents = Context.getParents(Start);
      if (Parents.empty())
        return false;
      if (Parents.size() > 1) {
        // If there are more than one parents, don't do the replacement unless
        // they are InitListsExpr (semantic and syntactic form). In this case we
        // can choose any one here, and the ASTVisitor will take care of
        // traversing the right one.
        for (const auto &Parent : Parents) {
          if (!Parent.get<InitListExpr>())
            return false;
        }
      }

      const ast_type_traits::DynTypedNode &Parent = Parents[0];

      SourceLocation Loc;
      if (const auto *D = Parent.get<Decl>())
        Loc = D->getLocStart();
      else if (const auto *S = Parent.get<Stmt>())
        Loc = S->getLocStart();

      // TypeLoc and NestedNameSpecifierLoc are members of the parent map. Skip
      // them and keep going up.
      if (Loc.isValid()) {
        if (!expandsFrom(Loc, MacroLoc)) {
          Result = Parent;
          return true;
        }
      }
      Start = Parent;
    }

    llvm_unreachable("findContainingAncestor");
  }

private:
  SourceManager &SM;
  ASTContext &Context;
  ArrayRef<StringRef> NullMacros;
  ClangTidyCheck &Check;
  Expr *FirstSubExpr;
  bool PruneSubtree;
};

} // namespace

UseNullptrCheck::UseNullptrCheck(StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      NullMacrosStr(Options.get("NullMacros", "")) {
  StringRef(NullMacrosStr).split(NullMacros, ",");
}

void UseNullptrCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "NullMacros", NullMacrosStr);
}

void UseNullptrCheck::registerMatchers(MatchFinder *Finder) {
  // Only register the matcher for C++. Because this checker is used for
  // modernization, it is reasonable to run it on any C++ standard with the
  // assumption the user is trying to modernize their codebase.
  if (getLangOpts().CPlusPlus)
    Finder->addMatcher(makeCastSequenceMatcher(), this);
}

void UseNullptrCheck::check(const MatchFinder::MatchResult &Result) {
  const auto *NullCast = Result.Nodes.getNodeAs<CastExpr>(CastSequence);
  assert(NullCast && "Bad Callback. No node provided");

  // Given an implicit null-ptr cast or an explicit cast with an implicit
  // null-to-pointer cast within use CastSequenceVisitor to identify sequences
  // of explicit casts that can be converted into 'nullptr'.
  CastSequenceVisitor(*Result.Context, NullMacros, *this)
      .TraverseStmt(const_cast<CastExpr *>(NullCast));
}

} // namespace modernize
} // namespace tidy
} // namespace clang
