clang: lib/Analysis/ThreadSafetyCommon.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

29#include "llvm/ADT/ScopeExit.h"

30#include "llvm/ADT/StringExtras.h"

31#include "llvm/ADT/StringRef.h"

32#include

33#include

34#include

35#include

36

37using namespace clang;

39

40

43 case Stmt::IntegerLiteralClass:

45 case Stmt::StringLiteralClass: {

46 std::string ret("\"");

48 ret += "\"";

49 return ret;

50 }

51 case Stmt::CharacterLiteralClass:

52 case Stmt::CXXNullPtrLiteralExprClass:

53 case Stmt::GNUNullExprClass:

54 case Stmt::CXXBoolLiteralExprClass:

55 case Stmt::FloatingLiteralClass:

56 case Stmt::ImaginaryLiteralClass:

57 case Stmt::ObjCStringLiteralClass:

58 default:

59 return "#lit";

60 }

61}

62

63

65 if (const auto *Ph = dyn_casttil::Phi(E))

67 return false;

68}

69

71 StringRef("mutex"),

72 false};

73

74

76 if (const auto *CA = TD.getAttr())

77 return {CA->getName(), TD.hasAttr()};

78

80}

81

82

96

101

103

105

107 Walker.walk(*this);

108 return Scfg;

109}

110

112 const auto *ME = dyn_cast(E->IgnoreParenCasts());

113 return ME ? ME->isArrow() : false;

114}

115

116

117

118

119

120

121

122

123

124

127 const Expr *DeclExp,

129

130 if (!DeclExp && Self)

132

134

135

136

137 if (!DeclExp)

138 ;

139 else if (const auto *ME = dyn_cast(DeclExp)) {

140 Ctx.SelfArg = ME->getBase();

142 } else if (const auto *CE = dyn_cast(DeclExp)) {

143 Ctx.SelfArg = CE->getImplicitObjectArgument();

145 Ctx.NumArgs = CE->getNumArgs();

146 Ctx.FunArgs = CE->getArgs();

147 } else if (const auto *CE = dyn_cast(DeclExp)) {

148

150 Ctx.SelfArg = CE->getArg(0);

152 Ctx.NumArgs = CE->getNumArgs() - 1;

153 Ctx.FunArgs = CE->getArgs() + 1;

154 } else {

155 Ctx.NumArgs = CE->getNumArgs();

156 Ctx.FunArgs = CE->getArgs();

157 }

158 } else if (const auto *CE = dyn_cast(DeclExp)) {

159 Ctx.SelfArg = nullptr;

160 Ctx.NumArgs = CE->getNumArgs();

161 Ctx.FunArgs = CE->getArgs();

162 }

163

164

165

166

167

168 if (const auto *CMD = dyn_cast(D))

169 if (CMD->getParent()->isLambda())

171

173 assert(!Ctx.SelfArg && "Ambiguous self argument");

174 assert(isa(D) && "Self argument requires function");

177 else

179

180

181 if (!AttrExp)

184 false);

185 else

187 }

188

189

190 if (!AttrExp)

192 else

194}

195

196

197

200 if (!AttrExp)

202

203 if (const auto* SLit = dyn_cast(AttrExp)) {

204 if (SLit->getString() == "*")

205

206

208 false, false);

209 else

210

212 }

213

214 bool Neg = false;

215 if (const auto *OE = dyn_cast(AttrExp)) {

216 if (OE->getOperator() == OO_Exclaim) {

217 Neg = true;

218 AttrExp = OE->getArg(0);

219 }

220 }

221 else if (const auto *UO = dyn_cast(AttrExp)) {

222 if (UO->getOpcode() == UO_LNot) {

223 Neg = true;

225 }

226 }

227

229

230

231

234

235

236 if (const auto *CE = dyn_casttil::Cast(E)) {

238 E = CE->expr();

239 }

241}

242

245 assert(VD);

246

247

248

251

252

253

254 auto Cleanup = llvm::make_scope_exit(

255 [&, RestoreClosure =

256 VarsBeingTranslated.empty() ? LookupLocalVarExpr : nullptr] {

257 VarsBeingTranslated.erase(VD->getCanonicalDecl());

258 if (VarsBeingTranslated.empty())

259 LookupLocalVarExpr = RestoreClosure;

260 });

