================
@@ -112,16 +122,29 @@ bool OriginManager::hasOrigins(QualType QT) const {
   // stored lambda's origins.
   if (isStdCallableWrapperType(RD))
     return true;
-  // TODO: Limit to lambdas for now. This will be extended to user-defined
-  // structs with pointer-like fields.
-  if (!RD->isLambda())
+  // A lambda has origins when any capture has a tracked type; the lambda
+  // itself is tracked as a single origin.
+  if (RD->isLambda()) {
+    for (const auto *FD : RD->fields())
+      if (hasOrigins(FD->getType()))
+        return true;
+    return false;
+  }
+  // TODO: Unions are not tracked.
+  if (RD->isUnion())
     return false;
   for (const auto *FD : RD->fields())
-    if (hasOrigins(FD->getType()))
+    if (FD->getAccess() == AS_public && hasOrigins(FD->getType()))
----------------
aeft wrote:

Updated. Now it can handle private fields (please see tests: 
`return_private_holder`, `return_via_other`). protected fields (and derived 
fields) are left for the follow-up PR.

Note I didn't add the `isAccessedField(FD)` gate to `hasOrigins` (only to 
`isTrackedField`). Adding it would introduce false positives: in 
`struct_field_safe`, `Inner`'s own fields aren't directly accessed, so 
`hasOrigins(Inner)` would become false, `s`'s `inner` field edge would be 
dropped, and `(void)s.inner` would no longer narrow the use away from `s.v`.

Conceptually, `hasOrigins` answers whether a type carries origins at all (i.e. 
whether to build a tree), which is broader than whether a field is expanded 
(`isTrackedField`): a record reached as a whole still needs a tree even when 
its sub-fields aren't individually accessed.

The only effect of not gating is that such a record gets a single origin that 
holds no loans, and there is no observable side effect.

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

Reply via email to