blob: 2d016cb13353877ded62a26d9ba925aba2ad3562 [file] [log] [blame]
Ted Kremeneke8f73162011-08-12 23:04:46 +00001//==- 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
17using namespace clang;
18
Angel Garcia Gomez637d1e62015-10-20 13:23:58 +000019ProgramPointTag::~ProgramPointTag() {}
Ted Kremeneke8f73162011-08-12 23:04:46 +000020
Anna Zaks8de8cfd2011-10-07 21:01:38 +000021ProgramPoint 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);
Anna Zaks8de8cfd2011-10-07 21:01:38 +000037 case ProgramPoint::PostLValueKind:
38 return PostLValue(S, LC, tag);
Anna Zaks7e53bd62012-04-20 21:59:08 +000039 case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
40 return PostStmtPurgeDeadSymbols(S, LC, tag);
41 case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
42 return PreStmtPurgeDeadSymbols(S, LC, tag);
Anna Zaks8de8cfd2011-10-07 21:01:38 +000043 }
44}
45
Eric Fiselier407584c2018-09-30 18:05:39 +000046LLVM_DUMP_METHOD void ProgramPoint::dump() const {
47 return print(/*CR=*/"\n", llvm::errs());
48}
49
George Karpenkov27ec2102018-09-27 01:46:18 +000050static 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
60void 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
Fangrui Song6907ce22018-07-30 19:24:48 +0000221SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
Anton Yartsev6a619222014-02-17 18:25:34 +0000222 StringRef Msg)
223 : Desc((MsgProvider + " : " + Msg).str()) {}
Ted Kremeneke8f73162011-08-12 23:04:46 +0000224
225StringRef SimpleProgramPointTag::getTagDescription() const {
Anton Yartsev6a619222014-02-17 18:25:34 +0000226 return Desc;
Ted Kremeneke8f73162011-08-12 23:04:46 +0000227}