[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:
parent
d34e84700a
commit
5669dfc68b
@ -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);
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user