xref: /freebsd/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/BlockCounter.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1 //==- BlockCounter.h - ADT for counting block visits -------------*- 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 BlockCounter, an abstract data type used to count
10 //  the number of times a given block has been visited along a path
11 //  analyzed by CoreEngine.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
16 #include "llvm/ADT/ImmutableMap.h"
17 
18 using namespace clang;
19 using namespace ento;
20 
21 namespace {
22 
23 class CountKey {
24   const StackFrameContext *CallSite;
25   unsigned BlockID;
26 
27 public:
CountKey(const StackFrameContext * CS,unsigned ID)28   CountKey(const StackFrameContext *CS, unsigned ID)
29     : CallSite(CS), BlockID(ID) {}
30 
operator ==(const CountKey & RHS) const31   bool operator==(const CountKey &RHS) const {
32     return (CallSite == RHS.CallSite) && (BlockID == RHS.BlockID);
33   }
34 
operator <(const CountKey & RHS) const35   bool operator<(const CountKey &RHS) const {
36     return std::tie(CallSite, BlockID) < std::tie(RHS.CallSite, RHS.BlockID);
37   }
38 
Profile(llvm::FoldingSetNodeID & ID) const39   void Profile(llvm::FoldingSetNodeID &ID) const {
40     ID.AddPointer(CallSite);
41     ID.AddInteger(BlockID);
42   }
43 };
44 
45 }
46 
47 typedef llvm::ImmutableMap<CountKey, unsigned> CountMap;
48 
GetMap(void * D)49 static inline CountMap GetMap(void *D) {
50   return CountMap(static_cast<CountMap::TreeTy*>(D));
51 }
52 
GetFactory(void * F)53 static inline CountMap::Factory& GetFactory(void *F) {
54   return *static_cast<CountMap::Factory*>(F);
55 }
56 
getNumVisited(const StackFrameContext * CallSite,unsigned BlockID) const57 unsigned BlockCounter::getNumVisited(const StackFrameContext *CallSite,
58                                        unsigned BlockID) const {
59   CountMap M = GetMap(Data);
60   CountMap::data_type* T = M.lookup(CountKey(CallSite, BlockID));
61   return T ? *T : 0;
62 }
63 
Factory(llvm::BumpPtrAllocator & Alloc)64 BlockCounter::Factory::Factory(llvm::BumpPtrAllocator& Alloc) {
65   F = new CountMap::Factory(Alloc);
66 }
67 
~Factory()68 BlockCounter::Factory::~Factory() {
69   delete static_cast<CountMap::Factory*>(F);
70 }
71 
72 BlockCounter
IncrementCount(BlockCounter BC,const StackFrameContext * CallSite,unsigned BlockID)73 BlockCounter::Factory::IncrementCount(BlockCounter BC,
74                                         const StackFrameContext *CallSite,
75                                         unsigned BlockID) {
76   return BlockCounter(GetFactory(F).add(GetMap(BC.Data),
77                                           CountKey(CallSite, BlockID),
78                              BC.getNumVisited(CallSite, BlockID)+1).getRoot());
79 }
80 
81 BlockCounter
GetEmptyCounter()82 BlockCounter::Factory::GetEmptyCounter() {
83   return BlockCounter(GetFactory(F).getEmptyMap().getRoot());
84 }
85