@@ -199,7 +199,7 @@ class GCChecker
199
199
static bool isGCTracked (const Expr *E);
200
200
bool isGloballyRootedType (QualType Type) const ;
201
201
static void dumpState (const ProgramStateRef &State);
202
- static bool declHasAnnotation (const clang::Decl *D, const char *which);
202
+ static const AnnotateAttr * declHasAnnotation (const clang::Decl *D, const char *which);
203
203
static bool isFDAnnotatedNotSafepoint (const clang::FunctionDecl *FD, const SourceManager &SM);
204
204
static const SourceManager &getSM (CheckerContext &C) { return C.getSourceManager (); }
205
205
bool isSafepoint (const CallEvent &Call, CheckerContext &C) const ;
@@ -251,6 +251,18 @@ class GCChecker
251
251
PDP VisitNode (const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override ;
252
252
};
253
253
254
+ class SafepointBugVisitor : public BugReporterVisitor {
255
+ public:
256
+ SafepointBugVisitor () {}
257
+
258
+ void Profile (llvm::FoldingSetNodeID &ID) const override {
259
+ static int X = 0 ;
260
+ ID.AddPointer (&X);
261
+ }
262
+
263
+ PDP VisitNode (const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &BR) override ;
264
+ };
265
+
254
266
class GCValueBugVisitor : public BugReporterVisitor {
255
267
protected:
256
268
SymbolRef Sym;
@@ -364,6 +376,33 @@ PDP GCChecker::GCBugVisitor::VisitNode(const ExplodedNode *N,
364
376
return nullptr ;
365
377
}
366
378
379
+ PDP GCChecker::SafepointBugVisitor::VisitNode (const ExplodedNode *N,
380
+ BugReporterContext &BRC, PathSensitiveBugReport &BR) {
381
+ const ExplodedNode *PrevN = N->getFirstPred ();
382
+ unsigned NewSafepointDisabled = N->getState ()->get <SafepointDisabledAt>();
383
+ unsigned OldSafepointDisabled = PrevN->getState ()->get <SafepointDisabledAt>();
384
+ if (NewSafepointDisabled != OldSafepointDisabled) {
385
+ const Decl *D = &N->getCodeDecl ();
386
+ const AnnotateAttr *Ann = declHasAnnotation (D, " julia_not_safepoint" );
387
+ PathDiagnosticLocation Pos;
388
+ if (OldSafepointDisabled == (unsigned )-1 ) {
389
+ if (Ann) {
390
+ Pos = PathDiagnosticLocation{Ann->getLoc (), BRC.getSourceManager ()};
391
+ return MakePDP (Pos, " Tracking JL_NOT_SAFEPOINT annotation here." );
392
+ } else {
393
+ PathDiagnosticLocation Pos = PathDiagnosticLocation::createDeclBegin (
394
+ N->getLocationContext (), BRC.getSourceManager ());
395
+ return MakePDP (Pos, " Tracking JL_NOT_SAFEPOINT annotation here." );
396
+ }
397
+ } else if (NewSafepointDisabled == (unsigned )-1 ) {
398
+ PathDiagnosticLocation Pos = PathDiagnosticLocation::createDeclBegin (
399
+ N->getLocationContext (), BRC.getSourceManager ());
400
+ return MakePDP (Pos, " Safepoints re-enabled here" );
401
+ }
402
+ }
403
+ return nullptr ;
404
+ }
405
+
367
406
PDP GCChecker::GCValueBugVisitor::ExplainNoPropagationFromExpr (
368
407
const clang::Expr *FromWhere, const ExplodedNode *N,
369
408
PathDiagnosticLocation Pos, BugReporterContext &BRC, PathSensitiveBugReport &BR) {
@@ -712,12 +751,12 @@ void GCChecker::checkEndFunction(const clang::ReturnStmt *RS,
712
751
}
713
752
}
714
753
715
- bool GCChecker::declHasAnnotation (const clang::Decl *D, const char *which) {
754
+ const AnnotateAttr * GCChecker::declHasAnnotation (const clang::Decl *D, const char *which) {
716
755
for (const auto *Ann : D->specific_attrs <AnnotateAttr>()) {
717
756
if (Ann->getAnnotation () == which)
718
- return true ;
757
+ return Ann ;
719
758
}
720
- return false ;
759
+ return nullptr ;
721
760
}
722
761
723
762
bool GCChecker::isFDAnnotatedNotSafepoint (const clang::FunctionDecl *FD, const SourceManager &SM) {
@@ -1302,6 +1341,7 @@ void GCChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
1302
1341
Report->addNote (
1303
1342
" Tried to call method defined here" ,
1304
1343
PathDiagnosticLocation::create (FD, C.getSourceManager ()));
1344
+ Report->addVisitor (make_unique<SafepointBugVisitor>());
1305
1345
},
1306
1346
C, (" Calling potential safepoint as " +
1307
1347
Call.getKindAsString () + " from function annotated JL_NOTSAFEPOINT" ).str ());
0 commit comments