262

265

266 if (LookupLocalVarExpr) {

267

268

269

270 if (const Expr *E = LookupLocalVarExpr(VD)) {

272

273

274

277 }

278 }

279 }

280

282}

283

284

285

286

288 if (!S)

289 return nullptr;

290

291

292

294 return E;

295

297 case Stmt::DeclRefExprClass:

299 case Stmt::CXXThisExprClass:

301 case Stmt::MemberExprClass:

303 case Stmt::ObjCIvarRefExprClass:

305 case Stmt::CallExprClass:

307 case Stmt::CXXMemberCallExprClass:

309 case Stmt::CXXOperatorCallExprClass:

311 case Stmt::UnaryOperatorClass:

313 case Stmt::BinaryOperatorClass:

314 case Stmt::CompoundAssignOperatorClass:

316

317 case Stmt::ArraySubscriptExprClass:

319 case Stmt::ConditionalOperatorClass:

320 return translateAbstractConditionalOperator(

322 case Stmt::BinaryConditionalOperatorClass:

323 return translateAbstractConditionalOperator(

325

326

327 case Stmt::ConstantExprClass:

329 case Stmt::ParenExprClass:

331 case Stmt::ExprWithCleanupsClass:

333 case Stmt::CXXBindTemporaryExprClass:

335 case Stmt::MaterializeTemporaryExprClass:

337

338

339 case Stmt::CharacterLiteralClass:

340 case Stmt::CXXNullPtrLiteralExprClass:

341 case Stmt::GNUNullExprClass:

342 case Stmt::CXXBoolLiteralExprClass:

343 case Stmt::FloatingLiteralClass:

344 case Stmt::ImaginaryLiteralClass:

345 case Stmt::IntegerLiteralClass:

346 case Stmt::StringLiteralClass:

347 case Stmt::ObjCStringLiteralClass:

349

350 case Stmt::DeclStmtClass:

352 case Stmt::StmtExprClass:

354 default:

355 break;

356 }

357 if (const auto *CE = dyn_cast(S))

358 return translateCastExpr(CE, Ctx);

359

361}

362

366

367

368 if (const auto *PV = dyn_cast(VD)) {

369 unsigned I = PV->getFunctionScopeIndex();

370 const DeclContext *D = PV->getDeclContext();

371 if (Ctx && Ctx->FunArgs) {

376

377 if (const Expr *const *FunArgs =

378 dyn_cast<const Expr *const *>(Ctx->FunArgs)) {

379 assert(I < Ctx->NumArgs);

381 }

382

383 assert(I == 0);

385 }

386 }

387

388

392 }

393

394 if (const auto *VarD = dyn_cast(VD))

396

397

398 return new (Arena) til::LiteralPtr(VD);

399}

400

401til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE,

403

404 if (Ctx && Ctx->SelfArg) {

405 if (const auto *SelfArg = dyn_cast<const Expr *>(Ctx->SelfArg))

407 else

409 }

410 assert(SelfVar && "We have no variable for 'this'!");

411 return SelfVar;

412}

413

415 if (const auto *V = dyn_casttil::Variable(E))

416 return V->clangDecl();

417 if (const auto *Ph = dyn_casttil::Phi(E))

418 return Ph->clangDecl();

419 if (const auto *P = dyn_casttil::Project(E))

420 return P->clangDecl();

421 if (const auto *L = dyn_casttil::LiteralPtr(E))

422 return L->clangDecl();

423 return nullptr;

424}

425

428 if (VD && VD->getType()->isAnyPointerType())

429 return true;

430 if (const auto *C = dyn_casttil::Cast(E))

432

433 return false;

434}

435

436

438 while (true) {

441 if (OverriddenMethods.begin() == OverriddenMethods.end())

442 return D;

443

444 D = *OverriddenMethods.begin();

445 }

446 return nullptr;

447}

448

449til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME,

452 til::SExpr *E = new (Arena) til::SApply(BE);

453

455 if (const auto *VD = dyn_cast(D))

457

458 til::Project *P = new (Arena) til::Project(E, D);

461 return P;

462}

463

