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