1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #include "clang/Analysis/ProgramPoint.h" |
15 | |
16 | using namespace clang; |
17 | |
18 | ProgramPointTag::~ProgramPointTag() {} |
19 | |
20 | ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K, |
21 | const LocationContext *LC, |
22 | const ProgramPointTag *tag){ |
23 | switch (K) { |
24 | default: |
25 | llvm_unreachable("Unhandled ProgramPoint kind"); |
26 | case ProgramPoint::PreStmtKind: |
27 | return PreStmt(S, LC, tag); |
28 | case ProgramPoint::PostStmtKind: |
29 | return PostStmt(S, LC, tag); |
30 | case ProgramPoint::PreLoadKind: |
31 | return PreLoad(S, LC, tag); |
32 | case ProgramPoint::PostLoadKind: |
33 | return PostLoad(S, LC, tag); |
34 | case ProgramPoint::PreStoreKind: |
35 | return PreStore(S, LC, tag); |
36 | case ProgramPoint::PostLValueKind: |
37 | return PostLValue(S, LC, tag); |
38 | case ProgramPoint::PostStmtPurgeDeadSymbolsKind: |
39 | return PostStmtPurgeDeadSymbols(S, LC, tag); |
40 | case ProgramPoint::PreStmtPurgeDeadSymbolsKind: |
41 | return PreStmtPurgeDeadSymbols(S, LC, tag); |
42 | } |
43 | } |
44 | |
45 | LLVM_DUMP_METHOD void ProgramPoint::dump() const { |
46 | return print(, llvm::errs()); |
47 | } |
48 | |
49 | static void printLocation(raw_ostream &Out, SourceLocation SLoc, |
50 | const SourceManager &SM, |
51 | StringRef CR, |
52 | StringRef Postfix) { |
53 | if (SLoc.isFileID()) { |
54 | Out << CR << "line=" << SM.getExpansionLineNumber(SLoc) |
55 | << " col=" << SM.getExpansionColumnNumber(SLoc) << Postfix; |
56 | } |
57 | } |
58 | |
59 | void ProgramPoint::print(StringRef CR, llvm::raw_ostream &Out) const { |
60 | const ASTContext &Context = |
61 | getLocationContext()->getAnalysisDeclContext()->getASTContext(); |
62 | const SourceManager &SM = Context.getSourceManager(); |
63 | switch (getKind()) { |
64 | case ProgramPoint::BlockEntranceKind: |
65 | Out << "Block Entrance: B" |
66 | << castAs<BlockEntrance>().getBlock()->getBlockID(); |
67 | break; |
68 | |
69 | case ProgramPoint::FunctionExitKind: { |
70 | auto FEP = getAs<FunctionExitPoint>(); |
71 | Out << "Function Exit: B" << FEP->getBlock()->getBlockID(); |
72 | if (const ReturnStmt *RS = FEP->getStmt()) { |
73 | Out << CR << " Return: S" << RS->getID(Context) << CR; |
74 | RS->printPretty(Out, , Context.getPrintingPolicy(), |
75 | , CR); |
76 | } |
77 | break; |
78 | } |
79 | case ProgramPoint::BlockExitKind: |
80 | assert(false); |
81 | break; |
82 | |
83 | case ProgramPoint::CallEnterKind: |
84 | Out << "CallEnter"; |
85 | break; |
86 | |
87 | case ProgramPoint::CallExitBeginKind: |
88 | Out << "CallExitBegin"; |
89 | break; |
90 | |
91 | case ProgramPoint::CallExitEndKind: |
92 | Out << "CallExitEnd"; |
93 | break; |
94 | |
95 | case ProgramPoint::PostStmtPurgeDeadSymbolsKind: |
96 | Out << "PostStmtPurgeDeadSymbols"; |
97 | break; |
98 | |
99 | case ProgramPoint::PreStmtPurgeDeadSymbolsKind: |
100 | Out << "PreStmtPurgeDeadSymbols"; |
101 | break; |
102 | |
103 | case ProgramPoint::EpsilonKind: |
104 | Out << "Epsilon Point"; |
105 | break; |
106 | |
107 | case ProgramPoint::LoopExitKind: { |
108 | LoopExit LE = castAs<LoopExit>(); |
109 | Out << "LoopExit: " << LE.getLoopStmt()->getStmtClassName(); |
110 | break; |
111 | } |
112 | |
113 | case ProgramPoint::PreImplicitCallKind: { |
114 | ImplicitCallPoint PC = castAs<ImplicitCallPoint>(); |
115 | Out << "PreCall: "; |
116 | PC.getDecl()->print(Out, Context.getLangOpts()); |
117 | printLocation(Out, PC.getLocation(), SM, CR, CR); |
118 | break; |
119 | } |
120 | |
121 | case ProgramPoint::PostImplicitCallKind: { |
122 | ImplicitCallPoint PC = castAs<ImplicitCallPoint>(); |
123 | Out << "PostCall: "; |
124 | PC.getDecl()->print(Out, Context.getLangOpts()); |
125 | printLocation(Out, PC.getLocation(), SM, CR, CR); |
126 | break; |
127 | } |
128 | |
129 | case ProgramPoint::PostInitializerKind: { |
130 | Out << "PostInitializer: "; |
131 | const CXXCtorInitializer *Init = castAs<PostInitializer>().getInitializer(); |
132 | if (const FieldDecl *FD = Init->getAnyMember()) |
133 | Out << *FD; |
134 | else { |
135 | QualType Ty = Init->getTypeSourceInfo()->getType(); |
136 | Ty = Ty.getLocalUnqualifiedType(); |
137 | Ty.print(Out, Context.getLangOpts()); |
138 | } |
139 | break; |
140 | } |
141 | |
142 | case ProgramPoint::BlockEdgeKind: { |
143 | const BlockEdge &E = castAs<BlockEdge>(); |
144 | Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B" |
145 | << E.getDst()->getBlockID() << ')'; |
146 | |
147 | if (const Stmt *T = E.getSrc()->getTerminator()) { |
148 | SourceLocation SLoc = T->getBeginLoc(); |
149 | |
150 | Out << "\\|Terminator: "; |
151 | E.getSrc()->printTerminator(Out, Context.getLangOpts()); |
152 | printLocation(Out, SLoc, SM, CR, ); |
153 | |
154 | if (isa<SwitchStmt>(T)) { |
155 | const Stmt *Label = E.getDst()->getLabel(); |
156 | |
157 | if (Label) { |
158 | if (const auto *C = dyn_cast<CaseStmt>(Label)) { |
159 | Out << CR << "case "; |
160 | if (C->getLHS()) |
161 | C->getLHS()->printPretty( |
162 | Out, nullptr, Context.getPrintingPolicy(), |
163 | , CR); |
164 | |
165 | if (const Stmt *RHS = C->getRHS()) { |
166 | Out << " .. "; |
167 | RHS->printPretty(Out, nullptr, Context.getPrintingPolicy(), |
168 | , CR); |
169 | } |
170 | |
171 | Out << ":"; |
172 | } else { |
173 | (Label)", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ProgramPoint.cpp", 173, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(isa<DefaultStmt>(Label)); |
174 | Out << CR << "default:"; |
175 | } |
176 | } else |
177 | Out << CR << "(implicit) default:"; |
178 | } else if (isa<IndirectGotoStmt>(T)) { |
179 | |
180 | } else { |
181 | Out << CR << "Condition: "; |
182 | if (*E.getSrc()->succ_begin() == E.getDst()) |
183 | Out << "true"; |
184 | else |
185 | Out << "false"; |
186 | } |
187 | |
188 | Out << CR; |
189 | } |
190 | |
191 | break; |
192 | } |
193 | |
194 | default: { |
195 | const Stmt *S = castAs<StmtPoint>().getStmt(); |
196 | (0) . __assert_fail ("S != nullptr && \"Expecting non-null Stmt\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ProgramPoint.cpp", 196, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(S != nullptr && "Expecting non-null Stmt"); |
197 | |
198 | Out << S->getStmtClassName() << " S" << S->getID(Context) << " <" |
199 | << (const void *)S << "> "; |
200 | S->printPretty(Out, , Context.getPrintingPolicy(), |
201 | , CR); |
202 | printLocation(Out, S->getBeginLoc(), SM, CR, ); |
203 | |
204 | if (getAs<PreStmt>()) |
205 | Out << CR << "PreStmt" << CR; |
206 | else if (getAs<PostLoad>()) |
207 | Out << CR << "PostLoad" << CR; |
208 | else if (getAs<PostStore>()) |
209 | Out << CR << "PostStore" << CR; |
210 | else if (getAs<PostLValue>()) |
211 | Out << CR << "PostLValue" << CR; |
212 | else if (getAs<PostAllocatorCall>()) |
213 | Out << CR << "PostAllocatorCall" << CR; |
214 | |
215 | break; |
216 | } |
217 | } |
218 | } |
219 | |
220 | SimpleProgramPointTag::SimpleProgramPointTag(StringRef MsgProvider, |
221 | StringRef Msg) |
222 | : Desc((MsgProvider + " : " + Msg).str()) {} |
223 | |
224 | StringRef SimpleProgramPointTag::getTagDescription() const { |
225 | return Desc; |
226 | } |
227 | |