@@ -35,9 +35,10 @@ class MatchDescendantVisitor
35
35
MatchDescendantVisitor (const internal::DynTypedMatcher *Matcher,
36
36
internal::ASTMatchFinder *Finder,
37
37
internal::BoundNodesTreeBuilder *Builder,
38
- internal::ASTMatchFinder::BindKind Bind)
38
+ internal::ASTMatchFinder::BindKind Bind,
39
+ const bool ignoreUnevaluatedContext)
39
40
: Matcher(Matcher), Finder(Finder), Builder(Builder), Bind(Bind),
40
- Matches (false ) {}
41
+ Matches (false ), ignoreUnevaluatedContext(ignoreUnevaluatedContext) {}
41
42
42
43
// Returns true if a match is found in a subtree of `DynNode`, which belongs
43
44
// to the same callable of `DynNode`.
@@ -70,6 +71,48 @@ class MatchDescendantVisitor
70
71
return VisitorBase::TraverseDecl (Node);
71
72
}
72
73
74
+ bool TraverseGenericSelectionExpr (GenericSelectionExpr *Node) {
75
+ // These are unevaluated, except the result expression.
76
+ if (ignoreUnevaluatedContext)
77
+ return TraverseStmt (Node->getResultExpr ());
78
+ return VisitorBase::TraverseGenericSelectionExpr (Node);
79
+ }
80
+
81
+ bool TraverseUnaryExprOrTypeTraitExpr (UnaryExprOrTypeTraitExpr *Node) {
82
+ // Unevaluated context.
83
+ if (ignoreUnevaluatedContext)
84
+ return true ;
85
+ return VisitorBase::TraverseUnaryExprOrTypeTraitExpr (Node);
86
+ }
87
+
88
+ bool TraverseTypeOfExprTypeLoc (TypeOfExprTypeLoc Node) {
89
+ // Unevaluated context.
90
+ if (ignoreUnevaluatedContext)
91
+ return true ;
92
+ return VisitorBase::TraverseTypeOfExprTypeLoc (Node);
93
+ }
94
+
95
+ bool TraverseDecltypeTypeLoc (DecltypeTypeLoc Node) {
96
+ // Unevaluated context.
97
+ if (ignoreUnevaluatedContext)
98
+ return true ;
99
+ return VisitorBase::TraverseDecltypeTypeLoc (Node);
100
+ }
101
+
102
+ bool TraverseCXXNoexceptExpr (CXXNoexceptExpr *Node) {
103
+ // Unevaluated context.
104
+ if (ignoreUnevaluatedContext)
105
+ return true ;
106
+ return VisitorBase::TraverseCXXNoexceptExpr (Node);
107
+ }
108
+
109
+ bool TraverseCXXTypeidExpr (CXXTypeidExpr *Node) {
110
+ // Unevaluated context.
111
+ if (ignoreUnevaluatedContext)
112
+ return true ;
113
+ return VisitorBase::TraverseCXXTypeidExpr (Node);
114
+ }
115
+
73
116
bool TraverseStmt (Stmt *Node, DataRecursionQueue *Queue = nullptr ) {
74
117
if (!Node)
75
118
return true ;
@@ -111,6 +154,7 @@ class MatchDescendantVisitor
111
154
internal::BoundNodesTreeBuilder ResultBindings;
112
155
const internal::ASTMatchFinder::BindKind Bind;
113
156
bool Matches;
157
+ bool ignoreUnevaluatedContext;
114
158
};
115
159
116
160
// Because we're dealing with raw pointers, let's define what we mean by that.
@@ -121,11 +165,18 @@ static auto hasPointerType() {
121
165
static auto hasArrayType () {
122
166
return hasType (hasCanonicalType (arrayType ()));
123
167
}
124
-
125
- AST_MATCHER_P (Stmt, forEveryDescendant , internal::Matcher<Stmt>, innerMatcher) {
168
+
169
+ AST_MATCHER_P (Stmt, forEachDescendantEvaluatedStmt , internal::Matcher<Stmt>, innerMatcher) {
126
170
const DynTypedMatcher &DTM = static_cast <DynTypedMatcher>(innerMatcher);
127
171
128
- MatchDescendantVisitor Visitor (&DTM, Finder, Builder, ASTMatchFinder::BK_All);
172
+ MatchDescendantVisitor Visitor (&DTM, Finder, Builder, ASTMatchFinder::BK_All, true );
173
+ return Visitor.findMatch (DynTypedNode::create (Node));
174
+ }
175
+
176
+ AST_MATCHER_P (Stmt, forEachDescendantStmt, internal::Matcher<Stmt>, innerMatcher) {
177
+ const DynTypedMatcher &DTM = static_cast <DynTypedMatcher>(innerMatcher);
178
+
179
+ MatchDescendantVisitor Visitor (&DTM, Finder, Builder, ASTMatchFinder::BK_All, false );
129
180
return Visitor.findMatch (DynTypedNode::create (Node));
130
181
}
131
182
@@ -870,32 +921,31 @@ findGadgets(const Decl *D, const UnsafeBufferUsageHandler &Handler) {
870
921
871
922
// clang-format off
872
923
M.addMatcher (
873
- stmt (forEveryDescendant (
874
- eachOf (
924
+ stmt (eachOf (
875
925
// A `FixableGadget` matcher and a `WarningGadget` matcher should not disable
876
926
// each other (they could if they were put in the same `anyOf` group).
877
927
// We also should make sure no two `FixableGadget` (resp. `WarningGadget`) matchers
878
928
// match for the same node, so that we can group them
879
929
// in one `anyOf` group (for better performance via short-circuiting).
880
- stmt (eachOf (
930
+ forEachDescendantStmt ( stmt (eachOf (
881
931
#define FIXABLE_GADGET (x ) \
882
932
x ## Gadget::matcher ().bind (#x),
883
933
#include " clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def"
884
- // Also match DeclStmts because we'll need them when fixing
885
- // their underlying VarDecls that otherwise don't have
886
- // any backreferences to DeclStmts.
887
- declStmt ().bind (" any_ds" )
888
- )),
889
- stmt (anyOf (
934
+ // In parallel, match all DeclRefExprs so that to find out
935
+ // whether there are any uncovered by gadgets.
936
+ declRefExpr (anyOf (hasPointerType (), hasArrayType ()), to (varDecl ())).bind (" any_dre" )
937
+ ))),
938
+ forEachDescendantEvaluatedStmt (stmt (anyOf (
890
939
// Add Gadget::matcher() for every gadget in the registry.
891
940
#define WARNING_GADGET (x ) \
892
941
allOf (x ## Gadget::matcher ().bind (#x), notInSafeBufferOptOut (&Handler)),
893
942
#include " clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def"
894
- // In parallel, match all DeclRefExprs so that to find out
895
- // whether there are any uncovered by gadgets.
896
- declRefExpr (anyOf (hasPointerType (), hasArrayType ()), to (varDecl ())).bind (" any_dre" )
897
- )))
898
- )),
943
+ // Also match DeclStmts because we'll need them when fixing
944
+ // their underlying VarDecls that otherwise don't have
945
+ // any backreferences to DeclStmts.
946
+ declStmt ().bind (" any_ds" )
947
+ ))
948
+ ))),
899
949
&CB
900
950
);
901
951
// clang-format on
0 commit comments