@@ -52,41 +52,105 @@ struct Origin {
5252 }
5353};
5454
55+ // / A tree of origins representing levels of indirection for pointer-like types.
56+ // /
57+ // / Each node in the tree contains an OriginID representing a level of
58+ // / indirection. The tree structure captures the multi-level nature of
59+ // / pointer and reference types in the lifetime analysis.
60+ // /
61+ // / Examples:
62+ // / - For `int& x`, the tree has depth 2:
63+ // / * Root: origin for the reference storage itself (the lvalue `x`)
64+ // / * Pointee: origin for what `x` refers to
65+ // /
66+ // / - For `int* p`, the tree has depth 2:
67+ // / * Root: origin for the pointer variable `p`
68+ // / * Pointee: origin for what `p` points to
69+ // /
70+ // / - For `View v` (where View is gsl::Pointer), the tree has depth 2:
71+ // / * Root: origin for the view object itself
72+ // / * Pointee: origin for what the view refers to
73+ // /
74+ // / - For `int** pp`, the tree has depth 3:
75+ // / * Root: origin for `pp` itself
76+ // / * Pointee: origin for `*pp` (what `pp` points to)
77+ // / * Pointee->Pointee: origin for `**pp` (what `*pp` points to)
78+ // /
79+ // / The tree structure enables the analysis to track how loans flow through
80+ // / different levels of indirection when assignments and dereferences occur.
81+ struct OriginTree {
82+ OriginID OID;
83+ OriginTree *Pointee = nullptr ;
84+
85+ OriginTree (OriginID OID) : OID(OID) {}
86+
87+ size_t getDepth () const {
88+ size_t Depth = 1 ;
89+ const OriginTree *T = this ;
90+ while (T->Pointee ) {
91+ T = T->Pointee ;
92+ Depth++;
93+ }
94+ return Depth;
95+ }
96+ };
97+
98+ bool isPointerLikeType (QualType QT);
99+
55100// / Manages the creation, storage, and retrieval of origins for pointer-like
56101// / variables and expressions.
57102class OriginManager {
58103public:
59- OriginManager () = default ;
60-
61- Origin &addOrigin (OriginID ID, const clang::ValueDecl &D);
62- Origin &addOrigin (OriginID ID, const clang::Expr &E);
63-
64- // TODO: Mark this method as const once we remove the call to getOrCreate.
65- OriginID get (const Expr &E);
66-
67- OriginID get (const ValueDecl &D);
68-
69- OriginID getOrCreate (const Expr &E);
104+ // / Gets or creates the OriginTree for a given ValueDecl.
105+ // /
106+ // / Creates a tree structure mirroring the levels of indirection in the
107+ // / declaration's type (e.g., `int** p` creates depth 3).
108+ // /
109+ // / \returns The OriginTree, or nullptr if the type is not pointer-like.
110+ OriginTree *getOrCreateTree (const ValueDecl *D);
111+
112+ // / Gets or creates the OriginTree for a given Expr.
113+ // /
114+ // / Creates a tree based on the expression's type and value category:
115+ // / - Lvalues get an implicit reference level (modeling addressability)
116+ // / - Rvalues of non-pointer type return nullptr (no trackable origin)
117+ // / - DeclRefExpr may reuse the underlying declaration's tree
118+ // /
119+ // / \returns The OriginTree, or nullptr for non-pointer rvalues.
120+ OriginTree *getOrCreateTree (const Expr *E, ASTContext &Ctx);
70121
71122 const Origin &getOrigin (OriginID ID) const ;
72123
73124 llvm::ArrayRef<Origin> getOrigins () const { return AllOrigins; }
74125
75- OriginID getOrCreate (const ValueDecl &D);
76-
77126 unsigned getNumOrigins () const { return NextOriginID.Value ; }
78127
79128 void dump (OriginID OID, llvm::raw_ostream &OS) const ;
80129
81130private:
82131 OriginID getNextOriginID () { return NextOriginID++; }
83132
133+ OriginTree *createNode (const ValueDecl *D) {
134+ OriginID NewID = getNextOriginID ();
135+ AllOrigins.emplace_back (NewID, D);
136+ return new (TreeAllocator.Allocate <OriginTree>()) OriginTree (NewID);
137+ }
138+ OriginTree *createNode (const Expr* E) {
139+ OriginID NewID = getNextOriginID ();
140+ AllOrigins.emplace_back (NewID, E);
141+ return new (TreeAllocator.Allocate <OriginTree>()) OriginTree (NewID);
142+ }
143+
144+ template <typename T>
145+ OriginTree *buildTreeForType (QualType QT, const T *Node);
146+
84147 OriginID NextOriginID{0 };
85- // / TODO(opt): Profile and evaluate the usefullness of small buffer
148+ // / TODO(opt): Profile and evaluate the usefulness of small buffer
86149 // / optimisation.
87150 llvm::SmallVector<Origin> AllOrigins;
88- llvm::DenseMap<const clang::ValueDecl *, OriginID> DeclToOriginID;
89- llvm::DenseMap<const clang::Expr *, OriginID> ExprToOriginID;
151+ llvm::BumpPtrAllocator TreeAllocator;
152+ llvm::DenseMap<const clang::ValueDecl *, OriginTree *> DeclToTree;
153+ llvm::DenseMap<const clang::Expr *, OriginTree *> ExprToTree;
90154};
91155} // namespace clang::lifetimes::internal
92156
0 commit comments