//===--- ProBoundsConstantArrayIndexCheck.cpp - clang-tidy-----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#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 {
namespace cppcoreguidelines {

ProBoundsConstantArrayIndexCheck::ProBoundsConstantArrayIndexCheck(
    StringRef Name, ClangTidyContext *Context)
    : ClangTidyCheck(Name, Context), GslHeader(Options.get("GslHeader", "")),
      Inserter(Options.getLocalOrGlobal("IncludeStyle",
                                        utils::IncludeSorter::IS_LLVM)) {}

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

void ProBoundsConstantArrayIndexCheck::registerPPCallbacks(
    const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) {
  Inserter.registerPreprocessor(PP);
}

void ProBoundsConstantArrayIndexCheck::registerMatchers(MatchFinder *Finder) {
  // Note: if a struct contains an array member, the compiler-generated
  // constructor has an arraySubscriptExpr.
  Finder->addMatcher(
      arraySubscriptExpr(
          hasBase(ignoringImpCasts(hasType(constantArrayType().bind("type")))),
          hasIndex(expr().bind("index")), unless(hasAncestor(isImplicit())))
          .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");

  if (IndexExpr->isValueDependent())
    return; // We check in the specialization.

  Optional<llvm::APSInt> Index =
      IndexExpr->getIntegerConstantExpr(*Result.Context);
  if (!Index) {
    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->getEndLoc(), ")")
           << Inserter.createMainFileIncludeInsertion(GslHeader);
    }
    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 cppcoreguidelines
} // namespace tidy
} // namespace clang
