[llvm-branch-commits] [clang] [LifetimeSafety][NFC] Add field-labeled child edges to OriginNode and generalize subtree walks (PR #201510)
Gábor Horváth via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jun 8 07:50:43 PDT 2026
================
@@ -49,27 +49,38 @@ bool FactsGenerator::hasOrigins(const Expr *E) const {
/// Propagates origin information from Src to Dst through all levels of
/// indirection, creating OriginFlowFacts at each level.
///
-/// This function enforces a critical type-safety invariant: both lists must
-/// have the same shape (same depth/structure). This invariant ensures that
-/// origins flow only between compatible types during expression evaluation.
+/// This function enforces a critical type-safety invariant: both trees
+/// must have the same pointee-chain depth, and field children are
+/// matched by `FieldDecl`. This invariant ensures that origins flow only
+/// between compatible types during expression evaluation. Field pairs
+/// found on both sides recurse; unmatched fields are skipped, which is
+/// exercised by `CK_DerivedToBase` flows where Base's and Derived's
+/// trees carry distinct direct-field FDs.
///
/// Examples:
/// - `int* p = &x;` flows origins from `&x` (depth 1) to `p` (depth 1)
/// - `int** pp = &p;` flows origins from `&p` (depth 2) to `pp` (depth 2)
/// * Level 1: pp <- p's address
/// * Level 2: (*pp) <- what p points to (i.e., &x)
/// - `View v = obj;` flows origins from `obj` (depth 1) to `v` (depth 1)
+/// - `S s2 = s;` flows the top-level origin and recursively flows each
+/// matching `FieldDecl` subtree, so loans on `s.v.inner` propagate to
+/// `s2.v.inner`.
void FactsGenerator::flow(OriginNode *Dst, OriginNode *Src, bool Kill) {
if (!Dst)
return;
assert(Src &&
"Dst is non-null but Src is null. List must have the same length");
assert(Dst->getLength() == Src->getLength() &&
- "Lists must have the same length");
+ "Pointee chains must have the same length");
while (Dst && Src) {
CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
Dst->getOriginID(), Src->getOriginID(), Kill));
+ for (const OriginNode::Edge &E : Dst->children())
----------------
Xazax-hun wrote:
I wonder if we should do a BFS with an explicit queue instead of DFS using the call stack for performance.
https://github.com/llvm/llvm-project/pull/201510
More information about the llvm-branch-commits
mailing list