[llvm-branch-commits] [clang] [LifetimeSafety] Track per-field origins for record types (PR #195603)
Zhijie Wang via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Sat Jun 13 17:04:37 PDT 2026
================
@@ -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
More information about the llvm-branch-commits
mailing list