47 auto Returns = [](
bool V) {
48 return returnStmt(hasReturnValue(cxxBoolLiteral(equals(V))));
51 const auto ReturnsButNotTrue =
52 returnStmt(hasReturnValue(unless(cxxBoolLiteral(equals(
true)))));
53 const auto ReturnsButNotFalse =
54 returnStmt(hasReturnValue(unless(cxxBoolLiteral(equals(
false)))));
55 const auto RangeInitMatcher =
56 optionally(expr(isUnsafeTemporaryRangeInit()).bind(
"unsafe_range_init"));
60 hasRangeInit(RangeInitMatcher),
61 nextStmt(Returns(
false).bind(
"final_return")),
62 hasBody(allOf(hasDescendant(Returns(
true)),
63 unless(anyOf(hasDescendant(breakStmt()),
64 hasDescendant(gotoStmt()),
65 hasDescendant(ReturnsButNotTrue))))))
71 hasRangeInit(RangeInitMatcher),
72 nextStmt(Returns(
true).bind(
"final_return")),
73 hasBody(allOf(hasDescendant(Returns(
false)),
74 unless(anyOf(hasDescendant(breakStmt()),
75 hasDescendant(gotoStmt()),
76 hasDescendant(ReturnsButNotFalse))))))
81static bool isViableLoop(
const CXXForRangeStmt &S, ASTContext &Context) {
82 ExprMutationAnalyzer Mutations(*S.getBody(), Context);
83 if (Mutations.isMutated(S.getLoopVariable()))
86 match(findAll(declRefExpr().bind(
"decl_ref")), *S.getBody(), Context);
88 return llvm::none_of(Matches, [&Mutations](
auto &DeclRef) {
90 return Mutations.isMutated(
91 DeclRef.template getNodeAs<DeclRefExpr>(
"decl_ref")->getDecl());
96 const auto *AnyOfS = Result.Nodes.getNodeAs<CXXForRangeStmt>(
"any_of_loop");
97 const auto *AllOfS = Result.Nodes.getNodeAs<CXXForRangeStmt>(
"all_of_loop");
98 const CXXForRangeStmt *S = AnyOfS ? AnyOfS : AllOfS;
103 const bool IsAnyOf = (AnyOfS !=
nullptr);
106 "replace loop by 'std%select{|::ranges}0::%select{all_of|any_of}1()'")
107 << getLangOpts().CPlusPlus20 << IsAnyOf;
109 if (
const auto *Init = Result.Nodes.getNodeAs<Expr>(
"unsafe_range_init")) {
110 if (getLangOpts().CPlusPlus20)
111 diag(Init->getExprLoc(),
112 "reusing the temporary range directly in the replacement may be "
113 "unsafe; consider materializing it in a local variable first, or "
114 "use 'std::ranges' algorithms which handle temporary ranges safely",
115 DiagnosticIDs::Note);
117 diag(Init->getExprLoc(),
118 "reusing the temporary range directly in the replacement may be "
119 "unsafe; consider materializing it in a local variable first",
120 DiagnosticIDs::Note);