1 //== ObjCAtSyncChecker.cpp - nil mutex checker for @synchronized -*- C++ -*--=//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This defines ObjCAtSyncChecker, a builtin check that checks for null pointers
11 // used as mutexes for @synchronized.
13 //===----------------------------------------------------------------------===//
15 #include "GRExprEngineInternalChecks.h"
16 #include "clang/Checker/BugReporter/BugType.h"
17 #include "clang/Checker/Checkers/DereferenceChecker.h"
18 #include "clang/Checker/PathSensitive/CheckerVisitor.h"
19 #include "clang/Checker/PathSensitive/GRExprEngine.h"
21 using namespace clang
;
24 class ObjCAtSyncChecker
: public CheckerVisitor
<ObjCAtSyncChecker
> {
28 ObjCAtSyncChecker() : BT_null(0), BT_undef(0) {}
29 static void *getTag() { static int tag
= 0; return &tag
; }
30 void PreVisitObjCAtSynchronizedStmt(CheckerContext
&C
,
31 const ObjCAtSynchronizedStmt
*S
);
33 } // end anonymous namespace
35 void clang::RegisterObjCAtSyncChecker(GRExprEngine
&Eng
) {
36 Eng
.registerCheck(new ObjCAtSyncChecker());
39 void ObjCAtSyncChecker::PreVisitObjCAtSynchronizedStmt(CheckerContext
&C
,
40 const ObjCAtSynchronizedStmt
*S
) {
42 const Expr
*Ex
= S
->getSynchExpr();
43 const GRState
*state
= C
.getState();
44 SVal V
= state
->getSVal(Ex
);
46 // Uninitialized value used for the mutex?
47 if (isa
<UndefinedVal
>(V
)) {
48 if (ExplodedNode
*N
= C
.GenerateSink()) {
50 BT_undef
= new BuiltinBug("Uninitialized value used as mutex "
52 EnhancedBugReport
*report
=
53 new EnhancedBugReport(*BT_undef
, BT_undef
->getDescription(), N
);
54 report
->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue
, Ex
);
60 // Check for null mutexes.
61 const GRState
*notNullState
, *nullState
;
62 llvm::tie(notNullState
, nullState
) = state
->Assume(cast
<DefinedSVal
>(V
));
66 // Generate an error node. This isn't a sink since
67 // a null mutex just means no synchronization occurs.
68 if (ExplodedNode
*N
= C
.GenerateNode(nullState
)) {
70 BT_null
= new BuiltinBug("Nil value used as mutex for @synchronized() "
71 "(no synchronization will occur)");
72 EnhancedBugReport
*report
=
73 new EnhancedBugReport(*BT_null
, BT_null
->getDescription(), N
);
74 report
->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue
,
80 // From this point forward, we know that the mutex is null.
81 C
.addTransition(nullState
);
85 C
.addTransition(notNullState
);