Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Analysis/ProgramPoint.cpp
35232 views
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
#include "clang/AST/ASTContext.h"
16
#include "clang/Basic/JsonSupport.h"
17
18
using namespace clang;
19
20
ProgramPointTag::~ProgramPointTag() {}
21
22
ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K,
23
const LocationContext *LC,
24
const ProgramPointTag *tag){
25
switch (K) {
26
default:
27
llvm_unreachable("Unhandled ProgramPoint kind");
28
case ProgramPoint::PreStmtKind:
29
return PreStmt(S, LC, tag);
30
case ProgramPoint::PostStmtKind:
31
return PostStmt(S, LC, tag);
32
case ProgramPoint::PreLoadKind:
33
return PreLoad(S, LC, tag);
34
case ProgramPoint::PostLoadKind:
35
return PostLoad(S, LC, tag);
36
case ProgramPoint::PreStoreKind:
37
return PreStore(S, LC, tag);
38
case ProgramPoint::PostLValueKind:
39
return PostLValue(S, LC, tag);
40
case ProgramPoint::PostStmtPurgeDeadSymbolsKind:
41
return PostStmtPurgeDeadSymbols(S, LC, tag);
42
case ProgramPoint::PreStmtPurgeDeadSymbolsKind:
43
return PreStmtPurgeDeadSymbols(S, LC, tag);
44
}
45
}
46
47
LLVM_DUMP_METHOD void ProgramPoint::dump() const {
48
return printJson(llvm::errs());
49
}
50
51
void ProgramPoint::printJson(llvm::raw_ostream &Out, const char *NL) const {
52
const ASTContext &Context =
53
getLocationContext()->getAnalysisDeclContext()->getASTContext();
54
const SourceManager &SM = Context.getSourceManager();
55
const PrintingPolicy &PP = Context.getPrintingPolicy();
56
const bool AddQuotes = true;
57
58
Out << "\"kind\": \"";
59
switch (getKind()) {
60
case ProgramPoint::BlockEntranceKind:
61
Out << "BlockEntrance\""
62
<< ", \"block_id\": "
63
<< castAs<BlockEntrance>().getBlock()->getBlockID();
64
break;
65
66
case ProgramPoint::FunctionExitKind: {
67
auto FEP = getAs<FunctionExitPoint>();
68
Out << "FunctionExit\""
69
<< ", \"block_id\": " << FEP->getBlock()->getBlockID()
70
<< ", \"stmt_id\": ";
71
72
if (const ReturnStmt *RS = FEP->getStmt()) {
73
Out << RS->getID(Context) << ", \"stmt\": ";
74
RS->printJson(Out, nullptr, PP, AddQuotes);
75
} else {
76
Out << "null, \"stmt\": null";
77
}
78
break;
79
}
80
case ProgramPoint::BlockExitKind:
81
llvm_unreachable("BlockExitKind");
82
break;
83
case ProgramPoint::CallEnterKind:
84
Out << "CallEnter\"";
85
break;
86
case ProgramPoint::CallExitBeginKind:
87
Out << "CallExitBegin\"";
88
break;
89
case ProgramPoint::CallExitEndKind:
90
Out << "CallExitEnd\"";
91
break;
92
case ProgramPoint::EpsilonKind:
93
Out << "EpsilonPoint\"";
94
break;
95
96
case ProgramPoint::LoopExitKind:
97
Out << "LoopExit\", \"stmt\": \""
98
<< castAs<LoopExit>().getLoopStmt()->getStmtClassName() << '\"';
99
break;
100
101
case ProgramPoint::PreImplicitCallKind: {
102
ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
103
Out << "PreCall\", \"decl\": \""
104
<< PC.getDecl()->getAsFunction()->getQualifiedNameAsString()
105
<< "\", \"location\": ";
106
printSourceLocationAsJson(Out, PC.getLocation(), SM);
107
break;
108
}
109
110
case ProgramPoint::PostImplicitCallKind: {
111
ImplicitCallPoint PC = castAs<ImplicitCallPoint>();
112
Out << "PostCall\", \"decl\": \""
113
<< PC.getDecl()->getAsFunction()->getQualifiedNameAsString()
114
<< "\", \"location\": ";
115
printSourceLocationAsJson(Out, PC.getLocation(), SM);
116
break;
117
}
118
119
case ProgramPoint::PostInitializerKind: {
120
Out << "PostInitializer\", ";
121
const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer();
122
if (const FieldDecl *FD = Init->getAnyMember()) {
123
Out << "\"field_decl\": \"" << *FD << '\"';
124
} else {
125
Out << "\"type\": \"";
126
QualType Ty = Init->getTypeSourceInfo()->getType();
127
Ty = Ty.getLocalUnqualifiedType();
128
Ty.print(Out, Context.getLangOpts());
129
Out << '\"';
130
}
131
break;
132
}
133
134
case ProgramPoint::BlockEdgeKind: {
135
const BlockEdge &E = castAs<BlockEdge>();
136
const Stmt *T = E.getSrc()->getTerminatorStmt();
137
Out << "Edge\", \"src_id\": " << E.getSrc()->getBlockID()
138
<< ", \"dst_id\": " << E.getDst()->getBlockID() << ", \"terminator\": ";
139
140
if (!T) {
141
Out << "null, \"term_kind\": null";
142
break;
143
}
144
145
E.getSrc()->printTerminatorJson(Out, Context.getLangOpts(),
146
/*AddQuotes=*/true);
147
Out << ", \"location\": ";
148
printSourceLocationAsJson(Out, T->getBeginLoc(), SM);
149
150
Out << ", \"term_kind\": \"";
151
if (isa<SwitchStmt>(T)) {
152
Out << "SwitchStmt\", \"case\": ";
153
if (const Stmt *Label = E.getDst()->getLabel()) {
154
if (const auto *C = dyn_cast<CaseStmt>(Label)) {
155
Out << "{ \"lhs\": ";
156
if (const Stmt *LHS = C->getLHS()) {
157
LHS->printJson(Out, nullptr, PP, AddQuotes);
158
} else {
159
Out << "null";
160
}
161
162
Out << ", \"rhs\": ";
163
if (const Stmt *RHS = C->getRHS()) {
164
RHS->printJson(Out, nullptr, PP, AddQuotes);
165
} else {
166
Out << "null";
167
}
168
Out << " }";
169
} else {
170
assert(isa<DefaultStmt>(Label));
171
Out << "\"default\"";
172
}
173
} else {
174
Out << "\"implicit default\"";
175
}
176
} else if (isa<IndirectGotoStmt>(T)) {
177
// FIXME: More info.
178
Out << "IndirectGotoStmt\"";
179
} else {
180
Out << "Condition\", \"value\": "
181
<< (*E.getSrc()->succ_begin() == E.getDst() ? "true" : "false");
182
}
183
break;
184
}
185
186
default: {
187
const Stmt *S = castAs<StmtPoint>().getStmt();
188
assert(S != nullptr && "Expecting non-null Stmt");
189
190
Out << "Statement\", \"stmt_kind\": \"" << S->getStmtClassName()
191
<< "\", \"stmt_id\": " << S->getID(Context)
192
<< ", \"pointer\": \"" << (const void *)S << "\", ";
193
if (const auto *CS = dyn_cast<CastExpr>(S))
194
Out << "\"cast_kind\": \"" << CS->getCastKindName() << "\", ";
195
196
Out << "\"pretty\": ";
197
198
S->printJson(Out, nullptr, PP, AddQuotes);
199
200
Out << ", \"location\": ";
201
printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
202
203
Out << ", \"stmt_point_kind\": \"";
204
if (getAs<PreLoad>())
205
Out << "PreLoad";
206
else if (getAs<PreStore>())
207
Out << "PreStore";
208
else if (getAs<PostAllocatorCall>())
209
Out << "PostAllocatorCall";
210
else if (getAs<PostCondition>())
211
Out << "PostCondition";
212
else if (getAs<PostLoad>())
213
Out << "PostLoad";
214
else if (getAs<PostLValue>())
215
Out << "PostLValue";
216
else if (getAs<PostStore>())
217
Out << "PostStore";
218
else if (getAs<PostStmt>())
219
Out << "PostStmt";
220
else if (getAs<PostStmtPurgeDeadSymbols>())
221
Out << "PostStmtPurgeDeadSymbols";
222
else if (getAs<PreStmtPurgeDeadSymbols>())
223
Out << "PreStmtPurgeDeadSymbols";
224
else if (getAs<PreStmt>())
225
Out << "PreStmt";
226
else {
227
Out << "\nKind: '" << getKind();
228
llvm_unreachable("' is unhandled StmtPoint kind!");
229
}
230
231
Out << '\"';
232
break;
233
}
234
}
235
}
236
237
SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider,
238
StringRef Msg)
239
: Desc((MsgProvider + " : " + Msg).str()) {}
240
241
StringRef SimpleProgramPointTag::getTagDescription() const {
242
return Desc;
243
}
244
245