//===--- StaticAssertCheck.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 "StaticAssertCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Lexer.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include <string>

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace misc {

StaticAssertCheck::StaticAssertCheck(StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context) {}

void StaticAssertCheck::registerMatchers(MatchFinder *Finder) {
  // This checker only makes sense for languages that have static assertion
  // capabilities: C++11 and C11.
  if (!(getLangOpts().CPlusPlus11 || getLangOpts().C11))
    return;

  auto NegatedString = unaryOperator(
      hasOperatorName("!"), hasUnaryOperand(ignoringImpCasts(stringLiteral())));
  auto IsAlwaysFalse =
      expr(anyOf(cxxBoolLiteral(equals(false)), integerLiteral(equals(0)),
                 cxxNullPtrLiteralExpr(), gnuNullExpr(), NegatedString))
          .bind("isAlwaysFalse");
  auto IsAlwaysFalseWithCast = ignoringParenImpCasts(anyOf(
      IsAlwaysFalse, cStyleCastExpr(has(ignoringParenImpCasts(IsAlwaysFalse)))
                         .bind("castExpr")));
  auto AssertExprRoot = anyOf(
      binaryOperator(
          anyOf(hasOperatorName("&&"), hasOperatorName("==")),
          hasEitherOperand(ignoringImpCasts(stringLiteral().bind("assertMSG"))),
          anyOf(binaryOperator(hasEitherOperand(IsAlwaysFalseWithCast)),
                anything()))
          .bind("assertExprRoot"),
      IsAlwaysFalse);
  auto NonConstexprFunctionCall =
      callExpr(hasDeclaration(functionDecl(unless(isConstexpr()))));
  auto AssertCondition =
      expr(
          anyOf(expr(ignoringParenCasts(anyOf(
                    AssertExprRoot, unaryOperator(hasUnaryOperand(
                                        ignoringParenCasts(AssertExprRoot)))))),
                anything()),
          unless(findAll(NonConstexprFunctionCall)))
          .bind("condition");
  auto Condition =
      anyOf(ignoringParenImpCasts(callExpr(
                hasDeclaration(functionDecl(hasName("__builtin_expect"))),
                hasArgument(0, AssertCondition))),
            AssertCondition);

  Finder->addMatcher(conditionalOperator(hasCondition(Condition),
                                         unless(isInTemplateInstantiation()))
                         .bind("condStmt"),
                     this);

  Finder->addMatcher(
      ifStmt(hasCondition(Condition), unless(isInTemplateInstantiation()))
          .bind("condStmt"),
      this);
}

void StaticAssertCheck::check(const MatchFinder::MatchResult &Result) {
  const ASTContext *ASTCtx = Result.Context;
  const LangOptions &Opts = ASTCtx->getLangOpts();
  const SourceManager &SM = ASTCtx->getSourceManager();
  const auto *CondStmt = Result.Nodes.getNodeAs<Stmt>("condStmt");
  const auto *Condition = Result.Nodes.getNodeAs<Expr>("condition");
  const auto *IsAlwaysFalse = Result.Nodes.getNodeAs<Expr>("isAlwaysFalse");
  const auto *AssertMSG = Result.Nodes.getNodeAs<StringLiteral>("assertMSG");
  const auto *AssertExprRoot =
      Result.Nodes.getNodeAs<BinaryOperator>("assertExprRoot");
  const auto *CastExpr = Result.Nodes.getNodeAs<CStyleCastExpr>("castExpr");
  SourceLocation AssertExpansionLoc = CondStmt->getLocStart();

  if (!AssertExpansionLoc.isValid() || !AssertExpansionLoc.isMacroID())
    return;

  StringRef MacroName =
      Lexer::getImmediateMacroName(AssertExpansionLoc, SM, Opts);

  if (MacroName != "assert" || Condition->isValueDependent() ||
      Condition->isTypeDependent() || Condition->isInstantiationDependent() ||
      !Condition->isEvaluatable(*ASTCtx))
    return;

  // False literal is not the result of macro expansion.
  if (IsAlwaysFalse && (!CastExpr || CastExpr->getType()->isPointerType())) {
    SourceLocation FalseLiteralLoc =
        SM.getImmediateSpellingLoc(IsAlwaysFalse->getExprLoc());
    if (!FalseLiteralLoc.isMacroID())
      return;

    StringRef FalseMacroName =
        Lexer::getImmediateMacroName(FalseLiteralLoc, SM, Opts);
    if (FalseMacroName.compare_lower("false") == 0 ||
        FalseMacroName.compare_lower("null") == 0)
      return;
  }

  SourceLocation AssertLoc = SM.getImmediateMacroCallerLoc(AssertExpansionLoc);

  SmallVector<FixItHint, 4> FixItHints;
  SourceLocation LastParenLoc;
  if (AssertLoc.isValid() && !AssertLoc.isMacroID() &&
      (LastParenLoc = getLastParenLoc(ASTCtx, AssertLoc)).isValid()) {
    FixItHints.push_back(
        FixItHint::CreateReplacement(SourceRange(AssertLoc), "static_assert"));

    std::string StaticAssertMSG = ", \"\"";
    if (AssertExprRoot) {
      FixItHints.push_back(FixItHint::CreateRemoval(
          SourceRange(AssertExprRoot->getOperatorLoc())));
      FixItHints.push_back(FixItHint::CreateRemoval(
          SourceRange(AssertMSG->getLocStart(), AssertMSG->getLocEnd())));
      StaticAssertMSG = (Twine(", \"") + AssertMSG->getString() + "\"").str();
    }

    FixItHints.push_back(
        FixItHint::CreateInsertion(LastParenLoc, StaticAssertMSG));
  }

  diag(AssertLoc, "found assert() that could be replaced by static_assert()")
      << FixItHints;
}

SourceLocation StaticAssertCheck::getLastParenLoc(const ASTContext *ASTCtx,
                                                  SourceLocation AssertLoc) {
  const LangOptions &Opts = ASTCtx->getLangOpts();
  const SourceManager &SM = ASTCtx->getSourceManager();

  llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getFileID(AssertLoc));
  if (!Buffer)
    return SourceLocation();

  const char *BufferPos = SM.getCharacterData(AssertLoc);

  Token Token;
  Lexer Lexer(SM.getLocForStartOfFile(SM.getFileID(AssertLoc)), Opts,
              Buffer->getBufferStart(), BufferPos, Buffer->getBufferEnd());

  //        assert                          first left parenthesis
  if (Lexer.LexFromRawLexer(Token) || Lexer.LexFromRawLexer(Token) ||
      !Token.is(tok::l_paren))
    return SourceLocation();

  unsigned int ParenCount = 1;
  while (ParenCount && !Lexer.LexFromRawLexer(Token)) {
    if (Token.is(tok::l_paren))
      ++ParenCount;
    else if (Token.is(tok::r_paren))
      --ParenCount;
  }

  return Token.getLocation();
}

} // namespace misc
} // namespace tidy
} // namespace clang
