aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Analysis/ThreadSafety.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:49:41 +0000
commit45b533945f0851ec234ca846e1af5ee1e4df0b6e (patch)
tree0a5b74c0b9ca73aded34df95c91fcaf3815230d8 /lib/Analysis/ThreadSafety.cpp
parent7e86edd64bfae4e324224452e4ea879b3371a4bd (diff)
downloadsrc-45b533945f0851ec234ca846e1af5ee1e4df0b6e.tar.gz
src-45b533945f0851ec234ca846e1af5ee1e4df0b6e.zip
Vendor import of clang trunk r256633:vendor/clang/clang-trunk-r256633
Notes
Notes: svn path=/vendor/clang/dist/; revision=292920 svn path=/vendor/clang/clang-trunk-r256633/; revision=292923; tag=vendor/clang/clang-trunk-r256633
Diffstat (limited to 'lib/Analysis/ThreadSafety.cpp')
-rw-r--r--lib/Analysis/ThreadSafety.cpp135
1 files changed, 70 insertions, 65 deletions
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index e2c6ab5d9485..b282a5bbd8d8 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -258,16 +258,15 @@ private:
typedef SmallVector<const ValueDecl*, 4> BeforeVect;
struct BeforeInfo {
- BeforeInfo() : Vect(nullptr), Visited(false) { }
- BeforeInfo(BeforeInfo &&O)
- : Vect(std::move(O.Vect)), Visited(O.Visited)
- {}
+ BeforeInfo() : Visited(0) {}
+ BeforeInfo(BeforeInfo &&O) : Vect(std::move(O.Vect)), Visited(O.Visited) {}
- std::unique_ptr<BeforeVect> Vect;
- int Visited;
+ BeforeVect Vect;
+ int Visited;
};
- typedef llvm::DenseMap<const ValueDecl*, BeforeInfo> BeforeMap;
+ typedef llvm::DenseMap<const ValueDecl *, std::unique_ptr<BeforeInfo>>
+ BeforeMap;
typedef llvm::DenseMap<const ValueDecl*, bool> CycleMap;
public:
@@ -276,6 +275,9 @@ public:
BeforeInfo* insertAttrExprs(const ValueDecl* Vd,
ThreadSafetyAnalyzer& Analyzer);
+ BeforeInfo *getBeforeInfoForDecl(const ValueDecl *Vd,
+ ThreadSafetyAnalyzer &Analyzer);
+
void checkBeforeAfter(const ValueDecl* Vd,
const FactSet& FSet,
ThreadSafetyAnalyzer& Analyzer,
@@ -787,7 +789,7 @@ static void findBlockLocations(CFG *CFGraph,
}
}
- if (!CurrBlockInfo->ExitLoc.isInvalid()) {
+ if (CurrBlockInfo->ExitLoc.isValid()) {
// This block contains at least one statement. Find the source location
// of the first statement in the block.
for (CFGBlock::const_iterator BI = CurrBlock->begin(),
@@ -965,26 +967,27 @@ public:
BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
ThreadSafetyAnalyzer& Analyzer) {
// Create a new entry for Vd.
- auto& Entry = BMap.FindAndConstruct(Vd);
- BeforeInfo* Info = &Entry.second;
- BeforeVect* Bv = nullptr;
+ BeforeInfo *Info = nullptr;
+ {
+ // Keep InfoPtr in its own scope in case BMap is modified later and the
+ // reference becomes invalid.
+ std::unique_ptr<BeforeInfo> &InfoPtr = BMap[Vd];
+ if (!InfoPtr)
+ InfoPtr.reset(new BeforeInfo());
+ Info = InfoPtr.get();
+ }
for (Attr* At : Vd->attrs()) {
switch (At->getKind()) {
case attr::AcquiredBefore: {
auto *A = cast<AcquiredBeforeAttr>(At);
- // Create a new BeforeVect for Vd if necessary.
- if (!Bv) {
- Bv = new BeforeVect;
- Info->Vect.reset(Bv);
- }
// Read exprs from the attribute, and add them to BeforeVect.
for (const auto *Arg : A->args()) {
CapabilityExpr Cp =
Analyzer.SxBuilder.translateAttrExpr(Arg, nullptr);
if (const ValueDecl *Cpvd = Cp.valueDecl()) {
- Bv->push_back(Cpvd);
+ Info->Vect.push_back(Cpvd);
auto It = BMap.find(Cpvd);
if (It == BMap.end())
insertAttrExprs(Cpvd, Analyzer);
@@ -1001,20 +1004,8 @@ BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
Analyzer.SxBuilder.translateAttrExpr(Arg, nullptr);
if (const ValueDecl *ArgVd = Cp.valueDecl()) {
// Get entry for mutex listed in attribute
- BeforeInfo* ArgInfo;
- auto It = BMap.find(ArgVd);
- if (It == BMap.end())
- ArgInfo = insertAttrExprs(ArgVd, Analyzer);
- else
- ArgInfo = &It->second;
-
- // Create a new BeforeVect if necessary.
- BeforeVect* ArgBv = ArgInfo->Vect.get();
- if (!ArgBv) {
- ArgBv = new BeforeVect;
- ArgInfo->Vect.reset(ArgBv);
- }
- ArgBv->push_back(Vd);
+ BeforeInfo *ArgInfo = getBeforeInfoForDecl(ArgVd, Analyzer);
+ ArgInfo->Vect.push_back(Vd);
}
}
break;
@@ -1027,6 +1018,18 @@ BeforeSet::BeforeInfo* BeforeSet::insertAttrExprs(const ValueDecl* Vd,
return Info;
}
+BeforeSet::BeforeInfo *
+BeforeSet::getBeforeInfoForDecl(const ValueDecl *Vd,
+ ThreadSafetyAnalyzer &Analyzer) {
+ auto It = BMap.find(Vd);
+ BeforeInfo *Info = nullptr;
+ if (It == BMap.end())
+ Info = insertAttrExprs(Vd, Analyzer);
+ else
+ Info = It->second.get();
+ assert(Info && "BMap contained nullptr?");
+ return Info;
+}
/// Return true if any mutexes in FSet are in the acquired_before set of Vd.
void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
@@ -1041,12 +1044,7 @@ void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
if (!Vd)
return false;
- BeforeSet::BeforeInfo* Info;
- auto It = BMap.find(Vd);
- if (It == BMap.end())
- Info = insertAttrExprs(Vd, Analyzer);
- else
- Info = &It->second;
+ BeforeSet::BeforeInfo *Info = getBeforeInfoForDecl(Vd, Analyzer);
if (Info->Visited == 1)
return true;
@@ -1054,13 +1052,12 @@ void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
if (Info->Visited == 2)
return false;
- BeforeVect* Bv = Info->Vect.get();
- if (!Bv)
+ if (Info->Vect.empty())
return false;
InfoVect.push_back(Info);
Info->Visited = 1;
- for (auto *Vdb : *Bv) {
+ for (auto *Vdb : Info->Vect) {
// Exclude mutexes in our immediate before set.
if (FSet.containsMutexDecl(Analyzer.FactMan, Vdb)) {
StringRef L1 = StartVd->getName();
@@ -1926,34 +1923,42 @@ void BuildLockset::VisitCallExpr(CallExpr *Exp) {
}
}
-
if (ExamineArgs) {
if (FunctionDecl *FD = Exp->getDirectCallee()) {
- unsigned Fn = FD->getNumParams();
- unsigned Cn = Exp->getNumArgs();
- unsigned Skip = 0;
-
- unsigned i = 0;
- if (OperatorFun) {
- if (isa<CXXMethodDecl>(FD)) {
- // First arg in operator call is implicit self argument,
- // and doesn't appear in the FunctionDecl.
- Skip = 1;
- Cn--;
- } else {
- // Ignore the first argument of operators; it's been checked above.
- i = 1;
+
+ // NO_THREAD_SAFETY_ANALYSIS does double duty here. Normally it
+ // only turns off checking within the body of a function, but we also
+ // use it to turn off checking in arguments to the function. This
+ // could result in some false negatives, but the alternative is to
+ // create yet another attribute.
+ //
+ if (!FD->hasAttr<NoThreadSafetyAnalysisAttr>()) {
+ unsigned Fn = FD->getNumParams();
+ unsigned Cn = Exp->getNumArgs();
+ unsigned Skip = 0;
+
+ unsigned i = 0;
+ if (OperatorFun) {
+ if (isa<CXXMethodDecl>(FD)) {
+ // First arg in operator call is implicit self argument,
+ // and doesn't appear in the FunctionDecl.
+ Skip = 1;
+ Cn--;
+ } else {
+ // Ignore the first argument of operators; it's been checked above.
+ i = 1;
+ }
+ }
+ // Ignore default arguments
+ unsigned n = (Fn < Cn) ? Fn : Cn;
+
+ for (; i < n; ++i) {
+ ParmVarDecl* Pvd = FD->getParamDecl(i);
+ Expr* Arg = Exp->getArg(i+Skip);
+ QualType Qt = Pvd->getType();
+ if (Qt->isReferenceType())
+ checkAccess(Arg, AK_Read, POK_PassByRef);
}
- }
- // Ignore default arguments
- unsigned n = (Fn < Cn) ? Fn : Cn;
-
- for (; i < n; ++i) {
- ParmVarDecl* Pvd = FD->getParamDecl(i);
- Expr* Arg = Exp->getArg(i+Skip);
- QualType Qt = Pvd->getType();
- if (Qt->isReferenceType())
- checkAccess(Arg, AK_Read, POK_PassByRef);
}
}
}