Add transfer function for `MaterializeTemporaryExpr` in nullability verification
This allows us to handle expressions where `prvalue` temporaries are written to memory so they can be bound to references. For example, passing a member call to a function that takes a const reference argument.
PiperOrigin-RevId: 502610175
diff --git a/nullability_verification/pointer_nullability_analysis.cc b/nullability_verification/pointer_nullability_analysis.cc
index fd73e18..a750066 100644
--- a/nullability_verification/pointer_nullability_analysis.cc
+++ b/nullability_verification/pointer_nullability_analysis.cc
@@ -486,6 +486,26 @@
});
}
+void transferNonFlowSensitiveMaterializeTemporaryExpr(
+ const MaterializeTemporaryExpr* MTE, const MatchFinder::MatchResult& MR,
+ TransferState<PointerNullabilityLattice>& State) {
+ State.Lattice.insertExprNullabilityIfAbsent(MTE, [&]() {
+ auto BaseNullability = State.Lattice.getExprNullability(MTE->getSubExpr());
+ if (BaseNullability.has_value()) {
+ return BaseNullability->vec();
+ } else {
+ // Since we process child nodes before parents, we should already have
+ // computed the base (child) nullability. However, this is not true in all
+ // test cases. So, we return unspecified nullability annotations.
+ // TODO: Fix this issue, add a CHECK(BaseNullability.has_value()) and
+ // remove the else branch.
+ llvm::dbgs() << "Nullability of child node not found\n";
+ return std::vector<NullabilityKind>(countPointersInType(MTE->getType()),
+ NullabilityKind::Unspecified);
+ }
+ });
+}
+
auto buildNonFlowSensitiveTransferer() {
return CFGMatchSwitchBuilder<TransferState<PointerNullabilityLattice>>()
.CaseOfCFGStmt<DeclRefExpr>(ast_matchers::declRefExpr(),
@@ -496,6 +516,9 @@
transferNonFlowSensitiveMemberCallExpr)
.CaseOfCFGStmt<CastExpr>(ast_matchers::castExpr(),
transferNonFlowSensitiveCastExpr)
+ .CaseOfCFGStmt<MaterializeTemporaryExpr>(
+ ast_matchers::materializeTemporaryExpr(),
+ transferNonFlowSensitiveMaterializeTemporaryExpr)
.Build();
}