Home | History | Annotate | Download | only in PathSensitive
      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 
     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. :)
     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 
     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. :)
     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 
    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. :)
    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