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 151