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