|
8 | 8 |
|
9 | 9 | #include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
|
10 | 10 | #include "clang/ASTMatchers/ASTMatchFinder.h"
|
11 |
| -#include "clang/AST/RecursiveASTVisitor.h" |
12 | 11 | #include "llvm/ADT/SmallVector.h"
|
13 | 12 |
|
14 | 13 | using namespace llvm;
|
15 | 14 | using namespace clang;
|
16 | 15 | using namespace ast_matchers;
|
17 | 16 |
|
18 |
| -namespace clang::ast_matchers { |
19 |
| -// A `RecursiveASTVisitor` that traverses all descendants of a given node "n" |
20 |
| -// except for those belonging to a different callable of "n". |
21 |
| -class MatchDescendantVisitor |
22 |
| - : public RecursiveASTVisitor<MatchDescendantVisitor> { |
23 |
| -public: |
24 |
| - typedef RecursiveASTVisitor<MatchDescendantVisitor> VisitorBase; |
25 |
| - |
26 |
| - // Creates an AST visitor that matches `Matcher` on all |
27 |
| - // descendants of a given node "n" except for the ones |
28 |
| - // belonging to a different callable of "n". |
29 |
| - MatchDescendantVisitor(const internal::DynTypedMatcher *Matcher, |
30 |
| - internal::ASTMatchFinder *Finder, |
31 |
| - internal::BoundNodesTreeBuilder *Builder, |
32 |
| - internal::ASTMatchFinder::BindKind Bind) |
33 |
| - : Matcher(Matcher), Finder(Finder), Builder(Builder), Bind(Bind), |
34 |
| - Matches(false) {} |
35 |
| - |
36 |
| - // Returns true if a match is found in a subtree of `DynNode`, which belongs |
37 |
| - // to the same callable of `DynNode`. |
38 |
| - bool findMatch(const DynTypedNode &DynNode) { |
39 |
| - Matches = false; |
40 |
| - if (const Stmt *StmtNode = DynNode.get<Stmt>()) { |
41 |
| - TraverseStmt(const_cast<Stmt *>(StmtNode)); |
42 |
| - *Builder = ResultBindings; |
43 |
| - return Matches; |
44 |
| - } |
45 |
| - return false; |
46 |
| - } |
47 |
| - |
48 |
| - // The following are overriding methods from the base visitor class. |
49 |
| - // They are public only to allow CRTP to work. They are *not *part |
50 |
| - // of the public API of this class. |
51 |
| - |
52 |
| - // For the matchers so far used in safe buffers, we only need to match |
53 |
| - // `Stmt`s. To override more as needed. |
54 |
| - |
55 |
| - bool TraverseDecl(Decl *Node) { |
56 |
| - if (!Node) |
57 |
| - return true; |
58 |
| - if (!match(*Node)) |
59 |
| - return false; |
60 |
| - // To skip callables: |
61 |
| - if (isa<FunctionDecl, BlockDecl, ObjCMethodDecl>(Node)) |
62 |
| - return true; |
63 |
| - // Traverse descendants |
64 |
| - return VisitorBase::TraverseDecl(Node); |
65 |
| - } |
66 |
| - |
67 |
| - bool TraverseStmt(Stmt *Node, DataRecursionQueue *Queue = nullptr) { |
68 |
| - if (!Node) |
69 |
| - return true; |
70 |
| - if (!match(*Node)) |
71 |
| - return false; |
72 |
| - // To skip callables: |
73 |
| - if (isa<LambdaExpr>(Node)) |
74 |
| - return true; |
75 |
| - return VisitorBase::TraverseStmt(Node); |
76 |
| - } |
77 |
| - |
78 |
| - bool shouldVisitTemplateInstantiations() const { return true; } |
79 |
| - bool shouldVisitImplicitCode() const { |
80 |
| - // TODO: let's ignore implicit code for now |
81 |
| - return false; |
82 |
| - } |
83 |
| - |
84 |
| -private: |
85 |
| - // Sets 'Matched' to true if 'Matcher' matches 'Node' |
86 |
| - // |
87 |
| - // Returns 'true' if traversal should continue after this function |
88 |
| - // returns, i.e. if no match is found or 'Bind' is 'BK_All'. |
89 |
| - template <typename T> bool match(const T &Node) { |
90 |
| - internal::BoundNodesTreeBuilder RecursiveBuilder(*Builder); |
91 |
| - |
92 |
| - if (Matcher->matches(DynTypedNode::create(Node), Finder, |
93 |
| - &RecursiveBuilder)) { |
94 |
| - ResultBindings.addMatch(RecursiveBuilder); |
95 |
| - Matches = true; |
96 |
| - if (Bind != internal::ASTMatchFinder::BK_All) |
97 |
| - return false; // Abort as soon as a match is found. |
98 |
| - } |
99 |
| - return true; |
100 |
| - } |
101 |
| - |
102 |
| - const internal::DynTypedMatcher *const Matcher; |
103 |
| - internal::ASTMatchFinder *const Finder; |
104 |
| - internal::BoundNodesTreeBuilder *const Builder; |
105 |
| - internal::BoundNodesTreeBuilder ResultBindings; |
106 |
| - const internal::ASTMatchFinder::BindKind Bind; |
107 |
| - bool Matches; |
108 |
| -}; |
109 |
| - |
110 |
| -AST_MATCHER_P(Stmt, forEveryDescendant, internal::Matcher<Stmt>, innerMatcher) { |
111 |
| - MatchDescendantVisitor Visitor(new DynTypedMatcher(innerMatcher), Finder, |
112 |
| - Builder, ASTMatchFinder::BK_All); |
113 |
| - return Visitor.findMatch(DynTypedNode::create(Node)); |
114 |
| -} |
115 |
| -} // namespace clang::ast_matchers |
116 |
| - |
117 | 17 | namespace {
|
118 | 18 | // Because the analysis revolves around variables and their types, we'll need to
|
119 | 19 | // track uses of variables (aka DeclRefExprs).
|
@@ -498,7 +398,7 @@ static std::pair<GadgetList, DeclUseTracker> findGadgets(const Decl *D) {
|
498 | 398 |
|
499 | 399 | // clang-format off
|
500 | 400 | M.addMatcher(
|
501 |
| - stmt(forEveryDescendant( |
| 401 | + stmt(forEachDescendant( |
502 | 402 | stmt(anyOf(
|
503 | 403 | // Add Gadget::matcher() for every gadget in the registry.
|
504 | 404 | #define GADGET(x) \
|
|
0 commit comments