]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / include / clang / StaticAnalyzer / Core / PathSensitive / SValVisitor.h
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