diff options
Diffstat (limited to 'lib/Analysis/ProgramPoint.cpp')
-rw-r--r-- | lib/Analysis/ProgramPoint.cpp | 225 |
1 files changed, 118 insertions, 107 deletions
diff --git a/lib/Analysis/ProgramPoint.cpp b/lib/Analysis/ProgramPoint.cpp index 2d016cb13353..97e90965d007 100644 --- a/lib/Analysis/ProgramPoint.cpp +++ b/lib/Analysis/ProgramPoint.cpp @@ -1,9 +1,8 @@ //==- 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. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -13,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/JsonSupport.h" using namespace clang; @@ -44,151 +44,141 @@ ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K, } 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; - } + return printJson(llvm::errs()); } -void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const { +void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const { const ASTContext &Context = getLocationContext()->getAnalysisDeclContext()->getASTContext(); const SourceManager &SM = Context.getSourceManager(); + const PrintingPolicy &PP = Context.getPrintingPolicy(); + const bool AddQuotes = true; + + Out << "\"kind\": \""; switch (getKind()) { case ProgramPoint::BlockEntranceKind: - Out << "Block Entrance: B" + Out << "BlockEntrance\"" + << ", \"block_id\": " << castAs<BlockEntrance>().getBlock()->getBlockID(); break; case ProgramPoint::FunctionExitKind: { auto FEP = getAs<FunctionExitPoint>(); - Out << "Function Exit: B" << FEP->getBlock()->getBlockID(); + Out << "FunctionExit\"" + << ", \"block_id\": " << FEP->getBlock()->getBlockID() + << ", \"stmt_id\": "; + 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); + Out << RS->getID(Context) << ", \"stmt\": "; + RS->printJson(Out, nullptr, PP, AddQuotes); + } else { + Out << "null, \"stmt\": null"; } break; } case ProgramPoint::BlockExitKind: - assert(false); + llvm_unreachable("BlockExitKind"); break; - case ProgramPoint::CallEnterKind: - Out << "CallEnter"; + Out << "CallEnter\""; break; - case ProgramPoint::CallExitBeginKind: - Out << "CallExitBegin"; + Out << "CallExitBegin\""; break; - case ProgramPoint::CallExitEndKind: - Out << "CallExitEnd"; - break; - - case ProgramPoint::PostStmtPurgeDeadSymbolsKind: - Out << "PostStmtPurgeDeadSymbols"; - break; - - case ProgramPoint::PreStmtPurgeDeadSymbolsKind: - Out << "PreStmtPurgeDeadSymbols"; + Out << "CallExitEnd\""; break; - case ProgramPoint::EpsilonKind: - Out << "Epsilon Point"; + Out << "EpsilonPoint\""; break; - case ProgramPoint::LoopExitKind: { - LoopExit LE = castAs<LoopExit>(); - Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName(); + case ProgramPoint::LoopExitKind: + Out << "LoopExit\", \"stmt\": \"" + << castAs<LoopExit>().getLoopStmt()->getStmtClassName() << '\"'; break; - } case ProgramPoint::PreImplicitCallKind: { ImplicitCallPoint PC = castAs<ImplicitCallPoint>(); - Out << "PreCall: "; - PC.getDecl()->print(Out, Context.getLangOpts()); - printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR); + Out << "PreCall\", \"decl\": \"" + << PC.getDecl()->getAsFunction()->getQualifiedNameAsString() + << "\", \"location\": "; + printSourceLocationAsJson(Out, PC.getLocation(), SM); break; } case ProgramPoint::PostImplicitCallKind: { ImplicitCallPoint PC = castAs<ImplicitCallPoint>(); - Out << "PostCall: "; - PC.getDecl()->print(Out, Context.getLangOpts()); - printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR); + Out << "PostCall\", \"decl\": \"" + << PC.getDecl()->getAsFunction()->getQualifiedNameAsString() + << "\", \"location\": "; + printSourceLocationAsJson(Out, PC.getLocation(), SM); break; } case ProgramPoint::PostInitializerKind: { - Out << "PostInitializer: "; + Out << "PostInitializer\", "; const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer(); - if (const FieldDecl *FD = Init->getAnyMember()) - Out << *FD; - else { + if (const FieldDecl *FD = Init->getAnyMember()) { + Out << "\"field_decl\": \"" << *FD << '\"'; + } else { + Out << "\"type\": \""; QualType Ty = Init->getTypeSourceInfo()->getType(); Ty = Ty.getLocalUnqualifiedType(); Ty.print(Out, Context.getLangOpts()); + Out << '\"'; } break; } case ProgramPoint::BlockEdgeKind: { const BlockEdge &E = castAs<BlockEdge>(); - 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<SwitchStmt>(T)) { - const Stmt *Label = E.getDst()->getLabel(); - - if (Label) { - if (const auto *C = dyn_cast<CaseStmt>(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 << ":"; + const Stmt *T = E.getSrc()->getTerminatorStmt(); + Out << "Edge\", \"src_id\": " << E.getSrc()->getBlockID() + << ", \"dst_id\": " << E.getDst()->getBlockID() << ", \"terminator\": "; + + if (!T) { + Out << "null, \"term_kind\": null"; + break; + } + + E.getSrc()->printTerminatorJson(Out, Context.getLangOpts(), + /*AddQuotes=*/true); + Out << ", \"location\": "; + printSourceLocationAsJson(Out, T->getBeginLoc(), SM); + + Out << ", \"term_kind\": \""; + if (isa<SwitchStmt>(T)) { + Out << "SwitchStmt\", \"case\": "; + if (const Stmt *Label = E.getDst()->getLabel()) { + if (const auto *C = dyn_cast<CaseStmt>(Label)) { + Out << "{ \"lhs\": "; + if (const Stmt *LHS = C->getLHS()) { + LHS->printJson(Out, nullptr, PP, AddQuotes); + } else { + Out << "null"; + } + + Out << ", \"rhs\": "; + if (const Stmt *RHS = C->getRHS()) { + RHS->printJson(Out, nullptr, PP, AddQuotes); } else { - assert(isa<DefaultStmt>(Label)); - Out << CR << "default:"; + Out << "null"; } - } else - Out << CR << "(implicit) default:"; - } else if (isa<IndirectGotoStmt>(T)) { - // FIXME + Out << " }"; + } else { + assert(isa<DefaultStmt>(Label)); + Out << "\"default\""; + } } else { - Out << CR << "Condition: "; - if (*E.getSrc()->succ_begin() == E.getDst()) - Out << "true"; - else - Out << "false"; + Out << "\"implicit default\""; } - - Out << CR; + } else if (isa<IndirectGotoStmt>(T)) { + // FIXME: More info. + Out << "IndirectGotoStmt\""; + } else { + Out << "Condition\", \"value\": " + << (*E.getSrc()->succ_begin() == E.getDst() ? "true" : "false"); } - break; } @@ -196,23 +186,44 @@ void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const { const Stmt *S = castAs<StmtPoint>().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=*/""); + Out << "Statement\", \"stmt_kind\": \"" << S->getStmtClassName() + << "\", \"stmt_id\": " << S->getID(Context) + << ", \"pointer\": \"" << (const void *)S << "\", \"pretty\": "; + + S->printJson(Out, nullptr, PP, AddQuotes); - if (getAs<PreStmt>()) - Out << CR << "PreStmt" << CR; + Out << ", \"location\": "; + printSourceLocationAsJson(Out, S->getBeginLoc(), SM); + + Out << ", \"stmt_point_kind\": \""; + if (getAs<PreLoad>()) + Out << "PreLoad"; + else if (getAs<PreStore>()) + Out << "PreStore"; + else if (getAs<PostAllocatorCall>()) + Out << "PostAllocatorCall"; + else if (getAs<PostCondition>()) + Out << "PostCondition"; else if (getAs<PostLoad>()) - Out << CR << "PostLoad" << CR; - else if (getAs<PostStore>()) - Out << CR << "PostStore" << CR; + Out << "PostLoad"; else if (getAs<PostLValue>()) - Out << CR << "PostLValue" << CR; - else if (getAs<PostAllocatorCall>()) - Out << CR << "PostAllocatorCall" << CR; + Out << "PostLValue"; + else if (getAs<PostStore>()) + Out << "PostStore"; + else if (getAs<PostStmt>()) + Out << "PostStmt"; + else if (getAs<PostStmtPurgeDeadSymbols>()) + Out << "PostStmtPurgeDeadSymbols"; + else if (getAs<PreStmtPurgeDeadSymbols>()) + Out << "PreStmtPurgeDeadSymbols"; + else if (getAs<PreStmt>()) + Out << "PreStmt"; + else { + Out << "\nKind: '" << getKind(); + llvm_unreachable("' is unhandled StmtPoint kind!"); + } + Out << '\"'; break; } } |