//===--- DanglingHandleCheck.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 "DanglingHandleCheck.h"
#include "../utils/Matchers.h"
#include "../utils/OptionsUtils.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

using namespace clang::ast_matchers;
using namespace clang::tidy::matchers;

namespace clang {
namespace tidy {
namespace bugprone {

namespace {

ast_matchers::internal::BindableMatcher<Stmt>
handleFrom(const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle,
           const ast_matchers::internal::Matcher<Expr> &Arg) {
  return expr(
      anyOf(cxxConstructExpr(hasDeclaration(cxxMethodDecl(ofClass(IsAHandle))),
                             hasArgument(0, Arg)),
            cxxMemberCallExpr(hasType(cxxRecordDecl(IsAHandle)),
                              callee(memberExpr(member(cxxConversionDecl()))),
                              on(Arg))));
}

ast_matchers::internal::Matcher<Stmt> handleFromTemporaryValue(
    const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle) {
  // If a ternary operator returns a temporary value, then both branches hold a
  // temporary value. If one of them is not a temporary then it must be copied
  // into one to satisfy the type of the operator.
  const auto TemporaryTernary =
      conditionalOperator(hasTrueExpression(cxxBindTemporaryExpr()),
                          hasFalseExpression(cxxBindTemporaryExpr()));

  return handleFrom(IsAHandle, anyOf(cxxBindTemporaryExpr(), TemporaryTernary));
}

ast_matchers::internal::Matcher<RecordDecl> isASequence() {
  return hasAnyName("::std::deque", "::std::forward_list", "::std::list",
                    "::std::vector");
}

ast_matchers::internal::Matcher<RecordDecl> isASet() {
  return hasAnyName("::std::set", "::std::multiset", "::std::unordered_set",
                    "::std::unordered_multiset");
}

ast_matchers::internal::Matcher<RecordDecl> isAMap() {
  return hasAnyName("::std::map", "::std::multimap", "::std::unordered_map",
                    "::std::unordered_multimap");
}

ast_matchers::internal::BindableMatcher<Stmt> makeContainerMatcher(
    const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle) {
  // This matcher could be expanded to detect:
  //  - Constructors: eg. vector<string_view>(3, string("A"));
  //  - emplace*(): This requires a different logic to determine that
  //                the conversion will happen inside the container.
  //  - map's insert: This requires detecting that the pair conversion triggers
  //                  the bug. A little more complicated than what we have now.
  return callExpr(
      hasAnyArgument(
          ignoringParenImpCasts(handleFromTemporaryValue(IsAHandle))),
      anyOf(
          // For sequences: assign, push_back, resize.
          cxxMemberCallExpr(
              callee(functionDecl(hasAnyName("assign", "push_back", "resize"))),
              on(expr(hasType(hasUnqualifiedDesugaredType(
                  recordType(hasDeclaration(recordDecl(isASequence())))))))),
          // For sequences and sets: insert.
          cxxMemberCallExpr(callee(functionDecl(hasName("insert"))),
                            on(expr(hasType(hasUnqualifiedDesugaredType(
                                recordType(hasDeclaration(recordDecl(
                                    anyOf(isASequence(), isASet()))))))))),
          // For maps: operator[].
          cxxOperatorCallExpr(callee(cxxMethodDecl(ofClass(isAMap()))),
                              hasOverloadedOperatorName("[]"))));
}

} // anonymous namespace

DanglingHandleCheck::DanglingHandleCheck(StringRef Name,
                                         ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context),
      HandleClasses(utils::options::parseStringList(Options.get(
          "HandleClasses",
          "std::basic_string_view;std::experimental::basic_string_view"))),
      IsAHandle(cxxRecordDecl(hasAnyName(std::vector<StringRef>(
                                  HandleClasses.begin(), HandleClasses.end())))
                    .bind("handle")) {}

void DanglingHandleCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "HandleClasses",
                utils::options::serializeStringList(HandleClasses));
}

void DanglingHandleCheck::registerMatchersForVariables(MatchFinder *Finder) {
  const auto ConvertedHandle = handleFromTemporaryValue(IsAHandle);

  // Find 'Handle foo(ReturnsAValue());'
  Finder->addMatcher(
      varDecl(hasType(hasUnqualifiedDesugaredType(
                  recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
              hasInitializer(
                  exprWithCleanups(has(ignoringParenImpCasts(ConvertedHandle)))
                      .bind("bad_stmt"))),
      this);

  // Find 'Handle foo = ReturnsAValue();'
  Finder->addMatcher(
      varDecl(
          hasType(hasUnqualifiedDesugaredType(
              recordType(hasDeclaration(cxxRecordDecl(IsAHandle))))),
          unless(parmVarDecl()),
          hasInitializer(exprWithCleanups(has(ignoringParenImpCasts(handleFrom(
                                              IsAHandle, ConvertedHandle))))
                             .bind("bad_stmt"))),
      this);
  // Find 'foo = ReturnsAValue();  // foo is Handle'
  Finder->addMatcher(
      cxxOperatorCallExpr(callee(cxxMethodDecl(ofClass(IsAHandle))),
                          hasOverloadedOperatorName("="),
                          hasArgument(1, ConvertedHandle))
          .bind("bad_stmt"),
      this);

  // Container insertions that will dangle.
  Finder->addMatcher(makeContainerMatcher(IsAHandle).bind("bad_stmt"), this);
}

void DanglingHandleCheck::registerMatchersForReturn(MatchFinder *Finder) {
  // Return a local.
  Finder->addMatcher(
      returnStmt(
          // The AST contains two constructor calls:
          //   1. Value to Handle conversion.
          //   2. Handle copy construction.
          // We have to match both.
          has(ignoringImplicit(handleFrom(
              IsAHandle,
              handleFrom(IsAHandle,
                         declRefExpr(to(varDecl(
                             // Is function scope ...
                             hasAutomaticStorageDuration(),
                             // ... and it is a local array or Value.
                             anyOf(hasType(arrayType()),
                                   hasType(hasUnqualifiedDesugaredType(
                                       recordType(hasDeclaration(recordDecl(
                                           unless(IsAHandle)))))))))))))),
          // Temporary fix for false positives inside lambdas.
          unless(hasAncestor(lambdaExpr())))
          .bind("bad_stmt"),
      this);

  // Return a temporary.
  Finder->addMatcher(
      returnStmt(
          has(ignoringParenImpCasts(exprWithCleanups(has(ignoringParenImpCasts(
              handleFrom(IsAHandle, handleFromTemporaryValue(IsAHandle))))))))
          .bind("bad_stmt"),
      this);
}

void DanglingHandleCheck::registerMatchers(MatchFinder *Finder) {
  registerMatchersForVariables(Finder);
  registerMatchersForReturn(Finder);
}

void DanglingHandleCheck::check(const MatchFinder::MatchResult &Result) {
  auto *Handle = Result.Nodes.getNodeAs<CXXRecordDecl>("handle");
  diag(Result.Nodes.getNodeAs<Stmt>("bad_stmt")->getLocStart(),
       "%0 outlives its value")
      << Handle->getQualifiedNameAsString();
}

} // namespace bugprone
} // namespace tidy
} // namespace clang
