ProgramPoint.h revision ca804539d908d3a0e8c72a0df5f1f571d29490bb
183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-// 2eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 3eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// The LLVM Compiler Infrastructure 4eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source 60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details. 7eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 8eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//===----------------------------------------------------------------------===// 9eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 1083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek// This file defines the interface ProgramPoint, which identifies a 1183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek// distinct location in a function. 12eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek// 13eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek//===----------------------------------------------------------------------===// 14eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek 1583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT 1683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT 17eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek 18c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xu#include "clang/Analysis/AnalysisContext.h" 19e41611aa2237d06a0ef61db4528fb2883a8defcdTed Kremenek#include "clang/Analysis/CFG.h" 2003013fa9a0bf1ef4b907f5fec006c8f4000fdd21Michael J. Spencer#include "llvm/Support/DataTypes.h" 214c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek#include "llvm/ADT/DenseMap.h" 225226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek#include "llvm/ADT/FoldingSet.h" 236bad354120ce0d35901e86ca63e5534b7b9ed092Ted Kremenek#include "llvm/Support/Casting.h" 24ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "llvm/ADT/StringRef.h" 254c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek#include <cassert> 2659753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek#include <utility> 27ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include <string> 28eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek 29eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremeneknamespace clang { 3025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu 31c6238d2786cfd961b94580b3d3675a1b3ff0721cZhongxing Xuclass AnalysisContext; 32102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass FunctionDecl; 33ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass LocationContext; 34ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag; 35ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek 3683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass ProgramPoint { 37eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic: 38cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek enum Kind { BlockEdgeKind, 39cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek BlockEntranceKind, 40cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek BlockExitKind, 41cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek PreStmtKind, 42cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek PostStmtKind, 43b4b817d704287836b52b34369009e682f208aa2bTed Kremenek PreLoadKind, 44cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek PostLoadKind, 45b4b817d704287836b52b34369009e682f208aa2bTed Kremenek PreStoreKind, 46cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek PostStoreKind, 47cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek PostPurgeDeadSymbolsKind, 48cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek PostStmtCustomKind, 498083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek PostConditionKind, 50cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek PostLValueKind, 519dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu PostInitializerKind, 52102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor CallEnterKind, 53102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor CallExitKind, 54f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek MinPostStmtKind = PostStmtKind, 554462ee2f0000e6cb966e3fff4516c84292f0cce8Ted Kremenek MaxPostStmtKind = CallExitKind }; 564c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek 57d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprivate: 58d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek std::pair<const void *, const void *> Data; 59d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek Kind K; 6025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu 6125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu // The LocationContext could be NULL to allow ProgramPoint to be used in 6225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu // context insensitive analysis. 6325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu const LocationContext *L; 64ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *Tag; 651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 66ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek ProgramPoint(); 67ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek 68d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected: 691eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump ProgramPoint(const void* P, Kind k, const LocationContext *l, 70ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 71a5fdd9ce694b1c2dbfd225cb6f55ef743d1ab562Douglas Gregor : Data(P, static_cast<const void*>(NULL)), K(k), L(l), Tag(tag) {} 721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 7325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l, 74ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 7525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : Data(P1, P2), K(k), L(l), Tag(tag) {} 76f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek 77d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekprotected: 78d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek const void* getData1() const { return Data.first; } 79d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek const void* getData2() const { return Data.second; } 801eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumppublic: 82d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek Kind getKind() const { return K; } 83d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 84ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *getTag() const { return Tag; } 8558465900ca10e53b8700a64e9265870de34e1acaTed Kremenek 86fafd3834754d2093e0ad7a1c005860fd527ecb7fZhongxing Xu const LocationContext *getLocationContext() const { return L; } 8725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu 88e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek // For use with DenseMap. This hash is probably slow. 89d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek unsigned getHashValue() const { 90e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek llvm::FoldingSetNodeID ID; 91d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek Profile(ID); 92e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek return ID.ComputeHash(); 93d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 9583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek static bool classof(const ProgramPoint*) { return true; } 96d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 97d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek bool operator==(const ProgramPoint & RHS) const { 9825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag; 99d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 100d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 101d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek bool operator!=(const ProgramPoint& RHS) const { 10225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu return K != RHS.K || Data != RHS.Data || L != RHS.L || Tag != RHS.Tag; 103d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 1041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1055226755ab5ce6346f98b5f41cdcffbe84c5bb484Ted Kremenek void Profile(llvm::FoldingSetNodeID& ID) const { 106d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek ID.AddInteger((unsigned) K); 107d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek ID.AddPointer(Data.first); 108d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek ID.AddPointer(Data.second); 10925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu ID.AddPointer(L); 110e8063ae53bd241de10ba1053054d06867a5c56abTed Kremenek ID.AddPointer(Tag); 1112680b5f926fad29c1a2b2723a70d189f4b637979Ted Kremenek } 112eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek}; 1131eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 11483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEntrance : public ProgramPoint { 115eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic: 1161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BlockEntrance(const CFGBlock* B, const LocationContext *L, 117ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 11825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : ProgramPoint(B, BlockEntranceKind, L, tag) {} 1191eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const CFGBlock* getBlock() const { 12103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu return reinterpret_cast<const CFGBlock*>(getData1()); 122bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek } 1231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const CFGElement getFirstElement() const { 125d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek const CFGBlock* B = getBlock(); 126852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek return B->empty() ? CFGElement() : B->front(); 127852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek } 128852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek 129b6a2b08a6b3fbce1a6a4b69d4185165de970696cTed Kremenek /// Create a new BlockEntrance object that is the same as the original 130b6a2b08a6b3fbce1a6a4b69d4185165de970696cTed Kremenek /// except for using the specified tag value. 131ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek BlockEntrance withTag(const ProgramPointTag *tag) { 132b6a2b08a6b3fbce1a6a4b69d4185165de970696cTed Kremenek return BlockEntrance(getBlock(), getLocationContext(), tag); 133b6a2b08a6b3fbce1a6a4b69d4185165de970696cTed Kremenek } 134b6a2b08a6b3fbce1a6a4b69d4185165de970696cTed Kremenek 13583c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek static bool classof(const ProgramPoint* Location) { 13683c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek return Location->getKind() == BlockEntranceKind; 137bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek } 138eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek}; 13983c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 14083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockExit : public ProgramPoint { 141eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic: 1421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump BlockExit(const CFGBlock* B, const LocationContext *L) 14325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : ProgramPoint(B, BlockExitKind, L) {} 1441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const CFGBlock* getBlock() const { 14603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu return reinterpret_cast<const CFGBlock*>(getData1()); 147bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek } 14883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 14903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const Stmt* getTerminator() const { 15083c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek return getBlock()->getTerminator(); 151bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek } 1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 15383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek static bool classof(const ProgramPoint* Location) { 15483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek return Location->getKind() == BlockExitKind; 155bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek } 156bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek}; 1571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1585f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass StmtPoint : public ProgramPoint { 1595f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekpublic: 1601eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L, 161ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag) 16225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : ProgramPoint(S, p2, k, L, tag) {} 1631eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1645f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const Stmt *getStmt() const { return (const Stmt*) getData1(); } 1651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1665f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek template <typename T> 1675f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); } 1681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1695f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek static bool classof(const ProgramPoint* Location) { 1705f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek unsigned k = Location->getKind(); 1715f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek return k >= PreStmtKind && k <= MaxPostStmtKind; 1725f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenek } 1731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 1741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 175eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek 1765f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PreStmt : public StmtPoint { 177cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenekpublic: 178ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag, 17925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu const Stmt *SubStmt = 0) 18025e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {} 181cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek 1821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump const Stmt *getSubStmt() const { return (const Stmt*) getData2(); } 183cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek 184cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek static bool classof(const ProgramPoint* Location) { 185cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek return Location->getKind() == PreStmtKind; 186cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek } 187cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek}; 188cdd4f1783da7c7565be2376d14ca6ab2625aa4b6Ted Kremenek 1895f85e17df3f5b0a8021443f2b590daecfb2cbd17Ted Kremenekclass PostStmt : public StmtPoint { 1901b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekprotected: 19125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L, 192ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag =0) 19325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : StmtPoint(S, data, k, L, tag) {} 1941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 195eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenekpublic: 1964bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek explicit PostStmt(const Stmt* S, Kind k, 197ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const LocationContext *L, const ProgramPointTag *tag = 0) 1984bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek : StmtPoint(S, NULL, k, L, tag) {} 1994bac726dadb09ee38bab8147f1e706380368b362Ted Kremenek 200ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek explicit PostStmt(const Stmt* S, const LocationContext *L, 201ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 20225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : StmtPoint(S, NULL, PostStmtKind, L, tag) {} 20383c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 20483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek static bool classof(const ProgramPoint* Location) { 2051b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek unsigned k = Location->getKind(); 206f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek return k >= MinPostStmtKind && k <= MaxPostStmtKind; 2071b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek } 2081b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek}; 2098c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek 210f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenekclass PostStmtCustom : public PostStmt { 2112680b5f926fad29c1a2b2723a70d189f4b637979Ted Kremenekpublic: 21259753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek PostStmtCustom(const Stmt* S, 21325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu const std::pair<const void*, const void*>* TaggedData,\ 21425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu const LocationContext *L) 21525e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : PostStmt(S, TaggedData, PostStmtCustomKind, L) {} 21659753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek 21759753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek const std::pair<const void*, const void*>& getTaggedPair() const { 218d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek return 219d6b9e37311013bdf24fd709f7e9962e3b141e6fbTed Kremenek *reinterpret_cast<const std::pair<const void*, const void*>*>(getData2()); 22059753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek } 2211eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22259753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek const void* getTag() const { return getTaggedPair().first; } 2231eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 22459753441b6391a9843eff287f0adb2614153b7c8Ted Kremenek const void* getTaggedData() const { return getTaggedPair().second; } 2251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 226f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek static bool classof(const ProgramPoint* Location) { 227f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek return Location->getKind() == PostStmtCustomKind; 228f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek } 229f4be8ee748831bc23e35b542e6c1bb6d1eb49baaTed Kremenek}; 2301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2318083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek// PostCondition represents the post program point of a branch condition. 2328083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekclass PostCondition : public PostStmt { 2338083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenekpublic: 234ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek PostCondition(const Stmt* S, const LocationContext *L, 235ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 2368083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek : PostStmt(S, PostConditionKind, L, tag) {} 2378083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek 2388083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek static bool classof(const ProgramPoint* Location) { 2398083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek return Location->getKind() == PostConditionKind; 2408083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek } 2418083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek}; 2428083414ee7cc8f5c807ed6a4e120fb4e0ab50ff8Ted Kremenek 243b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass LocationCheck : public StmtPoint { 244b4b817d704287836b52b34369009e682f208aa2bTed Kremenekprotected: 245b4b817d704287836b52b34369009e682f208aa2bTed Kremenek LocationCheck(const Stmt *S, const LocationContext *L, 246ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek ProgramPoint::Kind K, const ProgramPointTag *tag) 247b4b817d704287836b52b34369009e682f208aa2bTed Kremenek : StmtPoint(S, NULL, K, L, tag) {} 248b4b817d704287836b52b34369009e682f208aa2bTed Kremenek 249b4b817d704287836b52b34369009e682f208aa2bTed Kremenek static bool classof(const ProgramPoint *location) { 250b4b817d704287836b52b34369009e682f208aa2bTed Kremenek unsigned k = location->getKind(); 251d651141308a777d60ff98309d21e045bb936f8b7Ted Kremenek return k == PreLoadKind || k == PreStoreKind; 2528c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek } 2538c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek}; 254b4b817d704287836b52b34369009e682f208aa2bTed Kremenek 255b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreLoad : public LocationCheck { 2568c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic: 257ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek PreLoad(const Stmt *S, const LocationContext *L, 258ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 259b4b817d704287836b52b34369009e682f208aa2bTed Kremenek : LocationCheck(S, L, PreLoadKind, tag) {} 260b4b817d704287836b52b34369009e682f208aa2bTed Kremenek 261b4b817d704287836b52b34369009e682f208aa2bTed Kremenek static bool classof(const ProgramPoint *location) { 262b4b817d704287836b52b34369009e682f208aa2bTed Kremenek return location->getKind() == PreLoadKind; 2638c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek } 2648c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek}; 2651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 266b4b817d704287836b52b34369009e682f208aa2bTed Kremenekclass PreStore : public LocationCheck { 2678c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenekpublic: 268ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek PreStore(const Stmt *S, const LocationContext *L, 269ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 270b4b817d704287836b52b34369009e682f208aa2bTed Kremenek : LocationCheck(S, L, PreStoreKind, tag) {} 271b4b817d704287836b52b34369009e682f208aa2bTed Kremenek 272b4b817d704287836b52b34369009e682f208aa2bTed Kremenek static bool classof(const ProgramPoint *location) { 273b4b817d704287836b52b34369009e682f208aa2bTed Kremenek return location->getKind() == PreStoreKind; 2748c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek } 2758c354758c2d39db87c77c723d81e34b4d967f762Ted Kremenek}; 2761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2771b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekclass PostLoad : public PostStmt { 2781b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenekpublic: 279ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek PostLoad(const Stmt* S, const LocationContext *L, 280ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 28125e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : PostStmt(S, PostLoadKind, L, tag) {} 2821eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 2831b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek static bool classof(const ProgramPoint* Location) { 2841b8bd4d71c2098126041b4de4267175a82f0103cTed Kremenek return Location->getKind() == PostLoadKind; 285bd129696c554fbbcd9405104641e292f0fb4678dTed Kremenek } 286eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek}; 2871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 28882bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekclass PostStore : public PostStmt { 28982bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenekpublic: 290ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek PostStore(const Stmt* S, const LocationContext *L, 291ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 29225e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : PostStmt(S, PostStoreKind, L, tag) {} 2931eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 29482bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek static bool classof(const ProgramPoint* Location) { 29582bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek return Location->getKind() == PostStoreKind; 29682bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek } 29782bae3f6bf7bc4733d9c87659b266e23ad55f420Ted Kremenek}; 2987090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek 2997090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekclass PostLValue : public PostStmt { 3007090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenekpublic: 301ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek PostLValue(const Stmt* S, const LocationContext *L, 302ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 30325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : PostStmt(S, PostLValueKind, L, tag) {} 3041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 3057090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek static bool classof(const ProgramPoint* Location) { 3067090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek return Location->getKind() == PostLValueKind; 3077090d5465de7ca620da16211cf886edf1edc1f1fTed Kremenek } 3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}; 3091eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 310331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekclass PostPurgeDeadSymbols : public PostStmt { 311331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenekpublic: 3121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L, 313ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const ProgramPointTag *tag = 0) 31425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : PostStmt(S, PostPurgeDeadSymbolsKind, L, tag) {} 3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 316331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek static bool classof(const ProgramPoint* Location) { 317331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek return Location->getKind() == PostPurgeDeadSymbolsKind; 318331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek } 319331b0ac44b9eb0ffcba66b4f3f3f9adb27c2434fTed Kremenek}; 3201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32183c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenekclass BlockEdge : public ProgramPoint { 322b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenekpublic: 32325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L) 32425e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu : ProgramPoint(B1, B2, BlockEdgeKind, L) {} 3251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 32603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const CFGBlock* getSrc() const { 32703509aea098772644bf4662dc1c88634818ceeccZhongxing Xu return static_cast<const CFGBlock*>(getData1()); 328d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 3291eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 33003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu const CFGBlock* getDst() const { 33103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu return static_cast<const CFGBlock*>(getData2()); 332d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek } 3331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 33483c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek static bool classof(const ProgramPoint* Location) { 335d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek return Location->getKind() == BlockEdgeKind; 336b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek } 337b6d2360787e5a0bb5d26f3bc7a83059a8b050dc4Ted Kremenek}; 33883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenek 3399dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xuclass PostInitializer : public ProgramPoint { 3409dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xupublic: 341cbb67480094b3bcb5b715acd827cbad55e2a204cSean Hunt PostInitializer(const CXXCtorInitializer *I, 3429dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu const LocationContext *L) 3439dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu : ProgramPoint(I, PostInitializerKind, L) {} 3449dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu 3459dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu static bool classof(const ProgramPoint *Location) { 3469dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu return Location->getKind() == PostInitializerKind; 3479dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu } 3489dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu}; 3499dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu 350102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass CallEnter : public StmtPoint { 351102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic: 35219b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, 35319b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu const LocationContext *callerCtx) 35419b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {} 355102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor 356102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor const Stmt *getCallExpr() const { 357102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor return static_cast<const Stmt *>(getData1()); 358102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor } 359102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor 36019b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu const StackFrameContext *getCalleeContext() const { 36119b78d9e3dbbc27bbcbdd8c3017a00fe88849ecdZhongxing Xu return static_cast<const StackFrameContext *>(getData2()); 362102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor } 363102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor 364102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor static bool classof(const ProgramPoint *Location) { 365102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor return Location->getKind() == CallEnterKind; 366102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor } 367102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor}; 368102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor 369102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorclass CallExit : public StmtPoint { 370102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregorpublic: 371102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor // CallExit uses the callee's location context. 372102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor CallExit(const Stmt *S, const LocationContext *L) 373102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor : StmtPoint(S, 0, CallExitKind, L, 0) {} 374102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor 375102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor static bool classof(const ProgramPoint *Location) { 376102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor return Location->getKind() == CallExitKind; 377102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor } 378102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor}; 379102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor 380ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// ProgramPoints can be "tagged" as representing points specific to a given 381ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// analysis entity. Tags are abstract annotations, with an associated 382ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek/// description and potentially other information. 383ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass ProgramPointTag { 384ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic: 385ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {} 386ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek virtual ~ProgramPointTag(); 387ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek virtual StringRef getTagDescription() const = 0; 388ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek 389ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprotected: 390ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const void *getTagKind() { return TagKind; } 391ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek 392ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekprivate: 393ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek const void *TagKind; 394ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek}; 395ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek 396ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekclass SimpleProgramPointTag : public ProgramPointTag { 397ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek std::string desc; 398ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenekpublic: 399ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek SimpleProgramPointTag(StringRef description); 400ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek StringRef getTagDescription() const; 401ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek}; 4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 403eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek} // end namespace clang 4044c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek 4054c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek 4061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpnamespace llvm { // Traits specialization for DenseMap 4071eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 40883c01da96f57cf732a5da9a83e2981241f205dc4Ted Kremenektemplate <> struct DenseMapInfo<clang::ProgramPoint> { 4094c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek 410d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getEmptyKey() { 411d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek uintptr_t x = 4121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; 41325e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); 414d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek} 415d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 416d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic inline clang::ProgramPoint getTombstoneKey() { 417d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek uintptr_t x = 41825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; 41925e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); 420d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek} 421d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 422d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic unsigned getHashValue(const clang::ProgramPoint& Loc) { 423d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek return Loc.getHashValue(); 424d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek} 425d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 426d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenekstatic bool isEqual(const clang::ProgramPoint& L, 427d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek const clang::ProgramPoint& R) { 428d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek return L == R; 429d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek} 430d452758bb6b59340528a26def9ecc24b329d4ecfTed Kremenek 4314c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek}; 43206159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner 43306159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnertemplate <> 43406159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattnerstruct isPodLike<clang::ProgramPoint> { static const bool value = true; }; 43506159e878569e5f39bf0e8f11b84ac3ad0970597Chris Lattner 4364c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek} // end namespace llvm 4374c3fbe33194cd9b1bfff773647ed785b403e1ba5Ted Kremenek 438eb19188e668d0ad2c968fc0286a6922f9194deb4Ted Kremenek#endif 439