@@ -201,8 +201,13 @@ class GCChecker
201201 VS.FD = FD;
202202 return VS;
203203 }
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+ }
206211 }
207212 };
208213
@@ -884,7 +889,10 @@ void GCChecker::checkBeginFunction(CheckerContext &C) const {
884889 auto Param = State->getLValue (P, LCtx);
885890 const MemRegion *Root = State->getSVal (Param).getAsRegion ();
886891 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 ));
888896 } else if (isGCTrackedType (P->getType ())) {
889897 auto Param = State->getLValue (P, LCtx);
890898 SymbolRef AssignedSym = State->getSVal (Param).getAsSymbol ();
@@ -1631,6 +1639,11 @@ void GCChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
16311639 report_value_error (C, Sym, " Passing non-pinned value as argument to function that may GC" , range);
16321640 }
16331641 }
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+ }
16341647 }
16351648}
16361649
0 commit comments