Skip to content

Commit 42c7d46

Browse files
committed
Identify DeclRefExpr as a use of an origin
1 parent 440c3fe commit 42c7d46

File tree

1 file changed

+50
-19
lines changed

1 file changed

+50
-19
lines changed

clang/lib/Analysis/LifetimeSafety.cpp

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ class ReturnOfOriginFact : public Fact {
317317
class UseFact : public Fact {
318318
OriginID UsedOrigin;
319319
const Expr *UseExpr;
320+
bool IsWritten = false;
320321

321322
public:
322323
static bool classof(const Fact *F) { return F->getKind() == Kind::Use; }
@@ -326,6 +327,8 @@ class UseFact : public Fact {
326327

327328
OriginID getUsedOrigin() const { return UsedOrigin; }
328329
const Expr *getUseExpr() const { return UseExpr; }
330+
void markAsWritten() { IsWritten = true; }
331+
bool isWritten() const { return IsWritten; }
329332

330333
void dump(llvm::raw_ostream &OS, const OriginManager &OM) const override {
331334
OS << "Use (";
@@ -428,6 +431,8 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
428431
addAssignOriginFact(*VD, *InitExpr);
429432
}
430433

434+
void VisitDeclRefExpr(const DeclRefExpr *DRE) { handleUse(DRE); }
435+
431436
void VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *N) {
432437
/// TODO: Handle nullptr expr as a special 'null' loan. Uninitialized
433438
/// pointers can use the same type of loan.
@@ -461,10 +466,6 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
461466
}
462467
}
463468
}
464-
} else if (UO->getOpcode() == UO_Deref) {
465-
// This is a pointer use, like '*p'.
466-
OriginID OID = FactMgr.getOriginMgr().get(*UO->getSubExpr());
467-
CurrentBlockFacts.push_back(FactMgr.createFact<UseFact>(OID, UO));
468469
}
469470
}
470471

@@ -479,20 +480,13 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
479480
}
480481

481482
void VisitBinaryOperator(const BinaryOperator *BO) {
482-
if (BO->isAssignmentOp()) {
483-
const Expr *LHSExpr = BO->getLHS();
484-
const Expr *RHSExpr = BO->getRHS();
485-
486-
// We are interested in assignments like `ptr1 = ptr2` or `ptr = &var`
487-
// LHS must be a pointer/reference type that can be an origin.
488-
// RHS must also represent an origin (either another pointer/ref or an
489-
// address-of).
490-
if (const auto *DRE_LHS = dyn_cast<DeclRefExpr>(LHSExpr))
491-
if (const auto *VD_LHS =
492-
dyn_cast<ValueDecl>(DRE_LHS->getDecl()->getCanonicalDecl());
493-
VD_LHS && hasOrigin(VD_LHS->getType()))
494-
addAssignOriginFact(*VD_LHS, *RHSExpr);
495-
}
483+
if (BO->isAssignmentOp())
484+
handleAssignment(BO->getLHS(), BO->getRHS());
485+
}
486+
487+
void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE) {
488+
if (OCE->isAssignmentOp() && OCE->getNumArgs() == 2)
489+
handleAssignment(OCE->getArg(0), OCE->getArg(1));
496490
}
497491

498492
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE) {
@@ -559,9 +553,45 @@ class FactGeneratorVisitor : public ConstStmtVisitor<FactGeneratorVisitor> {
559553
return false;
560554
}
561555

556+
void handleAssignment(const Expr *LHSExpr, const Expr *RHSExpr) {
557+
// Find the underlying variable declaration for the left-hand side.
558+
if (const auto *DRE_LHS =
559+
dyn_cast<DeclRefExpr>(LHSExpr->IgnoreParenImpCasts())) {
560+
markUseAsWrite(DRE_LHS);
561+
if (const auto *VD_LHS = dyn_cast<ValueDecl>(DRE_LHS->getDecl()))
562+
if (hasOrigin(VD_LHS->getType()))
563+
// We are interested in assignments like `ptr1 = ptr2` or `ptr = &var`
564+
// LHS must be a pointer/reference type that can be an origin.
565+
// RHS must also represent an origin (either another pointer/ref or an
566+
// address-of).
567+
addAssignOriginFact(*VD_LHS, *RHSExpr);
568+
}
569+
}
570+
571+
// A DeclRefExpr is a use of the referenced decl. It is checked for
572+
// use-after-free unless it is being written to (e.g. on the left-hand side
573+
// of an assignment).
574+
void handleUse(const DeclRefExpr *DRE) {
575+
const auto *VD = dyn_cast<ValueDecl>(DRE->getDecl());
576+
if (VD && hasOrigin(VD->getType())) {
577+
OriginID OID = FactMgr.getOriginMgr().get(*VD);
578+
UseFact *UF = FactMgr.createFact<UseFact>(OID, DRE);
579+
CurrentBlockFacts.push_back(UF);
580+
assert(!UseFacts.contains(DRE));
581+
UseFacts[DRE] = UF;
582+
}
583+
}
584+
585+
void markUseAsWrite(const DeclRefExpr *DRE) {
586+
assert(UseFacts.contains(DRE));
587+
UseFacts[DRE]->markAsWritten();
588+
}
589+
562590
FactManager &FactMgr;
563591
const CFGBlock *CurrentBlock = nullptr;
564592
llvm::SmallVector<Fact *> CurrentBlockFacts;
593+
// Doc: Why do we need this ?
594+
llvm::DenseMap<const DeclRefExpr *, UseFact *> UseFacts;
565595
};
566596

567597
class FactGenerator : public RecursiveASTVisitor<FactGenerator> {
@@ -1076,7 +1106,8 @@ class LifetimeChecker {
10761106
/// graph. It determines if the loans held by the used origin have expired
10771107
/// at the point of use.
10781108
void checkUse(const UseFact *UF) {
1079-
1109+
if (UF->isWritten())
1110+
return;
10801111
OriginID O = UF->getUsedOrigin();
10811112

10821113
// Get the set of loans that the origin might hold at this program point.

0 commit comments

Comments
 (0)