clang-tools 22.0.0git
NondeterministicPointerIterationOrderCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "clang/Lex/Lexer.h"
11
12using namespace clang::ast_matchers;
13
14namespace clang::tidy::bugprone {
15
17 MatchFinder *Finder) {
18
19 auto LoopVariable = varDecl(hasType(
20 qualType(hasCanonicalType(anyOf(referenceType(), pointerType())))));
21
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")))));
27
28 Finder->addMatcher(cxxForRangeStmt(hasLoopVariable(LoopVariable),
29 hasRangeInit(RangeInit.bind("rangeinit")))
30 .bind("cxxForRangeStmt"),
31 this);
32
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")));
36
37 auto IteratesPointerEltsM = hasArgument(
38 0,
39 cxxMemberCallExpr(on(hasType(cxxRecordDecl(has(fieldDecl(hasType(qualType(
40 hasCanonicalType(pointsTo(hasCanonicalType(pointerType()))))))))))));
41
42 Finder->addMatcher(
43 callExpr(allOf(SortFuncM, IteratesPointerEltsM)).bind("sortsemantic"),
44 this);
45}
46
48 const MatchFinder::MatchResult &Result) {
49 const auto *ForRangePointers =
50 Result.Nodes.getNodeAs<CXXForRangeStmt>("cxxForRangeStmt");
51
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>(
56 "recorddecl")) {
57 const TemplateArgumentList &TemplateArgs =
58 ClassTemplate->getTemplateArgs();
59 const bool IsAlgoArgPointer =
60 TemplateArgs[0].getAsType()->isPointerType();
61
62 if (IsAlgoArgPointer) {
63 SourceRange R = RangeInit->getSourceRange();
64 diag(R.getBegin(), "iteration of pointers is nondeterministic") << R;
65 }
66 }
67 return;
68 }
69 const auto *SortPointers = Result.Nodes.getNodeAs<Stmt>("sortsemantic");
70
71 if ((SortPointers) && !(SortPointers->getBeginLoc().isMacroID())) {
72 SourceRange R = SortPointers->getSourceRange();
73 diag(R.getBegin(), "sorting pointers is nondeterministic") << R;
74 }
75}
76
77} // namespace clang::tidy::bugprone
void check(const ast_matchers::MatchFinder::MatchResult &Result) override