[clang] [LifetimeSafety] Trace assignment history for use-after-scope errors (PR #188467)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 26 04:28:00 PDT 2026
================
@@ -219,6 +227,194 @@ class LifetimeChecker {
}
}
+ std::optional<llvm::SmallVector<AssignmentPair>>
+ getAliasListInMultiBlock(const CFGBlock *StartBlock, const LoanID EndLoanID,
+ OriginID *StartOID) {
+ const ValueDecl *LastDestDecl = nullptr;
+ llvm::SmallVector<const CFGBlock *> PendingBlocks;
+ std::optional<AssignmentPair> StartStmt = std::nullopt;
+ std::optional<AssignmentPair> EndStmt = std::nullopt;
+ std::optional<OriginID> LastOriginID = std::nullopt;
+ llvm::SmallPtrSet<const CFGBlock *, 32> VistedBlocks;
+ llvm::DenseMap<AssignmentPair, AssignmentPair> VistedExprs;
+
+ const auto AliasStmtFilter = [&VistedExprs](const AssignmentPair StartStmt,
+ const AssignmentPair EndStmt) {
+ llvm::SmallVector<AssignmentPair> AliasStmts;
+ for (auto Stmt = StartStmt; Stmt != EndStmt;
+ Stmt = VistedExprs.at(Stmt)) {
+ AliasStmts.push_back(Stmt);
+ }
+ AliasStmts.push_back(EndStmt);
+ return AliasStmts;
+ };
+
+ PendingBlocks.push_back(StartBlock);
+
+ for (size_t i = 0; i < PendingBlocks.size(); ++i) {
+ const CFGBlock *CurrBlock = PendingBlocks[i];
+
+ const auto [BlockAliasList, Success, CurrLastDestDecl, CurrLastOriginID] =
+ getAliasListCore(CurrBlock, EndLoanID, StartOID, LastDestDecl,
+ LastOriginID);
+ if (CurrLastDestDecl)
+ LastDestDecl = CurrLastDestDecl;
+ if (CurrLastOriginID.has_value())
+ LastOriginID = CurrLastOriginID;
+
+ if (!BlockAliasList.empty()) {
+ if (VistedExprs.empty()) {
+ StartStmt = BlockAliasList[0];
+ }
+
+ for (size_t i = 0; i < BlockAliasList.size() - 1; ++i) {
+ VistedExprs.insert({BlockAliasList[i], BlockAliasList[i + 1]});
+ }
+
+ if (EndStmt.has_value())
+ VistedExprs.insert({EndStmt.value(), BlockAliasList[0]});
+
+ EndStmt = BlockAliasList[BlockAliasList.size() - 1];
+ }
+
+ if (Success && StartStmt.has_value() && EndStmt.has_value()) {
+ return AliasStmtFilter(StartStmt.value(), EndStmt.value());
+ }
+
+ for (const auto Block : CurrBlock->preds()) {
+ if (Block && VistedBlocks.insert(Block).second)
+ PendingBlocks.push_back(Block);
+ }
+
+ if (VistedBlocks.size() >= 32 && StartStmt.has_value() &&
+ EndStmt.has_value()) {
+ return AliasStmtFilter(StartStmt.value(), EndStmt.value());
+ }
+ }
+
+ if (StartStmt.has_value() && EndStmt.has_value()) {
+ return AliasStmtFilter(StartStmt.value(), EndStmt.value());
+ }
+
+ return std::nullopt;
+ }
+
+ std::optional<OriginSrcExpr> GetPureSrcExpr(const Expr *TargetExpr) {
+ if (!TargetExpr)
+ return std::nullopt;
+ const Expr *SExpr = TargetExpr->IgnoreParenCasts();
+ if (!SExpr)
+ return std::nullopt;
+
+ if (const auto *SDRExpr = llvm::dyn_cast<DeclRefExpr>(SExpr)) {
+ return SDRExpr;
+ }
+ if (const auto *STMExpr = llvm::dyn_cast<CXXTemporaryObjectExpr>(SExpr)) {
+ return STMExpr;
+ }
+ if (const auto *SCExpr = llvm::dyn_cast<CallExpr>(SExpr)) {
+ return SCExpr;
+ }
+
+ if (const auto *SCCExpr = llvm::dyn_cast<CXXConstructExpr>(SExpr)) {
+ if (SCCExpr->getNumArgs() > 0)
+ return GetPureSrcExpr(SCCExpr->getArg(0));
----------------
suoyuan666 wrote:
The implementation here is a bit unrefined, and I haven't found a better workaround yet.
My intention was to bypass this part because I don't believe the assignment statements we're searching for should involve explicit constructors; I only intend to match implicit ones here.
https://github.com/llvm/llvm-project/pull/188467
More information about the cfe-commits
mailing list