diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp | 135 |
1 files changed, 70 insertions, 65 deletions
diff --git a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp b/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp index e2c6ab5..b282a5b 100644 --- a/contrib/llvm/tools/clang/lib/Analysis/ThreadSafety.cpp +++ b/contrib/llvm/tools/clang/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); } } } |