1 //==- ProgramPoint.cpp - Program Points for Path-Sensitive Analysis -*- C++ -*-/ 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines the interface ProgramPoint, which identifies a 10 // distinct location in a function. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/Analysis/ProgramPoint.h" 15 16 using namespace clang; 17 18 ProgramPointTag::~ProgramPointTag() {} 19 20 ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K, 21 const LocationContext *LC, 22 const ProgramPointTag *tag){ 23 switch (K) { 24 default: 25 llvm_unreachable("Unhandled ProgramPoint kind"); 26 case ProgramPoint::PreStmtKind: 27 return PreStmt(S, LC, tag); 28 case ProgramPoint::PostStmtKind: 29 return PostStmt(S, LC, tag); 30 case ProgramPoint::PreLoadKind: 31 return PreLoad(S, LC, tag); 32 case ProgramPoint::PostLoadKind: 33 return PostLoad(S, LC, tag); 34 case ProgramPoint::PreStoreKind: 35 return PreStore(S, LC, tag); 36 case ProgramPoint::PostLValueKind: 37 return PostLValue(S, LC, tag); 38 case ProgramPoint::PostStmtPurgeDeadSymbolsKind: 39 return PostStmtPurgeDeadSymbols(S, LC, tag); 40 case ProgramPoint::PreStmtPurgeDeadSymbolsKind: 41 return PreStmtPurgeDeadSymbols(S, LC, tag); 42 } 43 } 44 45 LLVM_DUMP_METHOD void ProgramPoint::dump() const { 46 return print(/*CR=*/"\n", llvm::errs()); 47 } 48 49 static void printLocation(raw_ostream &Out, SourceLocation SLoc, 50 const SourceManager &SM, 51 StringRef CR, 52 StringRef Postfix) { 53 if (SLoc.isFileID()) { 54 Out << CR << "line=" << SM.getExpansionLineNumber(SLoc) 55 << " col=" << SM.getExpansionColumnNumber(SLoc) << Postfix; 56 } 57 } 58 59 void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const { 60 const ASTContext &Context = 61 getLocationContext()->getAnalysisDeclContext()->getASTContext(); 62 const SourceManager &SM = Context.getSourceManager(); 63 switch (getKind()) { 64 case ProgramPoint::BlockEntranceKind: 65 Out << "Block Entrance: B" 66 << castAs<BlockEntrance>().getBlock()->getBlockID(); 67 break; 68 69 case ProgramPoint::FunctionExitKind: { 70 auto FEP = getAs<FunctionExitPoint>(); 71 Out << "Function Exit: B" << FEP->getBlock()->getBlockID(); 72 if (const ReturnStmt *RS = FEP->getStmt()) { 73 Out << CR << " Return: S" << RS->getID(Context) << CR; 74 RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(), 75 /*Indentation=*/2, /*NewlineSymbol=*/CR); 76 } 77 break; 78 } 79 case ProgramPoint::BlockExitKind: 80 assert(false); 81 break; 82 83 case ProgramPoint::CallEnterKind: 84 Out << "CallEnter"; 85 break; 86 87 case ProgramPoint::CallExitBeginKind: 88 Out << "CallExitBegin"; 89 break; 90 91 case ProgramPoint::CallExitEndKind: 92 Out << "CallExitEnd"; 93 break; 94 95 case ProgramPoint::PostStmtPurgeDeadSymbolsKind: 96 Out << "PostStmtPurgeDeadSymbols"; 97 break; 98 99 case ProgramPoint::PreStmtPurgeDeadSymbolsKind: 100 Out << "PreStmtPurgeDeadSymbols"; 101 break; 102 103 case ProgramPoint::EpsilonKind: 104 Out << "Epsilon Point"; 105 break; 106 107 case ProgramPoint::LoopExitKind: { 108 LoopExit LE = castAs<LoopExit>(); 109 Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName(); 110 break; 111 } 112 113 case ProgramPoint::PreImplicitCallKind: { 114 ImplicitCallPoint PC = castAs<ImplicitCallPoint>(); 115 Out << "PreCall: "; 116 PC.getDecl()->print(Out, Context.getLangOpts()); 117 printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR); 118 break; 119 } 120 121 case ProgramPoint::PostImplicitCallKind: { 122 ImplicitCallPoint PC = castAs<ImplicitCallPoint>(); 123 Out << "PostCall: "; 124 PC.getDecl()->print(Out, Context.getLangOpts()); 125 printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR); 126 break; 127 } 128 129 case ProgramPoint::PostInitializerKind: { 130 Out << "PostInitializer: "; 131 const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer(); 132 if (const FieldDecl *FD = Init->getAnyMember()) 133 Out << *FD; 134 else { 135 QualType Ty = Init->getTypeSourceInfo()->getType(); 136 Ty = Ty.getLocalUnqualifiedType(); 137 Ty.print(Out, Context.getLangOpts()); 138 } 139 break; 140 } 141 142 case ProgramPoint::BlockEdgeKind: { 143 const BlockEdge &E = castAs<BlockEdge>(); 144 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B" 145 << E.getDst()->getBlockID() << ')'; 146 147 if (const Stmt *T = E.getSrc()->getTerminator()) { 148 SourceLocation SLoc = T->getBeginLoc(); 149 150 Out << "\\|Terminator: "; 151 E.getSrc()->printTerminator(Out, Context.getLangOpts()); 152 printLocation(Out, SLoc, SM, CR, /*Postfix=*/""); 153 154 if (isa<SwitchStmt>(T)) { 155 const Stmt *Label = E.getDst()->getLabel(); 156 157 if (Label) { 158 if (const auto *C = dyn_cast<CaseStmt>(Label)) { 159 Out << CR << "case "; 160 if (C->getLHS()) 161 C->getLHS()->printPretty( 162 Out, nullptr, Context.getPrintingPolicy(), 163 /*Indentation=*/0, /*NewlineSymbol=*/CR); 164 165 if (const Stmt *RHS = C->getRHS()) { 166 Out << " .. "; 167 RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(), 168 /*Indetation=*/0, /*NewlineSymbol=*/CR); 169 } 170 171 Out << ":"; 172 } else { 173 assert(isa<DefaultStmt>(Label)); 174 Out << CR << "default:"; 175 } 176 } else 177 Out << CR << "(implicit) default:"; 178 } else if (isa<IndirectGotoStmt>(T)) { 179 // FIXME 180 } else { 181 Out << CR << "Condition: "; 182 if (*E.getSrc()->succ_begin() == E.getDst()) 183 Out << "true"; 184 else 185 Out << "false"; 186 } 187 188 Out << CR; 189 } 190 191 break; 192 } 193 194 default: { 195 const Stmt *S = castAs<StmtPoint>().getStmt(); 196 assert(S != nullptr && "Expecting non-null Stmt"); 197 198 Out << S->getStmtClassName() << " S" << S->getID(Context) << " <" 199 << (const void *)S << "> "; 200 S->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(), 201 /*Indentation=*/2, /*NewlineSymbol=*/CR); 202 printLocation(Out, S->getBeginLoc(), SM, CR, /*Postfix=*/""); 203 204 if (getAs<PreStmt>()) 205 Out << CR << "PreStmt" << CR; 206 else if (getAs<PostLoad>()) 207 Out << CR << "PostLoad" << CR; 208 else if (getAs<PostStore>()) 209 Out << CR << "PostStore" << CR; 210 else if (getAs<PostLValue>()) 211 Out << CR << "PostLValue" << CR; 212 else if (getAs<PostAllocatorCall>()) 213 Out << CR << "PostAllocatorCall" << CR; 214 215 break; 216 } 217 } 218 } 219 220 SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider, 221 StringRef Msg) 222 : Desc((MsgProvider + " : " + Msg).str()) {} 223 224 StringRef SimpleProgramPointTag::getTagDescription() const { 225 return Desc; 226 } 227