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 21namespace clang { 22 23namespace ento { 24 25/// SValVisitor - this class implements a simple visitor for SVal 26/// subclasses. 27template <typename ImplClass, typename RetTy = void> class SValVisitor { 28public: 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. 75template <typename ImplClass, typename RetTy = void> class SymExprVisitor { 76public: 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. 105template <typename ImplClass, typename RetTy = void> class MemRegionVisitor { 106public: 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. 136template <typename ImplClass, typename RetTy = void> 137class FullSValVisitor : public SValVisitor<ImplClass, RetTy>, 138 public SymExprVisitor<ImplClass, RetTy>, 139 public MemRegionVisitor<ImplClass, RetTy> { 140public: 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