464til::SExpr *SExprBuilder::translateObjCIVarRefExpr(const ObjCIvarRefExpr *IVRE,

467 til::SExpr *E = new (Arena) til::SApply(BE);

468

470

471 til::Project *P = new (Arena) til::Project(E, D);

474 return P;

475}

476

477til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE,

479 const Expr *SelfE) {

480 if (CapabilityExprMode) {

481

483 FD = FD->getMostRecentDecl();

484 if (LockReturnedAttr *At = FD->getAttr()) {

487 LRCallCtx.SelfArg = SelfE;

488 LRCallCtx.NumArgs = CE->getNumArgs();

489 LRCallCtx.FunArgs = CE->getArgs();

490 return const_cast<til::SExpr *>(

492 }

493 }

494 }

495

497 for (const auto *Arg : CE->arguments()) {

498 til::SExpr *A = translate(Arg, Ctx);

499 E = new (Arena) til::Apply(E, A);

500 }

501 return new (Arena) til::Call(E, CE);

502}

503

504til::SExpr *SExprBuilder::translateCXXMemberCallExpr(

506 if (CapabilityExprMode) {

507

512

513 }

514 }

517}

518

519til::SExpr *SExprBuilder::translateCXXOperatorCallExpr(

520 const CXXOperatorCallExpr *OCE, CallingContext *Ctx) {

521 if (CapabilityExprMode) {

522

524 if (k == OO_Star || k == OO_Arrow) {

527

528 }

529 }

531}

532

533til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO,

536 case UO_PostInc:

537 case UO_PostDec:

538 case UO_PreInc:

539 case UO_PreDec:

540 return new (Arena) til::Undefined(UO);

541

542 case UO_AddrOf:

543 if (CapabilityExprMode) {

544

545 if (const auto *DRE = dyn_cast(UO->getSubExpr())) {

547

548

549 auto *W = new (Arena) til::Wildcard();

550 return new (Arena) til::Project(W, DRE->getDecl());

551 }

552 }

553 }

554

556

557

558 case UO_Deref:

559 case UO_Plus:

561

562 case UO_Minus:

563 return new (Arena)

565 case UO_Not:

566 return new (Arena)

568 case UO_LNot:

569 return new (Arena)

571

572

573 case UO_Real:

574 case UO_Imag:

575 case UO_Extension:

576 case UO_Coawait:

577 return new (Arena) til::Undefined(UO);

578 }

579 return new (Arena) til::Undefined(UO);

580}

581

583 const BinaryOperator *BO,

587 if (Reverse)

588 return new (Arena) til::BinaryOp(Op, E1, E0);

589 else

590 return new (Arena) til::BinaryOp(Op, E0, E1);

591}

592

594 const BinaryOperator *BO,

596 bool Assign) {

597 const Expr *LHS = BO->getLHS();

598 const Expr *RHS = BO->getRHS();

599 til::SExpr *E0 = translate(LHS, Ctx);

600 til::SExpr *E1 = translate(RHS, Ctx);

601

602 const ValueDecl *VD = nullptr;

603 til::SExpr *CV = nullptr;

604 if (const auto *DRE = dyn_cast(LHS)) {

606 CV = lookupVarDecl(VD);

607 }

608

609 if (!Assign) {

610 til::SExpr *Arg = CV ? CV : new (Arena) til::Load(E0);

611 E1 = new (Arena) til::BinaryOp(Op, Arg, E1);

612 E1 = addStatement(E1, nullptr, VD);

613 }

614 if (VD && CV)

615 return updateVarDecl(VD, E1);

616 return new (Arena) til::Store(E0, E1);

617}

618

619til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO,

622 case BO_PtrMemD:

623 case BO_PtrMemI:

624 return new (Arena) til::Undefined(BO);

625

626 case BO_Mul: return translateBinOp(til::BOP_Mul, BO, Ctx);

627 case BO_Div: return translateBinOp(til::BOP_Div, BO, Ctx);

628 case BO_Rem: return translateBinOp(til::BOP_Rem, BO, Ctx);

629 case BO_Add: return translateBinOp(til::BOP_Add, BO, Ctx);

630 case BO_Sub: return translateBinOp(til::BOP_Sub, BO, Ctx);

