1//===----- NondeterministicPointerIterationOrderCheck.cpp - clang-tidy ----===//
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
9#include "NondeterministicPointerIterationOrderCheck.h"
10#include "clang/Lex/Lexer.h"
11
12using namespace clang::ast_matchers;
13
14namespace clang::tidy::bugprone {
15
16void NondeterministicPointerIterationOrderCheck::registerMatchers(
17 MatchFinder *Finder) {
18
19 auto LoopVariable = varDecl(hasType(
20 InnerMatcher: qualType(hasCanonicalType(InnerMatcher: anyOf(referenceType(), pointerType())))));
21
22 auto RangeInit = declRefExpr(to(InnerMatcher: varDecl(
23 hasType(InnerMatcher: recordDecl(hasAnyName("std::unordered_set", "std::unordered_map",
24 "std::unordered_multiset",
25 "std::unordered_multimap"))
26 .bind(ID: "recorddecl")))));
27
28 Finder->addMatcher(NodeMatch: cxxForRangeStmt(hasLoopVariable(InnerMatcher: LoopVariable),
29 hasRangeInit(InnerMatcher: RangeInit.bind(ID: "rangeinit")))
30 .bind(ID: "cxxForRangeStmt"),
31 Action: this);
32
33 auto SortFuncM = callee(InnerMatcher: 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 N: 0,
39 InnerMatcher: cxxMemberCallExpr(on(InnerMatcher: hasType(InnerMatcher: cxxRecordDecl(has(fieldDecl(hasType(InnerMatcher: qualType(
40 hasCanonicalType(InnerMatcher: pointsTo(InnerMatcher: hasCanonicalType(InnerMatcher: pointerType()))))))))))));
41
42 Finder->addMatcher(
43 NodeMatch: callExpr(allOf(SortFuncM, IteratesPointerEltsM)).bind(ID: "sortsemantic"),
44 Action: this);
45}
46
47void NondeterministicPointerIterationOrderCheck::check(
48 const MatchFinder::MatchResult &Result) {
49 const auto *ForRangePointers =
50 Result.Nodes.getNodeAs<CXXForRangeStmt>(ID: "cxxForRangeStmt");
51
52 if ((ForRangePointers) && !(ForRangePointers->getBeginLoc().isMacroID())) {
53 const auto *RangeInit = Result.Nodes.getNodeAs<Stmt>(ID: "rangeinit");
54 if (const auto *ClassTemplate =
55 Result.Nodes.getNodeAs<ClassTemplateSpecializationDecl>(
56 ID: "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(Loc: R.getBegin(), Description: "iteration of pointers is nondeterministic") << R;
65 }
66 }
67 return;
68 }
69 const auto *SortPointers = Result.Nodes.getNodeAs<Stmt>(ID: "sortsemantic");
70
71 if ((SortPointers) && !(SortPointers->getBeginLoc().isMacroID())) {
72 SourceRange R = SortPointers->getSourceRange();
73 diag(Loc: R.getBegin(), Description: "sorting pointers is nondeterministic") << R;
74 }
75}
76
77} // namespace clang::tidy::bugprone
78

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp