================
@@ -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())
+ if (E.FD)
+ if (OriginNode *SrcF = Src->getFieldChild(E.FD))
+ flow(E.Child, SrcF, Kill);
----------------
Xazax-hun wrote:
In general, recursion can be a bit slow sometimes. I wonder if it is better to
do an explicit traversal. Also wondering if BFS is better than DFS here for
memory locality (like processing everything in one array first before moving to
another array).
https://github.com/llvm/llvm-project/pull/195603
_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits