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/MemRegion.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 19 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.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 { derived()28 ImplClass &derived() { return *static_cast<ImplClass *>(this); } 29 30 public: Visit(SVal V)31 RetTy Visit(SVal V) { 32 // Dispatch to VisitFooVal for each FooVal. 33 switch (V.getKind()) { 34 #define BASIC_SVAL(Id, Parent) \ 35 case SVal::Id##Kind: \ 36 return derived().Visit##Id(V.castAs<Id>()); 37 #define LOC_SVAL(Id, Parent) \ 38 case SVal::Loc##Id##Kind: \ 39 return derived().Visit##Id(V.castAs<loc::Id>()); 40 #define NONLOC_SVAL(Id, Parent) \ 41 case SVal::NonLoc##Id##Kind: \ 42 return derived().Visit##Id(V.castAs<nonloc::Id>()); 43 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" 44 } 45 llvm_unreachable("Unknown SVal kind!"); 46 } 47 48 // Dispatch to the more generic handler as a default implementation. 49 #define BASIC_SVAL(Id, Parent) \ 50 RetTy Visit##Id(Id V) { return derived().Visit##Parent(V.castAs<Id>()); } 51 #define ABSTRACT_SVAL(Id, Parent) BASIC_SVAL(Id, Parent) 52 #define LOC_SVAL(Id, Parent) \ 53 RetTy Visit##Id(loc::Id V) { return derived().VisitLoc(V.castAs<Loc>()); } 54 #define NONLOC_SVAL(Id, Parent) \ 55 RetTy Visit##Id(nonloc::Id V) { \ 56 return derived().VisitNonLoc(V.castAs<NonLoc>()); \ 57 } 58 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" 59 60 // Base case, ignore it. :) VisitSVal(SVal V)61 RetTy VisitSVal(SVal V) { return RetTy(); } 62 }; 63 64 /// SymExprVisitor - this class implements a simple visitor for SymExpr 65 /// subclasses. 66 template <typename ImplClass, typename RetTy = void> class SymExprVisitor { 67 public: 68 69 #define DISPATCH(CLASS) \ 70 return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(S)) 71 Visit(SymbolRef S)72 RetTy Visit(SymbolRef S) { 73 // Dispatch to VisitSymbolFoo for each SymbolFoo. 74 switch (S->getKind()) { 75 #define SYMBOL(Id, Parent) \ 76 case SymExpr::Id ## Kind: DISPATCH(Id); 77 #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" 78 } 79 llvm_unreachable("Unknown SymExpr kind!"); 80 } 81 82 // If the implementation chooses not to implement a certain visit method, fall 83 // back on visiting the superclass. 84 #define SYMBOL(Id, Parent) RetTy Visit ## Id(const Id *S) { DISPATCH(Parent); } 85 #define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent) 86 #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def" 87 88 // Base case, ignore it. :) VisitSymExpr(SymbolRef S)89 RetTy VisitSymExpr(SymbolRef S) { return RetTy(); } 90 91 #undef DISPATCH 92 }; 93 94 /// MemRegionVisitor - this class implements a simple visitor for MemRegion 95 /// subclasses. 96 template <typename ImplClass, typename RetTy = void> class MemRegionVisitor { 97 public: 98 99 #define DISPATCH(CLASS) \ 100 return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(R)) 101 Visit(const MemRegion * R)102 RetTy Visit(const MemRegion *R) { 103 // Dispatch to VisitFooRegion for each FooRegion. 104 switch (R->getKind()) { 105 #define REGION(Id, Parent) case MemRegion::Id ## Kind: DISPATCH(Id); 106 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def" 107 } 108 llvm_unreachable("Unknown MemRegion kind!"); 109 } 110 111 // If the implementation chooses not to implement a certain visit method, fall 112 // back on visiting the superclass. 113 #define REGION(Id, Parent) \ 114 RetTy Visit ## Id(const Id *R) { DISPATCH(Parent); } 115 #define ABSTRACT_REGION(Id, Parent) \ 116 REGION(Id, Parent) 117 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def" 118 119 // Base case, ignore it. :) VisitMemRegion(const MemRegion * R)120 RetTy VisitMemRegion(const MemRegion *R) { return RetTy(); } 121 122 #undef DISPATCH 123 }; 124 125 /// FullSValVisitor - a convenient mixed visitor for all three: 126 /// SVal, SymExpr and MemRegion subclasses. 127 template <typename ImplClass, typename RetTy = void> 128 class FullSValVisitor : public SValVisitor<ImplClass, RetTy>, 129 public SymExprVisitor<ImplClass, RetTy>, 130 public MemRegionVisitor<ImplClass, RetTy> { 131 public: 132 using SValVisitor<ImplClass, RetTy>::Visit; 133 using SymExprVisitor<ImplClass, RetTy>::Visit; 134 using MemRegionVisitor<ImplClass, RetTy>::Visit; 135 }; 136 137 } // end namespace ento 138 139 } // end namespace clang 140 141 #endif 142