Update aosp/master clang for rebase to r230699.
Change-Id: I6a546ab3d4ae37119eebb735e102cca4f80ab520
diff --git a/lib/Analysis/AnalysisDeclContext.cpp b/lib/Analysis/AnalysisDeclContext.cpp
index be66f32..4e623c8 100644
--- a/lib/Analysis/AnalysisDeclContext.cpp
+++ b/lib/Analysis/AnalysisDeclContext.cpp
@@ -530,14 +530,14 @@
return BV;
}
-std::pair<AnalysisDeclContext::referenced_decls_iterator,
- AnalysisDeclContext::referenced_decls_iterator>
+llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
if (!ReferencedBlockVars)
ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
- DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
- return std::make_pair(V->begin(), V->end());
+ const DeclVec *V =
+ LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
+ return llvm::make_range(V->begin(), V->end());
}
ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) {
diff --git a/lib/Analysis/BodyFarm.cpp b/lib/Analysis/BodyFarm.cpp
index 23286b2..7d1b235 100644
--- a/lib/Analysis/BodyFarm.cpp
+++ b/lib/Analysis/BodyFarm.cpp
@@ -13,11 +13,11 @@
//===----------------------------------------------------------------------===//
#include "BodyFarm.h"
-#include "clang/Analysis/CodeInjector.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/Analysis/CodeInjector.h"
#include "llvm/ADT/StringSwitch.h"
using namespace clang;
@@ -115,7 +115,7 @@
/* QualifierLoc = */ NestedNameSpecifierLoc(),
/* TemplateKWLoc = */ SourceLocation(),
/* D = */ const_cast<VarDecl*>(D),
- /* isEnclosingLocal = */ false,
+ /* RefersToEnclosingVariableOrCapture = */ false,
/* NameLoc = */ SourceLocation(),
/* T = */ D->getType(),
/* VK = */ VK_LValue);
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index d9073aa..5d06634 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -156,7 +156,7 @@
return !(*this == rhs);
}
- LLVM_EXPLICIT operator bool() const {
+ explicit operator bool() const {
return *this != const_iterator();
}
diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp
index f41a96d..91a8492 100644
--- a/lib/Analysis/CallGraph.cpp
+++ b/lib/Analysis/CallGraph.cpp
@@ -110,14 +110,13 @@
bool CallGraph::includeInGraph(const Decl *D) {
assert(D);
- if (!D->getBody())
+ if (!D->hasBody())
return false;
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// We skip function template definitions, as their semantics is
// only determined when they are instantiated.
- if (!FD->isThisDeclarationADefinition() ||
- FD->isDependentContext())
+ if (FD->isDependentContext())
return false;
IdentifierInfo *II = FD->getIdentifier();
@@ -125,11 +124,6 @@
return false;
}
- if (const ObjCMethodDecl *ID = dyn_cast<ObjCMethodDecl>(D)) {
- if (!ID->isThisDeclarationADefinition())
- return false;
- }
-
return true;
}
@@ -152,6 +146,9 @@
}
CallGraphNode *CallGraph::getOrInsertNode(Decl *F) {
+ if (F && !isa<ObjCMethodDecl>(F))
+ F = F->getCanonicalDecl();
+
CallGraphNode *&Node = FunctionMap[F];
if (Node)
return Node;
diff --git a/lib/Analysis/FormatString.cpp b/lib/Analysis/FormatString.cpp
index 8c663d8..662166c 100644
--- a/lib/Analysis/FormatString.cpp
+++ b/lib/Analysis/FormatString.cpp
@@ -552,6 +552,12 @@
// Objective-C specific specifiers.
case ObjCObjArg: return "@";
+ // FreeBSD kernel specific specifiers.
+ case FreeBSDbArg: return "b";
+ case FreeBSDDArg: return "D";
+ case FreeBSDrArg: return "r";
+ case FreeBSDyArg: return "y";
+
// GlibC specific specifiers.
case PrintErrno: return "m";
@@ -647,6 +653,9 @@
case ConversionSpecifier::XArg:
case ConversionSpecifier::nArg:
return true;
+ case ConversionSpecifier::FreeBSDrArg:
+ case ConversionSpecifier::FreeBSDyArg:
+ return Target.getTriple().isOSFreeBSD();
default:
return false;
}
@@ -677,6 +686,9 @@
case ConversionSpecifier::ScanListArg:
case ConversionSpecifier::ZArg:
return true;
+ case ConversionSpecifier::FreeBSDrArg:
+ case ConversionSpecifier::FreeBSDyArg:
+ return Target.getTriple().isOSFreeBSD();
default:
return false;
}
@@ -807,6 +819,10 @@
case ConversionSpecifier::SArg:
return LangOpt.ObjC1 || LangOpt.ObjC2;
case ConversionSpecifier::InvalidSpecifier:
+ case ConversionSpecifier::FreeBSDbArg:
+ case ConversionSpecifier::FreeBSDDArg:
+ case ConversionSpecifier::FreeBSDrArg:
+ case ConversionSpecifier::FreeBSDyArg:
case ConversionSpecifier::PrintErrno:
case ConversionSpecifier::DArg:
case ConversionSpecifier::OArg:
diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp
index 86b679c..0ab1580 100644
--- a/lib/Analysis/LiveVariables.cpp
+++ b/lib/Analysis/LiveVariables.cpp
@@ -356,11 +356,8 @@
}
void TransferFunctions::VisitBlockExpr(BlockExpr *BE) {
- AnalysisDeclContext::referenced_decls_iterator I, E;
- std::tie(I, E) =
- LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl());
- for ( ; I != E ; ++I) {
- const VarDecl *VD = *I;
+ for (const VarDecl *VD :
+ LV.analysisContext.getReferencedBlockVars(BE->getBlockDecl())) {
if (isAlwaysAlive(VD))
continue;
val.liveDecls = LV.DSetFact.add(val.liveDecls, VD);
diff --git a/lib/Analysis/PrintfFormatString.cpp b/lib/Analysis/PrintfFormatString.cpp
index 146635b..b8d3ec1 100644
--- a/lib/Analysis/PrintfFormatString.cpp
+++ b/lib/Analysis/PrintfFormatString.cpp
@@ -55,7 +55,8 @@
unsigned &argIndex,
const LangOptions &LO,
const TargetInfo &Target,
- bool Warn) {
+ bool Warn,
+ bool isFreeBSDKPrintf) {
using namespace clang::analyze_format_string;
using namespace clang::analyze_printf;
@@ -206,9 +207,24 @@
case '@': k = ConversionSpecifier::ObjCObjArg; break;
// Glibc specific.
case 'm': k = ConversionSpecifier::PrintErrno; break;
+ // FreeBSD kernel specific.
+ case 'b':
+ if (isFreeBSDKPrintf)
+ k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
+ break;
+ case 'r':
+ if (isFreeBSDKPrintf)
+ k = ConversionSpecifier::FreeBSDrArg; // int
+ break;
+ case 'y':
+ if (isFreeBSDKPrintf)
+ k = ConversionSpecifier::FreeBSDyArg; // int
+ break;
// Apple-specific.
case 'D':
- if (Target.getTriple().isOSDarwin())
+ if (isFreeBSDKPrintf)
+ k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
+ else if (Target.getTriple().isOSDarwin())
k = ConversionSpecifier::DArg;
break;
case 'O':
@@ -228,6 +244,10 @@
FS.setConversionSpecifier(CS);
if (CS.consumesDataArgument() && !FS.usesPositionalArg())
FS.setArgIndex(argIndex++);
+ // FreeBSD kernel specific.
+ if (k == ConversionSpecifier::FreeBSDbArg ||
+ k == ConversionSpecifier::FreeBSDDArg)
+ argIndex++;
if (k == ConversionSpecifier::InvalidSpecifier) {
// Assume the conversion takes one argument.
@@ -240,14 +260,16 @@
const char *I,
const char *E,
const LangOptions &LO,
- const TargetInfo &Target) {
+ const TargetInfo &Target,
+ bool isFreeBSDKPrintf) {
unsigned argIndex = 0;
// Keep looking for a format specifier until we have exhausted the string.
while (I != E) {
const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
- LO, Target, true);
+ LO, Target, true,
+ isFreeBSDKPrintf);
// Did a fail-stop error of any kind occur when parsing the specifier?
// If so, don't do any more processing.
if (FSR.shouldStop())
@@ -276,7 +298,8 @@
FormatStringHandler H;
while (I != E) {
const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
- LO, Target, false);
+ LO, Target, false,
+ false);
// Did a fail-stop error of any kind occur when parsing the specifier?
// If so, don't do any more processing.
if (FSR.shouldStop())
@@ -674,6 +697,8 @@
case ConversionSpecifier::GArg:
case ConversionSpecifier::aArg:
case ConversionSpecifier::AArg:
+ case ConversionSpecifier::FreeBSDrArg:
+ case ConversionSpecifier::FreeBSDyArg:
return true;
default:
@@ -699,6 +724,8 @@
case ConversionSpecifier::FArg:
case ConversionSpecifier::gArg:
case ConversionSpecifier::GArg:
+ case ConversionSpecifier::FreeBSDrArg:
+ case ConversionSpecifier::FreeBSDyArg:
return true;
default:
@@ -729,6 +756,8 @@
case ConversionSpecifier::FArg:
case ConversionSpecifier::gArg:
case ConversionSpecifier::GArg:
+ case ConversionSpecifier::FreeBSDrArg:
+ case ConversionSpecifier::FreeBSDyArg:
return true;
default:
@@ -753,6 +782,8 @@
case ConversionSpecifier::GArg:
case ConversionSpecifier::aArg:
case ConversionSpecifier::AArg:
+ case ConversionSpecifier::FreeBSDrArg:
+ case ConversionSpecifier::FreeBSDyArg:
return true;
default:
@@ -818,6 +849,8 @@
case ConversionSpecifier::gArg:
case ConversionSpecifier::GArg:
case ConversionSpecifier::sArg:
+ case ConversionSpecifier::FreeBSDrArg:
+ case ConversionSpecifier::FreeBSDyArg:
return true;
default:
diff --git a/lib/Analysis/ReachableCode.cpp b/lib/Analysis/ReachableCode.cpp
index b4a72a7..8165b09 100644
--- a/lib/Analysis/ReachableCode.cpp
+++ b/lib/Analysis/ReachableCode.cpp
@@ -13,15 +13,15 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/Analyses/ReachableCode.h"
-#include "clang/Lex/Preprocessor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprObjC.h"
-#include "clang/AST/StmtCXX.h"
#include "clang/AST/ParentMap.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/lib/Analysis/ThreadSafety.cpp b/lib/Analysis/ThreadSafety.cpp
index 4ddc21d..37819a7 100644
--- a/lib/Analysis/ThreadSafety.cpp
+++ b/lib/Analysis/ThreadSafety.cpp
@@ -22,10 +22,10 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/Analysis/Analyses/PostOrderCFGView.h"
#include "clang/Analysis/Analyses/ThreadSafety.h"
+#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
#include "clang/Analysis/Analyses/ThreadSafetyLogical.h"
#include "clang/Analysis/Analyses/ThreadSafetyTIL.h"
#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h"
-#include "clang/Analysis/Analyses/ThreadSafetyCommon.h"
#include "clang/Analysis/AnalysisContext.h"
#include "clang/Analysis/CFG.h"
#include "clang/Analysis/CFGStmtMap.h"
@@ -101,17 +101,22 @@
LockKind LKind; ///< exclusive or shared
SourceLocation AcquireLoc; ///< where it was acquired.
bool Asserted; ///< true if the lock was asserted
+ bool Declared; ///< true if the lock was declared
public:
FactEntry(const CapabilityExpr &CE, LockKind LK, SourceLocation Loc,
- bool Asrt)
- : CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Asserted(Asrt) {}
+ bool Asrt, bool Declrd = false)
+ : CapabilityExpr(CE), LKind(LK), AcquireLoc(Loc), Asserted(Asrt),
+ Declared(Declrd) {}
virtual ~FactEntry() {}
- LockKind kind() const { return LKind; }
+ LockKind kind() const { return LKind; }
SourceLocation loc() const { return AcquireLoc; }
bool asserted() const { return Asserted; }
+ bool declared() const { return Declared; }
+
+ void setDeclared(bool D) { Declared = D; }
virtual void
handleRemovalFromIntersection(const FactSet &FSet, FactManager &FactMan,
@@ -231,14 +236,59 @@
FactEntry *findPartialMatch(FactManager &FM,
const CapabilityExpr &CapE) const {
- auto I = std::find_if(begin(), end(), [&](FactID ID) {
+ auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool {
return FM[ID].partiallyMatches(CapE);
});
return I != end() ? &FM[*I] : nullptr;
}
+
+ bool containsMutexDecl(FactManager &FM, const ValueDecl* Vd) const {
+ auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool {
+ return FM[ID].valueDecl() == Vd;
+ });
+ return I != end();
+ }
};
+class ThreadSafetyAnalyzer;
+
+
+class BeforeSet {
+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)
+ {}
+
+ std::unique_ptr<BeforeVect> Vect;
+ int Visited;
+ };
+
+ typedef llvm::DenseMap<const ValueDecl*, BeforeInfo> BeforeMap;
+ typedef llvm::DenseMap<const ValueDecl*, bool> CycleMap;
+
+public:
+ BeforeSet() { }
+
+ BeforeInfo* insertAttrExprs(const ValueDecl* Vd,
+ ThreadSafetyAnalyzer& Analyzer);
+
+ void checkBeforeAfter(const ValueDecl* Vd,
+ const FactSet& FSet,
+ ThreadSafetyAnalyzer& Analyzer,
+ SourceLocation Loc, StringRef CapKind);
+
+private:
+ BeforeMap BMap;
+ CycleMap CycMap;
+};
+
+
+
typedef llvm::ImmutableMap<const NamedDecl*, unsigned> LocalVarContext;
class LocalVariableMap;
@@ -853,6 +903,7 @@
/// \brief Class which implements the core thread safety analysis routines.
class ThreadSafetyAnalyzer {
friend class BuildLockset;
+ friend class BeforeSet;
llvm::BumpPtrAllocator Bpa;
threadSafety::til::MemRegionRef Arena;
@@ -864,9 +915,11 @@
FactManager FactMan;
std::vector<CFGBlockInfo> BlockInfo;
+ BeforeSet* GlobalBeforeSet;
+
public:
- ThreadSafetyAnalyzer(ThreadSafetyHandler &H)
- : Arena(&Bpa), SxBuilder(Arena), Handler(H) {}
+ ThreadSafetyAnalyzer(ThreadSafetyHandler &H, BeforeSet* Bset)
+ : Arena(&Bpa), SxBuilder(Arena), Handler(H), GlobalBeforeSet(Bset) {}
bool inCurrentScope(const CapabilityExpr &CapE);
@@ -907,6 +960,135 @@
void runAnalysis(AnalysisDeclContext &AC);
};
+
+
+/// Process acquired_before and acquired_after attributes on Vd.
+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;
+
+ 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);
+ auto It = BMap.find(Cpvd);
+ if (It == BMap.end())
+ insertAttrExprs(Cpvd, Analyzer);
+ }
+ }
+ break;
+ }
+ case attr::AcquiredAfter: {
+ auto *A = cast<AcquiredAfterAttr>(At);
+
+ // 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 *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);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return Info;
+}
+
+
+/// Return true if any mutexes in FSet are in the acquired_before set of Vd.
+void BeforeSet::checkBeforeAfter(const ValueDecl* StartVd,
+ const FactSet& FSet,
+ ThreadSafetyAnalyzer& Analyzer,
+ SourceLocation Loc, StringRef CapKind) {
+ SmallVector<BeforeInfo*, 8> InfoVect;
+
+ // Do a depth-first traversal of Vd.
+ // Return true if there are cycles.
+ std::function<bool (const ValueDecl*)> traverse = [&](const ValueDecl* Vd) {
+ if (!Vd)
+ return false;
+
+ BeforeSet::BeforeInfo* Info;
+ auto It = BMap.find(Vd);
+ if (It == BMap.end())
+ Info = insertAttrExprs(Vd, Analyzer);
+ else
+ Info = &It->second;
+
+ if (Info->Visited == 1)
+ return true;
+
+ if (Info->Visited == 2)
+ return false;
+
+ BeforeVect* Bv = Info->Vect.get();
+ if (!Bv)
+ return false;
+
+ InfoVect.push_back(Info);
+ Info->Visited = 1;
+ for (auto *Vdb : *Bv) {
+ // Exclude mutexes in our immediate before set.
+ if (FSet.containsMutexDecl(Analyzer.FactMan, Vdb)) {
+ StringRef L1 = StartVd->getName();
+ StringRef L2 = Vdb->getName();
+ Analyzer.Handler.handleLockAcquiredBefore(CapKind, L1, L2, Loc);
+ }
+ // Transitively search other before sets, and warn on cycles.
+ if (traverse(Vdb)) {
+ if (CycMap.find(Vd) == CycMap.end()) {
+ CycMap.insert(std::make_pair(Vd, true));
+ StringRef L1 = Vd->getName();
+ Analyzer.Handler.handleBeforeAfterCycle(L1, Vd->getLocation());
+ }
+ }
+ }
+ Info->Visited = 2;
+ return false;
+ };
+
+ traverse(StartVd);
+
+ for (auto* Info : InfoVect)
+ Info->Visited = 0;
+}
+
+
+
/// \brief Gets the value decl pointer from DeclRefExprs or MemberExprs.
static const ValueDecl *getValueDecl(const Expr *Exp) {
if (const auto *CE = dyn_cast<ImplicitCastExpr>(Exp))
@@ -1020,7 +1202,13 @@
}
}
- // FIXME: deal with acquired before/after annotations.
+ // Check before/after constraints
+ if (Handler.issueBetaWarnings() &&
+ !Entry->asserted() && !Entry->declared()) {
+ GlobalBeforeSet->checkBeforeAfter(Entry->valueDecl(), FSet, *this,
+ Entry->loc(), DiagKind);
+ }
+
// FIXME: Don't always warn when we have support for reentrant locks.
if (FSet.findLock(FactMan, *Entry)) {
if (!Entry->asserted())
@@ -1230,7 +1418,7 @@
CapExprSet SharedLocksToAdd;
// If the condition is a call to a Trylock function, then grab the attributes
- for (auto *Attr : FunDecl->getAttrs()) {
+ for (auto *Attr : FunDecl->attrs()) {
switch (Attr->getKind()) {
case attr::ExclusiveTrylockFunction: {
ExclusiveTrylockFunctionAttr *A =
@@ -1500,13 +1688,23 @@
///
void BuildLockset::handleCall(Expr *Exp, const NamedDecl *D, VarDecl *VD) {
SourceLocation Loc = Exp->getExprLoc();
- const AttrVec &ArgAttrs = D->getAttrs();
CapExprSet ExclusiveLocksToAdd, SharedLocksToAdd;
CapExprSet ExclusiveLocksToRemove, SharedLocksToRemove, GenericLocksToRemove;
+ CapExprSet ScopedExclusiveReqs, ScopedSharedReqs;
StringRef CapDiagKind = "mutex";
- for(unsigned i = 0; i < ArgAttrs.size(); ++i) {
- Attr *At = const_cast<Attr*>(ArgAttrs[i]);
+ // Figure out if we're calling the constructor of scoped lockable class
+ bool isScopedVar = false;
+ if (VD) {
+ if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
+ const CXXRecordDecl* PD = CD->getParent();
+ if (PD && PD->hasAttr<ScopedLockableAttr>())
+ isScopedVar = true;
+ }
+ }
+
+ for(Attr *Atconst : D->attrs()) {
+ Attr* At = const_cast<Attr*>(Atconst);
switch (At->getKind()) {
// When we encounter a lock function, we need to add the lock to our
// lockset.
@@ -1564,10 +1762,17 @@
case attr::RequiresCapability: {
RequiresCapabilityAttr *A = cast<RequiresCapabilityAttr>(At);
- for (auto *Arg : A->args())
+ for (auto *Arg : A->args()) {
warnIfMutexNotHeld(D, Exp, A->isShared() ? AK_Read : AK_Written, Arg,
POK_FunctionCall, ClassifyDiagnostic(A),
Exp->getExprLoc());
+ // use for adopting a lock
+ if (isScopedVar) {
+ Analyzer->getMutexIDs(A->isShared() ? ScopedSharedReqs
+ : ScopedExclusiveReqs,
+ A, Exp, D, VD);
+ }
+ }
break;
}
@@ -1584,16 +1789,6 @@
}
}
- // Figure out if we're calling the constructor of scoped lockable class
- bool isScopedVar = false;
- if (VD) {
- if (const CXXConstructorDecl *CD = dyn_cast<const CXXConstructorDecl>(D)) {
- const CXXRecordDecl* PD = CD->getParent();
- if (PD && PD->hasAttr<ScopedLockableAttr>())
- isScopedVar = true;
- }
- }
-
// Add locks.
for (const auto &M : ExclusiveLocksToAdd)
Analyzer->addLock(FSet, llvm::make_unique<LockableFactEntry>(
@@ -1611,9 +1806,10 @@
// FIXME: does this store a pointer to DRE?
CapabilityExpr Scp = Analyzer->SxBuilder.translateAttrExpr(&DRE, nullptr);
- CapExprSet UnderlyingMutexes(ExclusiveLocksToAdd);
- std::copy(SharedLocksToAdd.begin(), SharedLocksToAdd.end(),
- std::back_inserter(UnderlyingMutexes));
+ std::copy(ScopedExclusiveReqs.begin(), ScopedExclusiveReqs.end(),
+ std::back_inserter(ExclusiveLocksToAdd));
+ std::copy(ScopedSharedReqs.begin(), ScopedSharedReqs.end(),
+ std::back_inserter(SharedLocksToAdd));
Analyzer->addLock(FSet,
llvm::make_unique<ScopedLockableFactEntry>(
Scp, MLoc, ExclusiveLocksToAdd, SharedLocksToAdd),
@@ -1940,14 +2136,13 @@
if (!SortedGraph->empty() && D->hasAttrs()) {
const CFGBlock *FirstBlock = *SortedGraph->begin();
FactSet &InitialLockset = BlockInfo[FirstBlock->getBlockID()].EntrySet;
- const AttrVec &ArgAttrs = D->getAttrs();
CapExprSet ExclusiveLocksToAdd;
CapExprSet SharedLocksToAdd;
StringRef CapDiagKind = "mutex";
SourceLocation Loc = D->getLocation();
- for (const auto *Attr : ArgAttrs) {
+ for (const auto *Attr : D->attrs()) {
Loc = Attr->getLocation();
if (const auto *A = dyn_cast<RequiresCapabilityAttr>(Attr)) {
getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A,
@@ -1979,14 +2174,16 @@
}
// FIXME -- Loc can be wrong here.
- for (const auto &Mu : ExclusiveLocksToAdd)
- addLock(InitialLockset,
- llvm::make_unique<LockableFactEntry>(Mu, LK_Exclusive, Loc),
- CapDiagKind, true);
- for (const auto &Mu : SharedLocksToAdd)
- addLock(InitialLockset,
- llvm::make_unique<LockableFactEntry>(Mu, LK_Shared, Loc),
- CapDiagKind, true);
+ for (const auto &Mu : ExclusiveLocksToAdd) {
+ auto Entry = llvm::make_unique<LockableFactEntry>(Mu, LK_Exclusive, Loc);
+ Entry->setDeclared(true);
+ addLock(InitialLockset, std::move(Entry), CapDiagKind, true);
+ }
+ for (const auto &Mu : SharedLocksToAdd) {
+ auto Entry = llvm::make_unique<LockableFactEntry>(Mu, LK_Shared, Loc);
+ Entry->setDeclared(true);
+ addLock(InitialLockset, std::move(Entry), CapDiagKind, true);
+ }
}
for (const auto *CurrBlock : *SortedGraph) {
@@ -2180,11 +2377,20 @@
/// at the end of each block, and issue warnings for thread safety violations.
/// Each block in the CFG is traversed exactly once.
void runThreadSafetyAnalysis(AnalysisDeclContext &AC,
- ThreadSafetyHandler &Handler) {
- ThreadSafetyAnalyzer Analyzer(Handler);
+ ThreadSafetyHandler &Handler,
+ BeforeSet **BSet) {
+ if (!*BSet)
+ *BSet = new BeforeSet;
+ ThreadSafetyAnalyzer Analyzer(Handler, *BSet);
Analyzer.runAnalysis(AC);
}
+
+void threadSafetyCleanup(BeforeSet* Cache) {
+ delete Cache;
+}
+
+
/// \brief Helper function that returns a LockKind required for the given level
/// of access.
LockKind getLockKindFromAccessKind(AccessKind AK) {
diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp
index 88a1cbf..563e059 100644
--- a/lib/Analysis/ThreadSafetyCommon.cpp
+++ b/lib/Analysis/ThreadSafetyCommon.cpp
@@ -28,7 +28,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-
#include <algorithm>
#include <climits>
#include <vector>
diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp
index 94f59f1..61a2592 100644
--- a/lib/Analysis/UninitializedValues.cpp
+++ b/lib/Analysis/UninitializedValues.cpp
@@ -419,7 +419,8 @@
// Classify arguments to std::move as used.
if (CE->getNumArgs() == 1) {
if (FunctionDecl *FD = CE->getDirectCallee()) {
- if (FD->getIdentifier() && FD->getIdentifier()->isStr("move")) {
+ if (FD->isInStdNamespace() && FD->getIdentifier() &&
+ FD->getIdentifier()->isStr("move")) {
classify(CE->getArg(0), Use);
return;
}