Skip to content

Commit

Permalink
Add JL_REQUIRE_TPIN for arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
qinsoon committed May 29, 2024
1 parent 7a45aa0 commit b9c0f8a
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 3 deletions.
19 changes: 16 additions & 3 deletions src/clangsa/GCChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,13 @@ class GCChecker
VS.FD = FD;
return VS;
}
// Assume arguments are pinned
return getRooted(nullptr, ValueState::Pinned, -1);
bool require_tpin = declHasAnnotation(PVD, "julia_require_tpin");
if (require_tpin) {
return getRooted(nullptr, ValueState::TransitivelyPinned, -1);
} else {
// Assume arguments are pinned
return getRooted(nullptr, ValueState::Pinned, -1);
}
}
};

Expand Down Expand Up @@ -884,7 +889,10 @@ void GCChecker::checkBeginFunction(CheckerContext &C) const {
auto Param = State->getLValue(P, LCtx);
const MemRegion *Root = State->getSVal(Param).getAsRegion();
State = State->set<GCRootMap>(Root, RootState::getRoot(-1));
State = State->set<GCPinMap>(Root, PinState::getPin(-1));
if (declHasAnnotation(P, "julia_require_tpin"))
State = State->set<GCPinMap>(Root, PinState::getTransitivePin(-1));
else
State = State->set<GCPinMap>(Root, PinState::getTransitivePin(-1));
} else if (isGCTrackedType(P->getType())) {
auto Param = State->getLValue(P, LCtx);
SymbolRef AssignedSym = State->getSVal(Param).getAsSymbol();
Expand Down Expand Up @@ -1631,6 +1639,11 @@ void GCChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
report_value_error(C, Sym, "Passing non-pinned value as argument to function that may GC", range);
}
}
if (FD && idx < FD->getNumParams() && declHasAnnotation(FD->getParamDecl(idx), "julia_require_tpin")) {
if (!ValState->isTransitivelyPinned()) {
report_value_error(C, Sym, "Passing non-tpinned argument to function that requires a tpin argument.");
}
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/support/analyzer_annotations.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#define JL_ALWAYS_LEAFTYPE JL_GLOBALLY_ROOTED
#define JL_ROOTS_TEMPORARILY __attribute__((annotate("julia_temporarily_roots")))
#define JL_REQUIRE_ROOTED_SLOT __attribute__((annotate("julia_require_rooted_slot")))
#define JL_REQUIRE_TPIN __attribute__((annotate("julia_require_tpin")))
#ifdef __cplusplus
extern "C" {
#endif
Expand Down Expand Up @@ -52,6 +53,7 @@ extern "C" {
#define JL_ALWAYS_LEAFTYPE
#define JL_ROOTS_TEMPORARILY
#define JL_REQUIRE_ROOTED_SLOT
#define JL_REQUIRE_TPIN
#define JL_GC_PROMISE_ROOTED(x) (void)(x)
#define jl_may_leak(x) (void)(x)

Expand Down
22 changes: 22 additions & 0 deletions test/clangsa/MissingPinning.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,25 @@ void rebind_tpin_simple2() {
look_at_value(v);
JL_GC_POP();
}

int transitive_closure(jl_value_t *v JL_REQUIRE_TPIN) {
if (jl_is_unionall(v)) {
jl_unionall_t *ua = (jl_unionall_t*)v;
return transitive_closure(ua->body);
}
return 0;
}

extern void look_at_tpin_value(jl_value_t *v JL_REQUIRE_TPIN);

int properly_tpin_arg(jl_value_t *v) {
JL_GC_PUSH1(&v);
look_at_tpin_value(v);
JL_GC_POP();
}

int no_tpin_arg(jl_value_t *v) {
look_at_tpin_value(v); // expected-warning{{Passing non-tpinned argument to function that requires a tpin argument}}
// expected-note@-1{{Passing non-tpinned argument to function that requires a tpin argument}}
// expected-note@+1{{Started tracking value here (root was inherited)}}
}

0 comments on commit b9c0f8a

Please sign in to comment.