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

1

2

3

4

5

6

7

8

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

13#include "llvm/Support/TimeProfiler.h"

14

16using llvm::isa_and_present;

17

21

25

29

30

31

32

33

36 if (const auto *VD = dyn_cast(DRE->getDecl())) {

38

40 }

41 return nullptr;

42}

43

45 llvm::TimeTraceScope TimeProfile("FactGenerator");

46 const CFG &Cfg = *AC.getCFG();

48

49

51 CurrentBlockFacts.clear();

52 EscapesInCurrentBlock.clear();

54 CurrentBlockFacts.append(PlaceholderLoanFacts.begin(),

55 PlaceholderLoanFacts.end());

56 for (unsigned I = 0; I < Block->size(); ++I) {

58 if (std::optional CS = Element.getAs<CFGStmt>())

59 Visit(CS->getStmt());

60 else if (std::optional LifetimeEnds =

62 handleLifetimeEnds(*LifetimeEnds);

63 }

64 CurrentBlockFacts.append(EscapesInCurrentBlock.begin(),

65 EscapesInCurrentBlock.end());

66 FactMgr.addBlockFacts(Block, CurrentBlockFacts);

67 }

68}

69

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

74 if (const Expr *InitExpr = VD->getInit())

75 killAndFlowOrigin(*VD, *InitExpr);

76}

77

79 handleUse(DRE);

80

81

82

83

84

85

86

87

88

89

92 OriginID ExprOID = FactMgr.getOriginMgr().getOrCreate(*DRE);

93 CurrentBlockFacts.push_back(

94 FactMgr.createFact<IssueFact>(L->getID(), ExprOID));

95 }

96 }

97}

98

101 handleGSLPointerConstruction(CCE);

102 return;

103 }

104}

105

107

108

110 isa_and_present(MCE->getCalleeDecl())) {

111

113 {MCE->getImplicitObjectArgument()},

114 true);

115 }

117

118

122

123 handleFunctionCall(MCE, Method, Args, false);

124 }

125}

126

129 {CE->getArgs(), CE->getNumArgs()});

130}

131

134

135

136 FactMgr.getOriginMgr().getOrCreate(*N);

137}

138

141 return;

142

143

144 killAndFlowOrigin(*ICE, *ICE->getSubExpr());

145}

146

148 if (UO->getOpcode() == UO_AddrOf) {

150

151

153 return;

154

155

156

157

158 killAndFlowOrigin(*UO, *SubExpr);

159 }

160}

161

165 OriginID OID = FactMgr.getOriginMgr().getOrCreate(*RetExpr);

166 EscapesInCurrentBlock.push_back(

168 }

169 }

170}

171

176

179

180

181 killAndFlowOrigin(*CO, *CO->getTrueExpr());

183 }

184}

185

187

188

190 handleAssignment(OCE->getArg(0), OCE->getArg(1));

191 return;

192 }

194 {OCE->getArgs(), OCE->getNumArgs()},

195 false);

196}

197

200

201

202 if (handleTestPoint(FCE))

203 return;

205 killAndFlowOrigin(*FCE, *FCE->getSubExpr());

206}

207

210 return;

211

212

214 killAndFlowOrigin(*ILE, *ILE->getInit(0));

215}

216

220 return;

221

222

223 killAndFlowOrigin(*MTE, *MTE->getSubExpr());

224}

225

226void FactsGenerator::handleLifetimeEnds(const CFGLifetimeEnds &LifetimeEnds) {

227

229 if (!LifetimeEndsVD)

230 return;

231

233 if (const auto *BL = dyn_cast(Loan)) {

234

235

236 if (BL->getAccessPath().D == LifetimeEndsVD)

239 }

240 }

241}

242

243void FactsGenerator::handleGSLPointerConstruction(const CXXConstructExpr *CCE) {

245 if (CCE->getNumArgs() != 1)

246 return;

248 killAndFlowOrigin(*CCE, *CCE->getArg(0));

249 else

250

251 handleFunctionCall(CCE, CCE->getConstructor(),

252 {CCE->getArgs(), CCE->getNumArgs()},

253 true);

254}

255

256

257

258

259

260void FactsGenerator::handleFunctionCall(const Expr *Call,

261 const FunctionDecl *FD,

262 ArrayRef<const Expr *> Args,

263 bool IsGslConstruction) {

264

266 return;

267 auto IsArgLifetimeBound = [FD](unsigned I) -> bool {

268 const ParmVarDecl *PVD = nullptr;

269 if (const auto *Method = dyn_cast(FD);

271 if (I == 0)

272

274 if ((I - 1) < Method->getNumParams())

275

276

277 PVD = Method->getParamDecl(I - 1);

278 } else if (I < FD->getNumParams())

279

280 PVD = FD->getParamDecl(I);

281 return PVD ? PVD->hasAttrclang::LifetimeBoundAttr() : false;

282 };

283 if (Args.empty())

284 return;

285 bool killedSrc = false;

286 for (unsigned I = 0; I < Args.size(); ++I)

287 if (IsGslConstruction || IsArgLifetimeBound(I)) {

288 if (!killedSrc) {

289 killedSrc = true;

290 killAndFlowOrigin(*Call, *Args[I]);

291 } else

292 flowOrigin(*Call, *Args[I]);

293 }

294}

295

296

297

