clang: include/clang/Analysis/Analyses/ThreadSafetyCommon.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H

22#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H

23

32#include "llvm/ADT/DenseMap.h"

33#include "llvm/ADT/PointerIntPair.h"

34#include "llvm/ADT/PointerUnion.h"

35#include "llvm/ADT/SmallVector.h"

36#include "llvm/Support/Casting.h"

37#include

38#include

39#include

40#include

41

43

44class AbstractConditionalOperator;

45class ArraySubscriptExpr;

46class BinaryOperator;

47class CallExpr;

48class CastExpr;

49class CXXDestructorDecl;

50class CXXMemberCallExpr;

51class CXXOperatorCallExpr;

52class CXXThisExpr;

53class DeclRefExpr;

54class DeclStmt;

55class Expr;

56class MemberExpr;

57class Stmt;

58class UnaryOperator;

59

60namespace threadSafety {

61

62

63namespace sx {

64

67}

68

70

71

72

73 if (isatil::Wildcard(E1))

74 return isatil::Wildcard(E2);

75 if (isatil::Wildcard(E2))

76 return isatil::Wildcard(E1);

77

79}

80

82 const auto *PE1 = dyn_cast_or_nulltil::Project(E1);

83 if (!PE1)

84 return false;

85 const auto *PE2 = dyn_cast_or_nulltil::Project(E2);

86 if (!PE2)

87 return false;

88 return PE1->clangDecl() == PE2->clangDecl();

89}

90

92 std::stringstream ss;

94 return ss.str();

95}

96

97}

98

99

100

101

103

105

106

107 void enterCFGBlock(const CFGBlock *B) {}

108

109

110 bool visitPredecessors() { return true; }

111

112

113 void handlePredecessor(const CFGBlock *Pred) {}

114

115

116 void handlePredecessorBackEdge(const CFGBlock *Pred) {}

117

118

119 void enterCFGBlockBody(const CFGBlock *B) {}

120

121

122 void handleStatement(const Stmt *S) {}

123

124

126

127

128 void exitCFGBlockBody(const CFGBlock *B) {}

129

130

131 bool visitSuccessors() { return true; }

132

133

134 void handleSuccessor(const CFGBlock *Succ) {}

135

136

137 void handleSuccessorBackEdge(const CFGBlock *Succ) {}

138

139

140 void exitCFGBlock(const CFGBlock *B) {}

141

142

144};

145

146

148public:

150

151

152

154 ACtx = ∾

155 CFGraph = AC.getCFG();

156 if (!CFGraph)

157 return false;

158

159

160 if (!isa_and_nonnull(AC.getDecl()))

161 return false;

162

164 if (!SortedGraph)

165 return false;

166

167 return true;

168 }

169

170

171 template

174

176

177 for (const auto *CurrBlock : *SortedGraph) {

178 VisitedBlocks.insert(CurrBlock);

179

180 V.enterCFGBlock(CurrBlock);

181

182

183 if (V.visitPredecessors()) {

185

187 SE = CurrBlock->pred_end();

188 SI != SE; ++SI) {

189 if (*SI == nullptr)

190 continue;

191

192 if (!VisitedBlocks.alreadySet(*SI)) {

193 BackEdges.push_back(*SI);

194 continue;

195 }

196 V.handlePredecessor(*SI);

197 }

198

199 for (auto *Blk : BackEdges)

200 V.handlePredecessorBackEdge(Blk);

201 }

202

203 V.enterCFGBlockBody(CurrBlock);

204

205

206 for (const auto &BI : *CurrBlock) {

207 switch (BI.getKind()) {

210 break;

211

217 V.handleDestructorCall(VD, DD);

218 break;

219 }

220 default:

221 break;

222 }

223 }

224

225 V.exitCFGBlockBody(CurrBlock);

226

227

228 if (V.visitSuccessors()) {

230

231

233 SE = CurrBlock->succ_end();

234 SI != SE; ++SI) {

235 if (*SI == nullptr)

236 continue;

237

238 if (!VisitedBlocks.alreadySet(*SI)) {

239 ForwardEdges.push_back(*SI);

240 continue;

241 }

242 V.handleSuccessorBackEdge(*SI);

243 }

244

245 for (auto *Blk : ForwardEdges)

246 V.handleSuccessor(Blk);

247 }

248

