blob: 1370d5dbacd95190c9f35094938eaafd5c01fd94 [file] [log] [blame]
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001//===- ThreadSafety.cpp ----------------------------------------*- C++ --*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// A intra-procedural analysis for thread safety (e.g. deadlocks and race
11// conditions), based off of an annotation system.
12//
Caitlin Sadowski19903462011-09-14 20:05:09 +000013// See http://clang.llvm.org/docs/LanguageExtensions.html#threadsafety for more
14// information.
Caitlin Sadowski402aa062011-09-09 16:11:56 +000015//
16//===----------------------------------------------------------------------===//
17
18#include "clang/Analysis/Analyses/ThreadSafety.h"
Ted Kremenek439ed162011-10-22 02:14:27 +000019#include "clang/Analysis/Analyses/PostOrderCFGView.h"
Caitlin Sadowskid5b16052011-09-09 23:00:59 +000020#include "clang/Analysis/AnalysisContext.h"
21#include "clang/Analysis/CFG.h"
22#include "clang/Analysis/CFGStmtMap.h"
Caitlin Sadowski402aa062011-09-09 16:11:56 +000023#include "clang/AST/DeclCXX.h"
24#include "clang/AST/ExprCXX.h"
25#include "clang/AST/StmtCXX.h"
26#include "clang/AST/StmtVisitor.h"
Caitlin Sadowskid5b16052011-09-09 23:00:59 +000027#include "clang/Basic/SourceManager.h"
28#include "clang/Basic/SourceLocation.h"
Caitlin Sadowski402aa062011-09-09 16:11:56 +000029#include "llvm/ADT/BitVector.h"
30#include "llvm/ADT/FoldingSet.h"
31#include "llvm/ADT/ImmutableMap.h"
32#include "llvm/ADT/PostOrderIterator.h"
33#include "llvm/ADT/SmallVector.h"
34#include "llvm/ADT/StringRef.h"
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +000035#include "llvm/Support/raw_ostream.h"
Caitlin Sadowski402aa062011-09-09 16:11:56 +000036#include <algorithm>
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +000037#include <utility>
Caitlin Sadowski402aa062011-09-09 16:11:56 +000038#include <vector>
39
40using namespace clang;
41using namespace thread_safety;
42
Caitlin Sadowski19903462011-09-14 20:05:09 +000043// Key method definition
44ThreadSafetyHandler::~ThreadSafetyHandler() {}
45
Caitlin Sadowski402aa062011-09-09 16:11:56 +000046namespace {
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +000047
Caitlin Sadowski402aa062011-09-09 16:11:56 +000048/// \brief A MutexID object uniquely identifies a particular mutex, and
49/// is built from an Expr* (i.e. calling a lock function).
50///
51/// Thread-safety analysis works by comparing lock expressions. Within the
52/// body of a function, an expression such as "x->foo->bar.mu" will resolve to
53/// a particular mutex object at run-time. Subsequent occurrences of the same
54/// expression (where "same" means syntactic equality) will refer to the same
55/// run-time object if three conditions hold:
56/// (1) Local variables in the expression, such as "x" have not changed.
57/// (2) Values on the heap that affect the expression have not changed.
58/// (3) The expression involves only pure function calls.
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +000059///
Caitlin Sadowski402aa062011-09-09 16:11:56 +000060/// The current implementation assumes, but does not verify, that multiple uses
61/// of the same lock expression satisfies these criteria.
62///
63/// Clang introduces an additional wrinkle, which is that it is difficult to
64/// derive canonical expressions, or compare expressions directly for equality.
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +000065/// Thus, we identify a mutex not by an Expr, but by the list of named
Caitlin Sadowski402aa062011-09-09 16:11:56 +000066/// declarations that are referenced by the Expr. In other words,
67/// x->foo->bar.mu will be a four element vector with the Decls for
68/// mu, bar, and foo, and x. The vector will uniquely identify the expression
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +000069/// for all practical purposes. Null is used to denote 'this'.
Caitlin Sadowski402aa062011-09-09 16:11:56 +000070///
71/// Note we will need to perform substitution on "this" and function parameter
72/// names when constructing a lock expression.
73///
74/// For example:
75/// class C { Mutex Mu; void lock() EXCLUSIVE_LOCK_FUNCTION(this->Mu); };
76/// void myFunc(C *X) { ... X->lock() ... }
77/// The original expression for the mutex acquired by myFunc is "this->Mu", but
78/// "X" is substituted for "this" so we get X->Mu();
79///
80/// For another example:
81/// foo(MyList *L) EXCLUSIVE_LOCKS_REQUIRED(L->Mu) { ... }
82/// MyList *MyL;
83/// foo(MyL); // requires lock MyL->Mu to be held
84class MutexID {
85 SmallVector<NamedDecl*, 2> DeclSeq;
86
87 /// Build a Decl sequence representing the lock from the given expression.
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +000088 /// Recursive function that terminates on DeclRefExpr.
89 /// Note: this function merely creates a MutexID; it does not check to
90 /// ensure that the original expression is a valid mutex expression.
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +000091 void buildMutexID(Expr *Exp, const NamedDecl *D, Expr *Parent,
92 unsigned NumArgs, Expr **FunArgs) {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +000093 if (!Exp) {
94 DeclSeq.clear();
95 return;
96 }
97
Caitlin Sadowski402aa062011-09-09 16:11:56 +000098 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Exp)) {
99 NamedDecl *ND = cast<NamedDecl>(DRE->getDecl()->getCanonicalDecl());
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +0000100 ParmVarDecl *PV = dyn_cast_or_null<ParmVarDecl>(ND);
101 if (PV) {
102 FunctionDecl *FD =
103 cast<FunctionDecl>(PV->getDeclContext())->getCanonicalDecl();
104 unsigned i = PV->getFunctionScopeIndex();
105
106 if (FunArgs && FD == D->getCanonicalDecl()) {
107 // Substitute call arguments for references to function parameters
108 assert(i < NumArgs);
109 buildMutexID(FunArgs[i], D, 0, 0, 0);
110 return;
111 }
112 // Map the param back to the param of the original function declaration.
113 DeclSeq.push_back(FD->getParamDecl(i));
114 return;
115 }
116 // Not a function parameter -- just store the reference.
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000117 DeclSeq.push_back(ND);
118 } else if (MemberExpr *ME = dyn_cast<MemberExpr>(Exp)) {
119 NamedDecl *ND = ME->getMemberDecl();
120 DeclSeq.push_back(ND);
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +0000121 buildMutexID(ME->getBase(), D, Parent, NumArgs, FunArgs);
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000122 } else if (isa<CXXThisExpr>(Exp)) {
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000123 if (Parent)
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +0000124 buildMutexID(Parent, D, 0, 0, 0);
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +0000125 else {
126 DeclSeq.push_back(0); // Use 0 to represent 'this'.
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000127 return; // mutexID is still valid in this case
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +0000128 }
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +0000129 } else if (UnaryOperator *UOE = dyn_cast<UnaryOperator>(Exp))
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +0000130 buildMutexID(UOE->getSubExpr(), D, Parent, NumArgs, FunArgs);
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +0000131 else if (CastExpr *CE = dyn_cast<CastExpr>(Exp))
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +0000132 buildMutexID(CE->getSubExpr(), D, Parent, NumArgs, FunArgs);
Caitlin Sadowski99107eb2011-09-09 16:21:55 +0000133 else
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000134 DeclSeq.clear(); // Mark as invalid lock expression.
135 }
136
137 /// \brief Construct a MutexID from an expression.
138 /// \param MutexExp The original mutex expression within an attribute
139 /// \param DeclExp An expression involving the Decl on which the attribute
140 /// occurs.
141 /// \param D The declaration to which the lock/unlock attribute is attached.
142 void buildMutexIDFromExp(Expr *MutexExp, Expr *DeclExp, const NamedDecl *D) {
143 Expr *Parent = 0;
DeLesley Hutchins81216392011-10-17 21:38:02 +0000144 unsigned NumArgs = 0;
145 Expr **FunArgs = 0;
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000146
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000147 // If we are processing a raw attribute expression, with no substitutions.
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000148 if (DeclExp == 0) {
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +0000149 buildMutexID(MutexExp, D, 0, 0, 0);
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000150 return;
151 }
152
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +0000153 // Examine DeclExp to find Parent and FunArgs, which are used to substitute
154 // for formal parameters when we call buildMutexID later.
DeLesley Hutchins81216392011-10-17 21:38:02 +0000155 if (MemberExpr *ME = dyn_cast<MemberExpr>(DeclExp)) {
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000156 Parent = ME->getBase();
DeLesley Hutchins81216392011-10-17 21:38:02 +0000157 } else if (CXXMemberCallExpr *CE = dyn_cast<CXXMemberCallExpr>(DeclExp)) {
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000158 Parent = CE->getImplicitObjectArgument();
DeLesley Hutchins81216392011-10-17 21:38:02 +0000159 NumArgs = CE->getNumArgs();
160 FunArgs = CE->getArgs();
DeLesley Hutchinsdf497822011-12-29 00:56:48 +0000161 } else if (CallExpr *CE = dyn_cast<CallExpr>(DeclExp)) {
162 NumArgs = CE->getNumArgs();
163 FunArgs = CE->getArgs();
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +0000164 } else if (CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(DeclExp)) {
165 Parent = 0; // FIXME -- get the parent from DeclStmt
166 NumArgs = CE->getNumArgs();
167 FunArgs = CE->getArgs();
DeLesley Hutchins6db51f72011-10-21 20:51:27 +0000168 } else if (D && isa<CXXDestructorDecl>(D)) {
169 // There's no such thing as a "destructor call" in the AST.
170 Parent = DeclExp;
DeLesley Hutchins81216392011-10-17 21:38:02 +0000171 }
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000172
173 // If the attribute has no arguments, then assume the argument is "this".
174 if (MutexExp == 0) {
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +0000175 buildMutexID(Parent, D, 0, 0, 0);
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000176 return;
177 }
DeLesley Hutchins81216392011-10-17 21:38:02 +0000178
DeLesley Hutchinse03b2b32012-01-20 23:24:41 +0000179 buildMutexID(MutexExp, D, Parent, NumArgs, FunArgs);
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000180 }
181
182public:
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000183 explicit MutexID(clang::Decl::EmptyShell e) {
184 DeclSeq.clear();
185 }
186
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000187 /// \param MutexExp The original mutex expression within an attribute
188 /// \param DeclExp An expression involving the Decl on which the attribute
189 /// occurs.
190 /// \param D The declaration to which the lock/unlock attribute is attached.
191 /// Caller must check isValid() after construction.
192 MutexID(Expr* MutexExp, Expr *DeclExp, const NamedDecl* D) {
193 buildMutexIDFromExp(MutexExp, DeclExp, D);
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000194 }
195
DeLesley Hutchins9f80a972011-10-17 21:33:35 +0000196 /// Return true if this is a valid decl sequence.
197 /// Caller must call this by hand after construction to handle errors.
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000198 bool isValid() const {
199 return !DeclSeq.empty();
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000200 }
201
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000202 /// Issue a warning about an invalid lock expression
203 static void warnInvalidLock(ThreadSafetyHandler &Handler, Expr* MutexExp,
204 Expr *DeclExp, const NamedDecl* D) {
205 SourceLocation Loc;
206 if (DeclExp)
207 Loc = DeclExp->getExprLoc();
208
209 // FIXME: add a note about the attribute location in MutexExp or D
210 if (Loc.isValid())
211 Handler.handleInvalidLockExp(Loc);
212 }
213
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000214 bool operator==(const MutexID &other) const {
215 return DeclSeq == other.DeclSeq;
216 }
217
218 bool operator!=(const MutexID &other) const {
219 return !(*this == other);
220 }
221
222 // SmallVector overloads Operator< to do lexicographic ordering. Note that
223 // we use pointer equality (and <) to compare NamedDecls. This means the order
224 // of MutexIDs in a lockset is nondeterministic. In order to output
225 // diagnostics in a deterministic ordering, we must order all diagnostics to
226 // output by SourceLocation when iterating through this lockset.
227 bool operator<(const MutexID &other) const {
228 return DeclSeq < other.DeclSeq;
229 }
230
231 /// \brief Returns the name of the first Decl in the list for a given MutexID;
232 /// e.g. the lock expression foo.bar() has name "bar".
233 /// The caret will point unambiguously to the lock expression, so using this
234 /// name in diagnostics is a way to get simple, and consistent, mutex names.
235 /// We do not want to output the entire expression text for security reasons.
236 StringRef getName() const {
Caitlin Sadowski194418f2011-09-14 20:00:24 +0000237 assert(isValid());
DeLesley Hutchins4bda3ec2012-02-16 17:03:24 +0000238 if (!DeclSeq.front())
239 return "this"; // Use 0 to represent 'this'.
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000240 return DeclSeq.front()->getName();
241 }
242
243 void Profile(llvm::FoldingSetNodeID &ID) const {
244 for (SmallVectorImpl<NamedDecl*>::const_iterator I = DeclSeq.begin(),
245 E = DeclSeq.end(); I != E; ++I) {
246 ID.AddPointer(*I);
247 }
248 }
249};
250
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000251
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000252/// \brief This is a helper class that stores info about the most recent
253/// accquire of a Lock.
254///
255/// The main body of the analysis maps MutexIDs to LockDatas.
256struct LockData {
257 SourceLocation AcquireLoc;
258
259 /// \brief LKind stores whether a lock is held shared or exclusively.
260 /// Note that this analysis does not currently support either re-entrant
261 /// locking or lock "upgrading" and "downgrading" between exclusive and
262 /// shared.
263 ///
264 /// FIXME: add support for re-entrant locking and lock up/downgrading
265 LockKind LKind;
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000266 MutexID UnderlyingMutex; // for ScopedLockable objects
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000267
268 LockData(SourceLocation AcquireLoc, LockKind LKind)
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000269 : AcquireLoc(AcquireLoc), LKind(LKind), UnderlyingMutex(Decl::EmptyShell())
270 {}
271
272 LockData(SourceLocation AcquireLoc, LockKind LKind, const MutexID &Mu)
273 : AcquireLoc(AcquireLoc), LKind(LKind), UnderlyingMutex(Mu) {}
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000274
275 bool operator==(const LockData &other) const {
276 return AcquireLoc == other.AcquireLoc && LKind == other.LKind;
277 }
278
279 bool operator!=(const LockData &other) const {
280 return !(*this == other);
281 }
282
283 void Profile(llvm::FoldingSetNodeID &ID) const {
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000284 ID.AddInteger(AcquireLoc.getRawEncoding());
285 ID.AddInteger(LKind);
286 }
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000287};
288
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000289
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000290/// A Lockset maps each MutexID (defined above) to information about how it has
291/// been locked.
292typedef llvm::ImmutableMap<MutexID, LockData> Lockset;
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000293typedef llvm::ImmutableMap<NamedDecl*, unsigned> LocalVarContext;
294
295class LocalVariableMap;
296
Richard Smith2e515622012-02-03 04:45:26 +0000297/// A side (entry or exit) of a CFG node.
298enum CFGBlockSide { CBS_Entry, CBS_Exit };
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000299
300/// CFGBlockInfo is a struct which contains all the information that is
301/// maintained for each block in the CFG. See LocalVariableMap for more
302/// information about the contexts.
303struct CFGBlockInfo {
304 Lockset EntrySet; // Lockset held at entry to block
305 Lockset ExitSet; // Lockset held at exit from block
306 LocalVarContext EntryContext; // Context held at entry to block
307 LocalVarContext ExitContext; // Context held at exit from block
Richard Smith2e515622012-02-03 04:45:26 +0000308 SourceLocation EntryLoc; // Location of first statement in block
309 SourceLocation ExitLoc; // Location of last statement in block.
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000310 unsigned EntryIndex; // Used to replay contexts later
311
Richard Smith2e515622012-02-03 04:45:26 +0000312 const Lockset &getSet(CFGBlockSide Side) const {
313 return Side == CBS_Entry ? EntrySet : ExitSet;
314 }
315 SourceLocation getLocation(CFGBlockSide Side) const {
316 return Side == CBS_Entry ? EntryLoc : ExitLoc;
317 }
318
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000319private:
320 CFGBlockInfo(Lockset EmptySet, LocalVarContext EmptyCtx)
321 : EntrySet(EmptySet), ExitSet(EmptySet),
322 EntryContext(EmptyCtx), ExitContext(EmptyCtx)
323 { }
324
325public:
326 static CFGBlockInfo getEmptyBlockInfo(Lockset::Factory &F,
327 LocalVariableMap &M);
328};
329
330
331
332// A LocalVariableMap maintains a map from local variables to their currently
333// valid definitions. It provides SSA-like functionality when traversing the
334// CFG. Like SSA, each definition or assignment to a variable is assigned a
335// unique name (an integer), which acts as the SSA name for that definition.
336// The total set of names is shared among all CFG basic blocks.
337// Unlike SSA, we do not rewrite expressions to replace local variables declrefs
338// with their SSA-names. Instead, we compute a Context for each point in the
339// code, which maps local variables to the appropriate SSA-name. This map
340// changes with each assignment.
341//
342// The map is computed in a single pass over the CFG. Subsequent analyses can
343// then query the map to find the appropriate Context for a statement, and use
344// that Context to look up the definitions of variables.
345class LocalVariableMap {
346public:
347 typedef LocalVarContext Context;
348
349 /// A VarDefinition consists of an expression, representing the value of the
350 /// variable, along with the context in which that expression should be
351 /// interpreted. A reference VarDefinition does not itself contain this
352 /// information, but instead contains a pointer to a previous VarDefinition.
353 struct VarDefinition {
354 public:
355 friend class LocalVariableMap;
356
357 NamedDecl *Dec; // The original declaration for this variable.
358 Expr *Exp; // The expression for this variable, OR
359 unsigned Ref; // Reference to another VarDefinition
360 Context Ctx; // The map with which Exp should be interpreted.
361
362 bool isReference() { return !Exp; }
363
364 private:
365 // Create ordinary variable definition
366 VarDefinition(NamedDecl *D, Expr *E, Context C)
367 : Dec(D), Exp(E), Ref(0), Ctx(C)
368 { }
369
370 // Create reference to previous definition
371 VarDefinition(NamedDecl *D, unsigned R, Context C)
372 : Dec(D), Exp(0), Ref(R), Ctx(C)
373 { }
374 };
375
376private:
377 Context::Factory ContextFactory;
378 std::vector<VarDefinition> VarDefinitions;
379 std::vector<unsigned> CtxIndices;
380 std::vector<std::pair<Stmt*, Context> > SavedContexts;
381
382public:
383 LocalVariableMap() {
384 // index 0 is a placeholder for undefined variables (aka phi-nodes).
385 VarDefinitions.push_back(VarDefinition(0, 0u, getEmptyContext()));
386 }
387
388 /// Look up a definition, within the given context.
389 const VarDefinition* lookup(NamedDecl *D, Context Ctx) {
390 const unsigned *i = Ctx.lookup(D);
391 if (!i)
392 return 0;
393 assert(*i < VarDefinitions.size());
394 return &VarDefinitions[*i];
395 }
396
397 /// Look up the definition for D within the given context. Returns
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +0000398 /// NULL if the expression is not statically known. If successful, also
399 /// modifies Ctx to hold the context of the return Expr.
400 Expr* lookupExpr(NamedDecl *D, Context &Ctx) {
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000401 const unsigned *P = Ctx.lookup(D);
402 if (!P)
403 return 0;
404
405 unsigned i = *P;
406 while (i > 0) {
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +0000407 if (VarDefinitions[i].Exp) {
408 Ctx = VarDefinitions[i].Ctx;
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000409 return VarDefinitions[i].Exp;
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +0000410 }
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000411 i = VarDefinitions[i].Ref;
412 }
413 return 0;
414 }
415
416 Context getEmptyContext() { return ContextFactory.getEmptyMap(); }
417
418 /// Return the next context after processing S. This function is used by
419 /// clients of the class to get the appropriate context when traversing the
420 /// CFG. It must be called for every assignment or DeclStmt.
421 Context getNextContext(unsigned &CtxIndex, Stmt *S, Context C) {
422 if (SavedContexts[CtxIndex+1].first == S) {
423 CtxIndex++;
424 Context Result = SavedContexts[CtxIndex].second;
425 return Result;
426 }
427 return C;
428 }
429
430 void dumpVarDefinitionName(unsigned i) {
431 if (i == 0) {
432 llvm::errs() << "Undefined";
433 return;
434 }
435 NamedDecl *Dec = VarDefinitions[i].Dec;
436 if (!Dec) {
437 llvm::errs() << "<<NULL>>";
438 return;
439 }
440 Dec->printName(llvm::errs());
441 llvm::errs() << "." << i << " " << ((void*) Dec);
442 }
443
444 /// Dumps an ASCII representation of the variable map to llvm::errs()
445 void dump() {
446 for (unsigned i = 1, e = VarDefinitions.size(); i < e; ++i) {
447 Expr *Exp = VarDefinitions[i].Exp;
448 unsigned Ref = VarDefinitions[i].Ref;
449
450 dumpVarDefinitionName(i);
451 llvm::errs() << " = ";
452 if (Exp) Exp->dump();
453 else {
454 dumpVarDefinitionName(Ref);
455 llvm::errs() << "\n";
456 }
457 }
458 }
459
460 /// Dumps an ASCII representation of a Context to llvm::errs()
461 void dumpContext(Context C) {
462 for (Context::iterator I = C.begin(), E = C.end(); I != E; ++I) {
463 NamedDecl *D = I.getKey();
464 D->printName(llvm::errs());
465 const unsigned *i = C.lookup(D);
466 llvm::errs() << " -> ";
467 dumpVarDefinitionName(*i);
468 llvm::errs() << "\n";
469 }
470 }
471
472 /// Builds the variable map.
473 void traverseCFG(CFG *CFGraph, PostOrderCFGView *SortedGraph,
474 std::vector<CFGBlockInfo> &BlockInfo);
475
476protected:
477 // Get the current context index
478 unsigned getContextIndex() { return SavedContexts.size()-1; }
479
480 // Save the current context for later replay
481 void saveContext(Stmt *S, Context C) {
482 SavedContexts.push_back(std::make_pair(S,C));
483 }
484
485 // Adds a new definition to the given context, and returns a new context.
486 // This method should be called when declaring a new variable.
487 Context addDefinition(NamedDecl *D, Expr *Exp, Context Ctx) {
488 assert(!Ctx.contains(D));
489 unsigned newID = VarDefinitions.size();
490 Context NewCtx = ContextFactory.add(Ctx, D, newID);
491 VarDefinitions.push_back(VarDefinition(D, Exp, Ctx));
492 return NewCtx;
493 }
494
495 // Add a new reference to an existing definition.
496 Context addReference(NamedDecl *D, unsigned i, Context Ctx) {
497 unsigned newID = VarDefinitions.size();
498 Context NewCtx = ContextFactory.add(Ctx, D, newID);
499 VarDefinitions.push_back(VarDefinition(D, i, Ctx));
500 return NewCtx;
501 }
502
503 // Updates a definition only if that definition is already in the map.
504 // This method should be called when assigning to an existing variable.
505 Context updateDefinition(NamedDecl *D, Expr *Exp, Context Ctx) {
506 if (Ctx.contains(D)) {
507 unsigned newID = VarDefinitions.size();
508 Context NewCtx = ContextFactory.remove(Ctx, D);
509 NewCtx = ContextFactory.add(NewCtx, D, newID);
510 VarDefinitions.push_back(VarDefinition(D, Exp, Ctx));
511 return NewCtx;
512 }
513 return Ctx;
514 }
515
516 // Removes a definition from the context, but keeps the variable name
517 // as a valid variable. The index 0 is a placeholder for cleared definitions.
518 Context clearDefinition(NamedDecl *D, Context Ctx) {
519 Context NewCtx = Ctx;
520 if (NewCtx.contains(D)) {
521 NewCtx = ContextFactory.remove(NewCtx, D);
522 NewCtx = ContextFactory.add(NewCtx, D, 0);
523 }
524 return NewCtx;
525 }
526
527 // Remove a definition entirely frmo the context.
528 Context removeDefinition(NamedDecl *D, Context Ctx) {
529 Context NewCtx = Ctx;
530 if (NewCtx.contains(D)) {
531 NewCtx = ContextFactory.remove(NewCtx, D);
532 }
533 return NewCtx;
534 }
535
536 Context intersectContexts(Context C1, Context C2);
537 Context createReferenceContext(Context C);
538 void intersectBackEdge(Context C1, Context C2);
539
540 friend class VarMapBuilder;
541};
542
543
544// This has to be defined after LocalVariableMap.
545CFGBlockInfo CFGBlockInfo::getEmptyBlockInfo(Lockset::Factory &F,
546 LocalVariableMap &M) {
547 return CFGBlockInfo(F.getEmptyMap(), M.getEmptyContext());
548}
549
550
551/// Visitor which builds a LocalVariableMap
552class VarMapBuilder : public StmtVisitor<VarMapBuilder> {
553public:
554 LocalVariableMap* VMap;
555 LocalVariableMap::Context Ctx;
556
557 VarMapBuilder(LocalVariableMap *VM, LocalVariableMap::Context C)
558 : VMap(VM), Ctx(C) {}
559
560 void VisitDeclStmt(DeclStmt *S);
561 void VisitBinaryOperator(BinaryOperator *BO);
562};
563
564
565// Add new local variables to the variable map
566void VarMapBuilder::VisitDeclStmt(DeclStmt *S) {
567 bool modifiedCtx = false;
568 DeclGroupRef DGrp = S->getDeclGroup();
569 for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
570 if (VarDecl *VD = dyn_cast_or_null<VarDecl>(*I)) {
571 Expr *E = VD->getInit();
572
573 // Add local variables with trivial type to the variable map
574 QualType T = VD->getType();
575 if (T.isTrivialType(VD->getASTContext())) {
576 Ctx = VMap->addDefinition(VD, E, Ctx);
577 modifiedCtx = true;
578 }
579 }
580 }
581 if (modifiedCtx)
582 VMap->saveContext(S, Ctx);
583}
584
585// Update local variable definitions in variable map
586void VarMapBuilder::VisitBinaryOperator(BinaryOperator *BO) {
587 if (!BO->isAssignmentOp())
588 return;
589
590 Expr *LHSExp = BO->getLHS()->IgnoreParenCasts();
591
592 // Update the variable map and current context.
593 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LHSExp)) {
594 ValueDecl *VDec = DRE->getDecl();
595 if (Ctx.lookup(VDec)) {
596 if (BO->getOpcode() == BO_Assign)
597 Ctx = VMap->updateDefinition(VDec, BO->getRHS(), Ctx);
598 else
599 // FIXME -- handle compound assignment operators
600 Ctx = VMap->clearDefinition(VDec, Ctx);
601 VMap->saveContext(BO, Ctx);
602 }
603 }
604}
605
606
607// Computes the intersection of two contexts. The intersection is the
608// set of variables which have the same definition in both contexts;
609// variables with different definitions are discarded.
610LocalVariableMap::Context
611LocalVariableMap::intersectContexts(Context C1, Context C2) {
612 Context Result = C1;
613 for (Context::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
614 NamedDecl *Dec = I.getKey();
615 unsigned i1 = I.getData();
616 const unsigned *i2 = C2.lookup(Dec);
617 if (!i2) // variable doesn't exist on second path
618 Result = removeDefinition(Dec, Result);
619 else if (*i2 != i1) // variable exists, but has different definition
620 Result = clearDefinition(Dec, Result);
621 }
622 return Result;
623}
624
625// For every variable in C, create a new variable that refers to the
626// definition in C. Return a new context that contains these new variables.
627// (We use this for a naive implementation of SSA on loop back-edges.)
628LocalVariableMap::Context LocalVariableMap::createReferenceContext(Context C) {
629 Context Result = getEmptyContext();
630 for (Context::iterator I = C.begin(), E = C.end(); I != E; ++I) {
631 NamedDecl *Dec = I.getKey();
632 unsigned i = I.getData();
633 Result = addReference(Dec, i, Result);
634 }
635 return Result;
636}
637
638// This routine also takes the intersection of C1 and C2, but it does so by
639// altering the VarDefinitions. C1 must be the result of an earlier call to
640// createReferenceContext.
641void LocalVariableMap::intersectBackEdge(Context C1, Context C2) {
642 for (Context::iterator I = C1.begin(), E = C1.end(); I != E; ++I) {
643 NamedDecl *Dec = I.getKey();
644 unsigned i1 = I.getData();
645 VarDefinition *VDef = &VarDefinitions[i1];
646 assert(VDef->isReference());
647
648 const unsigned *i2 = C2.lookup(Dec);
649 if (!i2 || (*i2 != i1))
650 VDef->Ref = 0; // Mark this variable as undefined
651 }
652}
653
654
655// Traverse the CFG in topological order, so all predecessors of a block
656// (excluding back-edges) are visited before the block itself. At
657// each point in the code, we calculate a Context, which holds the set of
658// variable definitions which are visible at that point in execution.
659// Visible variables are mapped to their definitions using an array that
660// contains all definitions.
661//
662// At join points in the CFG, the set is computed as the intersection of
663// the incoming sets along each edge, E.g.
664//
665// { Context | VarDefinitions }
666// int x = 0; { x -> x1 | x1 = 0 }
667// int y = 0; { x -> x1, y -> y1 | y1 = 0, x1 = 0 }
668// if (b) x = 1; { x -> x2, y -> y1 | x2 = 1, y1 = 0, ... }
669// else x = 2; { x -> x3, y -> y1 | x3 = 2, x2 = 1, ... }
670// ... { y -> y1 (x is unknown) | x3 = 2, x2 = 1, ... }
671//
672// This is essentially a simpler and more naive version of the standard SSA
673// algorithm. Those definitions that remain in the intersection are from blocks
674// that strictly dominate the current block. We do not bother to insert proper
675// phi nodes, because they are not used in our analysis; instead, wherever
676// a phi node would be required, we simply remove that definition from the
677// context (E.g. x above).
678//
679// The initial traversal does not capture back-edges, so those need to be
680// handled on a separate pass. Whenever the first pass encounters an
681// incoming back edge, it duplicates the context, creating new definitions
682// that refer back to the originals. (These correspond to places where SSA
683// might have to insert a phi node.) On the second pass, these definitions are
684// set to NULL if the the variable has changed on the back-edge (i.e. a phi
685// node was actually required.) E.g.
686//
687// { Context | VarDefinitions }
688// int x = 0, y = 0; { x -> x1, y -> y1 | y1 = 0, x1 = 0 }
689// while (b) { x -> x2, y -> y1 | [1st:] x2=x1; [2nd:] x2=NULL; }
690// x = x+1; { x -> x3, y -> y1 | x3 = x2 + 1, ... }
691// ... { y -> y1 | x3 = 2, x2 = 1, ... }
692//
693void LocalVariableMap::traverseCFG(CFG *CFGraph,
694 PostOrderCFGView *SortedGraph,
695 std::vector<CFGBlockInfo> &BlockInfo) {
696 PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
697
698 CtxIndices.resize(CFGraph->getNumBlockIDs());
699
700 for (PostOrderCFGView::iterator I = SortedGraph->begin(),
701 E = SortedGraph->end(); I!= E; ++I) {
702 const CFGBlock *CurrBlock = *I;
703 int CurrBlockID = CurrBlock->getBlockID();
704 CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
705
706 VisitedBlocks.insert(CurrBlock);
707
708 // Calculate the entry context for the current block
709 bool HasBackEdges = false;
710 bool CtxInit = true;
711 for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
712 PE = CurrBlock->pred_end(); PI != PE; ++PI) {
713 // if *PI -> CurrBlock is a back edge, so skip it
714 if (*PI == 0 || !VisitedBlocks.alreadySet(*PI)) {
715 HasBackEdges = true;
716 continue;
717 }
718
719 int PrevBlockID = (*PI)->getBlockID();
720 CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
721
722 if (CtxInit) {
723 CurrBlockInfo->EntryContext = PrevBlockInfo->ExitContext;
724 CtxInit = false;
725 }
726 else {
727 CurrBlockInfo->EntryContext =
728 intersectContexts(CurrBlockInfo->EntryContext,
729 PrevBlockInfo->ExitContext);
730 }
731 }
732
733 // Duplicate the context if we have back-edges, so we can call
734 // intersectBackEdges later.
735 if (HasBackEdges)
736 CurrBlockInfo->EntryContext =
737 createReferenceContext(CurrBlockInfo->EntryContext);
738
739 // Create a starting context index for the current block
740 saveContext(0, CurrBlockInfo->EntryContext);
741 CurrBlockInfo->EntryIndex = getContextIndex();
742
743 // Visit all the statements in the basic block.
744 VarMapBuilder VMapBuilder(this, CurrBlockInfo->EntryContext);
745 for (CFGBlock::const_iterator BI = CurrBlock->begin(),
746 BE = CurrBlock->end(); BI != BE; ++BI) {
747 switch (BI->getKind()) {
748 case CFGElement::Statement: {
749 const CFGStmt *CS = cast<CFGStmt>(&*BI);
750 VMapBuilder.Visit(const_cast<Stmt*>(CS->getStmt()));
751 break;
752 }
753 default:
754 break;
755 }
756 }
757 CurrBlockInfo->ExitContext = VMapBuilder.Ctx;
758
759 // Mark variables on back edges as "unknown" if they've been changed.
760 for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
761 SE = CurrBlock->succ_end(); SI != SE; ++SI) {
762 // if CurrBlock -> *SI is *not* a back edge
763 if (*SI == 0 || !VisitedBlocks.alreadySet(*SI))
764 continue;
765
766 CFGBlock *FirstLoopBlock = *SI;
767 Context LoopBegin = BlockInfo[FirstLoopBlock->getBlockID()].EntryContext;
768 Context LoopEnd = CurrBlockInfo->ExitContext;
769 intersectBackEdge(LoopBegin, LoopEnd);
770 }
771 }
772
773 // Put an extra entry at the end of the indexed context array
774 unsigned exitID = CFGraph->getExit().getBlockID();
775 saveContext(0, BlockInfo[exitID].ExitContext);
776}
777
Richard Smith2e515622012-02-03 04:45:26 +0000778/// Find the appropriate source locations to use when producing diagnostics for
779/// each block in the CFG.
780static void findBlockLocations(CFG *CFGraph,
781 PostOrderCFGView *SortedGraph,
782 std::vector<CFGBlockInfo> &BlockInfo) {
783 for (PostOrderCFGView::iterator I = SortedGraph->begin(),
784 E = SortedGraph->end(); I!= E; ++I) {
785 const CFGBlock *CurrBlock = *I;
786 CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlock->getBlockID()];
787
788 // Find the source location of the last statement in the block, if the
789 // block is not empty.
790 if (const Stmt *S = CurrBlock->getTerminator()) {
791 CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = S->getLocStart();
792 } else {
793 for (CFGBlock::const_reverse_iterator BI = CurrBlock->rbegin(),
794 BE = CurrBlock->rend(); BI != BE; ++BI) {
795 // FIXME: Handle other CFGElement kinds.
796 if (const CFGStmt *CS = dyn_cast<CFGStmt>(&*BI)) {
797 CurrBlockInfo->ExitLoc = CS->getStmt()->getLocStart();
798 break;
799 }
800 }
801 }
802
803 if (!CurrBlockInfo->ExitLoc.isInvalid()) {
804 // This block contains at least one statement. Find the source location
805 // of the first statement in the block.
806 for (CFGBlock::const_iterator BI = CurrBlock->begin(),
807 BE = CurrBlock->end(); BI != BE; ++BI) {
808 // FIXME: Handle other CFGElement kinds.
809 if (const CFGStmt *CS = dyn_cast<CFGStmt>(&*BI)) {
810 CurrBlockInfo->EntryLoc = CS->getStmt()->getLocStart();
811 break;
812 }
813 }
814 } else if (CurrBlock->pred_size() == 1 && *CurrBlock->pred_begin() &&
815 CurrBlock != &CFGraph->getExit()) {
816 // The block is empty, and has a single predecessor. Use its exit
817 // location.
818 CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc =
819 BlockInfo[(*CurrBlock->pred_begin())->getBlockID()].ExitLoc;
820 }
821 }
822}
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000823
824/// \brief Class which implements the core thread safety analysis routines.
825class ThreadSafetyAnalyzer {
826 friend class BuildLockset;
827
828 ThreadSafetyHandler &Handler;
829 Lockset::Factory LocksetFactory;
830 LocalVariableMap LocalVarMap;
831
832public:
833 ThreadSafetyAnalyzer(ThreadSafetyHandler &H) : Handler(H) {}
834
Richard Smith2e515622012-02-03 04:45:26 +0000835 Lockset intersectAndWarn(const CFGBlockInfo &Block1, CFGBlockSide Side1,
836 const CFGBlockInfo &Block2, CFGBlockSide Side2,
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000837 LockErrorKind LEK);
838
839 Lockset addLock(Lockset &LSet, Expr *MutexExp, const NamedDecl *D,
840 LockKind LK, SourceLocation Loc);
841
842 void runAnalysis(AnalysisDeclContext &AC);
843};
844
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000845
846/// \brief We use this class to visit different types of expressions in
847/// CFGBlocks, and build up the lockset.
848/// An expression may cause us to add or remove locks from the lockset, or else
849/// output error messages related to missing locks.
850/// FIXME: In future, we may be able to not inherit from a visitor.
851class BuildLockset : public StmtVisitor<BuildLockset> {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000852 friend class ThreadSafetyAnalyzer;
853
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000854 ThreadSafetyHandler &Handler;
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000855 Lockset::Factory &LocksetFactory;
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000856 LocalVariableMap &LocalVarMap;
857
858 Lockset LSet;
859 LocalVariableMap::Context LVarCtx;
860 unsigned CtxIndex;
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000861
862 // Helper functions
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000863 void addLock(const MutexID &Mutex, const LockData &LDat);
864 void removeLock(const MutexID &Mutex, SourceLocation UnlockLoc);
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000865
866 template <class AttrType>
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000867 void addLocksToSet(LockKind LK, AttrType *Attr,
868 Expr *Exp, NamedDecl *D, VarDecl *VD = 0);
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000869 void removeLocksFromSet(UnlockFunctionAttr *Attr,
870 Expr *Exp, NamedDecl* FunDecl);
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000871
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000872 const ValueDecl *getValueDecl(Expr *Exp);
873 void warnIfMutexNotHeld (const NamedDecl *D, Expr *Exp, AccessKind AK,
874 Expr *MutexExp, ProtectedOperationKind POK);
875 void checkAccess(Expr *Exp, AccessKind AK);
876 void checkDereference(Expr *Exp, AccessKind AK);
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000877 void handleCall(Expr *Exp, NamedDecl *D, VarDecl *VD = 0);
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000878
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +0000879 template <class AttrType>
880 void addTrylock(LockKind LK, AttrType *Attr, Expr *Exp, NamedDecl *FunDecl,
881 const CFGBlock* PredBlock, const CFGBlock *CurrBlock,
882 Expr *BrE, bool Neg);
883 CallExpr* getTrylockCallExpr(Stmt *Cond, LocalVariableMap::Context C,
884 bool &Negate);
885 void handleTrylock(Stmt *Cond, const CFGBlock* PredBlock,
886 const CFGBlock *CurrBlock);
887
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000888 /// \brief Returns true if the lockset contains a lock, regardless of whether
889 /// the lock is held exclusively or shared.
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000890 bool locksetContains(const MutexID &Lock) const {
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000891 return LSet.lookup(Lock);
892 }
893
894 /// \brief Returns true if the lockset contains a lock with the passed in
895 /// locktype.
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000896 bool locksetContains(const MutexID &Lock, LockKind KindRequested) const {
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000897 const LockData *LockHeld = LSet.lookup(Lock);
898 return (LockHeld && KindRequested == LockHeld->LKind);
899 }
900
901 /// \brief Returns true if the lockset contains a lock with at least the
902 /// passed in locktype. So for example, if we pass in LK_Shared, this function
903 /// returns true if the lock is held LK_Shared or LK_Exclusive. If we pass in
904 /// LK_Exclusive, this function returns true if the lock is held LK_Exclusive.
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000905 bool locksetContainsAtLeast(const MutexID &Lock,
906 LockKind KindRequested) const {
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000907 switch (KindRequested) {
908 case LK_Shared:
909 return locksetContains(Lock);
910 case LK_Exclusive:
911 return locksetContains(Lock, KindRequested);
912 }
Benjamin Kramerafc5b152011-09-10 21:52:04 +0000913 llvm_unreachable("Unknown LockKind");
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000914 }
915
916public:
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +0000917 BuildLockset(ThreadSafetyAnalyzer *analyzer, CFGBlockInfo &Info)
918 : StmtVisitor<BuildLockset>(),
919 Handler(analyzer->Handler),
920 LocksetFactory(analyzer->LocksetFactory),
921 LocalVarMap(analyzer->LocalVarMap),
922 LSet(Info.EntrySet),
923 LVarCtx(Info.EntryContext),
924 CtxIndex(Info.EntryIndex)
925 {}
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000926
927 void VisitUnaryOperator(UnaryOperator *UO);
928 void VisitBinaryOperator(BinaryOperator *BO);
929 void VisitCastExpr(CastExpr *CE);
DeLesley Hutchinsdf497822011-12-29 00:56:48 +0000930 void VisitCallExpr(CallExpr *Exp);
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +0000931 void VisitCXXConstructExpr(CXXConstructExpr *Exp);
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000932 void VisitDeclStmt(DeclStmt *S);
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000933};
934
935/// \brief Add a new lock to the lockset, warning if the lock is already there.
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000936/// \param Mutex -- the Mutex expression for the lock
937/// \param LDat -- the LockData for the lock
938void BuildLockset::addLock(const MutexID &Mutex, const LockData& LDat) {
939 // FIXME: deal with acquired before/after annotations.
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000940 // FIXME: Don't always warn when we have support for reentrant locks.
941 if (locksetContains(Mutex))
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000942 Handler.handleDoubleLock(Mutex.getName(), LDat.AcquireLoc);
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000943 else
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000944 LSet = LocksetFactory.add(LSet, Mutex, LDat);
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000945}
946
947/// \brief Remove a lock from the lockset, warning if the lock is not there.
948/// \param LockExp The lock expression corresponding to the lock to be removed
949/// \param UnlockLoc The source location of the unlock (only used in error msg)
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000950void BuildLockset::removeLock(const MutexID &Mutex, SourceLocation UnlockLoc) {
951 const LockData *LDat = LSet.lookup(Mutex);
952 if (!LDat)
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000953 Handler.handleUnmatchedUnlock(Mutex.getName(), UnlockLoc);
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000954 else {
955 // For scoped-lockable vars, remove the mutex associated with this var.
956 if (LDat->UnderlyingMutex.isValid())
957 removeLock(LDat->UnderlyingMutex, UnlockLoc);
958 LSet = LocksetFactory.remove(LSet, Mutex);
959 }
Caitlin Sadowski402aa062011-09-09 16:11:56 +0000960}
961
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000962/// \brief This function, parameterized by an attribute type, is used to add a
963/// set of locks specified as attribute arguments to the lockset.
964template <typename AttrType>
965void BuildLockset::addLocksToSet(LockKind LK, AttrType *Attr,
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000966 Expr *Exp, NamedDecl* FunDecl, VarDecl *VD) {
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000967 typedef typename AttrType::args_iterator iterator_type;
968
969 SourceLocation ExpLocation = Exp->getExprLoc();
970
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000971 // Figure out if we're calling the constructor of scoped lockable class
972 bool isScopedVar = false;
973 if (VD) {
974 if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FunDecl)) {
975 CXXRecordDecl* PD = CD->getParent();
976 if (PD && PD->getAttr<ScopedLockableAttr>())
977 isScopedVar = true;
978 }
979 }
980
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000981 if (Attr->args_size() == 0) {
982 // The mutex held is the "this" object.
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000983 MutexID Mutex(0, Exp, FunDecl);
984 if (!Mutex.isValid())
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000985 MutexID::warnInvalidLock(Handler, 0, Exp, FunDecl);
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000986 else
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000987 addLock(Mutex, LockData(ExpLocation, LK));
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +0000988 return;
989 }
990
991 for (iterator_type I=Attr->args_begin(), E=Attr->args_end(); I != E; ++I) {
992 MutexID Mutex(*I, Exp, FunDecl);
993 if (!Mutex.isValid())
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +0000994 MutexID::warnInvalidLock(Handler, *I, Exp, FunDecl);
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +0000995 else {
996 addLock(Mutex, LockData(ExpLocation, LK));
997 if (isScopedVar) {
998 // For scoped lockable vars, map this var to its underlying mutex.
999 DeclRefExpr DRE(VD, VD->getType(), VK_LValue, VD->getLocation());
1000 MutexID SMutex(&DRE, 0, 0);
1001 addLock(SMutex, LockData(VD->getLocation(), LK, Mutex));
1002 }
1003 }
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001004 }
1005}
1006
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001007/// \brief This function removes a set of locks specified as attribute
1008/// arguments from the lockset.
1009void BuildLockset::removeLocksFromSet(UnlockFunctionAttr *Attr,
1010 Expr *Exp, NamedDecl* FunDecl) {
1011 SourceLocation ExpLocation;
1012 if (Exp) ExpLocation = Exp->getExprLoc();
1013
1014 if (Attr->args_size() == 0) {
1015 // The mutex held is the "this" object.
1016 MutexID Mu(0, Exp, FunDecl);
1017 if (!Mu.isValid())
1018 MutexID::warnInvalidLock(Handler, 0, Exp, FunDecl);
1019 else
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001020 removeLock(Mu, ExpLocation);
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001021 return;
1022 }
1023
1024 for (UnlockFunctionAttr::args_iterator I = Attr->args_begin(),
1025 E = Attr->args_end(); I != E; ++I) {
1026 MutexID Mutex(*I, Exp, FunDecl);
1027 if (!Mutex.isValid())
1028 MutexID::warnInvalidLock(Handler, *I, Exp, FunDecl);
1029 else
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001030 removeLock(Mutex, ExpLocation);
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001031 }
1032}
1033
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001034/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs
1035const ValueDecl *BuildLockset::getValueDecl(Expr *Exp) {
1036 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Exp))
1037 return DR->getDecl();
1038
1039 if (const MemberExpr *ME = dyn_cast<MemberExpr>(Exp))
1040 return ME->getMemberDecl();
1041
1042 return 0;
1043}
1044
1045/// \brief Warn if the LSet does not contain a lock sufficient to protect access
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001046/// of at least the passed in AccessKind.
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001047void BuildLockset::warnIfMutexNotHeld(const NamedDecl *D, Expr *Exp,
1048 AccessKind AK, Expr *MutexExp,
1049 ProtectedOperationKind POK) {
1050 LockKind LK = getLockKindFromAccessKind(AK);
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001051
1052 MutexID Mutex(MutexExp, Exp, D);
Caitlin Sadowski194418f2011-09-14 20:00:24 +00001053 if (!Mutex.isValid())
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001054 MutexID::warnInvalidLock(Handler, MutexExp, Exp, D);
Caitlin Sadowski194418f2011-09-14 20:00:24 +00001055 else if (!locksetContainsAtLeast(Mutex, LK))
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001056 Handler.handleMutexNotHeld(D, POK, Mutex.getName(), LK, Exp->getExprLoc());
1057}
1058
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001059/// \brief This method identifies variable dereferences and checks pt_guarded_by
1060/// and pt_guarded_var annotations. Note that we only check these annotations
1061/// at the time a pointer is dereferenced.
1062/// FIXME: We need to check for other types of pointer dereferences
1063/// (e.g. [], ->) and deal with them here.
1064/// \param Exp An expression that has been read or written.
1065void BuildLockset::checkDereference(Expr *Exp, AccessKind AK) {
1066 UnaryOperator *UO = dyn_cast<UnaryOperator>(Exp);
1067 if (!UO || UO->getOpcode() != clang::UO_Deref)
1068 return;
1069 Exp = UO->getSubExpr()->IgnoreParenCasts();
1070
1071 const ValueDecl *D = getValueDecl(Exp);
1072 if(!D || !D->hasAttrs())
1073 return;
1074
1075 if (D->getAttr<PtGuardedVarAttr>() && LSet.isEmpty())
1076 Handler.handleNoMutexHeld(D, POK_VarDereference, AK, Exp->getExprLoc());
1077
1078 const AttrVec &ArgAttrs = D->getAttrs();
1079 for(unsigned i = 0, Size = ArgAttrs.size(); i < Size; ++i)
1080 if (PtGuardedByAttr *PGBAttr = dyn_cast<PtGuardedByAttr>(ArgAttrs[i]))
1081 warnIfMutexNotHeld(D, Exp, AK, PGBAttr->getArg(), POK_VarDereference);
1082}
1083
1084/// \brief Checks guarded_by and guarded_var attributes.
1085/// Whenever we identify an access (read or write) of a DeclRefExpr or
1086/// MemberExpr, we need to check whether there are any guarded_by or
1087/// guarded_var attributes, and make sure we hold the appropriate mutexes.
1088void BuildLockset::checkAccess(Expr *Exp, AccessKind AK) {
1089 const ValueDecl *D = getValueDecl(Exp);
1090 if(!D || !D->hasAttrs())
1091 return;
1092
1093 if (D->getAttr<GuardedVarAttr>() && LSet.isEmpty())
1094 Handler.handleNoMutexHeld(D, POK_VarAccess, AK, Exp->getExprLoc());
1095
1096 const AttrVec &ArgAttrs = D->getAttrs();
1097 for(unsigned i = 0, Size = ArgAttrs.size(); i < Size; ++i)
1098 if (GuardedByAttr *GBAttr = dyn_cast<GuardedByAttr>(ArgAttrs[i]))
1099 warnIfMutexNotHeld(D, Exp, AK, GBAttr->getArg(), POK_VarAccess);
1100}
1101
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001102/// \brief Process a function call, method call, constructor call,
1103/// or destructor call. This involves looking at the attributes on the
1104/// corresponding function/method/constructor/destructor, issuing warnings,
1105/// and updating the locksets accordingly.
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001106///
1107/// FIXME: For classes annotated with one of the guarded annotations, we need
1108/// to treat const method calls as reads and non-const method calls as writes,
1109/// and check that the appropriate locks are held. Non-const method calls with
1110/// the same signature as const method calls can be also treated as reads.
1111///
1112/// FIXME: We need to also visit CallExprs to catch/check global functions.
Caitlin Sadowski1748b122011-09-16 00:35:54 +00001113///
1114/// FIXME: Do not flag an error for member variables accessed in constructors/
1115/// destructors
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001116void BuildLockset::handleCall(Expr *Exp, NamedDecl *D, VarDecl *VD) {
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001117 AttrVec &ArgAttrs = D->getAttrs();
1118 for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
1119 Attr *Attr = ArgAttrs[i];
1120 switch (Attr->getKind()) {
1121 // When we encounter an exclusive lock function, we need to add the lock
1122 // to our lockset with kind exclusive.
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001123 case attr::ExclusiveLockFunction: {
1124 ExclusiveLockFunctionAttr *A = cast<ExclusiveLockFunctionAttr>(Attr);
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001125 addLocksToSet(LK_Exclusive, A, Exp, D, VD);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001126 break;
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001127 }
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001128
1129 // When we encounter a shared lock function, we need to add the lock
1130 // to our lockset with kind shared.
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001131 case attr::SharedLockFunction: {
1132 SharedLockFunctionAttr *A = cast<SharedLockFunctionAttr>(Attr);
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001133 addLocksToSet(LK_Shared, A, Exp, D, VD);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001134 break;
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001135 }
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001136
1137 // When we encounter an unlock function, we need to remove unlocked
1138 // mutexes from the lockset, and flag a warning if they are not there.
1139 case attr::UnlockFunction: {
1140 UnlockFunctionAttr *UFAttr = cast<UnlockFunctionAttr>(Attr);
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001141 removeLocksFromSet(UFAttr, Exp, D);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001142 break;
1143 }
1144
1145 case attr::ExclusiveLocksRequired: {
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001146 ExclusiveLocksRequiredAttr *ELRAttr =
1147 cast<ExclusiveLocksRequiredAttr>(Attr);
1148
1149 for (ExclusiveLocksRequiredAttr::args_iterator
1150 I = ELRAttr->args_begin(), E = ELRAttr->args_end(); I != E; ++I)
1151 warnIfMutexNotHeld(D, Exp, AK_Written, *I, POK_FunctionCall);
1152 break;
1153 }
1154
1155 case attr::SharedLocksRequired: {
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001156 SharedLocksRequiredAttr *SLRAttr = cast<SharedLocksRequiredAttr>(Attr);
1157
1158 for (SharedLocksRequiredAttr::args_iterator I = SLRAttr->args_begin(),
1159 E = SLRAttr->args_end(); I != E; ++I)
1160 warnIfMutexNotHeld(D, Exp, AK_Read, *I, POK_FunctionCall);
1161 break;
1162 }
1163
1164 case attr::LocksExcluded: {
1165 LocksExcludedAttr *LEAttr = cast<LocksExcludedAttr>(Attr);
1166 for (LocksExcludedAttr::args_iterator I = LEAttr->args_begin(),
1167 E = LEAttr->args_end(); I != E; ++I) {
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001168 MutexID Mutex(*I, Exp, D);
Caitlin Sadowski194418f2011-09-14 20:00:24 +00001169 if (!Mutex.isValid())
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001170 MutexID::warnInvalidLock(Handler, *I, Exp, D);
Caitlin Sadowski194418f2011-09-14 20:00:24 +00001171 else if (locksetContains(Mutex))
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001172 Handler.handleFunExcludesLock(D->getName(), Mutex.getName(),
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001173 Exp->getExprLoc());
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001174 }
1175 break;
1176 }
1177
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001178 // Ignore other (non thread-safety) attributes
1179 default:
1180 break;
1181 }
1182 }
1183}
1184
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001185
1186/// \brief Add lock to set, if the current block is in the taken branch of a
1187/// trylock.
1188template <class AttrType>
1189void BuildLockset::addTrylock(LockKind LK, AttrType *Attr, Expr *Exp,
1190 NamedDecl *FunDecl, const CFGBlock *PredBlock,
1191 const CFGBlock *CurrBlock, Expr *BrE, bool Neg) {
1192 // Find out which branch has the lock
1193 bool branch = 0;
1194 if (CXXBoolLiteralExpr *BLE = dyn_cast_or_null<CXXBoolLiteralExpr>(BrE)) {
1195 branch = BLE->getValue();
1196 }
1197 else if (IntegerLiteral *ILE = dyn_cast_or_null<IntegerLiteral>(BrE)) {
1198 branch = ILE->getValue().getBoolValue();
1199 }
1200 int branchnum = branch ? 0 : 1;
1201 if (Neg) branchnum = !branchnum;
1202
1203 // If we've taken the trylock branch, then add the lock
1204 int i = 0;
1205 for (CFGBlock::const_succ_iterator SI = PredBlock->succ_begin(),
1206 SE = PredBlock->succ_end(); SI != SE && i < 2; ++SI, ++i) {
1207 if (*SI == CurrBlock && i == branchnum) {
1208 addLocksToSet(LK, Attr, Exp, FunDecl, 0);
1209 }
1210 }
1211}
1212
1213
1214// If Cond can be traced back to a function call, return the call expression.
1215// The negate variable should be called with false, and will be set to true
1216// if the function call is negated, e.g. if (!mu.tryLock(...))
1217CallExpr* BuildLockset::getTrylockCallExpr(Stmt *Cond,
1218 LocalVariableMap::Context C,
1219 bool &Negate) {
1220 if (!Cond)
1221 return 0;
1222
1223 if (CallExpr *CallExp = dyn_cast<CallExpr>(Cond)) {
1224 return CallExp;
1225 }
1226 else if (ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(Cond)) {
1227 return getTrylockCallExpr(CE->getSubExpr(), C, Negate);
1228 }
1229 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Cond)) {
1230 Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C);
1231 return getTrylockCallExpr(E, C, Negate);
1232 }
1233 else if (UnaryOperator *UOP = dyn_cast<UnaryOperator>(Cond)) {
1234 if (UOP->getOpcode() == UO_LNot) {
1235 Negate = !Negate;
1236 return getTrylockCallExpr(UOP->getSubExpr(), C, Negate);
1237 }
1238 }
1239 // FIXME -- handle && and || as well.
1240 return NULL;
1241}
1242
1243
1244/// \brief Process a conditional branch from a previous block to the current
1245/// block, looking for trylock calls.
1246void BuildLockset::handleTrylock(Stmt *Cond, const CFGBlock *PredBlock,
1247 const CFGBlock *CurrBlock) {
1248 bool Negate = false;
1249 CallExpr *Exp = getTrylockCallExpr(Cond, LVarCtx, Negate);
1250 if (!Exp)
1251 return;
1252
1253 NamedDecl *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
1254 if(!FunDecl || !FunDecl->hasAttrs())
1255 return;
1256
1257 // If the condition is a call to a Trylock function, then grab the attributes
1258 AttrVec &ArgAttrs = FunDecl->getAttrs();
1259 for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
1260 Attr *Attr = ArgAttrs[i];
1261 switch (Attr->getKind()) {
1262 case attr::ExclusiveTrylockFunction: {
1263 ExclusiveTrylockFunctionAttr *A =
1264 cast<ExclusiveTrylockFunctionAttr>(Attr);
1265 addTrylock(LK_Exclusive, A, Exp, FunDecl, PredBlock, CurrBlock,
1266 A->getSuccessValue(), Negate);
1267 break;
1268 }
1269 case attr::SharedTrylockFunction: {
1270 SharedTrylockFunctionAttr *A =
1271 cast<SharedTrylockFunctionAttr>(Attr);
1272 addTrylock(LK_Shared, A, Exp, FunDecl, PredBlock, CurrBlock,
1273 A->getSuccessValue(), Negate);
1274 break;
1275 }
1276 default:
1277 break;
1278 }
1279 }
1280}
1281
1282
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001283/// \brief For unary operations which read and write a variable, we need to
1284/// check whether we hold any required mutexes. Reads are checked in
1285/// VisitCastExpr.
1286void BuildLockset::VisitUnaryOperator(UnaryOperator *UO) {
1287 switch (UO->getOpcode()) {
1288 case clang::UO_PostDec:
1289 case clang::UO_PostInc:
1290 case clang::UO_PreDec:
1291 case clang::UO_PreInc: {
1292 Expr *SubExp = UO->getSubExpr()->IgnoreParenCasts();
1293 checkAccess(SubExp, AK_Written);
1294 checkDereference(SubExp, AK_Written);
1295 break;
1296 }
1297 default:
1298 break;
1299 }
1300}
1301
1302/// For binary operations which assign to a variable (writes), we need to check
1303/// whether we hold any required mutexes.
1304/// FIXME: Deal with non-primitive types.
1305void BuildLockset::VisitBinaryOperator(BinaryOperator *BO) {
1306 if (!BO->isAssignmentOp())
1307 return;
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001308
1309 // adjust the context
1310 LVarCtx = LocalVarMap.getNextContext(CtxIndex, BO, LVarCtx);
1311
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001312 Expr *LHSExp = BO->getLHS()->IgnoreParenCasts();
1313 checkAccess(LHSExp, AK_Written);
1314 checkDereference(LHSExp, AK_Written);
1315}
1316
1317/// Whenever we do an LValue to Rvalue cast, we are reading a variable and
1318/// need to ensure we hold any required mutexes.
1319/// FIXME: Deal with non-primitive types.
1320void BuildLockset::VisitCastExpr(CastExpr *CE) {
1321 if (CE->getCastKind() != CK_LValueToRValue)
1322 return;
1323 Expr *SubExp = CE->getSubExpr()->IgnoreParenCasts();
1324 checkAccess(SubExp, AK_Read);
1325 checkDereference(SubExp, AK_Read);
1326}
1327
1328
DeLesley Hutchinsdf497822011-12-29 00:56:48 +00001329void BuildLockset::VisitCallExpr(CallExpr *Exp) {
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001330 NamedDecl *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl());
1331 if(!D || !D->hasAttrs())
1332 return;
1333 handleCall(Exp, D);
1334}
1335
1336void BuildLockset::VisitCXXConstructExpr(CXXConstructExpr *Exp) {
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001337 // FIXME -- only handles constructors in DeclStmt below.
1338}
1339
1340void BuildLockset::VisitDeclStmt(DeclStmt *S) {
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001341 // adjust the context
1342 LVarCtx = LocalVarMap.getNextContext(CtxIndex, S, LVarCtx);
1343
DeLesley Hutchins1fa3c062011-12-08 20:23:06 +00001344 DeclGroupRef DGrp = S->getDeclGroup();
1345 for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) {
1346 Decl *D = *I;
1347 if (VarDecl *VD = dyn_cast_or_null<VarDecl>(D)) {
1348 Expr *E = VD->getInit();
1349 if (CXXConstructExpr *CE = dyn_cast_or_null<CXXConstructExpr>(E)) {
1350 NamedDecl *CtorD = dyn_cast_or_null<NamedDecl>(CE->getConstructor());
1351 if (!CtorD || !CtorD->hasAttrs())
1352 return;
1353 handleCall(CE, CtorD, VD);
1354 }
1355 }
1356 }
DeLesley Hutchinse0eaa852011-10-21 18:06:53 +00001357}
1358
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001359
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +00001360/// \brief Compute the intersection of two locksets and issue warnings for any
1361/// locks in the symmetric difference.
1362///
1363/// This function is used at a merge point in the CFG when comparing the lockset
1364/// of each branch being merged. For example, given the following sequence:
1365/// A; if () then B; else C; D; we need to check that the lockset after B and C
1366/// are the same. In the event of a difference, we use the intersection of these
1367/// two locksets at the start of D.
Richard Smith2e515622012-02-03 04:45:26 +00001368Lockset ThreadSafetyAnalyzer::intersectAndWarn(const CFGBlockInfo &Block1,
1369 CFGBlockSide Side1,
1370 const CFGBlockInfo &Block2,
1371 CFGBlockSide Side2,
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001372 LockErrorKind LEK) {
Richard Smith2e515622012-02-03 04:45:26 +00001373 Lockset LSet1 = Block1.getSet(Side1);
1374 Lockset LSet2 = Block2.getSet(Side2);
1375
Caitlin Sadowski4e4bc752011-09-15 17:25:19 +00001376 Lockset Intersection = LSet1;
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001377 for (Lockset::iterator I = LSet2.begin(), E = LSet2.end(); I != E; ++I) {
1378 const MutexID &LSet2Mutex = I.getKey();
1379 const LockData &LSet2LockData = I.getData();
1380 if (const LockData *LD = LSet1.lookup(LSet2Mutex)) {
1381 if (LD->LKind != LSet2LockData.LKind) {
1382 Handler.handleExclusiveAndShared(LSet2Mutex.getName(),
1383 LSet2LockData.AcquireLoc,
1384 LD->AcquireLoc);
1385 if (LD->LKind != LK_Exclusive)
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001386 Intersection = LocksetFactory.add(Intersection, LSet2Mutex,
1387 LSet2LockData);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001388 }
1389 } else {
1390 Handler.handleMutexHeldEndOfScope(LSet2Mutex.getName(),
Richard Smith2e515622012-02-03 04:45:26 +00001391 LSet2LockData.AcquireLoc,
1392 Block1.getLocation(Side1), LEK);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001393 }
1394 }
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001395
1396 for (Lockset::iterator I = LSet1.begin(), E = LSet1.end(); I != E; ++I) {
1397 if (!LSet2.contains(I.getKey())) {
1398 const MutexID &Mutex = I.getKey();
1399 const LockData &MissingLock = I.getData();
1400 Handler.handleMutexHeldEndOfScope(Mutex.getName(),
Richard Smith2e515622012-02-03 04:45:26 +00001401 MissingLock.AcquireLoc,
1402 Block2.getLocation(Side2), LEK);
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001403 Intersection = LocksetFactory.remove(Intersection, Mutex);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001404 }
1405 }
1406 return Intersection;
1407}
1408
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001409Lockset ThreadSafetyAnalyzer::addLock(Lockset &LSet, Expr *MutexExp,
1410 const NamedDecl *D,
1411 LockKind LK, SourceLocation Loc) {
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001412 MutexID Mutex(MutexExp, 0, D);
Caitlin Sadowskicb967512011-09-15 17:43:08 +00001413 if (!Mutex.isValid()) {
DeLesley Hutchinsf1ac6372011-10-21 18:10:14 +00001414 MutexID::warnInvalidLock(Handler, MutexExp, 0, D);
Caitlin Sadowskicb967512011-09-15 17:43:08 +00001415 return LSet;
1416 }
1417 LockData NewLock(Loc, LK);
1418 return LocksetFactory.add(LSet, Mutex, NewLock);
1419}
1420
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001421/// \brief Check a function's CFG for thread-safety violations.
1422///
1423/// We traverse the blocks in the CFG, compute the set of mutexes that are held
1424/// at the end of each block, and issue warnings for thread safety violations.
1425/// Each block in the CFG is traversed exactly once.
Ted Kremenek1d26f482011-10-24 01:32:45 +00001426void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001427 CFG *CFGraph = AC.getCFG();
1428 if (!CFGraph) return;
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001429 const NamedDecl *D = dyn_cast_or_null<NamedDecl>(AC.getDecl());
1430
1431 if (!D)
1432 return; // Ignore anonymous functions for now.
1433 if (D->getAttr<NoThreadSafetyAnalysisAttr>())
1434 return;
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00001435 // FIXME: Do something a bit more intelligent inside constructor and
1436 // destructor code. Constructors and destructors must assume unique access
1437 // to 'this', so checks on member variable access is disabled, but we should
1438 // still enable checks on other objects.
1439 if (isa<CXXConstructorDecl>(D))
1440 return; // Don't check inside constructors.
1441 if (isa<CXXDestructorDecl>(D))
1442 return; // Don't check inside destructors.
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001443
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001444 std::vector<CFGBlockInfo> BlockInfo(CFGraph->getNumBlockIDs(),
1445 CFGBlockInfo::getEmptyBlockInfo(LocksetFactory, LocalVarMap));
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001446
1447 // We need to explore the CFG via a "topological" ordering.
1448 // That way, we will be guaranteed to have information about required
1449 // predecessor locksets when exploring a new block.
Ted Kremenek439ed162011-10-22 02:14:27 +00001450 PostOrderCFGView *SortedGraph = AC.getAnalysis<PostOrderCFGView>();
1451 PostOrderCFGView::CFGBlockSet VisitedBlocks(CFGraph);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001452
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001453 // Compute SSA names for local variables
1454 LocalVarMap.traverseCFG(CFGraph, SortedGraph, BlockInfo);
1455
Richard Smith2e515622012-02-03 04:45:26 +00001456 // Fill in source locations for all CFGBlocks.
1457 findBlockLocations(CFGraph, SortedGraph, BlockInfo);
1458
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001459 // Add locks from exclusive_locks_required and shared_locks_required
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00001460 // to initial lockset. Also turn off checking for lock and unlock functions.
1461 // FIXME: is there a more intelligent way to check lock/unlock functions?
Ted Kremenek439ed162011-10-22 02:14:27 +00001462 if (!SortedGraph->empty() && D->hasAttrs()) {
1463 const CFGBlock *FirstBlock = *SortedGraph->begin();
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001464 Lockset &InitialLockset = BlockInfo[FirstBlock->getBlockID()].EntrySet;
Caitlin Sadowskicb967512011-09-15 17:43:08 +00001465 const AttrVec &ArgAttrs = D->getAttrs();
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00001466 for (unsigned i = 0; i < ArgAttrs.size(); ++i) {
Caitlin Sadowskicb967512011-09-15 17:43:08 +00001467 Attr *Attr = ArgAttrs[i];
Caitlin Sadowski1748b122011-09-16 00:35:54 +00001468 SourceLocation AttrLoc = Attr->getLocation();
Caitlin Sadowskicb967512011-09-15 17:43:08 +00001469 if (SharedLocksRequiredAttr *SLRAttr
1470 = dyn_cast<SharedLocksRequiredAttr>(Attr)) {
1471 for (SharedLocksRequiredAttr::args_iterator
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00001472 SLRIter = SLRAttr->args_begin(),
1473 SLREnd = SLRAttr->args_end(); SLRIter != SLREnd; ++SLRIter)
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001474 InitialLockset = addLock(InitialLockset,
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001475 *SLRIter, D, LK_Shared,
Caitlin Sadowski1748b122011-09-16 00:35:54 +00001476 AttrLoc);
Caitlin Sadowskicb967512011-09-15 17:43:08 +00001477 } else if (ExclusiveLocksRequiredAttr *ELRAttr
1478 = dyn_cast<ExclusiveLocksRequiredAttr>(Attr)) {
1479 for (ExclusiveLocksRequiredAttr::args_iterator
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00001480 ELRIter = ELRAttr->args_begin(),
1481 ELREnd = ELRAttr->args_end(); ELRIter != ELREnd; ++ELRIter)
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001482 InitialLockset = addLock(InitialLockset,
DeLesley Hutchins9f80a972011-10-17 21:33:35 +00001483 *ELRIter, D, LK_Exclusive,
Caitlin Sadowski1748b122011-09-16 00:35:54 +00001484 AttrLoc);
DeLesley Hutchins2f13bec2012-02-16 17:13:43 +00001485 } else if (isa<UnlockFunctionAttr>(Attr)) {
1486 // Don't try to check unlock functions for now
1487 return;
1488 } else if (isa<ExclusiveLockFunctionAttr>(Attr)) {
1489 // Don't try to check lock functions for now
1490 return;
1491 } else if (isa<SharedLockFunctionAttr>(Attr)) {
1492 // Don't try to check lock functions for now
1493 return;
Caitlin Sadowskicb967512011-09-15 17:43:08 +00001494 }
1495 }
1496 }
1497
Ted Kremenek439ed162011-10-22 02:14:27 +00001498 for (PostOrderCFGView::iterator I = SortedGraph->begin(),
1499 E = SortedGraph->end(); I!= E; ++I) {
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001500 const CFGBlock *CurrBlock = *I;
1501 int CurrBlockID = CurrBlock->getBlockID();
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001502 CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001503
1504 // Use the default initial lockset in case there are no predecessors.
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001505 VisitedBlocks.insert(CurrBlock);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001506
1507 // Iterate through the predecessor blocks and warn if the lockset for all
1508 // predecessors is not the same. We take the entry lockset of the current
1509 // block to be the intersection of all previous locksets.
1510 // FIXME: By keeping the intersection, we may output more errors in future
1511 // for a lock which is not in the intersection, but was in the union. We
1512 // may want to also keep the union in future. As an example, let's say
1513 // the intersection contains Mutex L, and the union contains L and M.
1514 // Later we unlock M. At this point, we would output an error because we
1515 // never locked M; although the real error is probably that we forgot to
1516 // lock M on all code paths. Conversely, let's say that later we lock M.
1517 // In this case, we should compare against the intersection instead of the
1518 // union because the real error is probably that we forgot to unlock M on
1519 // all code paths.
1520 bool LocksetInitialized = false;
Richard Smithaacde712012-02-03 03:30:07 +00001521 llvm::SmallVector<CFGBlock*, 8> SpecialBlocks;
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001522 for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
1523 PE = CurrBlock->pred_end(); PI != PE; ++PI) {
1524
1525 // if *PI -> CurrBlock is a back edge
1526 if (*PI == 0 || !VisitedBlocks.alreadySet(*PI))
1527 continue;
1528
Richard Smithaacde712012-02-03 03:30:07 +00001529 // If the previous block ended in a 'continue' or 'break' statement, then
1530 // a difference in locksets is probably due to a bug in that block, rather
1531 // than in some other predecessor. In that case, keep the other
1532 // predecessor's lockset.
1533 if (const Stmt *Terminator = (*PI)->getTerminator()) {
1534 if (isa<ContinueStmt>(Terminator) || isa<BreakStmt>(Terminator)) {
1535 SpecialBlocks.push_back(*PI);
1536 continue;
1537 }
1538 }
1539
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001540 int PrevBlockID = (*PI)->getBlockID();
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001541 CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
1542
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001543 if (!LocksetInitialized) {
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001544 CurrBlockInfo->EntrySet = PrevBlockInfo->ExitSet;
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001545 LocksetInitialized = true;
1546 } else {
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001547 CurrBlockInfo->EntrySet =
Richard Smith2e515622012-02-03 04:45:26 +00001548 intersectAndWarn(*CurrBlockInfo, CBS_Entry,
1549 *PrevBlockInfo, CBS_Exit,
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001550 LEK_LockedSomePredecessors);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001551 }
1552 }
1553
Richard Smithaacde712012-02-03 03:30:07 +00001554 // Process continue and break blocks. Assume that the lockset for the
1555 // resulting block is unaffected by any discrepancies in them.
1556 for (unsigned SpecialI = 0, SpecialN = SpecialBlocks.size();
1557 SpecialI < SpecialN; ++SpecialI) {
1558 CFGBlock *PrevBlock = SpecialBlocks[SpecialI];
1559 int PrevBlockID = PrevBlock->getBlockID();
1560 CFGBlockInfo *PrevBlockInfo = &BlockInfo[PrevBlockID];
1561
1562 if (!LocksetInitialized) {
1563 CurrBlockInfo->EntrySet = PrevBlockInfo->ExitSet;
1564 LocksetInitialized = true;
1565 } else {
1566 // Determine whether this edge is a loop terminator for diagnostic
1567 // purposes. FIXME: A 'break' statement might be a loop terminator, but
1568 // it might also be part of a switch. Also, a subsequent destructor
1569 // might add to the lockset, in which case the real issue might be a
1570 // double lock on the other path.
1571 const Stmt *Terminator = PrevBlock->getTerminator();
1572 bool IsLoop = Terminator && isa<ContinueStmt>(Terminator);
1573
1574 // Do not update EntrySet.
Richard Smith2e515622012-02-03 04:45:26 +00001575 intersectAndWarn(*CurrBlockInfo, CBS_Entry, *PrevBlockInfo, CBS_Exit,
Richard Smithaacde712012-02-03 03:30:07 +00001576 IsLoop ? LEK_LockedSomeLoopIterations
1577 : LEK_LockedSomePredecessors);
1578 }
1579 }
1580
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001581 BuildLockset LocksetBuilder(this, *CurrBlockInfo);
DeLesley Hutchinsb4fa4182012-01-06 19:16:50 +00001582 CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(),
1583 PE = CurrBlock->pred_end();
1584 if (PI != PE) {
1585 // If the predecessor ended in a branch, then process any trylocks.
1586 // FIXME -- check to make sure there's only one predecessor.
1587 if (Stmt *TCE = (*PI)->getTerminatorCondition()) {
1588 LocksetBuilder.handleTrylock(TCE, *PI, CurrBlock);
1589 }
1590 }
1591
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001592 // Visit all the statements in the basic block.
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001593 for (CFGBlock::const_iterator BI = CurrBlock->begin(),
1594 BE = CurrBlock->end(); BI != BE; ++BI) {
DeLesley Hutchins6db51f72011-10-21 20:51:27 +00001595 switch (BI->getKind()) {
1596 case CFGElement::Statement: {
1597 const CFGStmt *CS = cast<CFGStmt>(&*BI);
1598 LocksetBuilder.Visit(const_cast<Stmt*>(CS->getStmt()));
1599 break;
1600 }
1601 // Ignore BaseDtor, MemberDtor, and TemporaryDtor for now.
1602 case CFGElement::AutomaticObjectDtor: {
1603 const CFGAutomaticObjDtor *AD = cast<CFGAutomaticObjDtor>(&*BI);
1604 CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>(
1605 AD->getDestructorDecl(AC.getASTContext()));
1606 if (!DD->hasAttrs())
1607 break;
1608
1609 // Create a dummy expression,
1610 VarDecl *VD = const_cast<VarDecl*>(AD->getVarDecl());
1611 DeclRefExpr DRE(VD, VD->getType(), VK_LValue,
1612 AD->getTriggerStmt()->getLocEnd());
1613 LocksetBuilder.handleCall(&DRE, DD);
1614 break;
1615 }
1616 default:
1617 break;
1618 }
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001619 }
DeLesley Hutchinsb37d2b52012-01-06 18:36:09 +00001620 CurrBlockInfo->ExitSet = LocksetBuilder.LSet;
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001621
1622 // For every back edge from CurrBlock (the end of the loop) to another block
1623 // (FirstLoopBlock) we need to check that the Lockset of Block is equal to
1624 // the one held at the beginning of FirstLoopBlock. We can look up the
1625 // Lockset held at the beginning of FirstLoopBlock in the EntryLockSets map.
1626 for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(),
1627 SE = CurrBlock->succ_end(); SI != SE; ++SI) {
1628
1629 // if CurrBlock -> *SI is *not* a back edge
1630 if (*SI == 0 || !VisitedBlocks.alreadySet(*SI))
1631 continue;
1632
1633 CFGBlock *FirstLoopBlock = *SI;
Richard Smith2e515622012-02-03 04:45:26 +00001634 CFGBlockInfo &PreLoop = BlockInfo[FirstLoopBlock->getBlockID()];
1635 CFGBlockInfo &LoopEnd = BlockInfo[CurrBlockID];
1636 intersectAndWarn(LoopEnd, CBS_Exit, PreLoop, CBS_Entry,
1637 LEK_LockedSomeLoopIterations);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001638 }
1639 }
1640
Richard Smith2e515622012-02-03 04:45:26 +00001641 CFGBlockInfo &Initial = BlockInfo[CFGraph->getEntry().getBlockID()];
1642 CFGBlockInfo &Final = BlockInfo[CFGraph->getExit().getBlockID()];
Caitlin Sadowski1748b122011-09-16 00:35:54 +00001643
1644 // FIXME: Should we call this function for all blocks which exit the function?
Richard Smith2e515622012-02-03 04:45:26 +00001645 intersectAndWarn(Initial, CBS_Entry, Final, CBS_Exit,
1646 LEK_LockedAtEndOfFunction);
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001647}
1648
1649} // end anonymous namespace
1650
1651
1652namespace clang {
1653namespace thread_safety {
1654
1655/// \brief Check a function's CFG for thread-safety violations.
1656///
1657/// We traverse the blocks in the CFG, compute the set of mutexes that are held
1658/// at the end of each block, and issue warnings for thread safety violations.
1659/// Each block in the CFG is traversed exactly once.
Ted Kremenek1d26f482011-10-24 01:32:45 +00001660void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001661 ThreadSafetyHandler &Handler) {
1662 ThreadSafetyAnalyzer Analyzer(Handler);
1663 Analyzer.runAnalysis(AC);
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001664}
1665
1666/// \brief Helper function that returns a LockKind required for the given level
1667/// of access.
1668LockKind getLockKindFromAccessKind(AccessKind AK) {
1669 switch (AK) {
1670 case AK_Read :
1671 return LK_Shared;
1672 case AK_Written :
1673 return LK_Exclusive;
1674 }
Benjamin Kramerafc5b152011-09-10 21:52:04 +00001675 llvm_unreachable("Unknown AccessKind");
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001676}
DeLesley Hutchinsa60448d2011-10-21 16:14:33 +00001677
Caitlin Sadowski402aa062011-09-09 16:11:56 +00001678}} // end namespace clang::thread_safety