11#include "../utils/Matchers.h"
12#include "../utils/OptionsUtils.h"
13#include "clang/Lex/Lexer.h"
14#include "llvm/ADT/StringRef.h"
23 "addr-of-container-expr";
35 IgnoredContainers(utils::options::parseStringList(
36 Options.get(
"IgnoredContainers",
""))) {}
44 has(cxxMethodDecl(isPublic(), hasName(
"data")).bind(
"data")))
48 const auto NonTemplateContainerType =
49 qualType(hasUnqualifiedDesugaredType(recordType(hasDeclaration(Record))));
50 const auto TemplateContainerType =
51 qualType(hasUnqualifiedDesugaredType(templateSpecializationType(
52 hasDeclaration(classTemplateDecl(has(Record))))));
55 qualType(anyOf(NonTemplateContainerType, TemplateContainerType));
57 const auto ContainerExpr = anyOf(
63 unaryOperator(hasOperatorName(
"&"),
64 hasUnaryOperand(expr(anyOf(hasType(
Container),
72 const auto Zero = integerLiteral(equals(0));
74 const auto SubscriptOperator = callee(cxxMethodDecl(hasName(
"operator[]")));
78 unless(isExpansionInSystemHeader()), hasOperatorName(
"&"),
80 anyOf(cxxOperatorCallExpr(SubscriptOperator, argumentCountIs(2),
81 hasArgument(0, ContainerExpr),
82 hasArgument(1, Zero)),
83 cxxMemberCallExpr(SubscriptOperator, on(ContainerExpr),
84 argumentCountIs(1), hasArgument(0, Zero)),
85 arraySubscriptExpr(hasLHS(ContainerExpr), hasRHS(Zero))))))
91 const auto *UO = Result.Nodes.getNodeAs<UnaryOperator>(
AddressOfName);
99 if (DCE && !
CE->getType()->isPointerType())
104 SourceRange SrcRange =
CE->getSourceRange();
106 std::string ReplacementText{
107 Lexer::getSourceText(CharSourceRange::getTokenRange(SrcRange),
110 if (!isa<DeclRefExpr, ArraySubscriptExpr, CXXOperatorCallExpr, CallExpr,
112 ReplacementText =
"(" + ReplacementText +
")";
114 if (
CE->getType()->isPointerType())
115 ReplacementText +=
"->data()";
117 ReplacementText +=
".data()";
120 FixItHint::CreateReplacement(UO->getSourceRange(), ReplacementText);
121 diag(UO->getBeginLoc(),
122 "'data' should be used for accessing the data pointer instead of taking "
123 "the address of the 0-th element")
llvm::SmallString< 256U > Name
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
Base class for all clang-tidy checks.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
const LangOptions & getLangOpts() const
Returns the language options from the context.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
ContainerDataPointerCheck(StringRef Name, ClangTidyContext *Context)
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
inline ::clang::ast_matchers::internal::Matcher< NamedDecl > matchesAnyListedName(llvm::ArrayRef< StringRef > NameList)
constexpr llvm::StringLiteral AddressOfName
constexpr llvm::StringLiteral DerefContainerExprName
constexpr llvm::StringLiteral AddrOfContainerExprName
constexpr llvm::StringLiteral ContainerExprName
std::string serializeStringList(ArrayRef< StringRef > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
llvm::StringMap< ClangTidyValue > OptionMap