Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===--- SValVisitor.h - Visitor for SVal subclasses ------------*- C++ -*-===// |
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 | // This file defines the SValVisitor, SymExprVisitor, and MemRegionVisitor |
||
10 | // interfaces, and also FullSValVisitor, which visits all three hierarchies. |
||
11 | // |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H |
||
15 | #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H |
||
16 | |||
17 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" |
||
18 | #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" |
||
19 | #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" |
||
20 | |||
21 | namespace clang { |
||
22 | |||
23 | namespace ento { |
||
24 | |||
25 | /// SValVisitor - this class implements a simple visitor for SVal |
||
26 | /// subclasses. |
||
27 | template <typename ImplClass, typename RetTy = void> class SValVisitor { |
||
28 | public: |
||
29 | |||
30 | #define DISPATCH(NAME, CLASS) \ |
||
31 | return static_cast<ImplClass *>(this)->Visit ## NAME(V.castAs<CLASS>()) |
||
32 | |||
33 | RetTy Visit(SVal V) { |
||
34 | // Dispatch to VisitFooVal for each FooVal. |
||
35 | // Take namespaces (loc:: and nonloc::) into account. |
||
36 | switch (V.getBaseKind()) { |
||
37 | #define BASIC_SVAL(Id, Parent) case SVal::Id ## Kind: DISPATCH(Id, Id); |
||
38 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" |
||
39 | case SVal::LocKind: |
||
40 | switch (V.getSubKind()) { |
||
41 | #define LOC_SVAL(Id, Parent) \ |
||
42 | case loc::Id ## Kind: DISPATCH(Loc ## Id, loc :: Id); |
||
43 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" |
||
44 | } |
||
45 | llvm_unreachable("Unknown Loc sub-kind!"); |
||
46 | case SVal::NonLocKind: |
||
47 | switch (V.getSubKind()) { |
||
48 | #define NONLOC_SVAL(Id, Parent) \ |
||
49 | case nonloc::Id ## Kind: DISPATCH(NonLoc ## Id, nonloc :: Id); |
||
50 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" |
||
51 | } |
||
52 | llvm_unreachable("Unknown NonLoc sub-kind!"); |
||
53 | } |
||
54 | llvm_unreachable("Unknown SVal kind!"); |
||
55 | } |
||
56 | |||
57 | #define BASIC_SVAL(Id, Parent) \ |
||
58 | RetTy Visit ## Id(Id V) { DISPATCH(Parent, Id); } |
||
59 | #define ABSTRACT_SVAL(Id, Parent) \ |
||
60 | BASIC_SVAL(Id, Parent) |
||
61 | #define LOC_SVAL(Id, Parent) \ |
||
62 | RetTy VisitLoc ## Id(loc::Id V) { DISPATCH(Parent, Parent); } |
||
63 | #define NONLOC_SVAL(Id, Parent) \ |
||
64 | RetTy VisitNonLoc ## Id(nonloc::Id V) { DISPATCH(Parent, Parent); } |
||
65 | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" |
||
66 | |||
67 | // Base case, ignore it. :) |
||
68 | RetTy VisitSVal(SVal V) { return RetTy(); } |
||
69 | |||
70 | #undef DISPATCH |
||
71 | }; |
||
72 | |||
73 | /// SymExprVisitor - this class implements a simple visitor for SymExpr |
||
74 | /// subclasses. |
||
75 | template <typename ImplClass, typename RetTy = void> class SymExprVisitor { |
||
76 | public: |
||
77 | |||
78 | #define DISPATCH(CLASS) \ |
||
79 | return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(S)) |
||
80 | |||
81 | RetTy Visit(SymbolRef S) { |
||
82 | // Dispatch to VisitSymbolFoo for each SymbolFoo. |
||
83 | switch (S->getKind()) { |
||
84 | #define SYMBOL(Id, Parent) \ |
||
85 | case SymExpr::Id ## Kind: DISPATCH(Id); |
||
86 | #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" |
||
87 | } |
||
88 | llvm_unreachable("Unknown SymExpr kind!"); |
||
89 | } |
||
90 | |||
91 | // If the implementation chooses not to implement a certain visit method, fall |
||
92 | // back on visiting the superclass. |
||
93 | #define SYMBOL(Id, Parent) RetTy Visit ## Id(const Id *S) { DISPATCH(Parent); } |
||
94 | #define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent) |
||
95 | #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" |
||
96 | |||
97 | // Base case, ignore it. :) |
||
98 | RetTy VisitSymExpr(SymbolRef S) { return RetTy(); } |
||
99 | |||
100 | #undef DISPATCH |
||
101 | }; |
||
102 | |||
103 | /// MemRegionVisitor - this class implements a simple visitor for MemRegion |
||
104 | /// subclasses. |
||
105 | template <typename ImplClass, typename RetTy = void> class MemRegionVisitor { |
||
106 | public: |
||
107 | |||
108 | #define DISPATCH(CLASS) \ |
||
109 | return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(R)) |
||
110 | |||
111 | RetTy Visit(const MemRegion *R) { |
||
112 | // Dispatch to VisitFooRegion for each FooRegion. |
||
113 | switch (R->getKind()) { |
||
114 | #define REGION(Id, Parent) case MemRegion::Id ## Kind: DISPATCH(Id); |
||
115 | #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def" |
||
116 | } |
||
117 | llvm_unreachable("Unknown MemRegion kind!"); |
||
118 | } |
||
119 | |||
120 | // If the implementation chooses not to implement a certain visit method, fall |
||
121 | // back on visiting the superclass. |
||
122 | #define REGION(Id, Parent) \ |
||
123 | RetTy Visit ## Id(const Id *R) { DISPATCH(Parent); } |
||
124 | #define ABSTRACT_REGION(Id, Parent) \ |
||
125 | REGION(Id, Parent) |
||
126 | #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def" |
||
127 | |||
128 | // Base case, ignore it. :) |
||
129 | RetTy VisitMemRegion(const MemRegion *R) { return RetTy(); } |
||
130 | |||
131 | #undef DISPATCH |
||
132 | }; |
||
133 | |||
134 | /// FullSValVisitor - a convenient mixed visitor for all three: |
||
135 | /// SVal, SymExpr and MemRegion subclasses. |
||
136 | template <typename ImplClass, typename RetTy = void> |
||
137 | class FullSValVisitor : public SValVisitor<ImplClass, RetTy>, |
||
138 | public SymExprVisitor<ImplClass, RetTy>, |
||
139 | public MemRegionVisitor<ImplClass, RetTy> { |
||
140 | public: |
||
141 | using SValVisitor<ImplClass, RetTy>::Visit; |
||
142 | using SymExprVisitor<ImplClass, RetTy>::Visit; |
||
143 | using MemRegionVisitor<ImplClass, RetTy>::Visit; |
||
144 | }; |
||
145 | |||
146 | } // end namespace ento |
||
147 | |||
148 | } // end namespace clang |
||
149 | |||
150 | #endif |