249 V.exitCFGBlock(CurrBlock);

250 }

251 V.exitCFG(&CFGraph->getExit());

252 }

253

256

258 return dyn_cast(ACtx->getDecl());

259 }

260

262

263private:

264 CFG *CFGraph = nullptr;

267};

268

269

270

271

273private:

274

275 llvm::PointerIntPair<const til::SExpr *, 1, bool> CapExpr;

276

277

278 StringRef CapKind;

279

280public:

283 : CapExpr(E, Neg), CapKind(Kind) {}

284

285

287

289 StringRef getKind() const { return CapKind; }

290 bool negative() const { return CapExpr.getInt(); }

291

293 return CapabilityExpr(CapExpr.getPointer(), CapKind, !CapExpr.getInt());

294 }

295

299 }

300

304 }

305

308 }

309

313 }

314

317 return nullptr;

318 if (const auto *P = dyn_casttil::Project(sexpr()))

319 return P->clangDecl();

320 if (const auto *P = dyn_casttil::LiteralPtr(sexpr()))

321 return P->clangDecl();

322 return nullptr;

323 }

324

329 }

330

332

333 bool isInvalid() const { return isa_and_nonnulltil::Undefined(sexpr()); }

334

335 bool isUniversal() const { return isa_and_nonnulltil::Wildcard(sexpr()); }

336};

337

338

340public:

341

342

343

344

345

346

347

348

349

351

353

354

356

357

358 llvm::PointerUnion<const Expr *, til::SExpr *> SelfArg = nullptr;

359

360

362

363

364 llvm::PointerUnion<const Expr *const *, til::SExpr *> FunArgs = nullptr;

365

366

368

371 };

372

374

377 }

378

379

380

382 const Expr *DeclExp,

384

386

387

389

390

391 std::pair<til::LiteralPtr *, StringRef>

393

394

395

396

399

401

404 }

405

408

409private:

410

412

420 const Expr *SelfE = nullptr);

438 til::SExpr *translateAbstractConditionalOperator(

440

442

443

444 using StatementMap = llvm::DenseMap<const Stmt *, til::SExpr *>;

445

446

447 using LVarIndexMap = llvm::DenseMap<const ValueDecl *, unsigned>;

448

449

450 using NameVarPair = std::pair<const ValueDecl *, til::SExpr *>;

452

453 struct BlockInfo {

455 bool HasBackEdges = false;

456

457

458 unsigned UnprocessedSuccessors = 0;

459

460

461 unsigned ProcessedPredecessors = 0;

462

463 BlockInfo() = default;

464 BlockInfo(BlockInfo &&) = default;

465 BlockInfo &operator=(BlockInfo &&) = default;

466 };

467

469 void enterCFGBlock(const CFGBlock *B);

470 bool visitPredecessors() { return true; }

471 void handlePredecessor(const CFGBlock *Pred);

472 void handlePredecessorBackEdge(const CFGBlock *Pred);

473 void enterCFGBlockBody(const CFGBlock *B);

474 void handleStatement(const Stmt *S);

476 void exitCFGBlockBody(const CFGBlock *B);

477 bool visitSuccessors() { return true; }

478 void handleSuccessor(const CFGBlock *Succ);

479 void handleSuccessorBackEdge(const CFGBlock *Succ);

480 void exitCFGBlock(const CFGBlock *B);

481 void exitCFG(const CFGBlock *Last);

482

483 void insertStmt(const Stmt *S, til::SExpr *E) {

484 SMap.insert(std::make_pair(S, E));

485 }

486

487 til::SExpr *addStatement(til::SExpr *E, const Stmt *S,

488 const ValueDecl *VD = nullptr);

489 til::SExpr *lookupVarDecl(const ValueDecl *VD);

490 til::SExpr *addVarDecl(const ValueDecl *VD, til::SExpr *E);

491 til::SExpr *updateVarDecl(const ValueDecl *VD, til::SExpr *E);

492

493 void makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E);

494 void mergeEntryMap(LVarDefinitionMap Map);

495 void mergeEntryMapBackEdge();

496 void mergePhiNodesBackEdge(const CFGBlock *Blk);

497

498private:

499

500

501 static const bool CapabilityExprMode = true;

502

503 til::MemRegionRef Arena;

504

505

506 til::Variable *SelfVar = nullptr;

507

