clang 23.0.0git
ProgramPoint.cpp
Go to the documentation of this file.
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
18
19using namespace clang;
20
22
24 const StackFrame *SF,
25 const ProgramPointTag *tag) {
26 switch (K) {
27 default:
28 llvm_unreachable("Unhandled ProgramPoint kind");
30 return PreStmt(S, SF, tag);
32 return PostStmt(S, SF, tag);
34 return PreLoad(S, SF, tag);
36 return PostLoad(S, SF, tag);
38 return PreStore(S, SF, tag);
40 return PostLValue(S, SF, tag);
42 return PostStmtPurgeDeadSymbols(S, SF, tag);
44 return PreStmtPurgeDeadSymbols(S, SF, tag);
45 }
46}
47
48LLVM_DUMP_METHOD void ProgramPoint::dump() const {
49 return printJson(llvm::errs());
50}
51
53 switch (K) {
54 case BlockEdgeKind:
55 return "BlockEdge";
57 return "BlockEntrance";
58 case BlockExitKind:
59 return "BlockExit";
60 case PreStmtKind:
61 return "PreStmt";
63 return "PreStmtPurgeDeadSymbols";
65 return "PostStmtPurgeDeadSymbols";
66 case PostStmtKind:
67 return "PostStmt";
68 case PreLoadKind:
69 return "PreLoad";
70 case PostLoadKind:
71 return "PostLoad";
72 case PreStoreKind:
73 return "PreStore";
74 case PostStoreKind:
75 return "PostStore";
77 return "PostCondition";
78 case PostLValueKind:
79 return "PostLValue";
81 return "PostAllocatorCall";
83 return "PostInitializer";
84 case CallEnterKind:
85 return "CallEnter";
87 return "CallExitBegin";
88 case CallExitEndKind:
89 return "CallExitEnd";
91 return "FunctionExit";
93 return "PreImplicitCall";
95 return "PostImplicitCall";
96 case LoopExitKind:
97 return "LoopExit";
98 case LifetimeEndKind:
99 return "LifetimeEnd";
100 case EpsilonKind:
101 return "Epsilon";
102 }
103 llvm_unreachable("Unknown ProgramPoint kind");
104}
105
106std::optional<SourceLocation> ProgramPoint::getSourceLocation() const {
107 switch (getKind()) {
108 case BlockEdgeKind:
109 // If needed, the source and or destination beginning can be used to get
110 // source location.
111 return std::nullopt;
113 // If needed, first statement of the block can be used.
114 return std::nullopt;
115 case BlockExitKind:
116 if (const auto *B = castAs<BlockExit>().getBlock()) {
117 if (const auto *T = B->getTerminatorStmt()) {
118 return T->getBeginLoc();
119 }
120 }
121 return std::nullopt;
122 case PreStmtKind:
125 case PostStmtKind:
126 case PreLoadKind:
127 case PostLoadKind:
128 case PreStoreKind:
129 case PostStoreKind:
131 case PostLValueKind:
133 if (const Stmt *S = castAs<StmtPoint>().getStmt())
134 return S->getBeginLoc();
135 return std::nullopt;
137 if (const auto *Init = castAs<PostInitializer>().getInitializer())
138 return Init->getSourceLocation();
139 return std::nullopt;
140 case CallEnterKind:
141 if (const Stmt *S = castAs<CallEnter>().getCallExpr())
142 return S->getBeginLoc();
143 return std::nullopt;
145 if (const Stmt *S = castAs<CallExitBegin>().getReturnStmt())
146 return S->getBeginLoc();
147 return std::nullopt;
148 case CallExitEndKind:
149 return std::nullopt;
150 case FunctionExitKind:
151 if (const auto *B = castAs<FunctionExitPoint>().getBlock();
152 B && B->getTerminatorStmt())
153 return B->getTerminatorStmt()->getBeginLoc();
154 return std::nullopt;
156 return castAs<ImplicitCallPoint>().getLocation();
158 return castAs<ImplicitCallPoint>().getLocation();
159 case LoopExitKind:
160 if (const Stmt *S = castAs<LoopExit>().getLoopStmt())
161 return S->getBeginLoc();
162 return std::nullopt;
163 case LifetimeEndKind:
164 if (const Stmt *S = castAs<LifetimeEnd>().getTriggerStmt())
165 return S->getBeginLoc();
166 return std::nullopt;
167 case EpsilonKind:
168 return std::nullopt;
169 }
170 llvm_unreachable("Unknown ProgramPoint kind");
171}
172
173void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
174 const ASTContext &Context =
176 const SourceManager &SM = Context.getSourceManager();
177 const PrintingPolicy &PP = Context.getPrintingPolicy();
178 const bool AddQuotes = true;
179
180 Out << "\"kind\": \"";
181 switch (getKind()) {
183 Out << "BlockEntrance\""
184 << ", \"block_id\": "
185 << castAs<BlockEntrance>().getBlock()->getBlockID();
186 break;
187
189 auto FEP = getAs<FunctionExitPoint>();
190 Out << "FunctionExit\""
191 << ", \"block_id\": " << FEP->getBlock()->getBlockID()
192 << ", \"stmt_id\": ";
193
194 if (const ReturnStmt *RS = FEP->getStmt()) {
195 Out << RS->getID(Context) << ", \"stmt\": ";
196 RS->printJson(Out, nullptr, PP, AddQuotes);
197 } else {
198 Out << "null, \"stmt\": null";
199 }
200 break;
201 }
203 llvm_unreachable("BlockExitKind");
204 break;
206 Out << "CallEnter\", \"callee_decl\": \"";
208 castAs<CallEnter>().getCalleeStackFrame()->getDecl())
209 << '\"';
210 break;
212 Out << "CallExitBegin\"";
213 break;
215 Out << "CallExitEnd\"";
216 break;
218 Out << "EpsilonPoint\"";
219 break;
220
222 Out << "LoopExit\", \"stmt\": \""
223 << castAs<LoopExit>().getLoopStmt()->getStmtClassName() << '\"';
224 break;
225
227 Out << "LifetimeEnd\", \"var\": \""
228 << castAs<LifetimeEnd>().getDecl()->getNameAsString() << '\"';
229 break;
230
233 Out << "PreCall\", \"decl\": \""
235 << "\", \"location\": ";
237 break;
238 }
239
242 Out << "PostCall\", \"decl\": \""
244 << "\", \"location\": ";
246 break;
247 }
248
250 Out << "PostInitializer\", ";
251 const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer();
252 if (const FieldDecl *FD = Init->getAnyMember()) {
253 Out << "\"field_decl\": \"" << *FD << '\"';
254 } else {
255 Out << "\"type\": \"";
256 QualType Ty = Init->getTypeSourceInfo()->getType();
257 Ty = Ty.getLocalUnqualifiedType();
258 Ty.print(Out, Context.getLangOpts());
259 Out << '\"';
260 }
261 break;
262 }
263
265 const BlockEdge &E = castAs<BlockEdge>();
266 const Stmt *T = E.getSrc()->getTerminatorStmt();
267 Out << "Edge\", \"src_id\": " << E.getSrc()->getBlockID()
268 << ", \"dst_id\": " << E.getDst()->getBlockID() << ", \"terminator\": ";
269
270 if (!T) {
271 Out << "null, \"term_kind\": null";
272 break;
273 }
274
275 E.getSrc()->printTerminatorJson(Out, Context.getLangOpts(),
276 /*AddQuotes=*/true);
277 Out << ", \"location\": ";
278 printSourceLocationAsJson(Out, T->getBeginLoc(), SM);
279
280 Out << ", \"term_kind\": \"";
281 if (isa<SwitchStmt>(T)) {
282 Out << "SwitchStmt\", \"case\": ";
283 if (const Stmt *Label = E.getDst()->getLabel()) {
284 if (const auto *C = dyn_cast<CaseStmt>(Label)) {
285 Out << "{ \"lhs\": ";
286 if (const Stmt *LHS = C->getLHS()) {
287 LHS->printJson(Out, nullptr, PP, AddQuotes);
288 } else {
289 Out << "null";
290 }
291
292 Out << ", \"rhs\": ";
293 if (const Stmt *RHS = C->getRHS()) {
294 RHS->printJson(Out, nullptr, PP, AddQuotes);
295 } else {
296 Out << "null";
297 }
298 Out << " }";
299 } else {
300 assert(isa<DefaultStmt>(Label));
301 Out << "\"default\"";
302 }
303 } else {
304 Out << "\"implicit default\"";
305 }
306 } else if (isa<IndirectGotoStmt>(T)) {
307 // FIXME: More info.
308 Out << "IndirectGotoStmt\"";
309 } else {
310 Out << "Condition\", \"value\": "
311 << (*E.getSrc()->succ_begin() == E.getDst() ? "true" : "false");
312 }
313 break;
314 }
315
316 default: {
317 const Stmt *S = castAs<StmtPoint>().getStmt();
318 assert(S != nullptr && "Expecting non-null Stmt");
319
320 Out << "Statement\", \"stmt_kind\": \"" << S->getStmtClassName()
321 << "\", \"stmt_id\": " << S->getID(Context)
322 << ", \"pointer\": \"" << (const void *)S << "\", ";
323 if (const auto *CS = dyn_cast<CastExpr>(S))
324 Out << "\"cast_kind\": \"" << CS->getCastKindName() << "\", ";
325
326 Out << "\"pretty\": ";
327
328 S->printJson(Out, nullptr, PP, AddQuotes);
329
330 Out << ", \"location\": ";
331 printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
332
333 Out << ", \"stmt_point_kind\": \"";
334 if (getAs<PreLoad>())
335 Out << "PreLoad";
336 else if (getAs<PreStore>())
337 Out << "PreStore";
338 else if (getAs<PostAllocatorCall>())
339 Out << "PostAllocatorCall";
340 else if (getAs<PostCondition>())
341 Out << "PostCondition";
342 else if (getAs<PostLoad>())
343 Out << "PostLoad";
344 else if (getAs<PostLValue>())
345 Out << "PostLValue";
346 else if (getAs<PostStore>())
347 Out << "PostStore";
348 else if (getAs<PostStmt>())
349 Out << "PostStmt";
351 Out << "PostStmtPurgeDeadSymbols";
353 Out << "PreStmtPurgeDeadSymbols";
354 else if (getAs<PreStmt>())
355 Out << "PreStmt";
356 else {
357 Out << "\nKind: '" << getKind();
358 llvm_unreachable("' is unhandled StmtPoint kind!");
359 }
360
361 Out << '\"';
362 break;
363 }
364 }
365}
366
368 StringRef Msg)
369 : Desc((MsgProvider + " : " + Msg).str()) {}
370
371StringRef SimpleProgramPointTag::getDebugTag() const { return Desc; }
Defines the clang::ASTContext interface.
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
#define SM(sm)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
static std::string getFunctionName(const Decl *D)
ASTContext & getASTContext() const
const CFGBlock * getSrc() const
const CFGBlock * getDst() const
void printTerminatorJson(raw_ostream &Out, const LangOptions &LO, bool AddQuotes) const
printTerminatorJson - Pretty-prints the terminator in JSON format.
Definition CFG.cpp:6418
Stmt * getLabel()
Definition CFG.h:1149
Stmt * getTerminatorStmt()
Definition CFG.h:1134
unsigned getBlockID() const
Definition CFG.h:1154
Represents a C++ base or member initializer.
Definition DeclCXX.h:2398
FunctionDecl * getAsFunction() LLVM_READONLY
Returns the function itself, or the templated function if this is a function template.
Definition DeclBase.cpp:273
Represents a member of a struct/union/class.
Definition Decl.h:3182
Represents an implicit call event.
SourceLocation getLocation() const
const Decl * getDecl() const
std::string getQualifiedNameAsString() const
Definition Decl.cpp:1681
Represents a point after we ran remove dead bindings AFTER processing the given statement.
Represents a point after we ran remove dead bindings BEFORE processing the given statement.
ProgramPoints can be "tagged" as representing points specific to a given analysis entity.
Kind getKind() const
T castAs() const
Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type.
static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, const StackFrame *SF, const ProgramPointTag *tag)
static StringRef getProgramPointKindName(Kind K)
ProgramPoint()=default
LLVM_DUMP_METHOD void dump() const
std::optional< SourceLocation > getSourceLocation() const
void printJson(llvm::raw_ostream &Out, const char *NL="\n") const
const StackFrame * getStackFrame() const
std::optional< T > getAs() const
Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType getLocalUnqualifiedType() const
Return this type with all of the instance-specific qualifiers removed, but without removing any quali...
Definition TypeBase.h:1240
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Definition Stmt.h:3170
StringRef getDebugTag() const override
The description of this program point which will be dumped for debugging purposes.
SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg)
This class handles loading and caching of source files into memory.
It represents a stack frame of the call stack.
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
Stmt - This represents one statement.
Definition Stmt.h:86
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
void printSourceLocationAsJson(raw_ostream &Out, SourceLocation Loc, const SourceManager &SM, bool AddBraces=true)
Definition JsonSupport.h:82
Describes how types, statements, expressions, and declarations should be printed.