[LifetimeSafety] Add support for lifetime capture_by (#196884)
This PR implements support for the `[[clang::lifetime_capture_by(X)]]`
attribute within the lifetime-safety analysis.
The PR introduces a new helper in `FactGenerator.cpp` called
`handleLifetimeCaptureBy` which detects
`[[clang::lifetime_capture_by(X)]]` on parameters. If detected, the
analyzer now generates an `OriginFlowFact` ensuring that captured
dependencies are added to the capturer's state. The PR supports
capture_by params and `this` and currently doesn't implement attributes
on function declarations.
Example:
Integrate `[[clang::lifetimebound]]`: This existing Clang annotation is
crucial for specifying that the lifetime of a function's output is tied
to one of its inputs.
```cpp
void setS(std::string_view& in, std::string_view out [[clang::lifetime_capture_by(X)]]);
std::string_view foo() {
std::string a = "on stack";
std::string_view res;
setS(res, a);
return res; // warning: returning address of local variable 'a'.
}
```
Lifetime Facts:
```cpp
Function: foo
Block B2:
End of Block
Block B1:
OriginFlow:
Dest: 0 (Expr: ImplicitCastExpr, Type : const char *)
Src: 1 (Expr: StringLiteral, Type : const char (&)[9])
Use (0 (Expr: ImplicitCastExpr, Type : const char *), Read)
Use (2 (Expr: CXXDefaultArgExpr, Type : const class std::allocator<char> &), Read)
Expire (MaterializeTemporaryExpr at 0x562afa69fdb0)
OriginFlow:
Dest: 3 (Decl: res, Type : std::string_view)
Src: 4 (Expr: CXXConstructExpr, Type : std::string_view)
Use (3 (Decl: res, Type : std::string_view), Read)
Issue (0 (Path: res), ToOrigin: 7 (Expr: DeclRefExpr, Decl: res))
Issue (1 (Path: a), ToOrigin: 8 (Expr: DeclRefExpr, Decl: a))
OriginFlow:
Dest: 9 (Expr: ImplicitCastExpr, Type : const class std::basic_string<char> &)
Src: 8 (Expr: DeclRefExpr, Decl: a)
Use (9 (Expr: ImplicitCastExpr, Type : const class std::basic_string<char> &), Read)
OriginFlow:
Dest: 10 (Expr: CXXMemberCallExpr, Type : __sv_type)
Src: 9 (Expr: ImplicitCastExpr, Type : const class std::basic_string<char> &)
OriginFlow:
Dest: 11 (Expr: ImplicitCastExpr, Type : __sv_type)
Src: 10 (Expr: CXXMemberCallExpr, Type : __sv_type)
Use (11 (Expr: ImplicitCastExpr, Type : __sv_type), Read)
// New Origin Flow fact added
OriginFlow:
Dest: 3 (Decl: res, Type : std::string_view)
Src: 11 (Expr: ImplicitCastExpr, Type : __sv_type), Merge
Use (3 (Decl: res, Type : std::string_view), Read)
Issue (2 (Path: res), ToOrigin: 12 (Expr: DeclRefExpr, Decl: res))
OriginFlow:
Dest: 13 (Expr: ImplicitCastExpr, Type : const std::string_view &)
Src: 12 (Expr: DeclRefExpr, Decl: res)
OriginFlow:
Dest: 14 (Expr: ImplicitCastExpr, Type : std::string_view)
Src: 3 (Decl: res, Type : std::string_view)
OriginFlow:
Dest: 15 (Expr: CXXConstructExpr, Type : std::string_view)
Src: 14 (Expr: ImplicitCastExpr, Type : std::string_view)
Expire (a)
Expire (res, Origin: 3 (Decl: res, Type : std::string_view))
OriginEscapes (15 (Expr: CXXConstructExpr, Type : std::string_view), via Return)
End of Block
Block B0:
End of Block
```