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 static void printLocation(raw_ostream &Out, SourceLocation SLoc, 47 const SourceManager &SM, 48 StringRef CR, 49 StringRef Postfix) { 50 if (SLoc.isFileID()) { 51 Out << CR << "line=" << SM.getExpansionLineNumber(SLoc) 52 << " col=" << SM.getExpansionColumnNumber(SLoc) << Postfix; 53 } 54 } 55 56 void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const { 57 const ASTContext &Context = 58 getLocationContext()->getAnalysisDeclContext()->getASTContext(); 59 const SourceManager &SM = Context.getSourceManager(); 60 switch (getKind()) { 61 case ProgramPoint::BlockEntranceKind: 62 Out << "Block Entrance: B" 63 << castAs<BlockEntrance>().getBlock()->getBlockID(); 64 break; 65 66 case ProgramPoint::FunctionExitKind: { 67 auto FEP = getAs<FunctionExitPoint>(); 68 Out << "Function Exit: B" << FEP->getBlock()->getBlockID(); 69 if (const ReturnStmt *RS = FEP->getStmt()) { 70 Out << CR << " Return: S" << RS->getID(Context) << CR; 71 RS->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(), 72 /*Indentation=*/2, /*NewlineSymbol=*/CR); 73 } 74 break; 75 } 76 case ProgramPoint::BlockExitKind: 77 assert(false); 78 break; 79 80 case ProgramPoint::CallEnterKind: 81 Out << "CallEnter"; 82 break; 83 84 case ProgramPoint::CallExitBeginKind: 85 Out << "CallExitBegin"; 86 break; 87 88 case ProgramPoint::CallExitEndKind: 89 Out << "CallExitEnd"; 90 break; 91 92 case ProgramPoint::PostStmtPurgeDeadSymbolsKind: 93 Out << "PostStmtPurgeDeadSymbols"; 94 break; 95 96 case ProgramPoint::PreStmtPurgeDeadSymbolsKind: 97 Out << "PreStmtPurgeDeadSymbols"; 98 break; 99 100 case ProgramPoint::EpsilonKind: 101 Out << "Epsilon Point"; 102 break; 103 104 case ProgramPoint::LoopExitKind: { 105 LoopExit LE = castAs<LoopExit>(); 106 Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName(); 107 break; 108 } 109 110 case ProgramPoint::PreImplicitCallKind: { 111 ImplicitCallPoint PC = castAs<ImplicitCallPoint>(); 112 Out << "PreCall: "; 113 PC.getDecl()->print(Out, Context.getLangOpts()); 114 printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR); 115 break; 116 } 117 118 case ProgramPoint::PostImplicitCallKind: { 119 ImplicitCallPoint PC = castAs<ImplicitCallPoint>(); 120 Out << "PostCall: "; 121 PC.getDecl()->print(Out, Context.getLangOpts()); 122 printLocation(Out, PC.getLocation(), SM, CR, /*Postfix=*/CR); 123 break; 124 } 125 126 case ProgramPoint::PostInitializerKind: { 127 Out << "PostInitializer: "; 128 const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer(); 129 if (const FieldDecl *FD = Init->getAnyMember()) 130 Out << *FD; 131 else { 132 QualType Ty = Init->getTypeSourceInfo()->getType(); 133 Ty = Ty.getLocalUnqualifiedType(); 134 Ty.print(Out, Context.getLangOpts()); 135 } 136 break; 137 } 138 139 case ProgramPoint::BlockEdgeKind: { 140 const BlockEdge &E = castAs<BlockEdge>(); 141 Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B" 142 << E.getDst()->getBlockID() << ')'; 143 144 if (const Stmt *T = E.getSrc()->getTerminator()) { 145 SourceLocation SLoc = T->getBeginLoc(); 146 147 Out << "\\|Terminator: "; 148 E.getSrc()->printTerminator(Out, Context.getLangOpts()); 149 printLocation(Out, SLoc, SM, CR, /*Postfix=*/""); 150 151 if (isa<SwitchStmt>(T)) { 152 const Stmt *Label = E.getDst()->getLabel(); 153 154 if (Label) { 155 if (const auto *C = dyn_cast<CaseStmt>(Label)) { 156 Out << CR << "case "; 157 if (C->getLHS()) 158 C->getLHS()->printPretty( 159 Out, nullptr, Context.getPrintingPolicy(), 160 /*Indentation=*/0, /*NewlineSymbol=*/CR); 161 162 if (const Stmt *RHS = C->getRHS()) { 163 Out << " .. "; 164 RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(), 165 /*Indetation=*/0, /*NewlineSymbol=*/CR); 166 } 167 168 Out << ":"; 169 } else { 170 assert(isa<DefaultStmt>(Label)); 171 Out << CR << "default:"; 172 } 173 } else 174 Out << CR << "(implicit) default:"; 175 } else if (isa<IndirectGotoStmt>(T)) { 176 // FIXME 177 } else { 178 Out << CR << "Condition: "; 179 if (*E.getSrc()->succ_begin() == E.getDst()) 180 Out << "true"; 181 else 182 Out << "false"; 183 } 184 185 Out << CR; 186 } 187 188 break; 189 } 190 191 default: { 192 const Stmt *S = castAs<StmtPoint>().getStmt(); 193 assert(S != nullptr && "Expecting non-null Stmt"); 194 195 Out << S->getStmtClassName() << " S" << S->getID(Context) << " <" 196 << (const void *)S << "> "; 197 S->printPretty(Out, /*helper=*/nullptr, Context.getPrintingPolicy(), 198 /*Indentation=*/2, /*NewlineSymbol=*/CR); 199 printLocation(Out, S->getBeginLoc(), SM, CR, /*Postfix=*/""); 200 201 if (getAs<PreStmt>()) 202 Out << CR << "PreStmt" << CR; 203 else if (getAs<PostLoad>()) 204 Out << CR << "PostLoad" << CR; 205 else if (getAs<PostStore>()) 206 Out << CR << "PostStore" << CR; 207 else if (getAs<PostLValue>()) 208 Out << CR << "PostLValue" << CR; 209 else if (getAs<PostAllocatorCall>()) 210 Out << CR << "PostAllocatorCall" << CR; 211 212 break; 213 } 214 } 215 } 216 217 SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider, 218 StringRef Msg) 219 : Desc((MsgProvider + " : " + Msg).str()) {} 220 221 StringRef SimpleProgramPointTag::getTagDescription() const { 222 return Desc; 223 } 224