Skip to content

Commit b9c0f8a

Browse files
committed
Add JL_REQUIRE_TPIN for arguments
1 parent 7a45aa0 commit b9c0f8a

File tree

3 files changed

+40
-3
lines changed

3 files changed

+40
-3
lines changed

src/clangsa/GCChecker.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

src/support/analyzer_annotations.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define JL_ALWAYS_LEAFTYPE JL_GLOBALLY_ROOTED
2424
#define JL_ROOTS_TEMPORARILY __attribute__((annotate("julia_temporarily_roots")))
2525
#define JL_REQUIRE_ROOTED_SLOT __attribute__((annotate("julia_require_rooted_slot")))
26+
#define JL_REQUIRE_TPIN __attribute__((annotate("julia_require_tpin")))
2627
#ifdef __cplusplus
2728
extern "C" {
2829
#endif
@@ -52,6 +53,7 @@ extern "C" {
5253
#define JL_ALWAYS_LEAFTYPE
5354
#define JL_ROOTS_TEMPORARILY
5455
#define JL_REQUIRE_ROOTED_SLOT
56+
#define JL_REQUIRE_TPIN
5557
#define JL_GC_PROMISE_ROOTED(x) (void)(x)
5658
#define jl_may_leak(x) (void)(x)
5759

test/clangsa/MissingPinning.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,25 @@ void rebind_tpin_simple2() {
179179
look_at_value(v);
180180
JL_GC_POP();
181181
}
182+
183+
int transitive_closure(jl_value_t *v JL_REQUIRE_TPIN) {
184+
if (jl_is_unionall(v)) {
185+
jl_unionall_t *ua = (jl_unionall_t*)v;
186+
return transitive_closure(ua->body);
187+
}
188+
return 0;
189+
}
190+
191+
extern void look_at_tpin_value(jl_value_t *v JL_REQUIRE_TPIN);
192+
193+
int properly_tpin_arg(jl_value_t *v) {
194+
JL_GC_PUSH1(&v);
195+
look_at_tpin_value(v);
196+
JL_GC_POP();
197+
}
198+
199+
int no_tpin_arg(jl_value_t *v) {
200+
look_at_tpin_value(v); // expected-warning{{Passing non-tpinned argument to function that requires a tpin argument}}
201+
// expected-note@-1{{Passing non-tpinned argument to function that requires a tpin argument}}
202+
// expected-note@+1{{Started tracking value here (root was inherited)}}
203+
}

0 commit comments

Comments
 (0)