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