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