//===--- ExceptionEscapeCheck.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 "ExceptionEscapeCheck.h"

#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"

#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringSet.h"

using namespace clang::ast_matchers;

namespace {
typedef llvm::SmallVector<const clang::Type *, 8> TypeVec;
} // namespace

namespace clang {

static bool isBaseOf(const Type *DerivedType, const Type *BaseType) {
  const auto *DerivedClass = DerivedType->getAsCXXRecordDecl();
  const auto *BaseClass = BaseType->getAsCXXRecordDecl();
  if (!DerivedClass || !BaseClass)
    return false;

  return !DerivedClass->forallBases(
      [BaseClass](const CXXRecordDecl *Cur) { return Cur != BaseClass; });
}

static const TypeVec
throwsException(const Stmt *St, const TypeVec &Caught,
                llvm::SmallSet<const FunctionDecl *, 32> &CallStack);

static const TypeVec
throwsException(const FunctionDecl *Func,
                llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
  if (CallStack.count(Func))
    return TypeVec();

  if (const Stmt *Body = Func->getBody()) {
    CallStack.insert(Func);
    const TypeVec Result = throwsException(Body, TypeVec(), CallStack);
    CallStack.erase(Func);
    return Result;
  }

  TypeVec Result;
  if (const auto *FPT = Func->getType()->getAs<FunctionProtoType>()) {
    for (const QualType Ex : FPT->exceptions()) {
      Result.push_back(Ex.getTypePtr());
    }
  }
  return Result;
}

static const TypeVec
throwsException(const Stmt *St, const TypeVec &Caught,
                llvm::SmallSet<const FunctionDecl *, 32> &CallStack) {
  TypeVec Results;

  if (!St)
    return Results;

  if (const auto *Throw = dyn_cast<CXXThrowExpr>(St)) {
    if (const auto *ThrownExpr = Throw->getSubExpr()) {
      const auto *ThrownType =
          ThrownExpr->getType()->getUnqualifiedDesugaredType();
      if (ThrownType->isReferenceType()) {
        ThrownType = ThrownType->castAs<ReferenceType>()
                         ->getPointeeType()
                         ->getUnqualifiedDesugaredType();
      }
      if (const auto *TD = ThrownType->getAsTagDecl()) {
        if (TD->getDeclName().isIdentifier() && TD->getName() == "bad_alloc"
            && TD->isInStdNamespace())
          return Results;
      }
      Results.push_back(ThrownExpr->getType()->getUnqualifiedDesugaredType());
    } else {
      Results.append(Caught.begin(), Caught.end());
    }
  } else if (const auto *Try = dyn_cast<CXXTryStmt>(St)) {
    TypeVec Uncaught = throwsException(Try->getTryBlock(), Caught, CallStack);
    for (unsigned i = 0; i < Try->getNumHandlers(); ++i) {
      const CXXCatchStmt *Catch = Try->getHandler(i);
      if (!Catch->getExceptionDecl()) {
        const TypeVec Rethrown =
            throwsException(Catch->getHandlerBlock(), Uncaught, CallStack);
        Results.append(Rethrown.begin(), Rethrown.end());
        Uncaught.clear();
      } else {
        const auto *CaughtType =
            Catch->getCaughtType()->getUnqualifiedDesugaredType();
        if (CaughtType->isReferenceType()) {
          CaughtType = CaughtType->castAs<ReferenceType>()
                           ->getPointeeType()
                           ->getUnqualifiedDesugaredType();
        }
        auto NewEnd =
            llvm::remove_if(Uncaught, [&CaughtType](const Type *ThrownType) {
              return ThrownType == CaughtType ||
                     isBaseOf(ThrownType, CaughtType);
            });
        if (NewEnd != Uncaught.end()) {
          Uncaught.erase(NewEnd, Uncaught.end());
          const TypeVec Rethrown = throwsException(
              Catch->getHandlerBlock(), TypeVec(1, CaughtType), CallStack);
          Results.append(Rethrown.begin(), Rethrown.end());
        }
      }
    }
    Results.append(Uncaught.begin(), Uncaught.end());
  } else if (const auto *Call = dyn_cast<CallExpr>(St)) {
    if (const FunctionDecl *Func = Call->getDirectCallee()) {
      TypeVec Excs = throwsException(Func, CallStack);
      Results.append(Excs.begin(), Excs.end());
    }
  } else {
    for (const Stmt *Child : St->children()) {
      TypeVec Excs = throwsException(Child, Caught, CallStack);
      Results.append(Excs.begin(), Excs.end());
    }
  }
  return Results;
}

static const TypeVec throwsException(const FunctionDecl *Func) {
  llvm::SmallSet<const FunctionDecl *, 32> CallStack;
  return throwsException(Func, CallStack);
}

namespace ast_matchers {
AST_MATCHER_P(FunctionDecl, throws, internal::Matcher<Type>, InnerMatcher) {
  TypeVec ExceptionList = throwsException(&Node);
  auto NewEnd = llvm::remove_if(
      ExceptionList, [this, Finder, Builder](const Type *Exception) {
        return !InnerMatcher.matches(*Exception, Finder, Builder);
      });
  ExceptionList.erase(NewEnd, ExceptionList.end());
  return ExceptionList.size();
}

AST_MATCHER_P(Type, isIgnored, llvm::StringSet<>, IgnoredExceptions) {
  if (const auto *TD = Node.getAsTagDecl()) {
    if (TD->getDeclName().isIdentifier())
      return IgnoredExceptions.count(TD->getName()) > 0;
  }
  return false;
}

AST_MATCHER_P(FunctionDecl, isEnabled, llvm::StringSet<>,
              FunctionsThatShouldNotThrow) {
  return FunctionsThatShouldNotThrow.count(Node.getNameAsString()) > 0;
}
} // namespace ast_matchers

namespace tidy {
namespace bugprone {

ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name,
                                           ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get(
                                         "FunctionsThatShouldNotThrow", "")),
      RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) {
  llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec,
      IgnoredExceptionsVec;
  StringRef(RawFunctionsThatShouldNotThrow)
      .split(FunctionsThatShouldNotThrowVec, ",", -1, false);
  FunctionsThatShouldNotThrow.insert(FunctionsThatShouldNotThrowVec.begin(),
                                     FunctionsThatShouldNotThrowVec.end());
  StringRef(RawIgnoredExceptions).split(IgnoredExceptionsVec, ",", -1, false);
  IgnoredExceptions.insert(IgnoredExceptionsVec.begin(),
                           IgnoredExceptionsVec.end());
}

void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "FunctionsThatShouldNotThrow",
                RawFunctionsThatShouldNotThrow);
  Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions);
}

void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      functionDecl(allOf(anyOf(isNoThrow(), cxxDestructorDecl(),
                               cxxConstructorDecl(isMoveConstructor()),
                               cxxMethodDecl(isMoveAssignmentOperator()),
                               hasName("main"), hasName("swap"),
                               isEnabled(FunctionsThatShouldNotThrow)),
                         throws(unless(isIgnored(IgnoredExceptions)))))
          .bind("thrower"),
      this);
}

void ExceptionEscapeCheck::check(const MatchFinder::MatchResult &Result) {
  const FunctionDecl *MatchedDecl =
      Result.Nodes.getNodeAs<FunctionDecl>("thrower");
  if (!MatchedDecl)
    return;

  // FIXME: We should provide more information about the exact location where
  // the exception is thrown, maybe the full path the exception escapes
  diag(MatchedDecl->getLocation(), "an exception may be thrown in function %0 "
       "which should not throw exceptions") << MatchedDecl;
}

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