Lines Matching +full:se +full:- +full:neg

1 //===- ThreadSafety.cpp ---------------------------------------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // A intra-procedural analysis for thread safety (e.g. deadlocks and race
15 //===----------------------------------------------------------------------===//
73 Loc = DeclExp->getExprLoc(); in warnInvalidLock()
103 /// FIXME: this analysis does not currently support re-entrant locking.
166 return static_cast<unsigned short>(Facts.size() - 1); in newFact()
219 for (unsigned i = 0; i < n-1; ++i) { in removeLock()
221 FactIDs[i] = FactIDs[n-1]; in removeLock()
226 if (FM[FactIDs[n-1]].matches(CapE)) { in removeLock()
248 auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool { in findLockUniv()
256 auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool { in findPartialMatch()
263 auto I = std::find_if(begin(), end(), [&](FactID ID) -> bool { in containsMutexDecl()
369 // valid definitions. It provides SSA-like functionality when traversing the
374 // with their SSA-names. Instead, we compute a Context for each point in the
375 // code, which maps local variables to the appropriate SSA-name. This map
424 // index 0 is a placeholder for undefined variables (aka phi-nodes). in LocalVariableMap()
480 Dec->printName(llvm::errs()); in dumpVarDefinitionName()
492 if (Exp) Exp->dump(); in dump()
504 D->printName(llvm::errs()); in dumpContext()
505 llvm::errs() << " -> "; in dumpContext()
519 unsigned getContextIndex() { return SavedContexts.size()-1; } in getContextIndex()
609 const DeclGroupRef DGrp = S->getDeclGroup(); in VisitDeclStmt()
612 const Expr *E = VD->getInit(); in VisitDeclStmt()
615 QualType T = VD->getType(); in VisitDeclStmt()
616 if (T.isTrivialType(VD->getASTContext())) { in VisitDeclStmt()
617 Ctx = VMap->addDefinition(VD, E, Ctx); in VisitDeclStmt()
623 VMap->saveContext(S, Ctx); in VisitDeclStmt()
628 if (!BO->isAssignmentOp()) in VisitBinaryOperator()
631 Expr *LHSExp = BO->getLHS()->IgnoreParenCasts(); in VisitBinaryOperator()
635 const ValueDecl *VDec = DRE->getDecl(); in VisitBinaryOperator()
637 if (BO->getOpcode() == BO_Assign) in VisitBinaryOperator()
638 Ctx = VMap->updateDefinition(VDec, BO->getRHS(), Ctx); in VisitBinaryOperator()
640 // FIXME -- handle compound assignment operators in VisitBinaryOperator()
641 Ctx = VMap->clearDefinition(VDec, Ctx); in VisitBinaryOperator()
642 VMap->saveContext(BO, Ctx); in VisitBinaryOperator()
666 // (We use this for a naive implementation of SSA on loop back-edges.)
681 assert(VDef->isReference()); in intersectBackEdge()
685 VDef->Ref = 0; // Mark this variable as undefined in intersectBackEdge()
690 // (excluding back-edges) are visited before the block itself. At
700 // int x = 0; { x -> x1 | x1 = 0 }
701 // int y = 0; { x -> x1, y -> y1 | y1 = 0, x1 = 0 }
702 // if (b) x = 1; { x -> x2, y -> y1 | x2 = 1, y1 = 0, ... }
703 // else x = 2; { x -> x3, y -> y1 | x3 = 2, x2 = 1, ... }
704 // ... { y -> y1 (x is unknown) | x3 = 2, x2 = 1, ... }
713 // The initial traversal does not capture back-edges, so those need to be
718 // set to NULL if the variable has changed on the back-edge (i.e. a phi
722 // int x = 0, y = 0; { x -> x1, y -> y1 | y1 = 0, x1 = 0 }
723 // while (b) { x -> x2, y -> y1 | [1st:] x2=x1; [2nd:] x2=NULL; }
724 // x = x+1; { x -> x3, y -> y1 | x3 = x2 + 1, ... }
725 // ... { y -> y1 | x3 = 2, x2 = 1, ... }
732 unsigned CurrBlockID = CurrBlock->getBlockID(); in traverseCFG()
740 for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(), in traverseCFG()
741 PE = CurrBlock->pred_end(); PI != PE; ++PI) { in traverseCFG()
742 // if *PI -> CurrBlock is a back edge, so skip it in traverseCFG()
748 unsigned PrevBlockID = (*PI)->getBlockID(); in traverseCFG()
752 CurrBlockInfo->EntryContext = PrevBlockInfo->ExitContext; in traverseCFG()
756 CurrBlockInfo->EntryContext = in traverseCFG()
757 intersectContexts(CurrBlockInfo->EntryContext, in traverseCFG()
758 PrevBlockInfo->ExitContext); in traverseCFG()
762 // Duplicate the context if we have back-edges, so we can call in traverseCFG()
765 CurrBlockInfo->EntryContext = in traverseCFG()
766 createReferenceContext(CurrBlockInfo->EntryContext); in traverseCFG()
769 saveContext(nullptr, CurrBlockInfo->EntryContext); in traverseCFG()
770 CurrBlockInfo->EntryIndex = getContextIndex(); in traverseCFG()
773 VarMapBuilder VMapBuilder(this, CurrBlockInfo->EntryContext); in traverseCFG()
785 CurrBlockInfo->ExitContext = VMapBuilder.Ctx; in traverseCFG()
788 for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(), in traverseCFG()
789 SE = CurrBlock->succ_end(); SI != SE; ++SI) { in traverseCFG() local
790 // if CurrBlock -> *SI is *not* a back edge in traverseCFG()
795 Context LoopBegin = BlockInfo[FirstLoopBlock->getBlockID()].EntryContext; in traverseCFG()
796 Context LoopEnd = CurrBlockInfo->ExitContext; in traverseCFG()
802 unsigned exitID = CFGraph->getExit().getBlockID(); in traverseCFG()
812 CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlock->getBlockID()]; in findBlockLocations()
816 if (const Stmt *S = CurrBlock->getTerminatorStmt()) { in findBlockLocations()
817 CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = S->getBeginLoc(); in findBlockLocations()
819 for (CFGBlock::const_reverse_iterator BI = CurrBlock->rbegin(), in findBlockLocations()
820 BE = CurrBlock->rend(); BI != BE; ++BI) { in findBlockLocations()
822 if (std::optional<CFGStmt> CS = BI->getAs<CFGStmt>()) { in findBlockLocations()
823 CurrBlockInfo->ExitLoc = CS->getStmt()->getBeginLoc(); in findBlockLocations()
829 if (CurrBlockInfo->ExitLoc.isValid()) { in findBlockLocations()
835 CurrBlockInfo->EntryLoc = CS->getStmt()->getBeginLoc(); in findBlockLocations()
839 } else if (CurrBlock->pred_size() == 1 && *CurrBlock->pred_begin() && in findBlockLocations()
840 CurrBlock != &CFGraph->getExit()) { in findBlockLocations()
843 CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = in findBlockLocations()
844 BlockInfo[(*CurrBlock->pred_begin())->getBlockID()].ExitLoc; in findBlockLocations()
845 } else if (CurrBlock->succ_size() == 1 && *CurrBlock->succ_begin()) { in findBlockLocations()
848 CurrBlockInfo->EntryLoc = CurrBlockInfo->ExitLoc = in findBlockLocations()
849 BlockInfo[(*CurrBlock->succ_begin())->getBlockID()].EntryLoc; in findBlockLocations()
977 Handler->handleDoubleLock(Cp.getKind(), Cp.toString(), Fact->loc(), in lock()
994 if (const FactEntry *Neg = FSet.findLock(FactMan, !Cp)) in unlock() local
995 PrevLoc = Neg->loc(); in unlock()
996 Handler->handleUnmatchedUnlock(Cp.getKind(), Cp.toString(), loc, PrevLoc); in unlock()
1039 Expr *BrE, bool Neg);
1091 for (const auto *At : Vd->attrs()) { in insertAttrExprs()
1092 switch (At->getKind()) { in insertAttrExprs()
1097 for (const auto *Arg : A->args()) { in insertAttrExprs()
1101 Info->Vect.push_back(Cpvd); in insertAttrExprs()
1113 for (const auto *Arg : A->args()) { in insertAttrExprs()
1119 ArgInfo->Vect.push_back(Vd); in insertAttrExprs()
1140 Info = It->second.get(); in getBeforeInfoForDecl()
1152 // Do a depth-first traversal of Vd. in checkBeforeAfter()
1160 if (Info->Visited == 1) in checkBeforeAfter()
1163 if (Info->Visited == 2) in checkBeforeAfter()
1166 if (Info->Vect.empty()) in checkBeforeAfter()
1170 Info->Visited = 1; in checkBeforeAfter()
1171 for (const auto *Vdb : Info->Vect) { in checkBeforeAfter()
1174 StringRef L1 = StartVd->getName(); in checkBeforeAfter()
1175 StringRef L2 = Vdb->getName(); in checkBeforeAfter()
1182 StringRef L1 = Vd->getName(); in checkBeforeAfter()
1183 Analyzer.Handler.handleBeforeAfterCycle(L1, Vd->getLocation()); in checkBeforeAfter()
1187 Info->Visited = 2; in checkBeforeAfter()
1194 Info->Visited = 0; in checkBeforeAfter()
1200 return getValueDecl(CE->getSubExpr()); in getValueDecl()
1203 return DR->getDecl(); in getValueDecl()
1206 return ME->getMemberDecl(); in getValueDecl()
1219 static yes& test(Inner *I, decltype(I->args()) * = nullptr);
1235 const ValueDecl *VD = LP->clangDecl(); in inCurrentScope()
1237 if (!VD || !VD->isDefinedOutsideFunctionOrMethod()) in inCurrentScope()
1240 if (isa<CXXRecordDecl>(VD->getDeclContext())) in inCurrentScope()
1250 const ValueDecl *VD = P->clangDecl(); in inCurrentScope()
1251 return VD->getDeclContext() == CurrentFunction->getDeclContext(); in inCurrentScope()
1258 /// \param ReqAttr -- true if this is part of an initial Requires attribute.
1262 if (Entry->shouldIgnore()) in addLock()
1265 if (!ReqAttr && !Entry->negative()) { in addLock()
1273 if (inCurrentScope(*Entry) && !Entry->asserted()) in addLock()
1274 Handler.handleNegativeNotHeld(Entry->getKind(), Entry->toString(), in addLock()
1275 NegC.toString(), Entry->loc()); in addLock()
1281 !Entry->asserted() && !Entry->declared()) { in addLock()
1282 GlobalBeforeSet->checkBeforeAfter(Entry->valueDecl(), FSet, *this, in addLock()
1283 Entry->loc(), Entry->getKind()); in addLock()
1288 if (!Entry->asserted()) in addLock()
1289 Cp->handleLock(FSet, FactMan, *Entry, Handler); in addLock()
1306 if (const FactEntry *Neg = FSet.findLock(FactMan, !Cp)) in removeLock() local
1307 PrevLoc = Neg->loc(); in removeLock()
1315 if (ReceivedKind != LK_Generic && LDat->kind() != ReceivedKind) { in removeLock()
1316 Handler.handleIncorrectUnlockKind(Cp.getKind(), Cp.toString(), LDat->kind(), in removeLock()
1317 ReceivedKind, LDat->loc(), UnlockLoc); in removeLock()
1320 LDat->handleUnlock(FSet, FactMan, Cp, UnlockLoc, FullyRemove, Handler); in removeLock()
1329 if (Attr->args_size() == 0) { in getMutexIDs()
1342 for (const auto *Arg : Attr->args()) { in getMutexIDs()
1362 Expr *BrE, bool Neg) { in getMutexIDs() argument
1366 branch = BLE->getValue(); in getMutexIDs()
1368 branch = ILE->getValue().getBoolValue(); in getMutexIDs()
1371 if (Neg) in getMutexIDs()
1376 for (CFGBlock::const_succ_iterator SI = PredBlock->succ_begin(), in getMutexIDs()
1377 SE = PredBlock->succ_end(); SI != SE && i < 2; ++SI, ++i) { in getMutexIDs() local
1388 TCond = BLE->getValue(); in getStaticBooleanValue()
1391 TCond = ILE->getValue().getBoolValue(); in getStaticBooleanValue()
1394 return getStaticBooleanValue(CE->getSubExpr(), TCond); in getStaticBooleanValue()
1408 if (CallExp->getBuiltinCallee() == Builtin::BI__builtin_expect) in getTrylockCallExpr()
1409 return getTrylockCallExpr(CallExp->getArg(0), C, Negate); in getTrylockCallExpr()
1413 return getTrylockCallExpr(PE->getSubExpr(), C, Negate); in getTrylockCallExpr()
1415 return getTrylockCallExpr(CE->getSubExpr(), C, Negate); in getTrylockCallExpr()
1417 return getTrylockCallExpr(FE->getSubExpr(), C, Negate); in getTrylockCallExpr()
1419 const Expr *E = LocalVarMap.lookupExpr(DRE->getDecl(), C); in getTrylockCallExpr()
1423 if (UOP->getOpcode() == UO_LNot) { in getTrylockCallExpr()
1425 return getTrylockCallExpr(UOP->getSubExpr(), C, Negate); in getTrylockCallExpr()
1430 if (BOP->getOpcode() == BO_EQ || BOP->getOpcode() == BO_NE) { in getTrylockCallExpr()
1431 if (BOP->getOpcode() == BO_NE) in getTrylockCallExpr()
1435 if (getStaticBooleanValue(BOP->getRHS(), TCond)) { in getTrylockCallExpr()
1437 return getTrylockCallExpr(BOP->getLHS(), C, Negate); in getTrylockCallExpr()
1440 if (getStaticBooleanValue(BOP->getLHS(), TCond)) { in getTrylockCallExpr()
1442 return getTrylockCallExpr(BOP->getRHS(), C, Negate); in getTrylockCallExpr()
1446 if (BOP->getOpcode() == BO_LAnd) { in getTrylockCallExpr()
1448 return getTrylockCallExpr(BOP->getRHS(), C, Negate); in getTrylockCallExpr()
1450 if (BOP->getOpcode() == BO_LOr) in getTrylockCallExpr()
1451 return getTrylockCallExpr(BOP->getRHS(), C, Negate); in getTrylockCallExpr()
1455 if (getStaticBooleanValue(COP->getTrueExpr(), TCond) && in getTrylockCallExpr()
1456 getStaticBooleanValue(COP->getFalseExpr(), FCond)) { in getTrylockCallExpr()
1458 return getTrylockCallExpr(COP->getCond(), C, Negate); in getTrylockCallExpr()
1461 return getTrylockCallExpr(COP->getCond(), C, Negate); in getTrylockCallExpr()
1477 const Stmt *Cond = PredBlock->getTerminatorCondition(); in getEdgeLockset()
1478 // We don't acquire try-locks on ?: branches, only when its result is used. in getEdgeLockset()
1479 if (!Cond || isa<ConditionalOperator>(PredBlock->getTerminatorStmt())) in getEdgeLockset()
1483 const CFGBlockInfo *PredBlockInfo = &BlockInfo[PredBlock->getBlockID()]; in getEdgeLockset()
1484 const LocalVarContext &LVarCtx = PredBlockInfo->ExitContext; in getEdgeLockset()
1490 auto *FunDecl = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl()); in getEdgeLockset()
1491 if(!FunDecl || !FunDecl->hasAttrs()) in getEdgeLockset()
1498 for (const auto *Attr : FunDecl->attrs()) { in getEdgeLockset()
1499 switch (Attr->getKind()) { in getEdgeLockset()
1502 getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A, in getEdgeLockset()
1503 Exp, FunDecl, PredBlock, CurrBlock, A->getSuccessValue(), in getEdgeLockset()
1510 A->getSuccessValue(), Negate); in getEdgeLockset()
1516 A->getSuccessValue(), Negate); in getEdgeLockset()
1525 SourceLocation Loc = Exp->getExprLoc(); in getEdgeLockset()
1555 Analyzer->checkAccess(FSet, Exp, AK, POK); in checkAccess()
1559 Analyzer->checkPtAccess(FSet, Exp, AK, POK); in checkPtAccess()
1608 Handler.handleFunExcludesLock(Cp.getKind(), D->getNameAsString(), in warnIfMutexNotHeld()
1633 std::string PartMatchStr = LDat->toString(); in warnIfMutexNotHeld()
1644 if (NoError && LDat && !LDat->isAtLeast(LK)) { in warnIfMutexNotHeld()
1665 Handler.handleFunExcludesLock(Cp.getKind(), D->getNameAsString(), in warnIfMutexHeld()
1678 Exp = Exp->IgnoreImplicit()->IgnoreParenCasts(); in checkAccess()
1680 SourceLocation Loc = Exp->getExprLoc(); in checkAccess()
1682 // Local variables of reference type cannot be re-assigned; in checkAccess()
1685 const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()->getCanonicalDecl()); in checkAccess()
1686 if (VD && VD->isLocalVarDecl() && VD->getType()->isReferenceType()) { in checkAccess()
1687 if (const auto *E = VD->getInit()) { in checkAccess()
1688 // Guard against self-initialization. e.g., int &i = i; in checkAccess()
1700 if (UO->getOpcode() == UO_Deref) in checkAccess()
1701 checkPtAccess(FSet, UO->getSubExpr(), AK, POK); in checkAccess()
1706 switch (BO->getOpcode()) { in checkAccess()
1708 return checkAccess(FSet, BO->getLHS(), AK, POK); in checkAccess()
1709 case BO_PtrMemI: // ->* in checkAccess()
1710 return checkPtAccess(FSet, BO->getLHS(), AK, POK); in checkAccess()
1717 checkPtAccess(FSet, AE->getLHS(), AK, POK); in checkAccess()
1722 if (ME->isArrow()) in checkAccess()
1723 checkPtAccess(FSet, ME->getBase(), AK, POK); in checkAccess()
1725 checkAccess(FSet, ME->getBase(), AK, POK); in checkAccess()
1729 if (!D || !D->hasAttrs()) in checkAccess()
1732 if (D->hasAttr<GuardedVarAttr>() && FSet.isEmpty(FactMan)) { in checkAccess()
1736 for (const auto *I : D->specific_attrs<GuardedByAttr>()) in checkAccess()
1737 warnIfMutexNotHeld(FSet, D, Exp, AK, I->getArg(), POK, nullptr, Loc); in checkAccess()
1747 Exp = PE->getSubExpr(); in checkPtAccess()
1751 if (CE->getCastKind() == CK_ArrayToPointerDecay) { in checkPtAccess()
1754 checkAccess(FSet, CE->getSubExpr(), AK, POK); in checkPtAccess()
1757 Exp = CE->getSubExpr(); in checkPtAccess()
1770 if (!D || !D->hasAttrs()) in checkPtAccess()
1773 if (D->hasAttr<PtGuardedVarAttr>() && FSet.isEmpty(FactMan)) in checkPtAccess()
1774 Handler.handleNoMutexHeld(D, PtPOK, AK, Exp->getExprLoc()); in checkPtAccess()
1776 for (auto const *I : D->specific_attrs<PtGuardedByAttr>()) in checkPtAccess()
1777 warnIfMutexNotHeld(FSet, D, Exp, AK, I->getArg(), PtPOK, nullptr, in checkPtAccess()
1778 Exp->getExprLoc()); in checkPtAccess()
1787 /// to treat const method calls as reads and non-const method calls as writes,
1788 /// and check that the appropriate locks are held. Non-const method calls with
1806 const auto *TagT = Exp->getType()->getAs<TagType>(); in handleCall()
1807 if (TagT && Exp->isPRValue()) { in handleCall()
1809 Analyzer->SxBuilder.createThisPlaceholder(Exp); in handleCall()
1811 Analyzer->ConstructedObjects.insert({Exp, Placeholder.first}); in handleCall()
1815 if (TagT->getDecl()->hasAttr<ScopedLockableAttr>()) in handleCall()
1820 Loc = Exp->getExprLoc(); in handleCall()
1823 for(const Attr *At : D->attrs()) { in handleCall()
1824 switch (At->getKind()) { in handleCall()
1829 Analyzer->getMutexIDs(A->isShared() ? SharedLocksToAdd in handleCall()
1842 Analyzer->getMutexIDs(AssertLocks, A, Exp, D, Self); in handleCall()
1844 Analyzer->addLock( in handleCall()
1853 Analyzer->getMutexIDs(AssertLocks, A, Exp, D, Self); in handleCall()
1855 Analyzer->addLock( in handleCall()
1864 Analyzer->getMutexIDs(AssertLocks, A, Exp, D, Self); in handleCall()
1866 Analyzer->addLock(FSet, std::make_unique<LockableFactEntry>( in handleCall()
1868 A->isShared() ? LK_Shared : LK_Exclusive, in handleCall()
1877 if (A->isGeneric()) in handleCall()
1878 Analyzer->getMutexIDs(GenericLocksToRemove, A, Exp, D, Self); in handleCall()
1879 else if (A->isShared()) in handleCall()
1880 Analyzer->getMutexIDs(SharedLocksToRemove, A, Exp, D, Self); in handleCall()
1882 Analyzer->getMutexIDs(ExclusiveLocksToRemove, A, Exp, D, Self); in handleCall()
1888 for (auto *Arg : A->args()) { in handleCall()
1889 Analyzer->warnIfMutexNotHeld(FSet, D, Exp, in handleCall()
1890 A->isShared() ? AK_Read : AK_Written, in handleCall()
1894 Analyzer->getMutexIDs(ScopedReqsAndExcludes, A, Exp, D, Self); in handleCall()
1901 for (auto *Arg : A->args()) { in handleCall()
1902 Analyzer->warnIfMutexHeld(FSet, D, Exp, Arg, Self, Loc); in handleCall()
1905 Analyzer->getMutexIDs(ScopedReqsAndExcludes, A, Exp, D, Self); in handleCall()
1910 // Ignore attributes unrelated to thread-safety in handleCall()
1917 // FIXME -- should only fully remove if the attribute refers to 'this'. in handleCall()
1920 Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Exclusive); in handleCall()
1922 Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Shared); in handleCall()
1924 Analyzer->removeLock(FSet, M, Loc, Dtor, LK_Generic); in handleCall()
1930 Analyzer->addLock(FSet, std::make_unique<LockableFactEntry>(M, LK_Exclusive, in handleCall()
1933 Analyzer->addLock( in handleCall()
1940 ScopedEntry->addLock(M); in handleCall()
1942 ScopedEntry->addLock(M); in handleCall()
1944 ScopedEntry->addLock(M); in handleCall()
1946 ScopedEntry->addExclusiveUnlock(M); in handleCall()
1948 ScopedEntry->addSharedUnlock(M); in handleCall()
1949 Analyzer->addLock(FSet, std::move(ScopedEntry)); in handleCall()
1957 switch (UO->getOpcode()) { in VisitUnaryOperator()
1962 checkAccess(UO->getSubExpr(), AK_Written); in VisitUnaryOperator()
1971 /// FIXME: Deal with non-primitive types.
1973 if (!BO->isAssignmentOp()) in VisitBinaryOperator()
1977 LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, BO, LVarCtx); in VisitBinaryOperator()
1979 checkAccess(BO->getLHS(), AK_Written); in VisitBinaryOperator()
1984 /// FIXME: Deal with non-primitive types.
1986 if (CE->getCastKind() != CK_LValueToRValue) in VisitCastExpr()
1988 checkAccess(CE->getSubExpr(), AK_Read); in VisitCastExpr()
2004 if (FD->hasAttr<NoThreadSafetyAnalysisAttr>()) in examineArguments()
2007 const ArrayRef<ParmVarDecl *> Params = FD->parameters(); in examineArguments()
2015 QualType Qt = (*Param)->getType(); in examineArguments()
2016 if (Qt->isReferenceType()) in examineArguments()
2023 const auto *ME = dyn_cast<MemberExpr>(CE->getCallee()); in VisitCallExpr()
2025 const CXXMethodDecl *MD = CE->getMethodDecl(); in VisitCallExpr()
2028 if (ME->isArrow()) { in VisitCallExpr()
2029 // Should perhaps be AK_Written if !MD->isConst(). in VisitCallExpr()
2030 checkPtAccess(CE->getImplicitObjectArgument(), AK_Read); in VisitCallExpr()
2032 // Should perhaps be AK_Written if !MD->isConst(). in VisitCallExpr()
2033 checkAccess(CE->getImplicitObjectArgument(), AK_Read); in VisitCallExpr()
2037 examineArguments(CE->getDirectCallee(), CE->arg_begin(), CE->arg_end()); in VisitCallExpr()
2039 OverloadedOperatorKind OEop = OE->getOperator(); in VisitCallExpr()
2052 checkAccess(OE->getArg(1), AK_Read); in VisitCallExpr()
2056 checkAccess(OE->getArg(0), AK_Written); in VisitCallExpr()
2062 if (!(OEop == OO_Star && OE->getNumArgs() > 1)) { in VisitCallExpr()
2064 checkPtAccess(OE->getArg(0), AK_Read); in VisitCallExpr()
2068 // TODO: get rid of this, and rely on pass-by-ref instead. in VisitCallExpr()
2069 const Expr *Obj = OE->getArg(0); in VisitCallExpr()
2073 // FunctionDecl, but for non-methods it does. in VisitCallExpr()
2074 const FunctionDecl *FD = OE->getDirectCallee(); in VisitCallExpr()
2075 examineArguments(FD, std::next(OE->arg_begin()), OE->arg_end(), in VisitCallExpr()
2081 examineArguments(Exp->getDirectCallee(), Exp->arg_begin(), Exp->arg_end()); in VisitCallExpr()
2084 auto *D = dyn_cast_or_null<NamedDecl>(Exp->getCalleeDecl()); in VisitCallExpr()
2085 if(!D || !D->hasAttrs()) in VisitCallExpr()
2091 const CXXConstructorDecl *D = Exp->getConstructor(); in VisitCXXConstructExpr()
2092 if (D && D->isCopyConstructor()) { in VisitCXXConstructExpr()
2093 const Expr* Source = Exp->getArg(0); in VisitCXXConstructExpr()
2096 examineArguments(D, Exp->arg_begin(), Exp->arg_end()); in VisitCXXConstructExpr()
2098 if (D && D->hasAttrs()) in VisitCXXConstructExpr()
2104 if (CE->getCastKind() == CK_NoOp) in UnpackConstruction()
2105 E = CE->getSubExpr()->IgnoreParens(); in UnpackConstruction()
2107 if (CE->getCastKind() == CK_ConstructorConversion || in UnpackConstruction()
2108 CE->getCastKind() == CK_UserDefinedConversion) in UnpackConstruction()
2109 E = CE->getSubExpr(); in UnpackConstruction()
2111 E = BTE->getSubExpr(); in UnpackConstruction()
2117 LVarCtx = Analyzer->LocalVarMap.getNextContext(CtxIndex, S, LVarCtx); in VisitDeclStmt()
2119 for (auto *D : S->getDeclGroup()) { in VisitDeclStmt()
2121 const Expr *E = VD->getInit(); in VisitDeclStmt()
2124 E = E->IgnoreParens(); in VisitDeclStmt()
2128 E = EWC->getSubExpr()->IgnoreParens(); in VisitDeclStmt()
2131 if (auto Object = Analyzer->ConstructedObjects.find(E); in VisitDeclStmt()
2132 Object != Analyzer->ConstructedObjects.end()) { in VisitDeclStmt()
2133 Object->second->setClangDecl(VD); in VisitDeclStmt()
2134 Analyzer->ConstructedObjects.erase(Object); in VisitDeclStmt()
2142 if (const ValueDecl *ExtD = Exp->getExtendingDecl()) { in VisitMaterializeTemporaryExpr()
2143 if (auto Object = Analyzer->ConstructedObjects.find( in VisitMaterializeTemporaryExpr()
2144 UnpackConstruction(Exp->getSubExpr())); in VisitMaterializeTemporaryExpr()
2145 Object != Analyzer->ConstructedObjects.end()) { in VisitMaterializeTemporaryExpr()
2146 Object->second->setClangDecl(ExtD); in VisitMaterializeTemporaryExpr()
2147 Analyzer->ConstructedObjects.erase(Object); in VisitMaterializeTemporaryExpr()
2153 if (Analyzer->CurrentFunction == nullptr) in VisitReturnStmt()
2155 const Expr *RetVal = S->getRetValue(); in VisitReturnStmt()
2162 Analyzer->CurrentFunction->getReturnType().getCanonicalType(); in VisitReturnStmt()
2163 if (ReturnType->isLValueReferenceType()) { in VisitReturnStmt()
2164 Analyzer->checkAccess( in VisitReturnStmt()
2166 ReturnType->getPointeeType().isConstQualified() ? AK_Read : AK_Written, in VisitReturnStmt()
2192 // The non-asserted capability is the one we want to track. in join()
2239 if (!EntryFact->managed() || ExitLEK == LEK_LockedSomeLoopIterations) in intersectAndWarn()
2240 EntryFact->handleRemovalFromIntersection(EntrySetOrig, FactMan, JoinLoc, in intersectAndWarn()
2250 if (B->hasNoReturnElement()) in neverReturns()
2252 if (B->empty()) in neverReturns()
2255 CFGElement Last = B->back(); in neverReturns()
2257 if (isa<CXXThrowExpr>(S->getStmt())) in neverReturns()
2263 /// Check a function's CFG for thread-safety violations.
2282 if (D->hasAttr<NoThreadSafetyAnalysisAttr>()) in runAnalysis()
2296 BlockInfo.resize(CFGraph->getNumBlockIDs(), in runAnalysis()
2305 CFGBlockInfo &Initial = BlockInfo[CFGraph->getEntry().getBlockID()]; in runAnalysis()
2306 CFGBlockInfo &Final = BlockInfo[CFGraph->getExit().getBlockID()]; in runAnalysis()
2324 if (!SortedGraph->empty() && D->hasAttrs()) { in runAnalysis()
2325 assert(*SortedGraph->begin() == &CFGraph->getEntry()); in runAnalysis()
2331 SourceLocation Loc = D->getLocation(); in runAnalysis()
2332 for (const auto *Attr : D->attrs()) { in runAnalysis()
2333 Loc = Attr->getLocation(); in runAnalysis()
2335 getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A, in runAnalysis()
2340 if (A->args_size() == 0) in runAnalysis()
2342 getMutexIDs(A->isShared() ? SharedLocksToAdd : ExclusiveLocksToAdd, A, in runAnalysis()
2346 if (A->args_size() == 0) in runAnalysis()
2348 getMutexIDs(A->isShared() ? SharedLocksAcquired in runAnalysis()
2363 // FIXME -- Loc can be wrong here. in runAnalysis()
2381 // by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then in runAnalysis()
2387 D->getLocation())); in runAnalysis()
2391 std::make_unique<LockableFactEntry>(Lock, LK_Shared, D->getLocation())); in runAnalysis()
2396 unsigned CurrBlockID = CurrBlock->getBlockID(); in runAnalysis()
2416 for (CFGBlock::const_pred_iterator PI = CurrBlock->pred_begin(), in runAnalysis()
2417 PE = CurrBlock->pred_end(); PI != PE; ++PI) { in runAnalysis()
2418 // if *PI -> CurrBlock is a back edge in runAnalysis()
2422 unsigned PrevBlockID = (*PI)->getBlockID(); in runAnalysis()
2426 if (neverReturns(*PI) || !PrevBlockInfo->Reachable) in runAnalysis()
2430 CurrBlockInfo->Reachable = true; in runAnalysis()
2433 getEdgeLockset(PrevLockset, PrevBlockInfo->ExitSet, *PI, CurrBlock); in runAnalysis()
2436 CurrBlockInfo->EntrySet = PrevLockset; in runAnalysis()
2443 CurrBlockInfo->EntrySet, PrevLockset, CurrBlockInfo->EntryLoc, in runAnalysis()
2444 isa_and_nonnull<ContinueStmt>((*PI)->getTerminatorStmt()) in runAnalysis()
2451 if (!CurrBlockInfo->Reachable) in runAnalysis()
2468 if (!DD->hasAttrs()) in runAnalysis()
2473 AD.getTriggerStmt()->getEndLoc()); in runAnalysis()
2481 CF.getVarDecl()->getLocation()); in runAnalysis()
2491 TD.getBindTemporaryExpr()->getSubExpr()); in runAnalysis()
2494 if (DD->hasAttrs()) in runAnalysis()
2496 LocksetBuilder.handleCall(nullptr, DD, Object->second, in runAnalysis()
2497 TD.getBindTemporaryExpr()->getEndLoc()); in runAnalysis()
2506 CurrBlockInfo->ExitSet = LocksetBuilder.FSet; in runAnalysis()
2512 for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(), in runAnalysis()
2513 SE = CurrBlock->succ_end(); SI != SE; ++SI) { in runAnalysis() local
2514 // if CurrBlock -> *SI is *not* a back edge in runAnalysis()
2519 CFGBlockInfo *PreLoop = &BlockInfo[FirstLoopBlock->getBlockID()]; in runAnalysis()
2521 intersectAndWarn(PreLoop->EntrySet, LoopEnd->ExitSet, PreLoop->EntryLoc, in runAnalysis()
2537 /// Check a function's CFG for thread-safety violations.