631 case BO_Shl: return translateBinOp(til::BOP_Shl, BO, Ctx);

632 case BO_Shr: return translateBinOp(til::BOP_Shr, BO, Ctx);

633 case BO_LT: return translateBinOp(til::BOP_Lt, BO, Ctx);

634 case BO_GT: return translateBinOp(til::BOP_Lt, BO, Ctx, true);

635 case BO_LE: return translateBinOp(til::BOP_Leq, BO, Ctx);

636 case BO_GE: return translateBinOp(til::BOP_Leq, BO, Ctx, true);

637 case BO_EQ: return translateBinOp(til::BOP_Eq, BO, Ctx);

638 case BO_NE: return translateBinOp(til::BOP_Neq, BO, Ctx);

639 case BO_Cmp: return translateBinOp(til::BOP_Cmp, BO, Ctx);

640 case BO_And: return translateBinOp(til::BOP_BitAnd, BO, Ctx);

641 case BO_Xor: return translateBinOp(til::BOP_BitXor, BO, Ctx);

642 case BO_Or: return translateBinOp(til::BOP_BitOr, BO, Ctx);

644 case BO_LOr: return translateBinOp(til::BOP_LogicOr, BO, Ctx);

645

646 case BO_Assign: return translateBinAssign(til::BOP_Eq, BO, Ctx, true);

647 case BO_MulAssign: return translateBinAssign(til::BOP_Mul, BO, Ctx);

648 case BO_DivAssign: return translateBinAssign(til::BOP_Div, BO, Ctx);

649 case BO_RemAssign: return translateBinAssign(til::BOP_Rem, BO, Ctx);

650 case BO_AddAssign: return translateBinAssign(til::BOP_Add, BO, Ctx);

651 case BO_SubAssign: return translateBinAssign(til::BOP_Sub, BO, Ctx);

652 case BO_ShlAssign: return translateBinAssign(til::BOP_Shl, BO, Ctx);

653 case BO_ShrAssign: return translateBinAssign(til::BOP_Shr, BO, Ctx);

654 case BO_AndAssign: return translateBinAssign(til::BOP_BitAnd, BO, Ctx);

655 case BO_XorAssign: return translateBinAssign(til::BOP_BitXor, BO, Ctx);

656 case BO_OrAssign: return translateBinAssign(til::BOP_BitOr, BO, Ctx);

657

658 case BO_Comma:

659

661 }

662 return new (Arena) til::Undefined(BO);

663}

664

668 switch (K) {

669 case CK_LValueToRValue: {

670 if (const auto *DRE = dyn_cast(CE->getSubExpr())) {

671 til::SExpr *E0 = lookupVarDecl(DRE->getDecl());

672 if (E0)

673 return E0;

674 }

676 return E0;

677

678

679 }

680 case CK_NoOp:

681 case CK_DerivedToBase:

682 case CK_UncheckedDerivedToBase:

683 case CK_ArrayToPointerDecay:

684 case CK_FunctionToPointerDecay: {

686 return E0;

687 }

688 default: {

689

691 if (CapabilityExprMode)

692 return E0;

694 }

695 }

696}

697

699SExprBuilder::translateArraySubscriptExpr(const ArraySubscriptExpr *E,

703 return new (Arena) til::ArrayIndex(E0, E1);

704}

705

707SExprBuilder::translateAbstractConditionalOperator(

708 const AbstractConditionalOperator *CO, CallingContext *Ctx) {

712 return new (Arena) til::IfThenElse(C, T, E);

713}

714

716SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) {

718 for (auto *I : DGrp) {

719 if (auto *VD = dyn_cast_or_null(I)) {

720 Expr *E = VD->getInit();

721 til::SExpr* SE = translate(E, Ctx);

722

723

726 return addVarDecl(VD, SE);

727 else {

728

729 }

730 }

731 }

732 return nullptr;

733}

734

735til::SExpr *SExprBuilder::translateStmtExpr(const StmtExpr *SE,

737

738

740 return CS->body_empty() ? new (Arena) til::Undefined(SE)

742}

743

744

745

746

747

749 const ValueDecl *VD) {

751 return E;

752 if (VD)

753 E = new (Arena) til::Variable(E, VD);

754 CurrentInstructions.push_back(E);

755 if (S)

756 insertStmt(S, E);

757 return E;

758}

