[LifetimeSafety] Propagate loans through pointer arithmetic (#189546)

This PR adds loan propagation for pointer arithmetic.

It also updates the tests to match the new behavior.

Fixes #180933
This commit is contained in:
NeKon69 2026-04-02 23:59:39 +03:00 committed by GitHub
parent d34e84700a
commit 5669dfc68b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 27 additions and 6 deletions

View File

@ -64,6 +64,8 @@ private:
void handleAssignment(const Expr *LHSExpr, const Expr *RHSExpr);
void handlePointerArithmetic(const BinaryOperator *BO);
void handleCXXCtorInitializer(const CXXCtorInitializer *CII);
void handleLifetimeEnds(const CFGLifetimeEnds &LifetimeEnds);

View File

@ -378,11 +378,22 @@ void FactsGenerator::handleAssignment(const Expr *LHSExpr,
flow(LHSList->peelOuterOrigin(), RHSList, /*Kill=*/true);
}
void FactsGenerator::handlePointerArithmetic(const BinaryOperator *BO) {
if (Expr *RHS = BO->getRHS(); RHS->getType()->isPointerType()) {
killAndFlowOrigin(*BO, *RHS);
return;
}
Expr *LHS = BO->getLHS();
assert(LHS->getType()->isPointerType() &&
"Pointer arithmetic must have a pointer operand");
killAndFlowOrigin(*BO, *LHS);
}
void FactsGenerator::VisitBinaryOperator(const BinaryOperator *BO) {
// TODO: Handle pointer arithmetic (e.g., `p + 1` or `1 + p`) where the
// result should have the same loans as the pointer operand.
if (BO->isCompoundAssignmentOp())
return;
if (BO->getType()->isPointerType() && BO->isAdditiveOp())
handlePointerArithmetic(BO);
handleUse(BO->getRHS());
if (BO->isAssignmentOp())
handleAssignment(BO->getLHS(), BO->getRHS());

View File

@ -436,6 +436,9 @@ struct MemberArrayReturn {
int* getData() { // expected-warning {{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}}
return arr; // expected-note {{param returned here}}
}
int* getLast() { // expected-warning {{implicit this in intra-TU function should be marked [[clang::lifetimebound]]}}
return arr + 10; // expected-note {{param returned here}}
}
};
} // namespace array

View File

@ -2069,14 +2069,19 @@ int* static_array() {
return &a[1];
}
// FIXME: Pointer arithmetic is not yet tracked.
void pointer_arithmetic_use_after_scope() {
int* p;
int* p2;
int* p3;
{
int a[10]{};
p = a + 5;
}
(void)*p; // Should warn.
p = a + 5; // expected-warning {{object whose reference is captured does not live long enough}}
p2 = a - 5; // expected-warning {{object whose reference is captured does not live long enough}}
p3 = 5 + a; // expected-warning {{object whose reference is captured does not live long enough}}
} // expected-note 3 {{destroyed here}}
(void)*p; // expected-note {{later used here}}
(void)*p2; // expected-note {{later used here}}
(void)*p3; // expected-note {{later used here}}
}
// FIXME: Copying a pointer value out of an array element is not tracked.