clang API Documentation
00001 //==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the interface ProgramPoint, which identifies a 00011 // distinct location in a function. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT 00016 #define LLVM_CLANG_ANALYSIS_PROGRAM_POINT 00017 00018 #include "clang/Analysis/AnalysisContext.h" 00019 #include "clang/Analysis/CFG.h" 00020 #include "llvm/Support/DataTypes.h" 00021 #include "llvm/ADT/DenseMap.h" 00022 #include "llvm/ADT/PointerIntPair.h" 00023 #include "llvm/ADT/FoldingSet.h" 00024 #include "llvm/Support/Casting.h" 00025 #include "llvm/ADT/StringRef.h" 00026 #include <cassert> 00027 #include <utility> 00028 #include <string> 00029 00030 namespace clang { 00031 00032 class AnalysisDeclContext; 00033 class FunctionDecl; 00034 class LocationContext; 00035 class ProgramPointTag; 00036 00037 class ProgramPoint { 00038 public: 00039 enum Kind { BlockEdgeKind, 00040 BlockEntranceKind, 00041 BlockExitKind, 00042 PreStmtKind, 00043 PreStmtPurgeDeadSymbolsKind, 00044 PostStmtPurgeDeadSymbolsKind, 00045 PostStmtKind, 00046 PreLoadKind, 00047 PostLoadKind, 00048 PreStoreKind, 00049 PostStoreKind, 00050 PostConditionKind, 00051 PostLValueKind, 00052 PostInitializerKind, 00053 CallEnterKind, 00054 CallExitBeginKind, 00055 CallExitEndKind, 00056 MinPostStmtKind = PostStmtKind, 00057 MaxPostStmtKind = CallExitEndKind, 00058 EpsilonKind}; 00059 00060 private: 00061 llvm::PointerIntPair<const void *, 2, unsigned> Data1; 00062 llvm::PointerIntPair<const void *, 2, unsigned> Data2; 00063 00064 // The LocationContext could be NULL to allow ProgramPoint to be used in 00065 // context insensitive analysis. 00066 llvm::PointerIntPair<const LocationContext *, 2, unsigned> L; 00067 00068 const ProgramPointTag *Tag; 00069 00070 ProgramPoint(); 00071 00072 protected: 00073 ProgramPoint(const void *P, 00074 Kind k, 00075 const LocationContext *l, 00076 const ProgramPointTag *tag = 0) 00077 : Data1(P, ((unsigned) k) & 0x3), 00078 Data2(0, (((unsigned) k) >> 2) & 0x3), 00079 L(l, (((unsigned) k) >> 4) & 0x3), 00080 Tag(tag) { 00081 assert(getKind() == k); 00082 assert(getLocationContext() == l); 00083 assert(getData1() == P); 00084 } 00085 00086 ProgramPoint(const void *P1, 00087 const void *P2, 00088 Kind k, 00089 const LocationContext *l, 00090 const ProgramPointTag *tag = 0) 00091 : Data1(P1, ((unsigned) k) & 0x3), 00092 Data2(P2, (((unsigned) k) >> 2) & 0x3), 00093 L(l, (((unsigned) k) >> 4) & 0x3), 00094 Tag(tag) {} 00095 00096 protected: 00097 const void *getData1() const { return Data1.getPointer(); } 00098 const void *getData2() const { return Data2.getPointer(); } 00099 void setData2(const void *d) { Data2.setPointer(d); } 00100 00101 public: 00102 /// Create a new ProgramPoint object that is the same as the original 00103 /// except for using the specified tag value. 00104 ProgramPoint withTag(const ProgramPointTag *tag) const { 00105 return ProgramPoint(getData1(), getData2(), getKind(), 00106 getLocationContext(), tag); 00107 } 00108 00109 Kind getKind() const { 00110 unsigned x = L.getInt(); 00111 x <<= 2; 00112 x |= Data2.getInt(); 00113 x <<= 2; 00114 x |= Data1.getInt(); 00115 return (Kind) x; 00116 } 00117 00118 /// \brief Is this a program point corresponding to purge/removal of dead 00119 /// symbols and bindings. 00120 bool isPurgeKind() { 00121 Kind K = getKind(); 00122 return (K == PostStmtPurgeDeadSymbolsKind || 00123 K == PreStmtPurgeDeadSymbolsKind); 00124 } 00125 00126 const ProgramPointTag *getTag() const { return Tag; } 00127 00128 const LocationContext *getLocationContext() const { 00129 return L.getPointer(); 00130 } 00131 00132 // For use with DenseMap. This hash is probably slow. 00133 unsigned getHashValue() const { 00134 llvm::FoldingSetNodeID ID; 00135 Profile(ID); 00136 return ID.ComputeHash(); 00137 } 00138 00139 static bool classof(const ProgramPoint*) { return true; } 00140 00141 bool operator==(const ProgramPoint & RHS) const { 00142 return Data1 == RHS.Data1 && 00143 Data2 == RHS.Data2 && 00144 L == RHS.L && 00145 Tag == RHS.Tag; 00146 } 00147 00148 bool operator!=(const ProgramPoint &RHS) const { 00149 return Data1 != RHS.Data1 || 00150 Data2 != RHS.Data2 || 00151 L != RHS.L || 00152 Tag != RHS.Tag; 00153 } 00154 00155 void Profile(llvm::FoldingSetNodeID& ID) const { 00156 ID.AddInteger((unsigned) getKind()); 00157 ID.AddPointer(getData1()); 00158 ID.AddPointer(getData2()); 00159 ID.AddPointer(getLocationContext()); 00160 ID.AddPointer(Tag); 00161 } 00162 00163 static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, 00164 const LocationContext *LC, 00165 const ProgramPointTag *tag); 00166 }; 00167 00168 class BlockEntrance : public ProgramPoint { 00169 public: 00170 BlockEntrance(const CFGBlock *B, const LocationContext *L, 00171 const ProgramPointTag *tag = 0) 00172 : ProgramPoint(B, BlockEntranceKind, L, tag) { 00173 assert(B && "BlockEntrance requires non-null block"); 00174 } 00175 00176 const CFGBlock *getBlock() const { 00177 return reinterpret_cast<const CFGBlock*>(getData1()); 00178 } 00179 00180 const CFGElement getFirstElement() const { 00181 const CFGBlock *B = getBlock(); 00182 return B->empty() ? CFGElement() : B->front(); 00183 } 00184 00185 static bool classof(const ProgramPoint* Location) { 00186 return Location->getKind() == BlockEntranceKind; 00187 } 00188 }; 00189 00190 class BlockExit : public ProgramPoint { 00191 public: 00192 BlockExit(const CFGBlock *B, const LocationContext *L) 00193 : ProgramPoint(B, BlockExitKind, L) {} 00194 00195 const CFGBlock *getBlock() const { 00196 return reinterpret_cast<const CFGBlock*>(getData1()); 00197 } 00198 00199 const Stmt *getTerminator() const { 00200 return getBlock()->getTerminator(); 00201 } 00202 00203 static bool classof(const ProgramPoint* Location) { 00204 return Location->getKind() == BlockExitKind; 00205 } 00206 }; 00207 00208 class StmtPoint : public ProgramPoint { 00209 public: 00210 StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L, 00211 const ProgramPointTag *tag) 00212 : ProgramPoint(S, p2, k, L, tag) {} 00213 00214 const Stmt *getStmt() const { return (const Stmt*) getData1(); } 00215 00216 template <typename T> 00217 const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); } 00218 00219 static bool classof(const ProgramPoint* Location) { 00220 unsigned k = Location->getKind(); 00221 return k >= PreStmtKind && k <= MaxPostStmtKind; 00222 } 00223 }; 00224 00225 00226 class PreStmt : public StmtPoint { 00227 public: 00228 PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag, 00229 const Stmt *SubStmt = 0) 00230 : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {} 00231 00232 const Stmt *getSubStmt() const { return (const Stmt*) getData2(); } 00233 00234 static bool classof(const ProgramPoint* Location) { 00235 return Location->getKind() == PreStmtKind; 00236 } 00237 }; 00238 00239 class PostStmt : public StmtPoint { 00240 protected: 00241 PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L, 00242 const ProgramPointTag *tag = 0) 00243 : StmtPoint(S, data, k, L, tag) {} 00244 00245 public: 00246 explicit PostStmt(const Stmt *S, Kind k, 00247 const LocationContext *L, const ProgramPointTag *tag = 0) 00248 : StmtPoint(S, NULL, k, L, tag) {} 00249 00250 explicit PostStmt(const Stmt *S, const LocationContext *L, 00251 const ProgramPointTag *tag = 0) 00252 : StmtPoint(S, NULL, PostStmtKind, L, tag) {} 00253 00254 static bool classof(const ProgramPoint* Location) { 00255 unsigned k = Location->getKind(); 00256 return k >= MinPostStmtKind && k <= MaxPostStmtKind; 00257 } 00258 }; 00259 00260 // PostCondition represents the post program point of a branch condition. 00261 class PostCondition : public PostStmt { 00262 public: 00263 PostCondition(const Stmt *S, const LocationContext *L, 00264 const ProgramPointTag *tag = 0) 00265 : PostStmt(S, PostConditionKind, L, tag) {} 00266 00267 static bool classof(const ProgramPoint* Location) { 00268 return Location->getKind() == PostConditionKind; 00269 } 00270 }; 00271 00272 class LocationCheck : public StmtPoint { 00273 protected: 00274 LocationCheck(const Stmt *S, const LocationContext *L, 00275 ProgramPoint::Kind K, const ProgramPointTag *tag) 00276 : StmtPoint(S, NULL, K, L, tag) {} 00277 00278 static bool classof(const ProgramPoint *location) { 00279 unsigned k = location->getKind(); 00280 return k == PreLoadKind || k == PreStoreKind; 00281 } 00282 }; 00283 00284 class PreLoad : public LocationCheck { 00285 public: 00286 PreLoad(const Stmt *S, const LocationContext *L, 00287 const ProgramPointTag *tag = 0) 00288 : LocationCheck(S, L, PreLoadKind, tag) {} 00289 00290 static bool classof(const ProgramPoint *location) { 00291 return location->getKind() == PreLoadKind; 00292 } 00293 }; 00294 00295 class PreStore : public LocationCheck { 00296 public: 00297 PreStore(const Stmt *S, const LocationContext *L, 00298 const ProgramPointTag *tag = 0) 00299 : LocationCheck(S, L, PreStoreKind, tag) {} 00300 00301 static bool classof(const ProgramPoint *location) { 00302 return location->getKind() == PreStoreKind; 00303 } 00304 }; 00305 00306 class PostLoad : public PostStmt { 00307 public: 00308 PostLoad(const Stmt *S, const LocationContext *L, 00309 const ProgramPointTag *tag = 0) 00310 : PostStmt(S, PostLoadKind, L, tag) {} 00311 00312 static bool classof(const ProgramPoint* Location) { 00313 return Location->getKind() == PostLoadKind; 00314 } 00315 }; 00316 00317 /// \class Represents a program point after a store evaluation. 00318 class PostStore : public PostStmt { 00319 public: 00320 /// Construct the post store point. 00321 /// \param Loc can be used to store the information about the location 00322 /// used in the form it was uttered in the code. 00323 PostStore(const Stmt *S, const LocationContext *L, const void *Loc, 00324 const ProgramPointTag *tag = 0) 00325 : PostStmt(S, PostStoreKind, L, tag) { 00326 assert(getData2() == 0); 00327 setData2(Loc); 00328 } 00329 00330 static bool classof(const ProgramPoint* Location) { 00331 return Location->getKind() == PostStoreKind; 00332 } 00333 00334 /// \brief Returns the information about the location used in the store, 00335 /// how it was uttered in the code. 00336 const void *getLocationValue() const { 00337 return getData2(); 00338 } 00339 00340 }; 00341 00342 class PostLValue : public PostStmt { 00343 public: 00344 PostLValue(const Stmt *S, const LocationContext *L, 00345 const ProgramPointTag *tag = 0) 00346 : PostStmt(S, PostLValueKind, L, tag) {} 00347 00348 static bool classof(const ProgramPoint* Location) { 00349 return Location->getKind() == PostLValueKind; 00350 } 00351 }; 00352 00353 /// \class Represents a point after we ran remove dead bindings BEFORE 00354 /// processing the given statement. 00355 class PreStmtPurgeDeadSymbols : public StmtPoint { 00356 public: 00357 PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, 00358 const ProgramPointTag *tag = 0) 00359 : StmtPoint(S, 0, PreStmtPurgeDeadSymbolsKind, L, tag) { } 00360 00361 static bool classof(const ProgramPoint* Location) { 00362 return Location->getKind() == PreStmtPurgeDeadSymbolsKind; 00363 } 00364 }; 00365 00366 /// \class Represents a point after we ran remove dead bindings AFTER 00367 /// processing the given statement. 00368 class PostStmtPurgeDeadSymbols : public StmtPoint { 00369 public: 00370 PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, 00371 const ProgramPointTag *tag = 0) 00372 : StmtPoint(S, 0, PostStmtPurgeDeadSymbolsKind, L, tag) { } 00373 00374 static bool classof(const ProgramPoint* Location) { 00375 return Location->getKind() == PostStmtPurgeDeadSymbolsKind; 00376 } 00377 }; 00378 00379 class BlockEdge : public ProgramPoint { 00380 public: 00381 BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L) 00382 : ProgramPoint(B1, B2, BlockEdgeKind, L) { 00383 assert(B1 && "BlockEdge: source block must be non-null"); 00384 assert(B2 && "BlockEdge: destination block must be non-null"); 00385 } 00386 00387 const CFGBlock *getSrc() const { 00388 return static_cast<const CFGBlock*>(getData1()); 00389 } 00390 00391 const CFGBlock *getDst() const { 00392 return static_cast<const CFGBlock*>(getData2()); 00393 } 00394 00395 static bool classof(const ProgramPoint* Location) { 00396 return Location->getKind() == BlockEdgeKind; 00397 } 00398 }; 00399 00400 class PostInitializer : public ProgramPoint { 00401 public: 00402 PostInitializer(const CXXCtorInitializer *I, 00403 const LocationContext *L) 00404 : ProgramPoint(I, PostInitializerKind, L) {} 00405 00406 static bool classof(const ProgramPoint *Location) { 00407 return Location->getKind() == PostInitializerKind; 00408 } 00409 }; 00410 00411 /// \class Represents a point when we begin processing an inlined call. 00412 class CallEnter : public StmtPoint { 00413 public: 00414 CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, 00415 const LocationContext *callerCtx) 00416 : StmtPoint(stmt, calleeCtx, CallEnterKind, callerCtx, 0) {} 00417 00418 const Stmt *getCallExpr() const { 00419 return static_cast<const Stmt *>(getData1()); 00420 } 00421 00422 const StackFrameContext *getCalleeContext() const { 00423 return static_cast<const StackFrameContext *>(getData2()); 00424 } 00425 00426 static bool classof(const ProgramPoint *Location) { 00427 return Location->getKind() == CallEnterKind; 00428 } 00429 }; 00430 00431 /// \class Represents a point when we start the call exit sequence (for 00432 /// inlined call). 00433 /// 00434 /// The call exit is simulated with a sequence of nodes, which occur between 00435 /// CallExitBegin and CallExitEnd. The following operations occur between the 00436 /// two program points: 00437 /// - CallExitBegin 00438 /// - Bind the return value 00439 /// - Run Remove dead bindings (to clean up the dead symbols from the callee). 00440 /// - CallExitEnd 00441 class CallExitBegin : public StmtPoint { 00442 public: 00443 // CallExitBegin uses the callee's location context. 00444 CallExitBegin(const Stmt *S, const LocationContext *L) 00445 : StmtPoint(S, 0, CallExitBeginKind, L, 0) {} 00446 00447 static bool classof(const ProgramPoint *Location) { 00448 return Location->getKind() == CallExitBeginKind; 00449 } 00450 }; 00451 00452 /// \class Represents a point when we finish the call exit sequence (for 00453 /// inlined call). 00454 /// \sa CallExitBegin 00455 class CallExitEnd : public StmtPoint { 00456 public: 00457 // CallExitEnd uses the caller's location context. 00458 CallExitEnd(const Stmt *S, const LocationContext *L) 00459 : StmtPoint(S, 0, CallExitEndKind, L, 0) {} 00460 00461 static bool classof(const ProgramPoint *Location) { 00462 return Location->getKind() == CallExitEndKind; 00463 } 00464 }; 00465 00466 /// This is a meta program point, which should be skipped by all the diagnostic 00467 /// reasoning etc. 00468 class EpsilonPoint : public ProgramPoint { 00469 public: 00470 EpsilonPoint(const LocationContext *L, const void *Data1, 00471 const void *Data2 = 0, const ProgramPointTag *tag = 0) 00472 : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {} 00473 00474 const void *getData() const { return getData1(); } 00475 00476 static bool classof(const ProgramPoint* Location) { 00477 return Location->getKind() == EpsilonKind; 00478 } 00479 }; 00480 00481 /// ProgramPoints can be "tagged" as representing points specific to a given 00482 /// analysis entity. Tags are abstract annotations, with an associated 00483 /// description and potentially other information. 00484 class ProgramPointTag { 00485 public: 00486 ProgramPointTag(void *tagKind = 0) : TagKind(tagKind) {} 00487 virtual ~ProgramPointTag(); 00488 virtual StringRef getTagDescription() const = 0; 00489 00490 protected: 00491 /// Used to implement 'classof' in subclasses. 00492 const void *getTagKind() { return TagKind; } 00493 00494 private: 00495 const void *TagKind; 00496 }; 00497 00498 class SimpleProgramPointTag : public ProgramPointTag { 00499 std::string desc; 00500 public: 00501 SimpleProgramPointTag(StringRef description); 00502 StringRef getTagDescription() const; 00503 }; 00504 00505 } // end namespace clang 00506 00507 00508 namespace llvm { // Traits specialization for DenseMap 00509 00510 template <> struct DenseMapInfo<clang::ProgramPoint> { 00511 00512 static inline clang::ProgramPoint getEmptyKey() { 00513 uintptr_t x = 00514 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; 00515 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); 00516 } 00517 00518 static inline clang::ProgramPoint getTombstoneKey() { 00519 uintptr_t x = 00520 reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; 00521 return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); 00522 } 00523 00524 static unsigned getHashValue(const clang::ProgramPoint &Loc) { 00525 return Loc.getHashValue(); 00526 } 00527 00528 static bool isEqual(const clang::ProgramPoint &L, 00529 const clang::ProgramPoint &R) { 00530 return L == R; 00531 } 00532 00533 }; 00534 00535 template <> 00536 struct isPodLike<clang::ProgramPoint> { static const bool value = true; }; 00537 00538 } // end namespace llvm 00539 00540 #endif