Index: include/clang/Analysis/ProgramPoint.h =================================================================== --- include/clang/Analysis/ProgramPoint.h +++ include/clang/Analysis/ProgramPoint.h @@ -215,6 +215,12 @@ ID.AddPointer(getTag()); } + void print(StringRef CR, llvm::raw_ostream &Out) const; + + LLVM_DUMP_METHOD void dump() const { + return print(/*CR=*/"\n", llvm::errs()); + } + static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const LocationContext *LC, const ProgramPointTag *tag); Index: lib/Analysis/ProgramPoint.cpp =================================================================== --- lib/Analysis/ProgramPoint.cpp +++ lib/Analysis/ProgramPoint.cpp @@ -43,6 +43,177 @@ } } +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()) {} Index: lib/StaticAnalyzer/Core/ExprEngine.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngine.cpp +++ lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -2962,183 +2962,6 @@ return {}; } - // De-duplicate some source location pretty-printing. - static void printLocation(raw_ostream &Out, - SourceLocation SLoc, - const SourceManager &SM, - StringRef Postfix="\\l") { - if (SLoc.isFileID()) { - Out << "\\lline=" - << SM.getExpansionLineNumber(SLoc) - << " col=" - << SM.getExpansionColumnNumber(SLoc) - << Postfix; - } - } - - static void dumpProgramPoint(ProgramPoint Loc, - const ASTContext &Context, - llvm::raw_string_ostream &Out) { - const SourceManager &SM = Context.getSourceManager(); - switch (Loc.getKind()) { - case ProgramPoint::BlockEntranceKind: - Out << "Block Entrance: B" - << Loc.castAs().getBlock()->getBlockID(); - break; - - case ProgramPoint::FunctionExitKind: { - auto FEP = Loc.getAs(); - Out << "Function Exit: B" - << FEP->getBlock()->getBlockID(); - if (const ReturnStmt *RS = FEP->getStmt()) { - Out << "\\l Return: S" << RS->getID(Context) << "\\l"; - RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(), - /*Indentation=*/2, /*NewlineSymbol=*/"\\l"); - } - 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 = Loc.castAs(); - Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName(); - break; - } - - case ProgramPoint::PreImplicitCallKind: { - ImplicitCallPoint PC = Loc.castAs(); - Out << "PreCall: "; - PC.getDecl()->print(Out, Context.getLangOpts()); - printLocation(Out, PC.getLocation(), SM); - break; - } - - case ProgramPoint::PostImplicitCallKind: { - ImplicitCallPoint PC = Loc.castAs(); - Out << "PostCall: "; - PC.getDecl()->print(Out, Context.getLangOpts()); - printLocation(Out, PC.getLocation(), SM); - break; - } - - case ProgramPoint::PostInitializerKind: { - Out << "PostInitializer: "; - const CXXCtorInitializer *Init = - Loc.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 = Loc.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, /*Postfix=*/""); - - if (isa(T)) { - const Stmt *Label = E.getDst()->getLabel(); - - if (Label) { - if (const auto *C = dyn_cast(Label)) { - Out << "\\lcase "; - if (C->getLHS()) - C->getLHS()->printPretty( - Out, nullptr, Context.getPrintingPolicy(), - /*Indentation=*/0, /*NewlineSymbol=*/"\\l"); - - if (const Stmt *RHS = C->getRHS()) { - Out << " .. "; - RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(), - /*Indetation=*/0, /*NewlineSymbol=*/"\\l"); - } - - Out << ":"; - } else { - assert(isa(Label)); - Out << "\\ldefault:"; - } - } else - Out << "\\l(implicit) default:"; - } else if (isa(T)) { - // FIXME - } else { - Out << "\\lCondition: "; - if (*E.getSrc()->succ_begin() == E.getDst()) - Out << "true"; - else - Out << "false"; - } - - Out << "\\l"; - } - - break; - } - - default: { - const Stmt *S = Loc.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=*/"\\l"); - printLocation(Out, S->getBeginLoc(), SM, /*Postfix=*/""); - - if (Loc.getAs()) - Out << "\\lPreStmt\\l"; - else if (Loc.getAs()) - Out << "\\lPostLoad\\l"; - else if (Loc.getAs()) - Out << "\\lPostStore\\l"; - else if (Loc.getAs()) - Out << "\\lPostLValue\\l"; - else if (Loc.getAs()) - Out << "\\lPostAllocatorCall\\l"; - - break; - } - } - } - static bool isNodeHidden(const ExplodedNode *N) { return N->isTrivial(); } @@ -3156,12 +2979,11 @@ } ProgramStateRef State = N->getState(); - const ASTContext &Context = State->getStateManager().getContext(); // Dump program point for all the previously skipped nodes. const ExplodedNode *OtherNode = FirstHiddenNode; while (true) { - dumpProgramPoint(OtherNode->getLocation(), Context, Out); + OtherNode->getLocation().print(/*CR=*/"\\l", Out); if (const ProgramPointTag *Tag = OtherNode->getLocation().getTag()) Out << "\\lTag:" << Tag->getTagDescription();