1 //===--- SValVisitor.h - Visitor for SVal subclasses ------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the SValVisitor, SymExprVisitor, and MemRegionVisitor 11 // interfaces, and also FullSValVisitor, which visits all three hierarchies. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H 16 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H 17 18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" 20 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" 21 22 namespace clang { 23 24 namespace ento { 25 26 /// SValVisitor - this class implements a simple visitor for SVal 27 /// subclasses. 28 template <typename ImplClass, typename RetTy = void> class SValVisitor { 29 public: 30 31 #define DISPATCH(NAME, CLASS) \ 32 return static_cast<ImplClass *>(this)->Visit ## NAME(V.castAs<CLASS>()) 33 Visit(SVal V)34 RetTy Visit(SVal V) { 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" 40 case SVal::LocKind: 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" 45 } 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" 52 } 53 llvm_unreachable("Unknown NonLoc sub-kind!"); 54 } 55 llvm_unreachable("Unknown SVal kind!"); 56 } 57 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" 67 68 // Base case, ignore it. :) VisitSVal(SVal V)69 RetTy VisitSVal(SVal V) { return RetTy(); } 70 71 #undef DISPATCH 72 }; 73 74 /// SymExprVisitor - this class implements a simple visitor for SymExpr 75 /// subclasses. 76 template <typename ImplClass, typename RetTy = void> class SymExprVisitor { 77 public: 78 79 #define DISPATCH(CLASS) \ 80 return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(S)) 81 Visit(SymbolRef 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" 88 } 89 llvm_unreachable("Unknown SymExpr kind!"); 90 } 91 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" 97 98 // Base case, ignore it. :) VisitSymExpr(SymbolRef S)99 RetTy VisitSymExpr(SymbolRef S) { return RetTy(); } 100 101 #undef DISPATCH 102 }; 103 104 /// MemRegionVisitor - this class implements a simple visitor for MemRegion 105 /// subclasses. 106 template <typename ImplClass, typename RetTy = void> class MemRegionVisitor { 107 public: 108 109 #define DISPATCH(CLASS) \ 110 return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(R)) 111 Visit(const MemRegion * 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" 117 } 118 llvm_unreachable("Unknown MemRegion kind!"); 119 } 120 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) \ 126 REGION(Id, Parent) 127 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def" 128 129 // Base case, ignore it. :) VisitMemRegion(const MemRegion * R)130 RetTy VisitMemRegion(const MemRegion *R) { return RetTy(); } 131 132 #undef DISPATCH 133 }; 134 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> { 141 public: 142 using SValVisitor<ImplClass, RetTy>::Visit; 143 using SymExprVisitor<ImplClass, RetTy>::Visit; 144 using MemRegionVisitor<ImplClass, RetTy>::Visit; 145 }; 146 147 } // end namespace ento 148 149 } // end namespace clang 150 151 #endif 152