https://github.com/aeft updated https://github.com/llvm/llvm-project/pull/201511
>From a60bad77589bdc28f239a0d6da890c845a701a46 Mon Sep 17 00:00:00 2001 From: Zhijie Wang <[email protected]> Date: Wed, 3 Jun 2026 20:58:24 -0700 Subject: [PATCH] [LifetimeSafety][NFC] Collect accessed fields in a unified pre-scan --- .../Analyses/LifetimeSafety/Origins.h | 19 +++++++++--- clang/lib/Analysis/LifetimeSafety/Origins.cpp | 30 ++++++++++++++----- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h index d39e402ce9334..eadac4fce9975 100644 --- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h +++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/Origins.h @@ -21,6 +21,7 @@ #include "clang/Analysis/Analyses/LifetimeSafety/LifetimeStats.h" #include "clang/Analysis/Analyses/LifetimeSafety/Utils.h" #include "clang/Analysis/AnalysisDeclContext.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/raw_ostream.h" namespace clang::lifetimes::internal { @@ -203,6 +204,10 @@ class OriginManager { bool hasOrigins(QualType QT) const; bool hasOrigins(const Expr *E) const; + bool isAccessedField(const FieldDecl *FD) const { + return AccessedFields.contains(FD); + } + void dump(OriginID OID, llvm::raw_ostream &OS) const; /// Collects statistics about expressions that lack associated origins. @@ -221,10 +226,13 @@ class OriginManager { void initializeThisOrigins(const Decl *D); - /// Pre-scans the function body (and constructor init lists) to discover - /// return types of lifetime-annotated calls (currently - /// [[clang::lifetimebound]]), registering them for origin tracking. - void collectLifetimeAnnotatedOriginTypes(const AnalysisDeclContext &AC); + /// Pre-scans the function body (and constructor init lists) to discover: + /// + /// 1. Return types of lifetime-annotated calls (currently + /// [[clang::lifetimebound]]), registering them for origin tracking. + /// + /// 2. The fields it accesses; the rest are excluded from origin tracking. + void runPreScan(const AnalysisDeclContext &AC); void registerLifetimeAnnotatedOriginType(QualType QT); ASTContext &AST; @@ -240,6 +248,9 @@ class OriginManager { /// because of lifetime annotations (currently [[clang::lifetimebound]]) on /// functions that return them. llvm::DenseSet<const Type *> LifetimeAnnotatedOriginTypes; + /// Fields accessed in the function body (or constructor init lists). + /// Fields outside this set are excluded from origin tracking. + llvm::SmallPtrSet<const FieldDecl *, 8> AccessedFields; }; } // namespace clang::lifetimes::internal diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp b/clang/lib/Analysis/LifetimeSafety/Origins.cpp index 8c659ea770461..8b52df2858484 100644 --- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp @@ -51,8 +51,7 @@ class MissingOriginCollector LifetimeSafetyStats &LSStats; }; -class LifetimeAnnotatedOriginTypeCollector - : public RecursiveASTVisitor<LifetimeAnnotatedOriginTypeCollector> { +class PreScanCollector : public RecursiveASTVisitor<PreScanCollector> { public: bool VisitCallExpr(const CallExpr *CE) { // Indirect calls (e.g., function pointers) are skipped because lifetime @@ -67,6 +66,12 @@ class LifetimeAnnotatedOriginTypeCollector return true; } + bool VisitMemberExpr(const MemberExpr *ME) { + if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) + AccessedFields.insert(FD); + return true; + } + bool shouldVisitLambdaBody() const { return false; } bool shouldVisitTemplateInstantiations() const { return true; } @@ -74,8 +79,13 @@ class LifetimeAnnotatedOriginTypeCollector return CollectedTypes; } + const llvm::SmallPtrSet<const FieldDecl *, 8> &getAccessedFields() const { + return AccessedFields; + } + private: llvm::SmallVector<QualType> CollectedTypes; + llvm::SmallPtrSet<const FieldDecl *, 8> AccessedFields; void collect(const FunctionDecl *FD, QualType RetType) { if (!FD) @@ -159,7 +169,7 @@ bool doesDeclHaveStorage(const ValueDecl *D) { OriginManager::OriginManager(const AnalysisDeclContext &AC) : AST(AC.getASTContext()) { - collectLifetimeAnnotatedOriginTypes(AC); + runPreScan(AC); initializeThisOrigins(AC.getDecl()); } @@ -312,16 +322,20 @@ void OriginManager::collectMissingOrigins(Stmt &FunctionBody, Collector.TraverseStmt(const_cast<Stmt *>(&FunctionBody)); } -void OriginManager::collectLifetimeAnnotatedOriginTypes( - const AnalysisDeclContext &AC) { - LifetimeAnnotatedOriginTypeCollector Collector; +void OriginManager::runPreScan(const AnalysisDeclContext &AC) { + PreScanCollector Collector; if (Stmt *Body = AC.getBody()) Collector.TraverseStmt(Body); if (const auto *CD = dyn_cast<CXXConstructorDecl>(AC.getDecl())) - for (const auto *Init : CD->inits()) - Collector.TraverseStmt(Init->getInit()); + for (const auto *Init : CD->inits()) { + if (const FieldDecl *FD = Init->getAnyMember()) + AccessedFields.insert(FD); + if (Expr *InitE = Init->getInit()) + Collector.TraverseStmt(InitE); + } for (QualType QT : Collector.getCollectedTypes()) registerLifetimeAnnotatedOriginType(QT); + AccessedFields.insert_range(Collector.getAccessedFields()); } void OriginManager::registerLifetimeAnnotatedOriginType(QualType QT) { _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
