@@ -201,8 +201,13 @@ class GCChecker
201
201
VS.FD = FD;
202
202
return VS;
203
203
}
204
- // Assume arguments are pinned
205
- return getRooted (nullptr , ValueState::Pinned, -1 );
204
+ bool require_tpin = declHasAnnotation (PVD, " julia_require_tpin" );
205
+ if (require_tpin) {
206
+ return getRooted (nullptr , ValueState::TransitivelyPinned, -1 );
207
+ } else {
208
+ // Assume arguments are pinned
209
+ return getRooted (nullptr , ValueState::Pinned, -1 );
210
+ }
206
211
}
207
212
};
208
213
@@ -884,7 +889,10 @@ void GCChecker::checkBeginFunction(CheckerContext &C) const {
884
889
auto Param = State->getLValue (P, LCtx);
885
890
const MemRegion *Root = State->getSVal (Param).getAsRegion ();
886
891
State = State->set <GCRootMap>(Root, RootState::getRoot (-1 ));
887
- State = State->set <GCPinMap>(Root, PinState::getPin (-1 ));
892
+ if (declHasAnnotation (P, " julia_require_tpin" ))
893
+ State = State->set <GCPinMap>(Root, PinState::getTransitivePin (-1 ));
894
+ else
895
+ State = State->set <GCPinMap>(Root, PinState::getTransitivePin (-1 ));
888
896
} else if (isGCTrackedType (P->getType ())) {
889
897
auto Param = State->getLValue (P, LCtx);
890
898
SymbolRef AssignedSym = State->getSVal (Param).getAsSymbol ();
@@ -1631,6 +1639,11 @@ void GCChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
1631
1639
report_value_error (C, Sym, " Passing non-pinned value as argument to function that may GC" , range);
1632
1640
}
1633
1641
}
1642
+ if (FD && idx < FD->getNumParams () && declHasAnnotation (FD->getParamDecl (idx), " julia_require_tpin" )) {
1643
+ if (!ValState->isTransitivelyPinned ()) {
1644
+ report_value_error (C, Sym, " Passing non-tpinned argument to function that requires a tpin argument." );
1645
+ }
1646
+ }
1634
1647
}
1635
1648
}
1636
1649
0 commit comments