Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <paul.heidekrue...@tum.de>, Paul =?utf-8?q?Heidekrüger?= <p...@paulhdk.com>, Paul =?utf-8?q?Heidekrüger?= <p...@paulhdk.com>, Paul =?utf-8?q?Heidekrüger?= <p...@paulhdk.com>, Paul =?utf-8?q?Heidekrüger?= <p...@paulhdk.com>, Paul =?utf-8?q?Heidekrüger?= <p...@paulhdk.com> Message-ID: In-Reply-To: <llvm.org/llvm/llvm-project/pull/95...@github.com>
================ @@ -0,0 +1,232 @@ +//===--- ProBoundsAvoidUncheckedContainerAccesses.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 "ProBoundsAvoidUncheckedContainerAccesses.h" +#include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "llvm/ADT/StringRef.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::cppcoreguidelines { + +static constexpr llvm::StringRef DefaultExclusionStr = + "::std::map;::std::unordered_map;::std::flat_map"; + +ProBoundsAvoidUncheckedContainerAccesses:: + ProBoundsAvoidUncheckedContainerAccesses(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) { + + ExcludedClassesStr = Options.get("ExcludeClasses", DefaultExclusionStr); + ExcludedClasses = + clang::tidy::utils::options::parseStringList(ExcludedClassesStr); + FixMode = Options.get("FixMode", None); + FixFunction = Options.get("FixFunction", "gsl::at"); +} + +void ProBoundsAvoidUncheckedContainerAccesses::storeOptions( + ClangTidyOptions::OptionMap &Opts) { + + Options.store(Opts, "FixFunction", FixFunction); + Options.store(Opts, "FixMode", FixMode); + Options.store(Opts, "ExcludeClasses", ExcludedClassesStr); +} + +// TODO: if at() is defined in another class in the class hierarchy of the class +// that defines the operator[] we matched on, findAlternative() will not detect +// it. +static const CXXMethodDecl * +findAlternativeAt(const CXXMethodDecl *MatchedOperator) { + const CXXRecordDecl *Parent = MatchedOperator->getParent(); + const QualType SubscriptThisObjType = + MatchedOperator->getFunctionObjectParameterReferenceType(); + + for (const CXXMethodDecl *Method : Parent->methods()) { + // Require 'Method' to be as accessible as 'MatchedOperator' or more + if (MatchedOperator->getAccess() < Method->getAccess()) + continue; + + if (MatchedOperator->isConst() != Method->isConst()) + continue; + + const QualType AtThisObjType = + Method->getFunctionObjectParameterReferenceType(); + if (SubscriptThisObjType != AtThisObjType) + continue; + + if (!Method->getNameInfo().getName().isIdentifier() || + Method->getName() != "at") + continue; + + const bool SameReturnType = + Method->getReturnType() == MatchedOperator->getReturnType(); + if (!SameReturnType) + continue; + + const bool SameNumberOfArguments = + Method->getNumParams() == MatchedOperator->getNumParams(); + if (!SameNumberOfArguments) + continue; + + for (unsigned ArgInd = 0; ArgInd < Method->getNumParams(); ArgInd++) { + const bool SameArgType = + Method->parameters()[ArgInd]->getOriginalType() == + MatchedOperator->parameters()[ArgInd]->getOriginalType(); + if (!SameArgType) + continue; + } + + return Method; + } + return nullptr; +} + +void ProBoundsAvoidUncheckedContainerAccesses::registerMatchers( + MatchFinder *Finder) { + Finder->addMatcher( + mapAnyOf(cxxOperatorCallExpr, cxxMemberCallExpr) + .with(callee( + cxxMethodDecl( + hasOverloadedOperatorName("[]"), + anyOf(parameterCountIs(0), parameterCountIs(1)), + unless(matchers::matchesAnyListedName(ExcludedClasses))) + .bind("operator"))) + .bind("caller"), + this); +} + +void ProBoundsAvoidUncheckedContainerAccesses::check( + const MatchFinder::MatchResult &Result) { + + const auto *MatchedExpr = Result.Nodes.getNodeAs<CallExpr>("caller"); + + if (FixMode == None) { + diag(MatchedExpr->getCallee()->getBeginLoc(), + "possibly unsafe 'operator[]', consider bounds-safe alternatives") + << MatchedExpr->getCallee()->getSourceRange(); + return; + } + + if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(MatchedExpr)) { + // Case: a[i] + auto LeftBracket = SourceRange(OCE->getCallee()->getBeginLoc(), + OCE->getCallee()->getBeginLoc()); + auto RightBracket = ---------------- vbvictor wrote: ```suggestion const auto RightBracket = ``` https://github.com/llvm/llvm-project/pull/95220 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits