1 //===--- SValVisitor.h - Visitor for SVal subclasses ------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the SValVisitor, SymExprVisitor, and MemRegionVisitor
11 // interfaces, and also FullSValVisitor, which visits all three hierarchies.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H
16 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H
18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
26 /// SValVisitor - this class implements a simple visitor for SVal
28 template <typename ImplClass, typename RetTy = void> class SValVisitor {
31 #define DISPATCH(NAME, CLASS) \
32 return static_cast<ImplClass *>(this)->Visit ## NAME(V.castAs<CLASS>())
35 // Dispatch to VisitFooVal for each FooVal.
36 // Take namespaces (loc:: and nonloc::) into account.
37 switch (V.getBaseKind()) {
38 #define BASIC_SVAL(Id, Parent) case SVal::Id ## Kind: DISPATCH(Id, Id);
39 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
41 switch (V.getSubKind()) {
42 #define LOC_SVAL(Id, Parent) \
43 case loc::Id ## Kind: DISPATCH(Loc ## Id, loc :: Id);
44 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
46 llvm_unreachable("Unknown Loc sub-kind!");
47 case SVal::NonLocKind:
48 switch (V.getSubKind()) {
49 #define NONLOC_SVAL(Id, Parent) \
50 case nonloc::Id ## Kind: DISPATCH(NonLoc ## Id, nonloc :: Id);
51 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
53 llvm_unreachable("Unknown NonLoc sub-kind!");
55 llvm_unreachable("Unknown SVal kind!");
58 #define BASIC_SVAL(Id, Parent) \
59 RetTy Visit ## Id(Id V) { DISPATCH(Parent, Id); }
60 #define ABSTRACT_SVAL(Id, Parent) \
61 BASIC_SVAL(Id, Parent)
62 #define LOC_SVAL(Id, Parent) \
63 RetTy VisitLoc ## Id(loc::Id V) { DISPATCH(Parent, Parent); }
64 #define NONLOC_SVAL(Id, Parent) \
65 RetTy VisitNonLoc ## Id(nonloc::Id V) { DISPATCH(Parent, Parent); }
66 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
68 // Base case, ignore it. :)
69 RetTy VisitSVal(SVal V) { return RetTy(); }
74 /// SymExprVisitor - this class implements a simple visitor for SymExpr
76 template <typename ImplClass, typename RetTy = void> class SymExprVisitor {
79 #define DISPATCH(CLASS) \
80 return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(S))
82 RetTy Visit(SymbolRef S) {
83 // Dispatch to VisitSymbolFoo for each SymbolFoo.
84 switch (S->getKind()) {
85 #define SYMBOL(Id, Parent) \
86 case SymExpr::Id ## Kind: DISPATCH(Id);
87 #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
89 llvm_unreachable("Unknown SymExpr kind!");
92 // If the implementation chooses not to implement a certain visit method, fall
93 // back on visiting the superclass.
94 #define SYMBOL(Id, Parent) RetTy Visit ## Id(const Id *S) { DISPATCH(Parent); }
95 #define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent)
96 #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
98 // Base case, ignore it. :)
99 RetTy VisitSymExpr(SymbolRef S) { return RetTy(); }
104 /// MemRegionVisitor - this class implements a simple visitor for MemRegion
106 template <typename ImplClass, typename RetTy = void> class MemRegionVisitor {
109 #define DISPATCH(CLASS) \
110 return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(R))
112 RetTy Visit(const MemRegion *R) {
113 // Dispatch to VisitFooRegion for each FooRegion.
114 switch (R->getKind()) {
115 #define REGION(Id, Parent) case MemRegion::Id ## Kind: DISPATCH(Id);
116 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
118 llvm_unreachable("Unknown MemRegion kind!");
121 // If the implementation chooses not to implement a certain visit method, fall
122 // back on visiting the superclass.
123 #define REGION(Id, Parent) \
124 RetTy Visit ## Id(const Id *R) { DISPATCH(Parent); }
125 #define ABSTRACT_REGION(Id, Parent) \
127 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
129 // Base case, ignore it. :)
130 RetTy VisitMemRegion(const MemRegion *R) { return RetTy(); }
135 /// FullSValVisitor - a convenient mixed visitor for all three:
136 /// SVal, SymExpr and MemRegion subclasses.
137 template <typename ImplClass, typename RetTy = void>
138 class FullSValVisitor : public SValVisitor<ImplClass, RetTy>,
139 public SymExprVisitor<ImplClass, RetTy>,
140 public MemRegionVisitor<ImplClass, RetTy> {
142 using SValVisitor<ImplClass, RetTy>::Visit;
143 using SymExprVisitor<ImplClass, RetTy>::Visit;
144 using MemRegionVisitor<ImplClass, RetTy>::Visit;
147 } // end namespace ento
149 } // end namespace clang