759

760

761til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) {

762 auto It = LVarIdxMap.find(VD);

763 if (It != LVarIdxMap.end()) {

764 assert(CurrentLVarMap[It->second].first == VD);

765 return CurrentLVarMap[It->second].second;

766 }

767 return nullptr;

768}

769

770

772 if (!E)

773 return;

774 if (auto *V = dyn_casttil::Variable(E)) {

775 if (V->clangDecl())

776 V->setClangDecl(VD);

777 }

778}

779

780

783 LVarIdxMap.insert(std::make_pair(VD, CurrentLVarMap.size()));

784 CurrentLVarMap.makeWritable();

785 CurrentLVarMap.push_back(std::make_pair(VD, E));

786 return E;

787}

788

789

792 auto It = LVarIdxMap.find(VD);

793 if (It == LVarIdxMap.end()) {

794 til::SExpr *Ptr = new (Arena) til::LiteralPtr(VD);

795 til::SExpr *St = new (Arena) til::Store(Ptr, E);

796 return St;

797 }

798 CurrentLVarMap.makeWritable();

799 CurrentLVarMap.elem(It->second).second = E;

800 return E;

801}

802

803

804

805

806void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) {

807 unsigned ArgIndex = CurrentBlockInfo->ProcessedPredecessors;

808 assert(ArgIndex > 0 && ArgIndex < NPreds);

809

810 til::SExpr *CurrE = CurrentLVarMap[i].second;

811 if (CurrE->block() == CurrentBB) {

812

813

814 auto *Ph = dyn_casttil::Phi(CurrE);

815 assert(Ph && "Expecting Phi node.");

816 if (E)

817 Ph->values()[ArgIndex] = E;

818 return;

819 }

820

821

822

823 til::Phi *Ph = new (Arena) til::Phi(Arena, NPreds);

825 for (unsigned PIdx = 0; PIdx < ArgIndex; ++PIdx)

826 Ph->values()[PIdx] = CurrE;

827 if (E)

828 Ph->values()[ArgIndex] = E;

830

831

834

835

836 CurrentArguments.push_back(Ph);

838 IncompleteArgs.push_back(Ph);

839

840 CurrentLVarMap.makeWritable();

841 CurrentLVarMap.elem(i).second = Ph;

842}

843

844

845

846void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) {

847 assert(CurrentBlockInfo && "Not processing a block!");

848

849 if (!CurrentLVarMap.valid()) {

850

851 CurrentLVarMap = std::move(Map);

852 return;

853 }

854 if (CurrentLVarMap.sameAs(Map))

855 return;

856

857 unsigned NPreds = CurrentBB->numPredecessors();

858 unsigned ESz = CurrentLVarMap.size();

859 unsigned MSz = Map.size();

860 unsigned Sz = std::min(ESz, MSz);

861

862 for (unsigned i = 0; i < Sz; ++i) {

863 if (CurrentLVarMap[i].first != Map[i].first) {

864

865 CurrentLVarMap.makeWritable();

866 CurrentLVarMap.downsize(i);

867 break;

868 }

869 if (CurrentLVarMap[i].second != Map[i].second)

870 makePhiNodeVar(i, NPreds, Map[i].second);

871 }

872 if (ESz > MSz) {

873 CurrentLVarMap.makeWritable();

874 CurrentLVarMap.downsize(Map.size());

875 }

876}

877

878

879

880void SExprBuilder::mergeEntryMapBackEdge() {

881

882

883

884

885

886

887

888

889 assert(CurrentBlockInfo && "Not processing a block!");

890

891 if (CurrentBlockInfo->HasBackEdges)

892 return;

893 CurrentBlockInfo->HasBackEdges = true;

894

895 CurrentLVarMap.makeWritable();

896 unsigned Sz = CurrentLVarMap.size();

897 unsigned NPreds = CurrentBB->numPredecessors();

898

899 for (unsigned i = 0; i < Sz; ++i)

900 makePhiNodeVar(i, NPreds, nullptr);

901}

902

903

904

905

906void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) {

908 unsigned ArgIndex = BBInfo[Blk->getBlockID()].ProcessedPredecessors;

909 assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors());

