//==- ProgramPoint.cpp - Program Points for Path-Sensitive Analysis -*- C++ -*-/ // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the interface ProgramPoint, which identifies a // distinct location in a function. // //===----------------------------------------------------------------------===// #include "clang/Analysis/ProgramPoint.h" using namespace clang; ProgramPointTag::~ProgramPointTag() {} ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const LocationContext *LC, const ProgramPointTag *tag){ switch (K) { default: llvm_unreachable("Unhandled ProgramPoint kind"); case ProgramPoint::PreStmtKind: return PreStmt(S, LC, tag); case ProgramPoint::PostStmtKind: return PostStmt(S, LC, tag); case ProgramPoint::PreLoadKind: return PreLoad(S, LC, tag); case ProgramPoint::PostLoadKind: return PostLoad(S, LC, tag); case ProgramPoint::PreStoreKind: return PreStore(S, LC, tag); case ProgramPoint::PostLValueKind: return PostLValue(S, LC, tag); case ProgramPoint::PostStmtPurgeDeadSymbolsKind: return PostStmtPurgeDeadSymbols(S, LC, tag); case ProgramPoint::PreStmtPurgeDeadSymbolsKind: return PreStmtPurgeDeadSymbols(S, LC, tag); } } LLVM_DUMP_METHOD void ProgramPoint::dump() const { return print(/*CR=*/"\n", llvm::errs()); } static void printLocation(raw_ostream &Out, SourceLocation SLoc, const SourceManager &SM, StringRef CR, StringRef Postfix) { if (SLoc.isFileID()) { Out << CR << "line=" << SM.getExpansionLineNumber(SLoc) << " col=" << SM.getExpansionColumnNumber(SLoc) << Postfix; } } void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const { const ASTContext &Context = getLocationContext()->getAnalysisDeclContext()->getASTContext(); const SourceManager &SM = Context.getSourceManager(); switch (getKind()) { case ProgramPoint::BlockEntranceKind: Out << "Block Entrance: B" << castAs().getBlock()->getBlockID(); break; case ProgramPoint::FunctionExitKind: { auto FEP = getAs(); Out << "Function Exit: B" << FEP->getBlock()->getBlockID(); if (const ReturnStmt *RS = FEP->getStmt()) { Out << CR << " Return: S" << RS->getID(Context) << CR; RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(), /*Indentation=*/2, /*NewlineSymbol=*/CR); } break; } case ProgramPoint::BlockExitKind: assert(false); break; case ProgramPoint::CallEnterKind: Out << "CallEnter"; break; case ProgramPoint::CallExitBeginKind: Out << "CallExitBegin"; break; case ProgramPoint::CallExitEndKind: Out << "CallExitEnd"; break; case ProgramPoint::PostStmtPurgeDeadSymbolsKind: Out << "PostStmtPurgeDeadSymbols"; break; case ProgramPoint::PreStmtPurgeDeadSymbolsKind: Out << "PreStmtPurgeDeadSymbols"; break; case ProgramPoint::EpsilonKind: Out << "Epsilon Point"; break; case ProgramPoint::LoopExitKind: { LoopExit LE = castAs(); Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName(); break; } case ProgramPoint::PreImplicitCallKind: { ImplicitCallPoint PC = castAs(); Out << "PreCall: "; PC.getDecl()->print(Out, Context.getLangOpts()); printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR); break; } case ProgramPoint::PostImplicitCallKind: { ImplicitCallPoint PC = castAs(); Out << "PostCall: "; PC.getDecl()->print(Out, Context.getLangOpts()); printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR); break; } case ProgramPoint::PostInitializerKind: { Out << "PostInitializer: "; const CXXCtorInitializer *Init = castAs().getInitializer(); if (const FieldDecl *FD = Init->getAnyMember()) Out << *FD; else { QualType Ty = Init->getTypeSourceInfo()->getType(); Ty = Ty.getLocalUnqualifiedType(); Ty.print(Out, Context.getLangOpts()); } break; } case ProgramPoint::BlockEdgeKind: { const BlockEdge &E = castAs(); Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B" << E.getDst()->getBlockID() << ')'; if (const Stmt *T = E.getSrc()->getTerminator()) { SourceLocation SLoc = T->getBeginLoc(); Out << "\\|Terminator: "; E.getSrc()->printTerminator(Out, Context.getLangOpts()); printLocation(Out, SLoc, SM, CR, /*Postfix=*/""); if (isa(T)) { const Stmt *Label = E.getDst()->getLabel(); if (Label) { if (const auto *C = dyn_cast(Label)) { Out << CR << "case "; if (C->getLHS()) C->getLHS()->printPretty( Out, nullptr, Context.getPrintingPolicy(), /*Indentation=*/0, /*NewlineSymbol=*/CR); if (const Stmt *RHS = C->getRHS()) { Out << " .. "; RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(), /*Indetation=*/0, /*NewlineSymbol=*/CR); } Out << ":"; } else { assert(isa(Label)); Out << CR << "default:"; } } else Out << CR << "(implicit) default:"; } else if (isa(T)) { // FIXME } else { Out << CR << "Condition: "; if (*E.getSrc()->succ_begin() == E.getDst()) Out << "true"; else Out << "false"; } Out << CR; } break; } default: { const Stmt *S = castAs().getStmt(); assert(S != nullptr && "Expecting non-null Stmt"); Out << S->getStmtClassName() << " S" << S->getID(Context) << " <" << (const void *)S << "> "; S->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(), /*Indentation=*/2, /*NewlineSymbol=*/CR); printLocation(Out, S->getBeginLoc(), SM, CR, /*Postfix=*/""); if (getAs()) Out << CR << "PreStmt" << CR; else if (getAs()) Out << CR << "PostLoad" << CR; else if (getAs()) Out << CR << "PostStore" << CR; else if (getAs()) Out << CR << "PostLValue" << CR; else if (getAs()) Out << CR << "PostAllocatorCall" << CR; break; } } } SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg) : Desc((MsgProvider + " : " + Msg).str()) {} StringRef SimpleProgramPointTag::getTagDescription() const { return Desc; }