10#include "clang/AST/ASTContext.h"
11#include "clang/ASTMatchers/ASTMatchFinder.h"
12#include "clang/Analysis/Analyses/ExprMutationAnalyzer.h"
13#include "clang/Frontend/CompilerInstance.h"
21AST_MATCHER_P(Stmt, nextStmt, ast_matchers::internal::Matcher<Stmt>,
23 DynTypedNodeList
Parents = Finder->getASTContext().getParents(Node);
27 auto *
C =
Parents[0].get<CompoundStmt>();
31 const auto *I = llvm::find(
C->body(), &Node);
32 assert(I !=
C->body_end() &&
"C is parent of Node");
33 if (++I ==
C->body_end())
36 return InnerMatcher.matches(**I, Finder,
Builder);
40namespace tidy::readability {
43 auto Returns = [](
bool V) {
44 return returnStmt(hasReturnValue(cxxBoolLiteral(equals(V))));
47 auto ReturnsButNotTrue =
48 returnStmt(hasReturnValue(unless(cxxBoolLiteral(equals(
true)))));
49 auto ReturnsButNotFalse =
50 returnStmt(hasReturnValue(unless(cxxBoolLiteral(equals(
false)))));
54 nextStmt(Returns(
false).bind(
"final_return")),
55 hasBody(allOf(hasDescendant(Returns(
true)),
56 unless(anyOf(hasDescendant(breakStmt()),
57 hasDescendant(gotoStmt()),
58 hasDescendant(ReturnsButNotTrue))))))
64 nextStmt(Returns(
true).bind(
"final_return")),
65 hasBody(allOf(hasDescendant(Returns(
false)),
66 unless(anyOf(hasDescendant(breakStmt()),
67 hasDescendant(gotoStmt()),
68 hasDescendant(ReturnsButNotFalse))))))
73static bool isViableLoop(
const CXXForRangeStmt &S, ASTContext &Context) {
75 ExprMutationAnalyzer Mutations(*S.getBody(), Context);
76 if (Mutations.isMutated(S.getLoopVariable()))
79 match(findAll(declRefExpr().bind(
"decl_ref")), *S.getBody(), Context);
81 return llvm::none_of(Matches, [&Mutations](
auto &
DeclRef) {
83 return Mutations.isMutated(
84 DeclRef.template getNodeAs<DeclRefExpr>(
"decl_ref")->getDecl());
90 if (
const auto *S = Result.Nodes.getNodeAs<CXXForRangeStmt>(
"any_of_loop")) {
94 diag(S->getForLoc(),
"replace loop by 'std%select{|::ranges}0::any_of()'")
96 }
else if (
const auto *S =
97 Result.Nodes.getNodeAs<CXXForRangeStmt>(
"all_of_loop")) {
101 diag(S->getForLoc(),
"replace loop by 'std%select{|::ranges}0::all_of()'")
CodeCompletionBuilder Builder
const DeclRefExpr * DeclRef
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.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
AST_MATCHER_P(UserDefinedLiteral, hasLiteral, clang::ast_matchers::internal::Matcher< Expr >, InnerMatcher)
static bool isViableLoop(const CXXForRangeStmt &S, ASTContext &Context)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//