910

911 for (til::SExpr *PE : BB->arguments()) {

912 auto *Ph = dyn_cast_or_nulltil::Phi(PE);

913 assert(Ph && "Expecting Phi Node.");

914 assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge.");

915

916 til::SExpr *E = lookupVarDecl(Ph->clangDecl());

917 assert(E && "Couldn't find local variable for Phi node.");

918 Ph->values()[ArgIndex] = E;

919 }

920}

921

922void SExprBuilder::enterCFG(CFG *Cfg, const NamedDecl *D,

923 const CFGBlock *First) {

924

926 Scfg = new (Arena) til::SCFG(Arena, NBlocks);

927

928

929 BBInfo.resize(NBlocks);

930 BlockMap.resize(NBlocks, nullptr);

931

932 for (auto *B : *Cfg) {

933 auto *BB = new (Arena) til::BasicBlock(Arena);

935 BlockMap[B->getBlockID()] = BB;

936 }

937

938 CurrentBB = lookupBlock(&Cfg->getEntry());

941 for (auto *Pm : Parms) {

942 QualType T = Pm->getType();

943 if (T.isTrivialType(Pm->getASTContext()))

944 continue;

945

946

947

948 til::SExpr *Lp = new (Arena) til::LiteralPtr(Pm);

949 til::SExpr *Ld = new (Arena) til::Load(Lp);

950 til::SExpr *V = addStatement(Ld, nullptr, Pm);

951 addVarDecl(Pm, V);

952 }

953}

954

955void SExprBuilder::enterCFGBlock(const CFGBlock *B) {

956

958 CurrentBB->reservePredecessors(B->pred_size());

959 Scfg->add(CurrentBB);

960

961 CurrentBlockInfo = &BBInfo[B->getBlockID()];

962

963

964

965

966}

967

968void SExprBuilder::handlePredecessor(const CFGBlock *Pred) {

969

970

971 CurrentBB->addPredecessor(BlockMap[Pred->getBlockID()]);

972 BlockInfo *PredInfo = &BBInfo[Pred->getBlockID()];

973 assert(PredInfo->UnprocessedSuccessors > 0);

974

975 if (--PredInfo->UnprocessedSuccessors == 0)

976 mergeEntryMap(std::move(PredInfo->ExitMap));

977 else

978 mergeEntryMap(PredInfo->ExitMap.clone());

979

980 ++CurrentBlockInfo->ProcessedPredecessors;

981}

982

983void SExprBuilder::handlePredecessorBackEdge(const CFGBlock *Pred) {

984 mergeEntryMapBackEdge();

985}

986

987void SExprBuilder::enterCFGBlockBody(const CFGBlock *B) {

988

989

990 CurrentBB->arguments().reserve(

991 static_cast<unsigned>(CurrentArguments.size()), Arena);

992 for (auto *A : CurrentArguments)

993 CurrentBB->addArgument(A);

994}

995

996void SExprBuilder::handleStatement(const Stmt *S) {

997 til::SExpr *E = translate(S, nullptr);

998 addStatement(E, S);

999}

1000

1001void SExprBuilder::handleDestructorCall(const VarDecl *VD,

1002 const CXXDestructorDecl *DD) {

1003 til::SExpr *Sf = new (Arena) til::LiteralPtr(VD);

1004 til::SExpr *Dr = new (Arena) til::LiteralPtr(DD);

1005 til::SExpr *Ap = new (Arena) til::Apply(Dr, Sf);

1006 til::SExpr *E = new (Arena) til::Call(Ap);

1007 addStatement(E, nullptr);

1008}

1009

1010void SExprBuilder::exitCFGBlockBody(const CFGBlock *B) {

1011 CurrentBB->instructions().reserve(

1012 static_cast<unsigned>(CurrentInstructions.size()), Arena);

1013 for (auto *V : CurrentInstructions)

1014 CurrentBB->addInstruction(V);

1015

1016

1019 if (N == 1) {

1021

1023 auto *Tm = new (Arena) til::Goto(BB, Idx);

1024 CurrentBB->setTerminator(Tm);

1025 }

1026 else if (N == 2) {

1029 ++It;

1031

1032 auto *Tm = new (Arena) til::Branch(C, BB1, BB2);

1033 CurrentBB->setTerminator(Tm);

1034 }

1035}

