Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -107,6 +107,12 @@ ~ProgramState(); + /// Get a pair of numbers uniquely identifying the state. + std::pair getID() const; + + /// Dump a unique ID to a given stream. + void dumpID(llvm::raw_ostream &Out) const; + /// Return the ProgramStateManager associated with this state. ProgramStateManager &getStateManager() const { return *stateMgr; Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -3129,8 +3129,9 @@ } ProgramStateRef state = N->getState(); - Out << "\\|StateID: " << (const void*) state.get() - << " NodeID: " << (const void*) N << "\\|"; + Out << "\\|StateID: "; + state->dumpID(Out); + Out << " NodeID: " << (const void*) N << "\\|"; state->printDOT(Out, N->getLocationContext()); Index: clang/lib/StaticAnalyzer/Core/ProgramState.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -69,6 +69,17 @@ stateMgr->getStoreManager().decrementReferenceCount(store); } +std::pair ProgramState::getID() const { + auto Out = getStateManager().Alloc.identifyObject(this); + return *Out; +} + +void ProgramState::dumpID(llvm::raw_ostream &Out) const { + auto P = getID(); + assert(P.second % alignof(ProgramState) == 0 && "Unexpected offset"); + Out << "(" << P.first << ", " << (P.second / alignof(ProgramState)) << ")"; +} + ProgramStateManager::ProgramStateManager(ASTContext &Ctx, StoreManagerCreator CreateSMgr, ConstraintManagerCreator CreateCMgr,