//===--- ProBoundsConstantArrayIndexCheck.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 "ProBoundsConstantArrayIndexCheck.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {

ProBoundsConstantArrayIndexCheck::ProBoundsConstantArrayIndexCheck(
    StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")),
      IncludeStyle(IncludeSorter::parseIncludeStyle(
          Options.get("IncludeStyle", "llvm"))) {}

void ProBoundsConstantArrayIndexCheck::storeOptions(
    ClangTidyOptions::OptionMap &Opts) {
  Options.store(Opts, "GslHeader", GslHeader);
  Options.store(Opts, "IncludeStyle", IncludeStyle);
}

void ProBoundsConstantArrayIndexCheck::registerPPCallbacks(
    CompilerInstance &Compiler) {
  if (!getLangOpts().CPlusPlus)
    return;

  Inserter.reset(new IncludeInserter(Compiler.getSourceManager(),
                                     Compiler.getLangOpts(), IncludeStyle));
  Compiler.getPreprocessor().addPPCallbacks(Inserter->CreatePPCallbacks());
}

void ProBoundsConstantArrayIndexCheck::registerMatchers(MatchFinder *Finder) {
  if (!getLangOpts().CPlusPlus)
    return;

  Finder->addMatcher(arraySubscriptExpr(hasBase(ignoringImpCasts(hasType(
                                            constantArrayType().bind("type")))),
                                        hasIndex(expr().bind("index")))
                         .bind("expr"),
                     this);

  Finder->addMatcher(
      cxxOperatorCallExpr(
          hasOverloadedOperatorName("[]"),
          hasArgument(
              0, hasType(cxxRecordDecl(hasName("::std::array")).bind("type"))),
          hasArgument(1, expr().bind("index")))
          .bind("expr"),
      this);
}

void ProBoundsConstantArrayIndexCheck::check(
    const MatchFinder::MatchResult &Result) {
  const auto *Matched = Result.Nodes.getNodeAs<Expr>("expr");
  const auto *IndexExpr = Result.Nodes.getNodeAs<Expr>("index");
  llvm::APSInt Index;
  if (!IndexExpr->isIntegerConstantExpr(Index, *Result.Context, nullptr,
                                        /*isEvaluated=*/true)) {
    SourceRange BaseRange;
    if (const auto *ArraySubscriptE = dyn_cast<ArraySubscriptExpr>(Matched))
      BaseRange = ArraySubscriptE->getBase()->getSourceRange();
    else
      BaseRange =
          dyn_cast<CXXOperatorCallExpr>(Matched)->getArg(0)->getSourceRange();
    SourceRange IndexRange = IndexExpr->getSourceRange();

    auto Diag = diag(Matched->getExprLoc(),
                     "do not use array subscript when the index is "
                     "not an integer constant expression; use gsl::at() "
                     "instead");
    if (!GslHeader.empty()) {
      Diag << FixItHint::CreateInsertion(BaseRange.getBegin(), "gsl::at(")
           << FixItHint::CreateReplacement(
                  SourceRange(BaseRange.getEnd().getLocWithOffset(1),
                              IndexRange.getBegin().getLocWithOffset(-1)),
                  ", ")
           << FixItHint::CreateReplacement(Matched->getLocEnd(), ")");

      Optional<FixItHint> Insertion = Inserter->CreateIncludeInsertion(
          Result.SourceManager->getMainFileID(), GslHeader,
          /*IsAngled=*/false);
      if (Insertion)
        Diag << Insertion.getValue();
    }
    return;
  }

  const auto *StdArrayDecl =
      Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>("type");

  // For static arrays, this is handled in clang-diagnostic-array-bounds.
  if (!StdArrayDecl)
    return;

  if (Index.isSigned() && Index.isNegative()) {
    diag(Matched->getExprLoc(),
         "std::array<> index %0 is negative")
        << Index.toString(10);
    return;
  }

  const TemplateArgumentList &TemplateArgs = StdArrayDecl->getTemplateArgs();
  if (TemplateArgs.size() < 2)
    return;
  // First template arg of std::array is the type, second arg is the size.
  const auto &SizeArg = TemplateArgs[1];
  if (SizeArg.getKind() != TemplateArgument::Integral)
    return;
  llvm::APInt ArraySize = SizeArg.getAsIntegral();

  // Get uint64_t values, because different bitwidths would lead to an assertion
  // in APInt::uge.
  if (Index.getZExtValue() >= ArraySize.getZExtValue()) {
    diag(Matched->getExprLoc(), "std::array<> index %0 is past the end of the array "
                                "(which contains %1 elements)")
        << Index.toString(10) << ArraySize.toString(10, false);
  }
}

} // namespace tidy
} // namespace clang