1036

1037void SExprBuilder::handleSuccessor(const CFGBlock *Succ) {

1038 ++CurrentBlockInfo->UnprocessedSuccessors;

1039}

1040

1041void SExprBuilder::handleSuccessorBackEdge(const CFGBlock *Succ) {

1042 mergePhiNodesBackEdge(Succ);

1043 ++BBInfo[Succ->getBlockID()].ProcessedPredecessors;

1044}

1045

1046void SExprBuilder::exitCFGBlock(const CFGBlock *B) {

1047 CurrentArguments.clear();

1048 CurrentInstructions.clear();

1049 CurrentBlockInfo->ExitMap = std::move(CurrentLVarMap);

1050 CurrentBB = nullptr;

1051 CurrentBlockInfo = nullptr;

1052}

1053

1054void SExprBuilder::exitCFG(const CFGBlock *Last) {

1055 for (auto *Ph : IncompleteArgs) {

1058 }

1059

1060 CurrentArguments.clear();

1061 CurrentInstructions.clear();

1062 IncompleteArgs.clear();

1063}

1064

1065#ifndef NDEBUG

1066namespace {

1067

1068class TILPrinter :

1070

1071}

1072

1073namespace clang {

1075

1077 llvm::BumpPtrAllocator Bpa;

1081 TILPrinter::print(Scfg, llvm::errs());

1082}

1083

1084}

1085}

1086#endif

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the clang::Expr interface and subclasses for C++ expressions.

static const Decl * getCanonicalDecl(const Decl *D)

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines an enumeration for C++ overloaded operators.

static std::string toString(const clang::SanitizerSet &Sanitizers)

Produce a string containing comma-separated names of sanitizers in Sanitizers set.

Defines various enumerations that describe declaration and type specifiers.

static bool isIncompletePhi(const til::SExpr *E)

Definition ThreadSafetyCommon.cpp:64

SExprBuilder::CallingContext CallingContext

Definition ThreadSafetyCommon.cpp:102

static const ValueDecl * getValueDeclFromSExpr(const til::SExpr *E)

Definition ThreadSafetyCommon.cpp:414

static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD)

Definition ThreadSafetyCommon.cpp:771

static bool hasAnyPointerType(const til::SExpr *E)

Definition ThreadSafetyCommon.cpp:426

static const CXXMethodDecl * getFirstVirtualDecl(const CXXMethodDecl *D)

Definition ThreadSafetyCommon.cpp:437

static std::pair< StringRef, bool > classifyCapability(const TypeDecl &TD)

Definition ThreadSafetyCommon.cpp:75

static bool isCalleeArrow(const Expr *E)

Definition ThreadSafetyCommon.cpp:111

static constexpr std::pair< StringRef, bool > ClassifyCapabilityFallback

Definition ThreadSafetyCommon.cpp:70

C Language Family Type Representation.

Expr * getCond() const

getCond - Return the expression representing the condition for the ?

Expr * getTrueExpr() const

getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...

Expr * getFalseExpr() const

getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...

succ_iterator succ_begin()

unsigned pred_size() const

unsigned getBlockID() const

Stmt * getTerminatorCondition(bool StripParens=true)

unsigned succ_size() const

unsigned getNumBlockIDs() const

Returns the total number of BlockIDs allocated (which start at 0).

CXXMethodDecl * getMethodDecl() const

Retrieve the declaration of the called method.

Expr * getImplicitObjectArgument() const

Retrieve the implicit object argument for the member call.

Represents a static or instance method of a struct/union/class.

overridden_method_range overridden_methods() const

CXXMethodDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

OverloadedOperatorKind getOperator() const

Returns the kind of overloaded operator that this expression refers to.

Expr * getArg(unsigned Arg)

getArg - Return the specified argument.

FunctionDecl * getDirectCallee()

If the callee is a FunctionDecl, return it. Otherwise return null.

unsigned getNumArgs() const

getNumArgs - Return the number of actual arguments to this call.

Expr ** getArgs()

Retrieve the call arguments.

CastKind getCastKind() const

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

A reference to a declared variable, function, enum, etc.