508 til::SCFG *Scfg = nullptr;

509

510

511 StatementMap SMap;

512

513

514 LVarIndexMap LVarIdxMap;

515

516

517 std::vector<til::BasicBlock *> BlockMap;

518

519

520 std::vector BBInfo;

521

522 LVarDefinitionMap CurrentLVarMap;

523 std::vector<til::Phi *> CurrentArguments;

524 std::vector<til::SExpr *> CurrentInstructions;

525 std::vector<til::Phi *> IncompleteArgs;

526 til::BasicBlock *CurrentBB = nullptr;

527 BlockInfo *CurrentBlockInfo = nullptr;

528};

529

530#ifndef NDEBUG

531

532void printSCFG(CFGWalker &Walker);

533#endif

534

535}

536}

537

538#endif

This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...

llvm::DenseMap< const Stmt *, CFGBlock * > SMap

enum clang::sema::@1725::IndirectLocalPathEntry::EntryKind Kind

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

SExprBuilder::CallingContext CallingContext

AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...

AnalysisDeclContext contains the context data for the function, method or block under analysis.

const Decl * getDecl() const

ASTContext & getASTContext() const

ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.

A builtin binary operation expression such as "x + y" or "x <= y".

Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...

const VarDecl * getVarDecl() const

Represents a single basic block in a source-level CFG.

AdjacentBlocks::const_iterator const_pred_iterator

unsigned getBlockID() const

AdjacentBlocks::const_iterator const_succ_iterator

T castAs() const

Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.

const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const

const Stmt * getStmt() const

Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.

Represents a C++ destructor within a class.

Represents a call to a member function that may be written either with member call syntax (e....

A call to an overloaded operator written using operator syntax.

Represents the this expression in C++.

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...

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

DeclStmt - Adaptor class for mixing declarations with statements and expressions.

This represents one expression.

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

This represents a decl that may have a name.

ObjCIvarRefExpr - A reference to an ObjC instance variable.

Implements a set of CFGBlocks using a BitVector.

std::pair< std::nullopt_t, bool > insert(const CFGBlock *Block)

Set the bit associated with a particular CFGBlock.

bool alreadySet(const CFGBlock *Block)

Check if the bit for a CFGBlock has been already set.

Stmt - This represents one statement.

UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...

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.

const PostOrderCFGView * getSortedGraph() const

const NamedDecl * getDecl() const

bool init(AnalysisDeclContext &AC)

const CFG * getGraph() const

CapabilityExpr operator!() const

bool shouldIgnore() const

CapabilityExpr(const til::SExpr *E, StringRef Kind, bool Neg)

bool matches(const CapabilityExpr &other) const

bool partiallyMatches(const CapabilityExpr &other) const

CapabilityExpr(const til::SExpr *, T, bool)=delete

bool equals(const CapabilityExpr &other) const

const til::SExpr * sexpr() const

bool matchesUniv(const CapabilityExpr &CapE) const

std::string toString() const

const ValueDecl * valueDecl() const

StringRef getKind() const

const til::SCFG * getCFG() 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.

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

SExprBuilder(til::MemRegionRef A)

std::pair< til::LiteralPtr *, StringRef > createThisPlaceholder(const Expr *Exp)

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

til::SCFG * buildCFG(CFGWalker &Walker)

til::LiteralPtr * createVariable(const VarDecl *VD)

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

A basic block is part of an SCFG.

static bool compareExprs(const SExpr *E1, const SExpr *E2)

A Literal pointer to an object allocated in memory.

static bool compareExprs(const SExpr *E1, const SExpr *E2)

static void print(const SExpr *E, std::ostream &SS)

An SCFG is a control-flow graph.

Base class for AST nodes in the typed intermediate language.

@ VK_SFun

SFunction (self) parameter.

void setKind(VariableKind K)

bool matches(const til::SExpr *E1, const til::SExpr *E2)

bool equals(const til::SExpr *E1, const til::SExpr *E2)

std::string toString(const til::SExpr *E)

bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2)

TIL_BinaryOpcode

Opcode for binary arithmetic operations.

void printSCFG(CFGWalker &Walker)

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

@ Self

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

const FunctionProtoType * T

Encapsulates the lexical context of a function call.

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

const NamedDecl * AttrDecl

CallingContext(CallingContext *P, const NamedDecl *D=nullptr)

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