================
@@ -878,6 +878,65 @@ void FactsGenerator::handleImplicitObjectFieldUses(const 
Expr *Call,
   });
 }
 
+void FactsGenerator::handleLifetimeCaptureBy(const FunctionDecl *FD,
+                                             ArrayRef<const Expr *> Args) {
+  if (Args.empty())
+    return;
+  // FIXME: Add support for capture_by on constructors.
+  if (isa<CXXConstructorDecl>(FD))
+    return;
+  const auto *Method = dyn_cast<CXXMethodDecl>(FD);
+  bool IsInstance =
+      Method && Method->isInstance() && !isa<CXXConstructorDecl>(FD);
+  auto getArgCaptureBy = [FD,
+                          IsInstance](unsigned I) -> LifetimeCaptureByAttr * {
+    const ParmVarDecl *PVD = nullptr;
+    if (IsInstance) {
+      // FIXME: Add support for I == 0 i.e. capture_by on function declarations
+      if (I > 0 && I - 1 < FD->getNumParams())
+        PVD = FD->getParamDecl(I - 1);
+    } else {
+      if (I < FD->getNumParams())
+        PVD = FD->getParamDecl(I);
+    }
+    return PVD ? PVD->getAttr<LifetimeCaptureByAttr>() : nullptr;
+  };
+  for (unsigned I = 0; I < Args.size(); ++I) {
+    const LifetimeCaptureByAttr *Attr = getArgCaptureBy(I);
+    if (!Attr)
+      continue;
+    OriginList *CapturedOriginList = getOriginsList(*Args[I]);
+    if (!CapturedOriginList)
+      continue;
+    if (isGslPointerType(Args[I]->getType())) {
+      assert(!Args[I]->isGLValue() || CapturedOriginList->getLength() >= 2);
+      CapturedOriginList = getRValueOrigins(Args[I], CapturedOriginList);
+    }
----------------
usx95 wrote:

This would benefit from a comment. Can you also give examples you are targeting 
here.

I am confused how is this working for this example:
```cpp
void setCaptureBy(View& res, View in [[clang::lifetime_capture_by(res)]]);

void transitive_capture() {
    View v1, v2;
    {
        MyObj local;
        v1 = local;
        setCaptureBy(v2, v1);
    }
    (void)v2;
}
```

The captured argument expression is already a rvalue. Why would be need to have 
another RValueOrigins

```
`-CXXConstructExpr <col:26> 'View' 'void (const View &) noexcept'
    |     `-ImplicitCastExpr <col:26> 'const View' lvalue <NoOp>
    |       `-DeclRefExpr <col:26> 'View' lvalue Var 0x3f280150 'v1' 'View'
```


Can you also test what happens when the `gsl::Pointer` is accepted as a ref ?
```cpp
struct [[gsl::Pointer]] OtherView {};

void foo(OtherView& res,
         View& view_ref [[capture_by(res)]])) {}
```

https://github.com/llvm/llvm-project/pull/196884
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to