298bool FactsGenerator::handleTestPoint(const CXXFunctionalCastExpr *FCE) {

299 if (!FCE->getType()->isVoidType())

300 return false;

301

302 const auto *SubExpr = FCE->getSubExpr()->IgnoreParenImpCasts();

303 if (const auto *SL = dyn_cast(SubExpr)) {

304 llvm::StringRef LiteralValue = SL->getString();

305 const std::string Prefix = "__lifetime_test_point_";

306

307 if (LiteralValue.starts_with(Prefix)) {

308 StringRef Annotation = LiteralValue.drop_front(Prefix.length());

309 CurrentBlockFacts.push_back(

310 FactMgr.createFact(Annotation));

311 return true;

312 }

313 }

314 return false;

315}

316

317void FactsGenerator::handleAssignment(const Expr *LHSExpr,

318 const Expr *RHSExpr) {

320 return;

321

322 if (const auto *DRE_LHS =

323 dyn_cast(LHSExpr->IgnoreParenImpCasts())) {

324 markUseAsWrite(DRE_LHS);

325 if (const auto *VD_LHS = dyn_cast(DRE_LHS->getDecl())) {

326

327

328 killAndFlowOrigin(*VD_LHS, *RHSExpr);

329 }

330 }

331}

332

333

334

335

336void FactsGenerator::handleUse(const DeclRefExpr *DRE) {

338 UseFact *UF = FactMgr.createFact(DRE, FactMgr.getOriginMgr());

339 CurrentBlockFacts.push_back(UF);

340 assert(!UseFacts.contains(DRE));

341 UseFacts[DRE] = UF;

342 }

343}

344

345void FactsGenerator::markUseAsWrite(const DeclRefExpr *DRE) {

347 return;

348 assert(UseFacts.contains(DRE));

349 UseFacts[DRE]->markAsWritten();

350}

351

352

353

354llvm::SmallVector<Fact *> FactsGenerator::issuePlaceholderLoans() {

355 const auto *FD = dyn_cast(AC.getDecl());

356 if (!FD)

357 return {};

358

359 llvm::SmallVector<Fact *> PlaceholderLoanFacts;

360 for (const ParmVarDecl *PVD : FD->parameters()) {

362 const PlaceholderLoan *L =

363 FactMgr.getLoanMgr().createLoan(PVD);

364 OriginID OID = FactMgr.getOriginMgr().getOrCreate(*PVD);

365 PlaceholderLoanFacts.push_back(

366 FactMgr.createFact(L->getID(), OID));

367 }

368 }

369 return PlaceholderLoanFacts;

370}

371

372}

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

static bool isAssignmentOp(Opcode Opc)

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

Represents a top-level expression in a basic block.

std::optional< T > getAs() const

Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...

Represents the point where the lifetime of an automatic object ends.

const Stmt * getTriggerStmt() const

const VarDecl * getVarDecl() const

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

Represents a call to a C++ constructor.

Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr....

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

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.

The null pointer literal (C++11 [lex.nullptr])

A call to an overloaded operator written using operator syntax.

static bool isAssignmentOp(OverloadedOperatorKind Opc)

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

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.

ConditionalOperator - The ?

Expr * getFalseExpr() const

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

Expr * getTrueExpr() const

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

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

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

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

This represents one expression.

ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...

Describes an C or C++ initializer list.

unsigned getNumInits() const

const Expr * getInit(unsigned Init) const

Represents a prvalue temporary that is written into memory so that a reference can bind to it.

Expr * getSubExpr() const

Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.

A (possibly-)qualified type.

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

RetTy Visit(PTR(Stmt) S, ParamTys... P)

SourceLocation getEndLoc() const LLVM_READONLY

bool isPointerOrReferenceType() const

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

Expr * getSubExpr() const

Represents a variable declaration or definition.

FactType * createFact(Args &&...args)

LoanManager & getLoanMgr()

void VisitDeclRefExpr(const DeclRefExpr *DRE)

Definition FactsGenerator.cpp:78

void VisitBinaryOperator(const BinaryOperator *BO)

Definition FactsGenerator.cpp:172

void VisitCallExpr(const CallExpr *CE)

Definition FactsGenerator.cpp:127

void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE)

Definition FactsGenerator.cpp:217

void VisitReturnStmt(const ReturnStmt *RS)

Definition FactsGenerator.cpp:162

void VisitCXXConstructExpr(const CXXConstructExpr *CCE)

Definition FactsGenerator.cpp:99

void VisitImplicitCastExpr(const ImplicitCastExpr *ICE)

Definition FactsGenerator.cpp:139

void run()

Definition FactsGenerator.cpp:44

void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE)

Definition FactsGenerator.cpp:198

void VisitInitListExpr(const InitListExpr *ILE)

Definition FactsGenerator.cpp:208

void VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *N)

Definition FactsGenerator.cpp:132

void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE)

Definition FactsGenerator.cpp:186

void VisitUnaryOperator(const UnaryOperator *UO)

Definition FactsGenerator.cpp:147

void VisitDeclStmt(const DeclStmt *DS)

Definition FactsGenerator.cpp:70

void VisitConditionalOperator(const ConditionalOperator *CO)

Definition FactsGenerator.cpp:177

void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE)

Definition FactsGenerator.cpp:106

llvm::ArrayRef< const Loan * > getLoans() const

LoanType * createLoan(Args &&...args)

An abstract base class for a single "Loan" which represents lending a storage in memory.

PathLoan represents lending a storage location that is visible within the function's scope (e....

static const PathLoan * createLoan(FactManager &FactMgr, const DeclRefExpr *DRE)

Creates a loan for the storage path of a given declaration reference.

Definition FactsGenerator.cpp:34

static bool hasOrigin(const Expr *E)

Definition FactsGenerator.cpp:22

utils::ID< struct OriginTag > OriginID

static bool isPointerType(QualType QT)

Definition FactsGenerator.cpp:18

bool isGslPointerType(QualType QT)

bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)

Represents the storage location being borrowed, e.g., a specific stack variable.