================
@@ -52,41 +62,118 @@ struct Origin {
}
};
-/// Manages the creation, storage, and retrieval of origins for pointer-like
-/// variables and expressions.
-class OriginManager {
+/// A list of origins representing levels of indirection for pointer-like
types.
+///
+/// Each node in the list contains an OriginID representing a level of
+/// indirection. The list structure captures the multi-level nature of
+/// pointer and reference types in the lifetime analysis.
+///
+/// Examples:
+/// - For `int& x`, the list has size 2:
+/// * Root: origin for the reference storage itself (the lvalue `x`)
+/// * Pointee: origin for what `x` refers to
+///
+/// - For `int* p`, the list has size 2:
+/// * Root: origin for the pointer variable `p`
+/// * Pointee: origin for what `p` points to
+///
+/// - For `View v` (where View is gsl::Pointer), the list has size 2:
+/// * Root: origin for the view object itself
+/// * Pointee: origin for what the view refers to
+///
+/// - For `int** pp`, the list has size 3:
+/// * Root: origin for `pp` itself
+/// * Pointee: origin for `*pp` (what `pp` points to)
+/// * Pointee->Pointee: origin for `**pp` (what `*pp` points to)
+///
+/// The list structure enables the analysis to track how loans flow through
+/// different levels of indirection when assignments and dereferences occur.
+class OriginList {
public:
- OriginManager() = default;
+ OriginList(OriginID OID) : OuterOID(OID) {}
+
+ OriginList *peelOuterOrigin() { return InnerList; }
+ OriginID getOuterOriginID() const { return OuterOID; }
- Origin &addOrigin(OriginID ID, const clang::ValueDecl &D);
- Origin &addOrigin(OriginID ID, const clang::Expr &E);
+ void setInnerOriginList(OriginList *Inner) { InnerList = Inner; }
- // TODO: Mark this method as const once we remove the call to getOrCreate.
- OriginID get(const Expr &E);
+ size_t getLength() const {
+ size_t Length = 1;
+ const OriginList *T = this;
+ while (T->InnerList) {
+ T = T->InnerList;
+ Length++;
+ }
+ return Length;
+ }
- OriginID get(const ValueDecl &D);
+private:
+ OriginID OuterOID;
+ OriginList *InnerList = nullptr;
+};
- OriginID getOrCreate(const Expr &E);
+bool hasOrigins(QualType QT);
+bool hasOrigins(const Expr *E);
+bool doesDeclHaveStorage(const ValueDecl *D);
+
+/// Manages the creation, storage, and retrieval of origins for pointer-like
+/// variables and expressions.
+class OriginManager {
+public:
+ explicit OriginManager(ASTContext &AST) : AST(AST) {}
+
+ /// Gets or creates the OriginList for a given ValueDecl.
+ ///
+ /// Creates a list structure mirroring the levels of indirection in the
+ /// declaration's type (e.g., `int** p` creates list of size 2).
+ ///
+ /// \returns The OriginList, or nullptr if the type is not pointer-like.
+ OriginList *getOrCreateList(const ValueDecl *D);
+
+ /// Gets or creates the OriginList for a given Expr.
+ ///
+ /// Creates a list based on the expression's type and value category:
+ /// - Lvalues get an implicit reference level (modeling addressability)
+ /// - Rvalues of non-pointer type return nullptr (no trackable origin)
+ /// - DeclRefExpr may reuse the underlying declaration's list
+ ///
+ /// \returns The OriginList, or nullptr for non-pointer rvalues.
+ OriginList *getOrCreateList(const Expr *E, size_t Depth = 0);
const Origin &getOrigin(OriginID ID) const;
llvm::ArrayRef<Origin> getOrigins() const { return AllOrigins; }
- OriginID getOrCreate(const ValueDecl &D);
-
unsigned getNumOrigins() const { return NextOriginID.Value; }
void dump(OriginID OID, llvm::raw_ostream &OS) const;
private:
OriginID getNextOriginID() { return NextOriginID++; }
+ OriginList *createNode(const ValueDecl *D, QualType QT) {
+ OriginID NewID = getNextOriginID();
+ AllOrigins.emplace_back(NewID, D, QT.getTypePtrOrNull());
+ return new (ListAllocator.Allocate<OriginList>()) OriginList(NewID);
+ }
+
+ OriginList *createNode(const Expr *E, QualType QT) {
+ OriginID NewID = getNextOriginID();
+ AllOrigins.emplace_back(NewID, E, QT.getTypePtrOrNull());
+ return new (ListAllocator.Allocate<OriginList>()) OriginList(NewID);
+ }
----------------
ymand wrote:
why define these in the header (given that they are private)?
https://github.com/llvm/llvm-project/pull/168344
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits