10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Lex/Preprocessor.h"
19 namespace cppcoreguidelines {
21 ProBoundsConstantArrayIndexCheck::ProBoundsConstantArrayIndexCheck(
24 IncludeStyle(Options.getLocalOrGlobal(
"IncludeStyle",
25 utils::IncludeSorter::IS_LLVM)) {}
34 const SourceManager &SM, Preprocessor *
PP, Preprocessor *ModuleExpanderPP) {
35 Inserter = std::make_unique<utils::IncludeInserter>(SM,
getLangOpts(),
37 PP->addPPCallbacks(Inserter->CreatePPCallbacks());
45 hasBase(ignoringImpCasts(hasType(constantArrayType().bind(
"type")))),
46 hasIndex(expr().bind(
"index")), unless(hasAncestor(isImplicit())))
52 hasOverloadedOperatorName(
"[]"),
54 0, hasType(cxxRecordDecl(hasName(
"::std::array")).bind(
"type"))),
55 hasArgument(1, expr().bind(
"index")))
61 const MatchFinder::MatchResult &Result) {
62 const auto *Matched = Result.Nodes.getNodeAs<Expr>(
"expr");
63 const auto *IndexExpr = Result.Nodes.getNodeAs<Expr>(
"index");
65 if (IndexExpr->isValueDependent())
69 if (!IndexExpr->isIntegerConstantExpr(
Index, *Result.Context,
nullptr,
71 SourceRange BaseRange;
72 if (
const auto *ArraySubscriptE = dyn_cast<ArraySubscriptExpr>(Matched))
73 BaseRange = ArraySubscriptE->getBase()->getSourceRange();
76 dyn_cast<CXXOperatorCallExpr>(Matched)->getArg(0)->getSourceRange();
77 SourceRange IndexRange = IndexExpr->getSourceRange();
79 auto Diag =
diag(Matched->getExprLoc(),
80 "do not use array subscript when the index is "
81 "not an integer constant expression; use gsl::at() "
83 if (!GslHeader.empty()) {
84 Diag << FixItHint::CreateInsertion(BaseRange.getBegin(),
"gsl::at(")
85 << FixItHint::CreateReplacement(
86 SourceRange(BaseRange.getEnd().getLocWithOffset(1),
87 IndexRange.getBegin().getLocWithOffset(-1)),
89 << FixItHint::CreateReplacement(Matched->getEndLoc(),
")")
90 << Inserter->CreateIncludeInsertion(
91 Result.SourceManager->getMainFileID(), GslHeader,
97 const auto *StdArrayDecl =
98 Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>(
"type");
105 diag(Matched->getExprLoc(),
"std::array<> index %0 is negative")
106 <<
Index.toString(10);
110 const TemplateArgumentList &TemplateArgs = StdArrayDecl->getTemplateArgs();
111 if (TemplateArgs.size() < 2)
114 const auto &SizeArg = TemplateArgs[1];
115 if (SizeArg.getKind() != TemplateArgument::Integral)
117 llvm::APInt ArraySize = SizeArg.getAsIntegral();
121 if (
Index.getZExtValue() >= ArraySize.getZExtValue()) {
122 diag(Matched->getExprLoc(),
123 "std::array<> index %0 is past the end of the array "
124 "(which contains %1 elements)")
125 <<
Index.toString(10) << ArraySize.toString(10,
false);