Path: blob/main/contrib/llvm-project/clang/lib/Analysis/ProgramPoint.cpp
35232 views
//==- ProgramPoint.cpp - Program Points for Path-Sensitive Analysis -*- C++ -*-/1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines the interface ProgramPoint, which identifies a9// distinct location in a function.10//11//===----------------------------------------------------------------------===//1213#include "clang/Analysis/ProgramPoint.h"14#include "clang/AST/ASTContext.h"15#include "clang/Basic/JsonSupport.h"1617using namespace clang;1819ProgramPointTag::~ProgramPointTag() {}2021ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K,22const LocationContext *LC,23const ProgramPointTag *tag){24switch (K) {25default:26llvm_unreachable("Unhandled ProgramPoint kind");27case ProgramPoint::PreStmtKind:28return PreStmt(S, LC, tag);29case ProgramPoint::PostStmtKind:30return PostStmt(S, LC, tag);31case ProgramPoint::PreLoadKind:32return PreLoad(S, LC, tag);33case ProgramPoint::PostLoadKind:34return PostLoad(S, LC, tag);35case ProgramPoint::PreStoreKind:36return PreStore(S, LC, tag);37case ProgramPoint::PostLValueKind:38return PostLValue(S, LC, tag);39case ProgramPoint::PostStmtPurgeDeadSymbolsKind:40return PostStmtPurgeDeadSymbols(S, LC, tag);41case ProgramPoint::PreStmtPurgeDeadSymbolsKind:42return PreStmtPurgeDeadSymbols(S, LC, tag);43}44}4546LLVM_DUMP_METHOD void ProgramPoint::dump() const {47return printJson(llvm::errs());48}4950void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {51const ASTContext &Context =52getLocationContext()->getAnalysisDeclContext()->getASTContext();53const SourceManager &SM = Context.getSourceManager();54const PrintingPolicy &PP = Context.getPrintingPolicy();55const bool AddQuotes = true;5657Out << "\"kind\": \"";58switch (getKind()) {59case ProgramPoint::BlockEntranceKind:60Out << "BlockEntrance\""61<< ", \"block_id\": "62<< castAs<BlockEntrance>().getBlock()->getBlockID();63break;6465case ProgramPoint::FunctionExitKind: {66auto FEP = getAs<FunctionExitPoint>();67Out << "FunctionExit\""68<< ", \"block_id\": " << FEP->getBlock()->getBlockID()69<< ", \"stmt_id\": ";7071if (const ReturnStmt *RS = FEP->getStmt()) {72Out << RS->getID(Context) << ", \"stmt\": ";73RS->printJson(Out, nullptr, PP, AddQuotes);74} else {75Out << "null, \"stmt\": null";76}77break;78}79case ProgramPoint::BlockExitKind:80llvm_unreachable("BlockExitKind");81break;82case ProgramPoint::CallEnterKind:83Out << "CallEnter\"";84break;85case ProgramPoint::CallExitBeginKind:86Out << "CallExitBegin\"";87break;88case ProgramPoint::CallExitEndKind:89Out << "CallExitEnd\"";90break;91case ProgramPoint::EpsilonKind:92Out << "EpsilonPoint\"";93break;9495case ProgramPoint::LoopExitKind:96Out << "LoopExit\", \"stmt\": \""97<< castAs<LoopExit>().getLoopStmt()->getStmtClassName() << '\"';98break;99100case ProgramPoint::PreImplicitCallKind: {101ImplicitCallPoint PC = castAs<ImplicitCallPoint>();102Out << "PreCall\", \"decl\": \""103<< PC.getDecl()->getAsFunction()->getQualifiedNameAsString()104<< "\", \"location\": ";105printSourceLocationAsJson(Out, PC.getLocation(), SM);106break;107}108109case ProgramPoint::PostImplicitCallKind: {110ImplicitCallPoint PC = castAs<ImplicitCallPoint>();111Out << "PostCall\", \"decl\": \""112<< PC.getDecl()->getAsFunction()->getQualifiedNameAsString()113<< "\", \"location\": ";114printSourceLocationAsJson(Out, PC.getLocation(), SM);115break;116}117118case ProgramPoint::PostInitializerKind: {119Out << "PostInitializer\", ";120const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer();121if (const FieldDecl *FD = Init->getAnyMember()) {122Out << "\"field_decl\": \"" << *FD << '\"';123} else {124Out << "\"type\": \"";125QualType Ty = Init->getTypeSourceInfo()->getType();126Ty = Ty.getLocalUnqualifiedType();127Ty.print(Out, Context.getLangOpts());128Out << '\"';129}130break;131}132133case ProgramPoint::BlockEdgeKind: {134const BlockEdge &E = castAs<BlockEdge>();135const Stmt *T = E.getSrc()->getTerminatorStmt();136Out << "Edge\", \"src_id\": " << E.getSrc()->getBlockID()137<< ", \"dst_id\": " << E.getDst()->getBlockID() << ", \"terminator\": ";138139if (!T) {140Out << "null, \"term_kind\": null";141break;142}143144E.getSrc()->printTerminatorJson(Out, Context.getLangOpts(),145/*AddQuotes=*/true);146Out << ", \"location\": ";147printSourceLocationAsJson(Out, T->getBeginLoc(), SM);148149Out << ", \"term_kind\": \"";150if (isa<SwitchStmt>(T)) {151Out << "SwitchStmt\", \"case\": ";152if (const Stmt *Label = E.getDst()->getLabel()) {153if (const auto *C = dyn_cast<CaseStmt>(Label)) {154Out << "{ \"lhs\": ";155if (const Stmt *LHS = C->getLHS()) {156LHS->printJson(Out, nullptr, PP, AddQuotes);157} else {158Out << "null";159}160161Out << ", \"rhs\": ";162if (const Stmt *RHS = C->getRHS()) {163RHS->printJson(Out, nullptr, PP, AddQuotes);164} else {165Out << "null";166}167Out << " }";168} else {169assert(isa<DefaultStmt>(Label));170Out << "\"default\"";171}172} else {173Out << "\"implicit default\"";174}175} else if (isa<IndirectGotoStmt>(T)) {176// FIXME: More info.177Out << "IndirectGotoStmt\"";178} else {179Out << "Condition\", \"value\": "180<< (*E.getSrc()->succ_begin() == E.getDst() ? "true" : "false");181}182break;183}184185default: {186const Stmt *S = castAs<StmtPoint>().getStmt();187assert(S != nullptr && "Expecting non-null Stmt");188189Out << "Statement\", \"stmt_kind\": \"" << S->getStmtClassName()190<< "\", \"stmt_id\": " << S->getID(Context)191<< ", \"pointer\": \"" << (const void *)S << "\", ";192if (const auto *CS = dyn_cast<CastExpr>(S))193Out << "\"cast_kind\": \"" << CS->getCastKindName() << "\", ";194195Out << "\"pretty\": ";196197S->printJson(Out, nullptr, PP, AddQuotes);198199Out << ", \"location\": ";200printSourceLocationAsJson(Out, S->getBeginLoc(), SM);201202Out << ", \"stmt_point_kind\": \"";203if (getAs<PreLoad>())204Out << "PreLoad";205else if (getAs<PreStore>())206Out << "PreStore";207else if (getAs<PostAllocatorCall>())208Out << "PostAllocatorCall";209else if (getAs<PostCondition>())210Out << "PostCondition";211else if (getAs<PostLoad>())212Out << "PostLoad";213else if (getAs<PostLValue>())214Out << "PostLValue";215else if (getAs<PostStore>())216Out << "PostStore";217else if (getAs<PostStmt>())218Out << "PostStmt";219else if (getAs<PostStmtPurgeDeadSymbols>())220Out << "PostStmtPurgeDeadSymbols";221else if (getAs<PreStmtPurgeDeadSymbols>())222Out << "PreStmtPurgeDeadSymbols";223else if (getAs<PreStmt>())224Out << "PreStmt";225else {226Out << "\nKind: '" << getKind();227llvm_unreachable("' is unhandled StmtPoint kind!");228}229230Out << '\"';231break;232}233}234}235236SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,237StringRef Msg)238: Desc((MsgProvider + " : " + Msg).str()) {}239240StringRef SimpleProgramPointTag::getTagDescription() const {241return Desc;242}243244245