const DeclGroupRef getDeclGroup() const

Decl - This represents one declaration (or definition), e.g.

ASTContext & getASTContext() const LLVM_READONLY

virtual Decl * getCanonicalDecl()

Retrieves the "canonical" declaration of the given declaration.

This represents one expression.

Expr * IgnoreParenCasts() LLVM_READONLY

Skip past any parentheses and casts which might surround this expression until reaching a fixed point...

Expr * IgnoreImplicit() LLVM_READONLY

Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.

ValueDecl * getMemberDecl() const

Retrieve the member declaration to which this expression refers.

This represents a decl that may have a name.

std::string getNameAsString() const

Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...

bool isCXXInstanceMember() const

Determine whether the given declaration is an instance member of a C++ class.

ObjCIvarDecl * getCanonicalDecl() override

Retrieves the canonical declaration of this field.

const Expr * getBase() const

A (possibly-)qualified type.

CompoundStmt * getSubStmt()

Stmt - This represents one statement.

StmtClass getStmtClass() const

Represents a declaration of a type.

RecordDecl * getAsRecordDecl() const

Retrieves the RecordDecl this type refers to.

bool isPointerType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isPointerOrReferenceType() const

const T * getAs() const

Member-template getAs'.

Expr * getSubExpr() const

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

Represents a variable declaration or definition.

VarDecl * getCanonicalDecl() override

Retrieves the "canonical" declaration of the given declaration.

bool isStaticLocal() const

Returns true if a variable with function scope is a static local variable.

const til::SExpr * sexpr() const

CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D, const Expr *DeclExp, til::SExpr *Self=nullptr)

Translate a clang expression in an attribute to a til::SExpr.

Definition ThreadSafetyCommon.cpp:125

til::SExpr * translate(const Stmt *S, CallingContext *Ctx)

Definition ThreadSafetyCommon.cpp:287

til::SExpr * lookupStmt(const Stmt *S)

Definition ThreadSafetyCommon.cpp:104

til::SCFG * buildCFG(CFGWalker &Walker)

Definition ThreadSafetyCommon.cpp:106

til::SExpr * translateVariable(const VarDecl *VD, CallingContext *Ctx)

Definition ThreadSafetyCommon.cpp:243

til::BasicBlock * lookupBlock(const CFGBlock *B)

const InstrArray & arguments() const

void reserveInstructions(unsigned Nins)

unsigned findPredecessorIndex(const BasicBlock *BB) const

Return the index of BB, or Predecessors.size if BB is not a predecessor.

A Literal pointer to an object allocated in memory.

const ValueDecl * clangDecl() const

Return the clang declaration of the variable for this Phi node, if any.

void setClangDecl(const ValueDecl *Cvd)

Set the clang variable associated with this Phi node.

const ValArray & values() const

An SCFG is a control-flow graph.

Base class for AST nodes in the typed intermediate language.

BasicBlock * block() const

Returns the block, if this is an instruction in a basic block, otherwise returns null.

void setValues(unsigned Sz, const T &C)

Placeholder for expressions that cannot be represented in the TIL.

Placeholder for a wildcard that matches any other expression.

bool isTrivial(const SExpr *E)

void simplifyIncompleteArg(til::Phi *Ph)

TIL_BinaryOpcode

Opcode for binary arithmetic operations.

void printSCFG(CFGWalker &Walker)

Definition ThreadSafetyCommon.cpp:1076

std::string getSourceLiteralString(const Expr *CE)

Definition ThreadSafetyCommon.cpp:41

The JSON file list parser is used to communicate input to InstallAPI.

OverloadedOperatorKind

Enumeration specifying the different kinds of C++ overloaded operators.

bool isa(CodeGen::Address addr)

@ Self

'self' clause, allowed on Compute and Combined Constructs, plus 'update'.

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

@ Result

The result type of a method or function.

const FunctionProtoType * T

CastKind

CastKind - The kind of operation required for a conversion.

U cast(CodeGen::Address addr)

Encapsulates the lexical context of a function call.

llvm::PointerUnion< const Expr *const *, til::SExpr * > FunArgs

const NamedDecl * AttrDecl

llvm::PointerUnion< const Expr *, til::SExpr * > SelfArg