17 MatchFinder *Finder) {
18 auto LoopVariable = varDecl(hasType(
19 qualType(hasCanonicalType(anyOf(referenceType(), pointerType())))));
21 auto RangeInit = declRefExpr(to(varDecl(
22 hasType(recordDecl(hasAnyName(
"std::unordered_set",
"std::unordered_map",
23 "std::unordered_multiset",
24 "std::unordered_multimap"))
25 .bind(
"recorddecl")))));
27 Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVariable),
28 hasRangeInit(RangeInit.bind(
"rangeinit")))
29 .bind(
"cxxForRangeStmt"),
32 auto SortFuncM = callee(functionDecl(hasAnyName(
33 "std::is_sorted",
"std::nth_element",
"std::sort",
"std::partial_sort",
34 "std::partition",
"std::stable_partition",
"std::stable_sort")));
36 auto IteratesPointerEltsM = hasArgument(
38 cxxMemberCallExpr(on(hasType(cxxRecordDecl(has(fieldDecl(hasType(qualType(
39 hasCanonicalType(pointsTo(hasCanonicalType(pointerType()))))))))))));
42 callExpr(allOf(SortFuncM, IteratesPointerEltsM)).bind(
"sortsemantic"),
47 const MatchFinder::MatchResult &Result) {
48 const auto *ForRangePointers =
49 Result.Nodes.getNodeAs<CXXForRangeStmt>(
"cxxForRangeStmt");
51 if ((ForRangePointers) && !(ForRangePointers->getBeginLoc().isMacroID())) {
52 const auto *RangeInit = Result.Nodes.getNodeAs<Stmt>(
"rangeinit");
53 if (
const auto *ClassTemplate =
54 Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>(
56 const TemplateArgumentList &TemplateArgs =
57 ClassTemplate->getTemplateArgs();
58 const bool IsAlgoArgPointer =
59 TemplateArgs[0].getAsType()->isPointerType();
61 if (IsAlgoArgPointer) {
62 const SourceRange R = RangeInit->getSourceRange();
63 diag(R.getBegin(),
"iteration of pointers is nondeterministic") << R;
68 const auto *SortPointers = Result.Nodes.getNodeAs<Stmt>(
"sortsemantic");
70 if ((SortPointers) && !(SortPointers->getBeginLoc().isMacroID())) {
71 const SourceRange R = SortPointers->getSourceRange();
72 diag(R.getBegin(),
"sorting pointers is nondeterministic") << R;