ProgramPoint.h revision 3d7c44e01d568e5d5c0fac9c6ccb3f080157ba19
15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-//
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// License. See LICENSE.TXT for details.
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//===----------------------------------------------------------------------===//
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//  This file defines the interface ProgramPoint, which identifies a
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//  distinct location in a function.
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//===----------------------------------------------------------------------===//
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "clang/Analysis/AnalysisContext.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "clang/Analysis/CFG.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/Support/DataTypes.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/ADT/DenseMap.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/ADT/FoldingSet.h"
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/Support/Casting.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "llvm/ADT/StringRef.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <cassert>
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <utility>
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <string>
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace clang {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class AnalysisDeclContext;
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class FunctionDecl;
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class LocationContext;
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ProgramPointTag;
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ProgramPoint {
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)public:
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  enum Kind { BlockEdgeKind,
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              BlockEntranceKind,
40c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch              BlockExitKind,
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              PreStmtKind,
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              PostStmtKind,
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              PreLoadKind,
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              PostLoadKind,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              PreStoreKind,
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              PostStoreKind,
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)              PostPurgeDeadSymbolsKind,
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              PostConditionKind,
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              PostLValueKind,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              PostInitializerKind,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              CallEnterKind,
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              CallExitKind,
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              MinPostStmtKind = PostStmtKind,
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              MaxPostStmtKind = CallExitKind };
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)private:
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::pair<const void *, const void *> Data;
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  Kind K;
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The LocationContext could be NULL to allow ProgramPoint to be used in
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // context insensitive analysis.
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const LocationContext *L;
6323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  const ProgramPointTag *Tag;
6423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
6523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ProgramPoint();
6623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)protected:
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ProgramPoint(const void *P, Kind k, const LocationContext *l,
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               const ProgramPointTag *tag = 0)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {}
71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  ProgramPoint(const void *P1, const void *P2, Kind k, const LocationContext *l,
73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch               const ProgramPointTag *tag = 0)
74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    : Data(P1, P2), K(k), L(l), Tag(tag) {}
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)protected:
770529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const void *getData1() const { return Data.first; }
780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  const void *getData2() const { return Data.second; }
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void setData2(const void *d) { Data.second = d; }
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)public:
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /// Create a new ProgramPoint object that is the same as the original
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  /// except for using the specified tag value.
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ProgramPoint withTag(const ProgramPointTag *tag) const {
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ProgramPoint(Data.first, Data.second, K, L, tag);
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  Kind getKind() const { return K; }
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const ProgramPointTag *getTag() const { return Tag; }
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const LocationContext *getLocationContext() const { return L; }
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // For use with DenseMap.  This hash is probably slow.
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  unsigned getHashValue() const {
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    llvm::FoldingSetNodeID ID;
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    Profile(ID);
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return ID.ComputeHash();
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static bool classof(const ProgramPoint*) { return true; }
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool operator==(const ProgramPoint & RHS) const {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag;
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool operator!=(const ProgramPoint &RHS) const {
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void Profile(llvm::FoldingSetNodeID& ID) const {
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ID.AddInteger((unsigned) K);
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ID.AddPointer(Data.first);
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ID.AddPointer(Data.second);
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ID.AddPointer(L);
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ID.AddPointer(Tag);
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      const LocationContext *LC,
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      const ProgramPointTag *tag);
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class BlockEntrance : public ProgramPoint {
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)public:
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BlockEntrance(const CFGBlock *B, const LocationContext *L,
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const ProgramPointTag *tag = 0)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : ProgramPoint(B, BlockEntranceKind, L, tag) {
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    assert(B && "BlockEntrance requires non-null block");
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const CFGBlock *getBlock() const {
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return reinterpret_cast<const CFGBlock*>(getData1());
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const CFGElement getFirstElement() const {
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CFGBlock *B = getBlock();
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return B->empty() ? CFGElement() : B->front();
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static bool classof(const ProgramPoint* Location) {
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Location->getKind() == BlockEntranceKind;
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class BlockExit : public ProgramPoint {
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)public:
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BlockExit(const CFGBlock *B, const LocationContext *L)
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : ProgramPoint(B, BlockExitKind, L) {}
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const CFGBlock *getBlock() const {
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return reinterpret_cast<const CFGBlock*>(getData1());
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const Stmt *getTerminator() const {
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return getBlock()->getTerminator();
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static bool classof(const ProgramPoint* Location) {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return Location->getKind() == BlockExitKind;
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
165c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochclass StmtPoint : public ProgramPoint {
166c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochpublic:
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L,
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            const ProgramPointTag *tag)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : ProgramPoint(S, p2, k, L, tag) {}
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const Stmt *getStmt() const { return (const Stmt*) getData1(); }
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
173  template <typename T>
174  const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); }
175
176  static bool classof(const ProgramPoint* Location) {
177    unsigned k = Location->getKind();
178    return k >= PreStmtKind && k <= MaxPostStmtKind;
179  }
180};
181
182
183class PreStmt : public StmtPoint {
184public:
185  PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag,
186          const Stmt *SubStmt = 0)
187    : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {}
188
189  const Stmt *getSubStmt() const { return (const Stmt*) getData2(); }
190
191  static bool classof(const ProgramPoint* Location) {
192    return Location->getKind() == PreStmtKind;
193  }
194};
195
196class PostStmt : public StmtPoint {
197protected:
198  PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L,
199           const ProgramPointTag *tag = 0)
200    : StmtPoint(S, data, k, L, tag) {}
201
202public:
203  explicit PostStmt(const Stmt *S, Kind k,
204                    const LocationContext *L, const ProgramPointTag *tag = 0)
205    : StmtPoint(S, NULL, k, L, tag) {}
206
207  explicit PostStmt(const Stmt *S, const LocationContext *L,
208                    const ProgramPointTag *tag = 0)
209    : StmtPoint(S, NULL, PostStmtKind, L, tag) {}
210
211  static bool classof(const ProgramPoint* Location) {
212    unsigned k = Location->getKind();
213    return k >= MinPostStmtKind && k <= MaxPostStmtKind;
214  }
215};
216
217// PostCondition represents the post program point of a branch condition.
218class PostCondition : public PostStmt {
219public:
220  PostCondition(const Stmt *S, const LocationContext *L,
221                const ProgramPointTag *tag = 0)
222    : PostStmt(S, PostConditionKind, L, tag) {}
223
224  static bool classof(const ProgramPoint* Location) {
225    return Location->getKind() == PostConditionKind;
226  }
227};
228
229class LocationCheck : public StmtPoint {
230protected:
231  LocationCheck(const Stmt *S, const LocationContext *L,
232                ProgramPoint::Kind K, const ProgramPointTag *tag)
233    : StmtPoint(S, NULL, K, L, tag) {}
234
235  static bool classof(const ProgramPoint *location) {
236    unsigned k = location->getKind();
237    return k == PreLoadKind || k == PreStoreKind;
238  }
239};
240
241class PreLoad : public LocationCheck {
242public:
243  PreLoad(const Stmt *S, const LocationContext *L,
244          const ProgramPointTag *tag = 0)
245    : LocationCheck(S, L, PreLoadKind, tag) {}
246
247  static bool classof(const ProgramPoint *location) {
248    return location->getKind() == PreLoadKind;
249  }
250};
251
252class PreStore : public LocationCheck {
253public:
254  PreStore(const Stmt *S, const LocationContext *L,
255           const ProgramPointTag *tag = 0)
256  : LocationCheck(S, L, PreStoreKind, tag) {}
257
258  static bool classof(const ProgramPoint *location) {
259    return location->getKind() == PreStoreKind;
260  }
261};
262
263class PostLoad : public PostStmt {
264public:
265  PostLoad(const Stmt *S, const LocationContext *L,
266           const ProgramPointTag *tag = 0)
267    : PostStmt(S, PostLoadKind, L, tag) {}
268
269  static bool classof(const ProgramPoint* Location) {
270    return Location->getKind() == PostLoadKind;
271  }
272};
273
274/// \class Represents a program point after a store evaluation.
275class PostStore : public PostStmt {
276public:
277  /// Construct the post store point.
278  /// \param Loc can be used to store the information about the location
279  /// used in the form it was uttered in the code.
280  PostStore(const Stmt *S, const LocationContext *L, const void *Loc,
281            const ProgramPointTag *tag = 0)
282    : PostStmt(S, PostStoreKind, L, tag) {
283    assert(getData2() == 0);
284    setData2(Loc);
285  }
286
287  static bool classof(const ProgramPoint* Location) {
288    return Location->getKind() == PostStoreKind;
289  }
290
291  /// \brief Returns the information about the location used in the store,
292  /// how it was uttered in the code.
293  const void *getLocationValue() const {
294    return getData2();
295  }
296
297};
298
299class PostLValue : public PostStmt {
300public:
301  PostLValue(const Stmt *S, const LocationContext *L,
302             const ProgramPointTag *tag = 0)
303    : PostStmt(S, PostLValueKind, L, tag) {}
304
305  static bool classof(const ProgramPoint* Location) {
306    return Location->getKind() == PostLValueKind;
307  }
308};
309
310class PostPurgeDeadSymbols : public PostStmt {
311public:
312  PostPurgeDeadSymbols(const Stmt *S, const LocationContext *L,
313                       const ProgramPointTag *tag = 0)
314    : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {}
315
316  static bool classof(const ProgramPoint* Location) {
317    return Location->getKind() == PostPurgeDeadSymbolsKind;
318  }
319};
320
321class BlockEdge : public ProgramPoint {
322public:
323  BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L)
324    : ProgramPoint(B1, B2, BlockEdgeKind, L) {
325    assert(B1 && "BlockEdge: source block must be non-null");
326    assert(B2 && "BlockEdge: destination block must be non-null");
327  }
328
329  const CFGBlock *getSrc() const {
330    return static_cast<const CFGBlock*>(getData1());
331  }
332
333  const CFGBlock *getDst() const {
334    return static_cast<const CFGBlock*>(getData2());
335  }
336
337  static bool classof(const ProgramPoint* Location) {
338    return Location->getKind() == BlockEdgeKind;
339  }
340};
341
342class PostInitializer : public ProgramPoint {
343public:
344  PostInitializer(const CXXCtorInitializer *I,
345                  const LocationContext *L)
346    : ProgramPoint(I, PostInitializerKind, L) {}
347
348  static bool classof(const ProgramPoint *Location) {
349    return Location->getKind() == PostInitializerKind;
350  }
351};
352
353class CallEnter : public StmtPoint {
354public:
355  CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx,
356            const LocationContext *callerCtx)
357    : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {}
358
359  const Stmt *getCallExpr() const {
360    return static_cast<const Stmt *>(getData1());
361  }
362
363  const StackFrameContext *getCalleeContext() const {
364    return static_cast<const StackFrameContext *>(getData2());
365  }
366
367  static bool classof(const ProgramPoint *Location) {
368    return Location->getKind() == CallEnterKind;
369  }
370};
371
372class CallExit : public StmtPoint {
373public:
374  // CallExit uses the callee's location context.
375  CallExit(const Stmt *S, const LocationContext *L)
376    : StmtPoint(S, 0, CallExitKind, L, 0) {}
377
378  static bool classof(const ProgramPoint *Location) {
379    return Location->getKind() == CallExitKind;
380  }
381};
382
383/// ProgramPoints can be "tagged" as representing points specific to a given
384/// analysis entity.  Tags are abstract annotations, with an associated
385/// description and potentially other information.
386class ProgramPointTag {
387public:
388  ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {}
389  virtual ~ProgramPointTag();
390  virtual StringRef getTagDescription() const = 0;
391
392protected:
393  /// Used to implement 'classof' in subclasses.
394  const void *getTagKind() { return TagKind; }
395
396private:
397  const void *TagKind;
398};
399
400class SimpleProgramPointTag : public ProgramPointTag {
401  std::string desc;
402public:
403  SimpleProgramPointTag(StringRef description);
404  StringRef getTagDescription() const;
405};
406
407} // end namespace clang
408
409
410namespace llvm { // Traits specialization for DenseMap
411
412template <> struct DenseMapInfo<clang::ProgramPoint> {
413
414static inline clang::ProgramPoint getEmptyKey() {
415  uintptr_t x =
416   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7;
417  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
418}
419
420static inline clang::ProgramPoint getTombstoneKey() {
421  uintptr_t x =
422   reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7;
423  return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0);
424}
425
426static unsigned getHashValue(const clang::ProgramPoint &Loc) {
427  return Loc.getHashValue();
428}
429
430static bool isEqual(const clang::ProgramPoint &L,
431                    const clang::ProgramPoint &R) {
432  return L == R;
433}
434
435};
436
437template <>
438struct isPodLike<clang::ProgramPoint> { static const bool value = true; };
439
440} // end namespace llvm
441
442#endif
443