Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:09

0001 //===--- SValVisitor.h - Visitor for SVal subclasses ------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  This file defines the SValVisitor, SymExprVisitor, and MemRegionVisitor
0010 //  interfaces, and also FullSValVisitor, which visits all three hierarchies.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H
0015 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALVISITOR_H
0016 
0017 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
0018 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
0019 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
0020 
0021 namespace clang {
0022 
0023 namespace ento {
0024 
0025 /// SValVisitor - this class implements a simple visitor for SVal
0026 /// subclasses.
0027 template <typename ImplClass, typename RetTy = void> class SValVisitor {
0028   ImplClass &derived() { return *static_cast<ImplClass *>(this); }
0029 
0030 public:
0031   RetTy Visit(SVal V) {
0032     // Dispatch to VisitFooVal for each FooVal.
0033     switch (V.getKind()) {
0034 #define BASIC_SVAL(Id, Parent)                                                 \
0035   case SVal::Id##Kind:                                                         \
0036     return derived().Visit##Id(V.castAs<Id>());
0037 #define LOC_SVAL(Id, Parent)                                                   \
0038   case SVal::Loc##Id##Kind:                                                    \
0039     return derived().Visit##Id(V.castAs<loc::Id>());
0040 #define NONLOC_SVAL(Id, Parent)                                                \
0041   case SVal::NonLoc##Id##Kind:                                                 \
0042     return derived().Visit##Id(V.castAs<nonloc::Id>());
0043 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
0044     }
0045     llvm_unreachable("Unknown SVal kind!");
0046   }
0047 
0048   // Dispatch to the more generic handler as a default implementation.
0049 #define BASIC_SVAL(Id, Parent)                                                 \
0050   RetTy Visit##Id(Id V) { return derived().Visit##Parent(V.castAs<Id>()); }
0051 #define ABSTRACT_SVAL(Id, Parent) BASIC_SVAL(Id, Parent)
0052 #define LOC_SVAL(Id, Parent)                                                   \
0053   RetTy Visit##Id(loc::Id V) { return derived().VisitLoc(V.castAs<Loc>()); }
0054 #define NONLOC_SVAL(Id, Parent)                                                \
0055   RetTy Visit##Id(nonloc::Id V) {                                              \
0056     return derived().VisitNonLoc(V.castAs<NonLoc>());                          \
0057   }
0058 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def"
0059 
0060   // Base case, ignore it. :)
0061   RetTy VisitSVal(SVal V) { return RetTy(); }
0062 };
0063 
0064 /// SymExprVisitor - this class implements a simple visitor for SymExpr
0065 /// subclasses.
0066 template <typename ImplClass, typename RetTy = void> class SymExprVisitor {
0067 public:
0068 
0069 #define DISPATCH(CLASS) \
0070     return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(S))
0071 
0072   RetTy Visit(SymbolRef S) {
0073     // Dispatch to VisitSymbolFoo for each SymbolFoo.
0074     switch (S->getKind()) {
0075 #define SYMBOL(Id, Parent) \
0076     case SymExpr::Id ## Kind: DISPATCH(Id);
0077 #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
0078     }
0079     llvm_unreachable("Unknown SymExpr kind!");
0080   }
0081 
0082   // If the implementation chooses not to implement a certain visit method, fall
0083   // back on visiting the superclass.
0084 #define SYMBOL(Id, Parent) RetTy Visit ## Id(const Id *S) { DISPATCH(Parent); }
0085 #define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent)
0086 #include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
0087 
0088   // Base case, ignore it. :)
0089   RetTy VisitSymExpr(SymbolRef S) { return RetTy(); }
0090 
0091 #undef DISPATCH
0092 };
0093 
0094 /// MemRegionVisitor - this class implements a simple visitor for MemRegion
0095 /// subclasses.
0096 template <typename ImplClass, typename RetTy = void> class MemRegionVisitor {
0097 public:
0098 
0099 #define DISPATCH(CLASS) \
0100   return static_cast<ImplClass *>(this)->Visit ## CLASS(cast<CLASS>(R))
0101 
0102   RetTy Visit(const MemRegion *R) {
0103     // Dispatch to VisitFooRegion for each FooRegion.
0104     switch (R->getKind()) {
0105 #define REGION(Id, Parent) case MemRegion::Id ## Kind: DISPATCH(Id);
0106 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
0107     }
0108     llvm_unreachable("Unknown MemRegion kind!");
0109   }
0110 
0111   // If the implementation chooses not to implement a certain visit method, fall
0112   // back on visiting the superclass.
0113 #define REGION(Id, Parent) \
0114   RetTy Visit ## Id(const Id *R) { DISPATCH(Parent); }
0115 #define ABSTRACT_REGION(Id, Parent) \
0116   REGION(Id, Parent)
0117 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
0118 
0119   // Base case, ignore it. :)
0120   RetTy VisitMemRegion(const MemRegion *R) { return RetTy(); }
0121 
0122 #undef DISPATCH
0123 };
0124 
0125 /// FullSValVisitor - a convenient mixed visitor for all three:
0126 /// SVal, SymExpr and MemRegion subclasses.
0127 template <typename ImplClass, typename RetTy = void>
0128 class FullSValVisitor : public SValVisitor<ImplClass, RetTy>,
0129                         public SymExprVisitor<ImplClass, RetTy>,
0130                         public MemRegionVisitor<ImplClass, RetTy> {
0131 public:
0132   using SValVisitor<ImplClass, RetTy>::Visit;
0133   using SymExprVisitor<ImplClass, RetTy>::Visit;
0134   using MemRegionVisitor<ImplClass, RetTy>::Visit;
0135 };
0136 
0137 } // end namespace ento
0138 
0139 } // end namespace clang
0140 
0141 #endif