aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Analysis
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
commit6a0372513edbc473b538d2f724efac50405d6fef (patch)
tree8f7776b7310bebaf415ac5b69e46e9f928c37144 /lib/Analysis
parent809500fc2c13c8173a16b052304d983864e4a1e1 (diff)
downloadsrc-6a0372513edbc473b538d2f724efac50405d6fef.tar.gz
src-6a0372513edbc473b538d2f724efac50405d6fef.zip
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3vendor/clang/clang-release_33-r183502
Notes
Notes: svn path=/vendor/clang/dist/; revision=251609 svn path=/vendor/clang/clang-release_33-r183502/; revision=251610; tag=vendor/clang/clang-release_33-r183502
Diffstat (limited to 'lib/Analysis')
-rw-r--r--lib/Analysis/BodyFarm.cpp8
-rw-r--r--lib/Analysis/CFG.cpp5
-rw-r--r--lib/Analysis/ThreadSafety.cpp58
3 files changed, 57 insertions, 14 deletions
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index dda26bfab894..4d5c2ee236f9 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -194,8 +194,8 @@ static Stmt *create_dispatch_once(ASTContext &C, const FunctionDecl *D) {
// (1) Create the call.
DeclRefExpr *DR = M.makeDeclRefExpr(Block);
ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
- CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef<Expr*>(), C.VoidTy,
- VK_RValue, SourceLocation());
+ CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
+ SourceLocation());
// (2) Create the assignment to the predicate.
IntegerLiteral *IL =
@@ -257,8 +257,8 @@ static Stmt *create_dispatch_sync(ASTContext &C, const FunctionDecl *D) {
ASTMaker M(C);
DeclRefExpr *DR = M.makeDeclRefExpr(PV);
ImplicitCastExpr *ICE = M.makeLvalueToRvalue(DR, Ty);
- CallExpr *CE = new (C) CallExpr(C, ICE, ArrayRef<Expr*>(), C.VoidTy,
- VK_RValue, SourceLocation());
+ CallExpr *CE = new (C) CallExpr(C, ICE, None, C.VoidTy, VK_RValue,
+ SourceLocation());
return CE;
}
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index 1adb8b84e462..096c7a080bf6 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -1085,11 +1085,16 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
return VisitExprWithCleanups(cast<ExprWithCleanups>(S), asc);
case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXDefaultInitExprClass:
// FIXME: The expression inside a CXXDefaultArgExpr is owned by the
// called function's declaration, not by the caller. If we simply add
// this expression to the CFG, we could end up with the same Expr
// appearing multiple times.
// PR13385 / <rdar://problem/12156507>
+ //
+ // It's likewise possible for multiple CXXDefaultInitExprs for the same
+ // expression to be used in the same function (through aggregate
+ // initialization).
return VisitStmt(S, asc);
case Stmt::CXXBindTemporaryExprClass:
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index 4fe342dcc8c2..479d9a301f4b 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -2279,6 +2279,10 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
// Fill in source locations for all CFGBlocks.
findBlockLocations(CFGraph, SortedGraph, BlockInfo);
+ MutexIDList ExclusiveLocksAcquired;
+ MutexIDList SharedLocksAcquired;
+ MutexIDList LocksReleased;
+
// Add locks from exclusive_locks_required and shared_locks_required
// to initial lockset. Also turn off checking for lock and unlock functions.
// FIXME: is there a more intelligent way to check lock/unlock functions?
@@ -2300,15 +2304,30 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
} else if (SharedLocksRequiredAttr *A
= dyn_cast<SharedLocksRequiredAttr>(Attr)) {
getMutexIDs(SharedLocksToAdd, A, (Expr*) 0, D);
- } else if (isa<UnlockFunctionAttr>(Attr)) {
- // Don't try to check unlock functions for now
- return;
- } else if (isa<ExclusiveLockFunctionAttr>(Attr)) {
- // Don't try to check lock functions for now
- return;
- } else if (isa<SharedLockFunctionAttr>(Attr)) {
- // Don't try to check lock functions for now
- return;
+ } else if (UnlockFunctionAttr *A = dyn_cast<UnlockFunctionAttr>(Attr)) {
+ if (!Handler.issueBetaWarnings())
+ return;
+ // UNLOCK_FUNCTION() is used to hide the underlying lock implementation.
+ // We must ignore such methods.
+ if (A->args_size() == 0)
+ return;
+ // FIXME -- deal with exclusive vs. shared unlock functions?
+ getMutexIDs(ExclusiveLocksToAdd, A, (Expr*) 0, D);
+ getMutexIDs(LocksReleased, A, (Expr*) 0, D);
+ } else if (ExclusiveLockFunctionAttr *A
+ = dyn_cast<ExclusiveLockFunctionAttr>(Attr)) {
+ if (!Handler.issueBetaWarnings())
+ return;
+ if (A->args_size() == 0)
+ return;
+ getMutexIDs(ExclusiveLocksAcquired, A, (Expr*) 0, D);
+ } else if (SharedLockFunctionAttr *A
+ = dyn_cast<SharedLockFunctionAttr>(Attr)) {
+ if (!Handler.issueBetaWarnings())
+ return;
+ if (A->args_size() == 0)
+ return;
+ getMutexIDs(SharedLocksAcquired, A, (Expr*) 0, D);
} else if (isa<ExclusiveTrylockFunctionAttr>(Attr)) {
// Don't try to check trylock functions for now
return;
@@ -2491,8 +2510,27 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
if (!Final->Reachable)
return;
+ // By default, we expect all locks held on entry to be held on exit.
+ FactSet ExpectedExitSet = Initial->EntrySet;
+
+ // Adjust the expected exit set by adding or removing locks, as declared
+ // by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then
+ // issue the appropriate warning.
+ // FIXME: the location here is not quite right.
+ for (unsigned i=0,n=ExclusiveLocksAcquired.size(); i<n; ++i) {
+ ExpectedExitSet.addLock(FactMan, ExclusiveLocksAcquired[i],
+ LockData(D->getLocation(), LK_Exclusive));
+ }
+ for (unsigned i=0,n=SharedLocksAcquired.size(); i<n; ++i) {
+ ExpectedExitSet.addLock(FactMan, SharedLocksAcquired[i],
+ LockData(D->getLocation(), LK_Shared));
+ }
+ for (unsigned i=0,n=LocksReleased.size(); i<n; ++i) {
+ ExpectedExitSet.removeLock(FactMan, LocksReleased[i]);
+ }
+
// FIXME: Should we call this function for all blocks which exit the function?
- intersectAndWarn(Initial->EntrySet, Final->ExitSet,
+ intersectAndWarn(ExpectedExitSet, Final->ExitSet,
Final->ExitLoc,
LEK_LockedAtEndOfFunction,
LEK_NotLockedAtEndOfFunction,