1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include "clang/Analysis/Analyses/ThreadSafetyCommon.h" |
14 | #include "clang/AST/Attr.h" |
15 | #include "clang/AST/Decl.h" |
16 | #include "clang/AST/DeclCXX.h" |
17 | #include "clang/AST/DeclGroup.h" |
18 | #include "clang/AST/DeclObjC.h" |
19 | #include "clang/AST/Expr.h" |
20 | #include "clang/AST/ExprCXX.h" |
21 | #include "clang/AST/OperationKinds.h" |
22 | #include "clang/AST/Stmt.h" |
23 | #include "clang/AST/Type.h" |
24 | #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" |
25 | #include "clang/Analysis/CFG.h" |
26 | #include "clang/Basic/LLVM.h" |
27 | #include "clang/Basic/OperatorKinds.h" |
28 | #include "clang/Basic/Specifiers.h" |
29 | #include "llvm/ADT/StringRef.h" |
30 | #include "llvm/Support/Casting.h" |
31 | #include <algorithm> |
32 | #include <cassert> |
33 | #include <string> |
34 | #include <utility> |
35 | |
36 | using namespace clang; |
37 | using namespace threadSafety; |
38 | |
39 | |
40 | std::string threadSafety::getSourceLiteralString(const Expr *CE) { |
41 | switch (CE->getStmtClass()) { |
42 | case Stmt::IntegerLiteralClass: |
43 | return cast<IntegerLiteral>(CE)->getValue().toString(10, true); |
44 | case Stmt::StringLiteralClass: { |
45 | std::string ret("\""); |
46 | ret += cast<StringLiteral>(CE)->getString(); |
47 | ret += "\""; |
48 | return ret; |
49 | } |
50 | case Stmt::CharacterLiteralClass: |
51 | case Stmt::CXXNullPtrLiteralExprClass: |
52 | case Stmt::GNUNullExprClass: |
53 | case Stmt::CXXBoolLiteralExprClass: |
54 | case Stmt::FloatingLiteralClass: |
55 | case Stmt::ImaginaryLiteralClass: |
56 | case Stmt::ObjCStringLiteralClass: |
57 | default: |
58 | return "#lit"; |
59 | } |
60 | } |
61 | |
62 | |
63 | static bool isIncompletePhi(const til::SExpr *E) { |
64 | if (const auto *Ph = dyn_cast<til::Phi>(E)) |
65 | return Ph->status() == til::Phi::PH_Incomplete; |
66 | return false; |
67 | } |
68 | |
69 | using CallingContext = SExprBuilder::CallingContext; |
70 | |
71 | til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) { |
72 | auto It = SMap.find(S); |
73 | if (It != SMap.end()) |
74 | return It->second; |
75 | return nullptr; |
76 | } |
77 | |
78 | til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) { |
79 | Walker.walk(*this); |
80 | return Scfg; |
81 | } |
82 | |
83 | static bool isCalleeArrow(const Expr *E) { |
84 | const auto *ME = dyn_cast<MemberExpr>(E->IgnoreParenCasts()); |
85 | return ME ? ME->isArrow() : false; |
86 | } |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, |
96 | const NamedDecl *D, |
97 | const Expr *DeclExp, |
98 | VarDecl *SelfDecl) { |
99 | |
100 | if (!DeclExp) |
101 | return translateAttrExpr(AttrExp, nullptr); |
102 | |
103 | CallingContext Ctx(nullptr, D); |
104 | |
105 | |
106 | |
107 | if (const auto *ME = dyn_cast<MemberExpr>(DeclExp)) { |
108 | Ctx.SelfArg = ME->getBase(); |
109 | Ctx.SelfArrow = ME->isArrow(); |
110 | } else if (const auto *CE = dyn_cast<CXXMemberCallExpr>(DeclExp)) { |
111 | Ctx.SelfArg = CE->getImplicitObjectArgument(); |
112 | Ctx.SelfArrow = isCalleeArrow(CE->getCallee()); |
113 | Ctx.NumArgs = CE->getNumArgs(); |
114 | Ctx.FunArgs = CE->getArgs(); |
115 | } else if (const auto *CE = dyn_cast<CallExpr>(DeclExp)) { |
116 | Ctx.NumArgs = CE->getNumArgs(); |
117 | Ctx.FunArgs = CE->getArgs(); |
118 | } else if (const auto *CE = dyn_cast<CXXConstructExpr>(DeclExp)) { |
119 | Ctx.SelfArg = nullptr; |
120 | Ctx.NumArgs = CE->getNumArgs(); |
121 | Ctx.FunArgs = CE->getArgs(); |
122 | } else if (D && isa<CXXDestructorDecl>(D)) { |
123 | |
124 | Ctx.SelfArg = DeclExp; |
125 | } |
126 | |
127 | |
128 | |
129 | if (SelfDecl && !Ctx.SelfArg) { |
130 | DeclRefExpr SelfDRE(SelfDecl->getASTContext(), SelfDecl, false, |
131 | SelfDecl->getType(), VK_LValue, |
132 | SelfDecl->getLocation()); |
133 | Ctx.SelfArg = &SelfDRE; |
134 | |
135 | |
136 | if (!AttrExp) |
137 | return translateAttrExpr(Ctx.SelfArg, nullptr); |
138 | else |
139 | return translateAttrExpr(AttrExp, &Ctx); |
140 | } |
141 | |
142 | |
143 | if (!AttrExp) |
144 | return translateAttrExpr(Ctx.SelfArg, nullptr); |
145 | else |
146 | return translateAttrExpr(AttrExp, &Ctx); |
147 | } |
148 | |
149 | |
150 | |
151 | CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, |
152 | CallingContext *Ctx) { |
153 | if (!AttrExp) |
154 | return CapabilityExpr(nullptr, false); |
155 | |
156 | if (const auto* SLit = dyn_cast<StringLiteral>(AttrExp)) { |
157 | if (SLit->getString() == StringRef("*")) |
158 | |
159 | |
160 | return CapabilityExpr(new (Arena) til::Wildcard(), false); |
161 | else |
162 | |
163 | return CapabilityExpr(nullptr, false); |
164 | } |
165 | |
166 | bool Neg = false; |
167 | if (const auto *OE = dyn_cast<CXXOperatorCallExpr>(AttrExp)) { |
168 | if (OE->getOperator() == OO_Exclaim) { |
169 | Neg = true; |
170 | AttrExp = OE->getArg(0); |
171 | } |
172 | } |
173 | else if (const auto *UO = dyn_cast<UnaryOperator>(AttrExp)) { |
174 | if (UO->getOpcode() == UO_LNot) { |
175 | Neg = true; |
176 | AttrExp = UO->getSubExpr(); |
177 | } |
178 | } |
179 | |
180 | til::SExpr *E = translate(AttrExp, Ctx); |
181 | |
182 | |
183 | |
184 | if (!E || isa<til::Literal>(E)) |
185 | return CapabilityExpr(nullptr, false); |
186 | |
187 | |
188 | if (const auto *CE = dyn_cast_or_null<til::Cast>(E)) { |
189 | if (CE->castOpcode() == til::CAST_objToPtr) |
190 | return CapabilityExpr(CE->expr(), Neg); |
191 | } |
192 | return CapabilityExpr(E, Neg); |
193 | } |
194 | |
195 | |
196 | |
197 | |
198 | til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) { |
199 | if (!S) |
200 | return nullptr; |
201 | |
202 | |
203 | |
204 | if (til::SExpr *E = lookupStmt(S)) |
205 | return E; |
206 | |
207 | switch (S->getStmtClass()) { |
208 | case Stmt::DeclRefExprClass: |
209 | return translateDeclRefExpr(cast<DeclRefExpr>(S), Ctx); |
210 | case Stmt::CXXThisExprClass: |
211 | return translateCXXThisExpr(cast<CXXThisExpr>(S), Ctx); |
212 | case Stmt::MemberExprClass: |
213 | return translateMemberExpr(cast<MemberExpr>(S), Ctx); |
214 | case Stmt::ObjCIvarRefExprClass: |
215 | return translateObjCIVarRefExpr(cast<ObjCIvarRefExpr>(S), Ctx); |
216 | case Stmt::CallExprClass: |
217 | return translateCallExpr(cast<CallExpr>(S), Ctx); |
218 | case Stmt::CXXMemberCallExprClass: |
219 | return translateCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), Ctx); |
220 | case Stmt::CXXOperatorCallExprClass: |
221 | return translateCXXOperatorCallExpr(cast<CXXOperatorCallExpr>(S), Ctx); |
222 | case Stmt::UnaryOperatorClass: |
223 | return translateUnaryOperator(cast<UnaryOperator>(S), Ctx); |
224 | case Stmt::BinaryOperatorClass: |
225 | case Stmt::CompoundAssignOperatorClass: |
226 | return translateBinaryOperator(cast<BinaryOperator>(S), Ctx); |
227 | |
228 | case Stmt::ArraySubscriptExprClass: |
229 | return translateArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Ctx); |
230 | case Stmt::ConditionalOperatorClass: |
231 | return translateAbstractConditionalOperator( |
232 | cast<ConditionalOperator>(S), Ctx); |
233 | case Stmt::BinaryConditionalOperatorClass: |
234 | return translateAbstractConditionalOperator( |
235 | cast<BinaryConditionalOperator>(S), Ctx); |
236 | |
237 | |
238 | case Stmt::ConstantExprClass: |
239 | return translate(cast<ConstantExpr>(S)->getSubExpr(), Ctx); |
240 | case Stmt::ParenExprClass: |
241 | return translate(cast<ParenExpr>(S)->getSubExpr(), Ctx); |
242 | case Stmt::ExprWithCleanupsClass: |
243 | return translate(cast<ExprWithCleanups>(S)->getSubExpr(), Ctx); |
244 | case Stmt::CXXBindTemporaryExprClass: |
245 | return translate(cast<CXXBindTemporaryExpr>(S)->getSubExpr(), Ctx); |
246 | case Stmt::MaterializeTemporaryExprClass: |
247 | return translate(cast<MaterializeTemporaryExpr>(S)->GetTemporaryExpr(), |
248 | Ctx); |
249 | |
250 | |
251 | case Stmt::CharacterLiteralClass: |
252 | case Stmt::CXXNullPtrLiteralExprClass: |
253 | case Stmt::GNUNullExprClass: |
254 | case Stmt::CXXBoolLiteralExprClass: |
255 | case Stmt::FloatingLiteralClass: |
256 | case Stmt::ImaginaryLiteralClass: |
257 | case Stmt::IntegerLiteralClass: |
258 | case Stmt::StringLiteralClass: |
259 | case Stmt::ObjCStringLiteralClass: |
260 | return new (Arena) til::Literal(cast<Expr>(S)); |
261 | |
262 | case Stmt::DeclStmtClass: |
263 | return translateDeclStmt(cast<DeclStmt>(S), Ctx); |
264 | default: |
265 | break; |
266 | } |
267 | if (const auto *CE = dyn_cast<CastExpr>(S)) |
268 | return translateCastExpr(CE, Ctx); |
269 | |
270 | return new (Arena) til::Undefined(S); |
271 | } |
272 | |
273 | til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE, |
274 | CallingContext *Ctx) { |
275 | const auto *VD = cast<ValueDecl>(DRE->getDecl()->getCanonicalDecl()); |
276 | |
277 | |
278 | if (const auto *PV = dyn_cast_or_null<ParmVarDecl>(VD)) { |
279 | unsigned I = PV->getFunctionScopeIndex(); |
280 | const DeclContext *D = PV->getDeclContext(); |
281 | if (Ctx && Ctx->FunArgs) { |
282 | const Decl *Canonical = Ctx->AttrDecl->getCanonicalDecl(); |
283 | if (isa<FunctionDecl>(D) |
284 | ? (cast<FunctionDecl>(D)->getCanonicalDecl() == Canonical) |
285 | : (cast<ObjCMethodDecl>(D)->getCanonicalDecl() == Canonical)) { |
286 | |
287 | NumArgs", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 287, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(I < Ctx->NumArgs); |
288 | return translate(Ctx->FunArgs[I], Ctx->Prev); |
289 | } |
290 | } |
291 | |
292 | |
293 | VD = isa<FunctionDecl>(D) |
294 | ? cast<FunctionDecl>(D)->getCanonicalDecl()->getParamDecl(I) |
295 | : cast<ObjCMethodDecl>(D)->getCanonicalDecl()->getParamDecl(I); |
296 | } |
297 | |
298 | |
299 | return new (Arena) til::LiteralPtr(VD); |
300 | } |
301 | |
302 | til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE, |
303 | CallingContext *Ctx) { |
304 | |
305 | if (Ctx && Ctx->SelfArg) |
306 | return translate(Ctx->SelfArg, Ctx->Prev); |
307 | (0) . __assert_fail ("SelfVar && \"We have no variable for 'this'!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 307, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(SelfVar && "We have no variable for 'this'!"); |
308 | return SelfVar; |
309 | } |
310 | |
311 | static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) { |
312 | if (const auto *V = dyn_cast<til::Variable>(E)) |
313 | return V->clangDecl(); |
314 | if (const auto *Ph = dyn_cast<til::Phi>(E)) |
315 | return Ph->clangDecl(); |
316 | if (const auto *P = dyn_cast<til::Project>(E)) |
317 | return P->clangDecl(); |
318 | if (const auto *L = dyn_cast<til::LiteralPtr>(E)) |
319 | return L->clangDecl(); |
320 | return nullptr; |
321 | } |
322 | |
323 | static bool hasAnyPointerType(const til::SExpr *E) { |
324 | auto *VD = getValueDeclFromSExpr(E); |
325 | if (VD && VD->getType()->isAnyPointerType()) |
326 | return true; |
327 | if (const auto *C = dyn_cast<til::Cast>(E)) |
328 | return C->castOpcode() == til::CAST_objToPtr; |
329 | |
330 | return false; |
331 | } |
332 | |
333 | |
334 | static const CXXMethodDecl *getFirstVirtualDecl(const CXXMethodDecl *D) { |
335 | while (true) { |
336 | D = D->getCanonicalDecl(); |
337 | auto OverriddenMethods = D->overridden_methods(); |
338 | if (OverriddenMethods.begin() == OverriddenMethods.end()) |
339 | return D; |
340 | |
341 | D = *OverriddenMethods.begin(); |
342 | } |
343 | return nullptr; |
344 | } |
345 | |
346 | til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME, |
347 | CallingContext *Ctx) { |
348 | til::SExpr *BE = translate(ME->getBase(), Ctx); |
349 | til::SExpr *E = new (Arena) til::SApply(BE); |
350 | |
351 | const auto *D = cast<ValueDecl>(ME->getMemberDecl()->getCanonicalDecl()); |
352 | if (const auto *VD = dyn_cast<CXXMethodDecl>(D)) |
353 | D = getFirstVirtualDecl(VD); |
354 | |
355 | til::Project *P = new (Arena) til::Project(E, D); |
356 | if (hasAnyPointerType(BE)) |
357 | P->setArrow(true); |
358 | return P; |
359 | } |
360 | |
361 | til::SExpr *SExprBuilder::translateObjCIVarRefExpr(const ObjCIvarRefExpr *IVRE, |
362 | CallingContext *Ctx) { |
363 | til::SExpr *BE = translate(IVRE->getBase(), Ctx); |
364 | til::SExpr *E = new (Arena) til::SApply(BE); |
365 | |
366 | const auto *D = cast<ObjCIvarDecl>(IVRE->getDecl()->getCanonicalDecl()); |
367 | |
368 | til::Project *P = new (Arena) til::Project(E, D); |
369 | if (hasAnyPointerType(BE)) |
370 | P->setArrow(true); |
371 | return P; |
372 | } |
373 | |
374 | til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE, |
375 | CallingContext *Ctx, |
376 | const Expr *SelfE) { |
377 | if (CapabilityExprMode) { |
378 | |
379 | if (const FunctionDecl *FD = CE->getDirectCallee()) { |
380 | FD = FD->getMostRecentDecl(); |
381 | if (LockReturnedAttr *At = FD->getAttr<LockReturnedAttr>()) { |
382 | CallingContext LRCallCtx(Ctx); |
383 | LRCallCtx.AttrDecl = CE->getDirectCallee(); |
384 | LRCallCtx.SelfArg = SelfE; |
385 | LRCallCtx.NumArgs = CE->getNumArgs(); |
386 | LRCallCtx.FunArgs = CE->getArgs(); |
387 | return const_cast<til::SExpr *>( |
388 | translateAttrExpr(At->getArg(), &LRCallCtx).sexpr()); |
389 | } |
390 | } |
391 | } |
392 | |
393 | til::SExpr *E = translate(CE->getCallee(), Ctx); |
394 | for (const auto *Arg : CE->arguments()) { |
395 | til::SExpr *A = translate(Arg, Ctx); |
396 | E = new (Arena) til::Apply(E, A); |
397 | } |
398 | return new (Arena) til::Call(E, CE); |
399 | } |
400 | |
401 | til::SExpr *SExprBuilder::translateCXXMemberCallExpr( |
402 | const CXXMemberCallExpr *ME, CallingContext *Ctx) { |
403 | if (CapabilityExprMode) { |
404 | |
405 | if (ME->getMethodDecl()->getNameAsString() == "get" && |
406 | ME->getNumArgs() == 0) { |
407 | auto *E = translate(ME->getImplicitObjectArgument(), Ctx); |
408 | return new (Arena) til::Cast(til::CAST_objToPtr, E); |
409 | |
410 | } |
411 | } |
412 | return translateCallExpr(cast<CallExpr>(ME), Ctx, |
413 | ME->getImplicitObjectArgument()); |
414 | } |
415 | |
416 | til::SExpr *SExprBuilder::translateCXXOperatorCallExpr( |
417 | const CXXOperatorCallExpr *OCE, CallingContext *Ctx) { |
418 | if (CapabilityExprMode) { |
419 | |
420 | OverloadedOperatorKind k = OCE->getOperator(); |
421 | if (k == OO_Star || k == OO_Arrow) { |
422 | auto *E = translate(OCE->getArg(0), Ctx); |
423 | return new (Arena) til::Cast(til::CAST_objToPtr, E); |
424 | |
425 | } |
426 | } |
427 | return translateCallExpr(cast<CallExpr>(OCE), Ctx); |
428 | } |
429 | |
430 | til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO, |
431 | CallingContext *Ctx) { |
432 | switch (UO->getOpcode()) { |
433 | case UO_PostInc: |
434 | case UO_PostDec: |
435 | case UO_PreInc: |
436 | case UO_PreDec: |
437 | return new (Arena) til::Undefined(UO); |
438 | |
439 | case UO_AddrOf: |
440 | if (CapabilityExprMode) { |
441 | |
442 | if (const auto *DRE = dyn_cast<DeclRefExpr>(UO->getSubExpr())) { |
443 | if (DRE->getDecl()->isCXXInstanceMember()) { |
444 | |
445 | |
446 | auto *W = new (Arena) til::Wildcard(); |
447 | return new (Arena) til::Project(W, DRE->getDecl()); |
448 | } |
449 | } |
450 | } |
451 | |
452 | return translate(UO->getSubExpr(), Ctx); |
453 | |
454 | |
455 | case UO_Deref: |
456 | case UO_Plus: |
457 | return translate(UO->getSubExpr(), Ctx); |
458 | |
459 | case UO_Minus: |
460 | return new (Arena) |
461 | til::UnaryOp(til::UOP_Minus, translate(UO->getSubExpr(), Ctx)); |
462 | case UO_Not: |
463 | return new (Arena) |
464 | til::UnaryOp(til::UOP_BitNot, translate(UO->getSubExpr(), Ctx)); |
465 | case UO_LNot: |
466 | return new (Arena) |
467 | til::UnaryOp(til::UOP_LogicNot, translate(UO->getSubExpr(), Ctx)); |
468 | |
469 | |
470 | case UO_Real: |
471 | case UO_Imag: |
472 | case UO_Extension: |
473 | case UO_Coawait: |
474 | return new (Arena) til::Undefined(UO); |
475 | } |
476 | return new (Arena) til::Undefined(UO); |
477 | } |
478 | |
479 | til::SExpr *SExprBuilder::translateBinOp(til::TIL_BinaryOpcode Op, |
480 | const BinaryOperator *BO, |
481 | CallingContext *Ctx, bool Reverse) { |
482 | til::SExpr *E0 = translate(BO->getLHS(), Ctx); |
483 | til::SExpr *E1 = translate(BO->getRHS(), Ctx); |
484 | if (Reverse) |
485 | return new (Arena) til::BinaryOp(Op, E1, E0); |
486 | else |
487 | return new (Arena) til::BinaryOp(Op, E0, E1); |
488 | } |
489 | |
490 | til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op, |
491 | const BinaryOperator *BO, |
492 | CallingContext *Ctx, |
493 | bool Assign) { |
494 | const Expr *LHS = BO->getLHS(); |
495 | const Expr *RHS = BO->getRHS(); |
496 | til::SExpr *E0 = translate(LHS, Ctx); |
497 | til::SExpr *E1 = translate(RHS, Ctx); |
498 | |
499 | const ValueDecl *VD = nullptr; |
500 | til::SExpr *CV = nullptr; |
501 | if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS)) { |
502 | VD = DRE->getDecl(); |
503 | CV = lookupVarDecl(VD); |
504 | } |
505 | |
506 | if (!Assign) { |
507 | til::SExpr *Arg = CV ? CV : new (Arena) til::Load(E0); |
508 | E1 = new (Arena) til::BinaryOp(Op, Arg, E1); |
509 | E1 = addStatement(E1, nullptr, VD); |
510 | } |
511 | if (VD && CV) |
512 | return updateVarDecl(VD, E1); |
513 | return new (Arena) til::Store(E0, E1); |
514 | } |
515 | |
516 | til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO, |
517 | CallingContext *Ctx) { |
518 | switch (BO->getOpcode()) { |
519 | case BO_PtrMemD: |
520 | case BO_PtrMemI: |
521 | return new (Arena) til::Undefined(BO); |
522 | |
523 | case BO_Mul: return translateBinOp(til::BOP_Mul, BO, Ctx); |
524 | case BO_Div: return translateBinOp(til::BOP_Div, BO, Ctx); |
525 | case BO_Rem: return translateBinOp(til::BOP_Rem, BO, Ctx); |
526 | case BO_Add: return translateBinOp(til::BOP_Add, BO, Ctx); |
527 | case BO_Sub: return translateBinOp(til::BOP_Sub, BO, Ctx); |
528 | case BO_Shl: return translateBinOp(til::BOP_Shl, BO, Ctx); |
529 | case BO_Shr: return translateBinOp(til::BOP_Shr, BO, Ctx); |
530 | case BO_LT: return translateBinOp(til::BOP_Lt, BO, Ctx); |
531 | case BO_GT: return translateBinOp(til::BOP_Lt, BO, Ctx, true); |
532 | case BO_LE: return translateBinOp(til::BOP_Leq, BO, Ctx); |
533 | case BO_GE: return translateBinOp(til::BOP_Leq, BO, Ctx, true); |
534 | case BO_EQ: return translateBinOp(til::BOP_Eq, BO, Ctx); |
535 | case BO_NE: return translateBinOp(til::BOP_Neq, BO, Ctx); |
536 | case BO_Cmp: return translateBinOp(til::BOP_Cmp, BO, Ctx); |
537 | case BO_And: return translateBinOp(til::BOP_BitAnd, BO, Ctx); |
538 | case BO_Xor: return translateBinOp(til::BOP_BitXor, BO, Ctx); |
539 | case BO_Or: return translateBinOp(til::BOP_BitOr, BO, Ctx); |
540 | case BO_LAnd: return translateBinOp(til::BOP_LogicAnd, BO, Ctx); |
541 | case BO_LOr: return translateBinOp(til::BOP_LogicOr, BO, Ctx); |
542 | |
543 | case BO_Assign: return translateBinAssign(til::BOP_Eq, BO, Ctx, true); |
544 | case BO_MulAssign: return translateBinAssign(til::BOP_Mul, BO, Ctx); |
545 | case BO_DivAssign: return translateBinAssign(til::BOP_Div, BO, Ctx); |
546 | case BO_RemAssign: return translateBinAssign(til::BOP_Rem, BO, Ctx); |
547 | case BO_AddAssign: return translateBinAssign(til::BOP_Add, BO, Ctx); |
548 | case BO_SubAssign: return translateBinAssign(til::BOP_Sub, BO, Ctx); |
549 | case BO_ShlAssign: return translateBinAssign(til::BOP_Shl, BO, Ctx); |
550 | case BO_ShrAssign: return translateBinAssign(til::BOP_Shr, BO, Ctx); |
551 | case BO_AndAssign: return translateBinAssign(til::BOP_BitAnd, BO, Ctx); |
552 | case BO_XorAssign: return translateBinAssign(til::BOP_BitXor, BO, Ctx); |
553 | case BO_OrAssign: return translateBinAssign(til::BOP_BitOr, BO, Ctx); |
554 | |
555 | case BO_Comma: |
556 | |
557 | return translate(BO->getRHS(), Ctx); |
558 | } |
559 | return new (Arena) til::Undefined(BO); |
560 | } |
561 | |
562 | til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE, |
563 | CallingContext *Ctx) { |
564 | CastKind K = CE->getCastKind(); |
565 | switch (K) { |
566 | case CK_LValueToRValue: { |
567 | if (const auto *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr())) { |
568 | til::SExpr *E0 = lookupVarDecl(DRE->getDecl()); |
569 | if (E0) |
570 | return E0; |
571 | } |
572 | til::SExpr *E0 = translate(CE->getSubExpr(), Ctx); |
573 | return E0; |
574 | |
575 | |
576 | } |
577 | case CK_NoOp: |
578 | case CK_DerivedToBase: |
579 | case CK_UncheckedDerivedToBase: |
580 | case CK_ArrayToPointerDecay: |
581 | case CK_FunctionToPointerDecay: { |
582 | til::SExpr *E0 = translate(CE->getSubExpr(), Ctx); |
583 | return E0; |
584 | } |
585 | default: { |
586 | |
587 | til::SExpr *E0 = translate(CE->getSubExpr(), Ctx); |
588 | if (CapabilityExprMode) |
589 | return E0; |
590 | return new (Arena) til::Cast(til::CAST_none, E0); |
591 | } |
592 | } |
593 | } |
594 | |
595 | til::SExpr * |
596 | SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E, |
597 | CallingContext *Ctx) { |
598 | til::SExpr *E0 = translate(E->getBase(), Ctx); |
599 | til::SExpr *E1 = translate(E->getIdx(), Ctx); |
600 | return new (Arena) til::ArrayIndex(E0, E1); |
601 | } |
602 | |
603 | til::SExpr * |
604 | SExprBuilder::translateAbstractConditionalOperator( |
605 | const AbstractConditionalOperator *CO, CallingContext *Ctx) { |
606 | auto *C = translate(CO->getCond(), Ctx); |
607 | auto *T = translate(CO->getTrueExpr(), Ctx); |
608 | auto *E = translate(CO->getFalseExpr(), Ctx); |
609 | return new (Arena) til::IfThenElse(C, T, E); |
610 | } |
611 | |
612 | til::SExpr * |
613 | SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) { |
614 | DeclGroupRef DGrp = S->getDeclGroup(); |
615 | for (auto I : DGrp) { |
616 | if (auto *VD = dyn_cast_or_null<VarDecl>(I)) { |
617 | Expr *E = VD->getInit(); |
618 | til::SExpr* SE = translate(E, Ctx); |
619 | |
620 | |
621 | QualType T = VD->getType(); |
622 | if (T.isTrivialType(VD->getASTContext())) |
623 | return addVarDecl(VD, SE); |
624 | else { |
625 | |
626 | } |
627 | } |
628 | } |
629 | return nullptr; |
630 | } |
631 | |
632 | |
633 | |
634 | |
635 | |
636 | til::SExpr *SExprBuilder::addStatement(til::SExpr* E, const Stmt *S, |
637 | const ValueDecl *VD) { |
638 | if (!E || !CurrentBB || E->block() || til::ThreadSafetyTIL::isTrivial(E)) |
639 | return E; |
640 | if (VD) |
641 | E = new (Arena) til::Variable(E, VD); |
642 | CurrentInstructions.push_back(E); |
643 | if (S) |
644 | insertStmt(S, E); |
645 | return E; |
646 | } |
647 | |
648 | |
649 | til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) { |
650 | auto It = LVarIdxMap.find(VD); |
651 | if (It != LVarIdxMap.end()) { |
652 | second].first == VD", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 652, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CurrentLVarMap[It->second].first == VD); |
653 | return CurrentLVarMap[It->second].second; |
654 | } |
655 | return nullptr; |
656 | } |
657 | |
658 | |
659 | static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) { |
660 | if (!E) |
661 | return; |
662 | if (auto *V = dyn_cast<til::Variable>(E)) { |
663 | if (!V->clangDecl()) |
664 | V->setClangDecl(VD); |
665 | } |
666 | } |
667 | |
668 | |
669 | til::SExpr *SExprBuilder::addVarDecl(const ValueDecl *VD, til::SExpr *E) { |
670 | maybeUpdateVD(E, VD); |
671 | LVarIdxMap.insert(std::make_pair(VD, CurrentLVarMap.size())); |
672 | CurrentLVarMap.makeWritable(); |
673 | CurrentLVarMap.push_back(std::make_pair(VD, E)); |
674 | return E; |
675 | } |
676 | |
677 | |
678 | til::SExpr *SExprBuilder::updateVarDecl(const ValueDecl *VD, til::SExpr *E) { |
679 | maybeUpdateVD(E, VD); |
680 | auto It = LVarIdxMap.find(VD); |
681 | if (It == LVarIdxMap.end()) { |
682 | til::SExpr *Ptr = new (Arena) til::LiteralPtr(VD); |
683 | til::SExpr *St = new (Arena) til::Store(Ptr, E); |
684 | return St; |
685 | } |
686 | CurrentLVarMap.makeWritable(); |
687 | CurrentLVarMap.elem(It->second).second = E; |
688 | return E; |
689 | } |
690 | |
691 | |
692 | |
693 | |
694 | void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) { |
695 | unsigned ArgIndex = CurrentBlockInfo->ProcessedPredecessors; |
696 | 0 && ArgIndex < NPreds", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 696, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(ArgIndex > 0 && ArgIndex < NPreds); |
697 | |
698 | til::SExpr *CurrE = CurrentLVarMap[i].second; |
699 | if (CurrE->block() == CurrentBB) { |
700 | |
701 | |
702 | auto *Ph = dyn_cast<til::Phi>(CurrE); |
703 | (0) . __assert_fail ("Ph && \"Expecting Phi node.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 703, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Ph && "Expecting Phi node."); |
704 | if (E) |
705 | Ph->values()[ArgIndex] = E; |
706 | return; |
707 | } |
708 | |
709 | |
710 | |
711 | til::Phi *Ph = new (Arena) til::Phi(Arena, NPreds); |
712 | Ph->values().setValues(NPreds, nullptr); |
713 | for (unsigned PIdx = 0; PIdx < ArgIndex; ++PIdx) |
714 | Ph->values()[PIdx] = CurrE; |
715 | if (E) |
716 | Ph->values()[ArgIndex] = E; |
717 | Ph->setClangDecl(CurrentLVarMap[i].first); |
718 | |
719 | |
720 | if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE)) |
721 | Ph->setStatus(til::Phi::PH_Incomplete); |
722 | |
723 | |
724 | CurrentArguments.push_back(Ph); |
725 | if (Ph->status() == til::Phi::PH_Incomplete) |
726 | IncompleteArgs.push_back(Ph); |
727 | |
728 | CurrentLVarMap.makeWritable(); |
729 | CurrentLVarMap.elem(i).second = Ph; |
730 | } |
731 | |
732 | |
733 | |
734 | void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) { |
735 | (0) . __assert_fail ("CurrentBlockInfo && \"Not processing a block!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 735, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CurrentBlockInfo && "Not processing a block!"); |
736 | |
737 | if (!CurrentLVarMap.valid()) { |
738 | |
739 | CurrentLVarMap = std::move(Map); |
740 | return; |
741 | } |
742 | if (CurrentLVarMap.sameAs(Map)) |
743 | return; |
744 | |
745 | unsigned NPreds = CurrentBB->numPredecessors(); |
746 | unsigned ESz = CurrentLVarMap.size(); |
747 | unsigned MSz = Map.size(); |
748 | unsigned Sz = std::min(ESz, MSz); |
749 | |
750 | for (unsigned i = 0; i < Sz; ++i) { |
751 | if (CurrentLVarMap[i].first != Map[i].first) { |
752 | |
753 | CurrentLVarMap.makeWritable(); |
754 | CurrentLVarMap.downsize(i); |
755 | break; |
756 | } |
757 | if (CurrentLVarMap[i].second != Map[i].second) |
758 | makePhiNodeVar(i, NPreds, Map[i].second); |
759 | } |
760 | if (ESz > MSz) { |
761 | CurrentLVarMap.makeWritable(); |
762 | CurrentLVarMap.downsize(Map.size()); |
763 | } |
764 | } |
765 | |
766 | |
767 | |
768 | void SExprBuilder::mergeEntryMapBackEdge() { |
769 | |
770 | |
771 | |
772 | |
773 | |
774 | |
775 | |
776 | |
777 | (0) . __assert_fail ("CurrentBlockInfo && \"Not processing a block!\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 777, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(CurrentBlockInfo && "Not processing a block!"); |
778 | |
779 | if (CurrentBlockInfo->HasBackEdges) |
780 | return; |
781 | CurrentBlockInfo->HasBackEdges = true; |
782 | |
783 | CurrentLVarMap.makeWritable(); |
784 | unsigned Sz = CurrentLVarMap.size(); |
785 | unsigned NPreds = CurrentBB->numPredecessors(); |
786 | |
787 | for (unsigned i = 0; i < Sz; ++i) |
788 | makePhiNodeVar(i, NPreds, nullptr); |
789 | } |
790 | |
791 | |
792 | |
793 | |
794 | void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) { |
795 | til::BasicBlock *BB = lookupBlock(Blk); |
796 | unsigned ArgIndex = BBInfo[Blk->getBlockID()].ProcessedPredecessors; |
797 | 0 && ArgIndex < BB->numPredecessors()", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 797, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors()); |
798 | |
799 | for (til::SExpr *PE : BB->arguments()) { |
800 | auto *Ph = dyn_cast_or_null<til::Phi>(PE); |
801 | (0) . __assert_fail ("Ph && \"Expecting Phi Node.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 801, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Ph && "Expecting Phi Node."); |
802 | (0) . __assert_fail ("Ph->values()[ArgIndex] == nullptr && \"Wrong index for back edge.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 802, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge."); |
803 | |
804 | til::SExpr *E = lookupVarDecl(Ph->clangDecl()); |
805 | (0) . __assert_fail ("E && \"Couldn't find local variable for Phi node.\"", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 805, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(E && "Couldn't find local variable for Phi node."); |
806 | Ph->values()[ArgIndex] = E; |
807 | } |
808 | } |
809 | |
810 | void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D, |
811 | const CFGBlock *First) { |
812 | |
813 | unsigned NBlocks = Cfg->getNumBlockIDs(); |
814 | Scfg = new (Arena) til::SCFG(Arena, NBlocks); |
815 | |
816 | |
817 | BBInfo.resize(NBlocks); |
818 | BlockMap.resize(NBlocks, nullptr); |
819 | |
820 | for (auto *B : *Cfg) { |
821 | auto *BB = new (Arena) til::BasicBlock(Arena); |
822 | BB->reserveInstructions(B->size()); |
823 | BlockMap[B->getBlockID()] = BB; |
824 | } |
825 | |
826 | CurrentBB = lookupBlock(&Cfg->getEntry()); |
827 | auto Parms = isa<ObjCMethodDecl>(D) ? cast<ObjCMethodDecl>(D)->parameters() |
828 | : cast<FunctionDecl>(D)->parameters(); |
829 | for (auto *Pm : Parms) { |
830 | QualType T = Pm->getType(); |
831 | if (!T.isTrivialType(Pm->getASTContext())) |
832 | continue; |
833 | |
834 | |
835 | |
836 | til::SExpr *Lp = new (Arena) til::LiteralPtr(Pm); |
837 | til::SExpr *Ld = new (Arena) til::Load(Lp); |
838 | til::SExpr *V = addStatement(Ld, nullptr, Pm); |
839 | addVarDecl(Pm, V); |
840 | } |
841 | } |
842 | |
843 | void SExprBuilder::enterCFGBlock(const CFGBlock *B) { |
844 | |
845 | CurrentBB = lookupBlock(B); |
846 | CurrentBB->reservePredecessors(B->pred_size()); |
847 | Scfg->add(CurrentBB); |
848 | |
849 | CurrentBlockInfo = &BBInfo[B->getBlockID()]; |
850 | |
851 | |
852 | |
853 | |
854 | } |
855 | |
856 | void SExprBuilder::handlePredecessor(const CFGBlock *Pred) { |
857 | |
858 | |
859 | CurrentBB->addPredecessor(BlockMap[Pred->getBlockID()]); |
860 | BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()]; |
861 | UnprocessedSuccessors > 0", "/home/seafit/code_projects/clang_source/clang/lib/Analysis/ThreadSafetyCommon.cpp", 861, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(PredInfo->UnprocessedSuccessors > 0); |
862 | |
863 | if (--PredInfo->UnprocessedSuccessors == 0) |
864 | mergeEntryMap(std::move(PredInfo->ExitMap)); |
865 | else |
866 | mergeEntryMap(PredInfo->ExitMap.clone()); |
867 | |
868 | ++CurrentBlockInfo->ProcessedPredecessors; |
869 | } |
870 | |
871 | void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) { |
872 | mergeEntryMapBackEdge(); |
873 | } |
874 | |
875 | void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) { |
876 | |
877 | |
878 | CurrentBB->arguments().reserve( |
879 | static_cast<unsigned>(CurrentArguments.size()), Arena); |
880 | for (auto *A : CurrentArguments) |
881 | CurrentBB->addArgument(A); |
882 | } |
883 | |
884 | void SExprBuilder::handleStatement(const Stmt *S) { |
885 | til::SExpr *E = translate(S, nullptr); |
886 | addStatement(E, S); |
887 | } |
888 | |
889 | void SExprBuilder::handleDestructorCall(const VarDecl *VD, |
890 | const CXXDestructorDecl *DD) { |
891 | til::SExpr *Sf = new (Arena) til::LiteralPtr(VD); |
892 | til::SExpr *Dr = new (Arena) til::LiteralPtr(DD); |
893 | til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf); |
894 | til::SExpr *E = new (Arena) til::Call(Ap); |
895 | addStatement(E, nullptr); |
896 | } |
897 | |
898 | void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) { |
899 | CurrentBB->instructions().reserve( |
900 | static_cast<unsigned>(CurrentInstructions.size()), Arena); |
901 | for (auto *V : CurrentInstructions) |
902 | CurrentBB->addInstruction(V); |
903 | |
904 | |
905 | unsigned N = B->succ_size(); |
906 | auto It = B->succ_begin(); |
907 | if (N == 1) { |
908 | til::BasicBlock *BB = *It ? lookupBlock(*It) : nullptr; |
909 | |
910 | unsigned Idx = BB ? BB->findPredecessorIndex(CurrentBB) : 0; |
911 | auto *Tm = new (Arena) til::Goto(BB, Idx); |
912 | CurrentBB->setTerminator(Tm); |
913 | } |
914 | else if (N == 2) { |
915 | til::SExpr *C = translate(B->getTerminatorCondition(true), nullptr); |
916 | til::BasicBlock *BB1 = *It ? lookupBlock(*It) : nullptr; |
917 | ++It; |
918 | til::BasicBlock *BB2 = *It ? lookupBlock(*It) : nullptr; |
919 | |
920 | auto *Tm = new (Arena) til::Branch(C, BB1, BB2); |
921 | CurrentBB->setTerminator(Tm); |
922 | } |
923 | } |
924 | |
925 | void SExprBuilder::handleSuccessor(const CFGBlock *Succ) { |
926 | ++CurrentBlockInfo->UnprocessedSuccessors; |
927 | } |
928 | |
929 | void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) { |
930 | mergePhiNodesBackEdge(Succ); |
931 | ++BBInfo[Succ->getBlockID()].ProcessedPredecessors; |
932 | } |
933 | |
934 | void SExprBuilder::exitCFGBlock(const CFGBlock *B) { |
935 | CurrentArguments.clear(); |
936 | CurrentInstructions.clear(); |
937 | CurrentBlockInfo->ExitMap = std::move(CurrentLVarMap); |
938 | CurrentBB = nullptr; |
939 | CurrentBlockInfo = nullptr; |
940 | } |
941 | |
942 | void SExprBuilder::exitCFG(const CFGBlock *Last) { |
943 | for (auto *Ph : IncompleteArgs) { |
944 | if (Ph->status() == til::Phi::PH_Incomplete) |
945 | simplifyIncompleteArg(Ph); |
946 | } |
947 | |
948 | CurrentArguments.clear(); |
949 | CurrentInstructions.clear(); |
950 | IncompleteArgs.clear(); |
951 | } |
952 | |
953 | |
954 | |
955 | |
956 | |
957 | |
958 | |
959 | |
960 | |
961 | |
962 | |
963 | |
964 | |
965 | |
966 | |
967 | |
968 | |
969 | |
970 | |
971 | |
972 | |
973 | |
974 | |
975 | |