diff options
Diffstat (limited to 'lib/Analysis/ThreadSafety.cpp')
-rw-r--r-- | lib/Analysis/ThreadSafety.cpp | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp index 504a24c0fa..e8bae52bd5 100644 --- a/lib/Analysis/ThreadSafety.cpp +++ b/lib/Analysis/ThreadSafety.cpp @@ -119,6 +119,10 @@ public: iterator end() { return Blocks.rend(); } + + bool empty() { + return begin() == end(); + } }; /// \brief A MutexID object uniquely identifies a particular mutex, and @@ -640,7 +644,7 @@ static Lockset intersectAndWarn(ThreadSafetyHandler &Handler, } /// \brief Returns the location of the first Stmt in a Block. -static SourceLocation getFirstStmtLocation(CFGBlock *Block) { +static SourceLocation getFirstStmtLocation(const CFGBlock *Block) { SourceLocation Loc; for (CFGBlock::const_iterator BI = Block->begin(), BE = Block->end(); BI != BE; ++BI) { @@ -649,13 +653,26 @@ static SourceLocation getFirstStmtLocation(CFGBlock *Block) { if (Loc.isValid()) return Loc; } } - if (Stmt *S = Block->getTerminator().getStmt()) { + if (const Stmt *S = Block->getTerminator().getStmt()) { Loc = S->getLocStart(); if (Loc.isValid()) return Loc; } return Loc; } +static Lockset addLock(ThreadSafetyHandler &Handler, + Lockset::Factory &LocksetFactory, + Lockset &LSet, Expr *LockExp, LockKind LK, + SourceLocation Loc) { + MutexID Mutex(LockExp, 0); + if (!Mutex.isValid()) { + Handler.handleInvalidLockExp(LockExp->getExprLoc()); + return LSet; + } + LockData NewLock(Loc, LK); + return LocksetFactory.add(LSet, Mutex, NewLock); +} + namespace clang { namespace thread_safety { /// \brief Check a function's CFG for thread-safety violations. @@ -684,6 +701,32 @@ void runThreadSafetyAnalysis(AnalysisContext &AC, TopologicallySortedCFG SortedGraph(CFGraph); CFGBlockSet VisitedBlocks(CFGraph); + if (!SortedGraph.empty() && D->hasAttrs()) { + const CFGBlock *FirstBlock = *SortedGraph.begin(); + Lockset &InitialLockset = EntryLocksets[FirstBlock->getBlockID()]; + const AttrVec &ArgAttrs = D->getAttrs(); + for(unsigned i = 0; i < ArgAttrs.size(); ++i) { + Attr *Attr = ArgAttrs[i]; + if (SharedLocksRequiredAttr *SLRAttr + = dyn_cast<SharedLocksRequiredAttr>(Attr)) { + for (SharedLocksRequiredAttr::args_iterator + SLRIter = SLRAttr->args_begin(), + SLREnd = SLRAttr->args_end(); SLRIter != SLREnd; ++SLRIter) + InitialLockset = addLock(Handler, LocksetFactory, InitialLockset, + *SLRIter, LK_Shared, + getFirstStmtLocation(FirstBlock)); + } else if (ExclusiveLocksRequiredAttr *ELRAttr + = dyn_cast<ExclusiveLocksRequiredAttr>(Attr)) { + for (ExclusiveLocksRequiredAttr::args_iterator + ELRIter = ELRAttr->args_begin(), + ELREnd = ELRAttr->args_end(); ELRIter != ELREnd; ++ELRIter) + InitialLockset = addLock(Handler, LocksetFactory, InitialLockset, + *ELRIter, LK_Exclusive, + getFirstStmtLocation(FirstBlock)); + } + } + } + for (TopologicallySortedCFG::iterator I = SortedGraph.begin(), E = SortedGraph.end(); I!= E; ++I) { const CFGBlock *CurrBlock = *I; |