@@ -1008,7 +1008,7 @@ class ThreadSafetyAnalyzer {
10081008 threadSafety::SExprBuilder SxBuilder;
10091009
10101010 ThreadSafetyHandler &Handler;
1011- const FunctionDecl *CurrentFunction ;
1011+ const CXXMethodDecl *CurrentMethod = nullptr ;
10121012 LocalVariableMap LocalVarMap;
10131013 FactManager FactMan;
10141014 std::vector<CFGBlockInfo> BlockInfo;
@@ -1243,10 +1243,10 @@ bool ThreadSafetyAnalyzer::inCurrentScope(const CapabilityExpr &CapE) {
12431243
12441244 // Members are in scope from methods of the same class.
12451245 if (const auto *P = dyn_cast<til::Project>(SExp)) {
1246- if (!isa_and_nonnull<CXXMethodDecl>(CurrentFunction) )
1246+ if (!CurrentMethod )
12471247 return false ;
12481248 const ValueDecl *VD = P->clangDecl ();
1249- return VD->getDeclContext () == CurrentFunction ->getDeclContext ();
1249+ return VD->getDeclContext () == CurrentMethod ->getDeclContext ();
12501250 }
12511251
12521252 return false ;
@@ -1541,8 +1541,6 @@ class BuildLockset : public ConstStmtVisitor<BuildLockset> {
15411541
15421542 ThreadSafetyAnalyzer *Analyzer;
15431543 FactSet FSet;
1544- // The fact set for the function on exit.
1545- const FactSet &FunctionExitFSet;
15461544 // / Maps constructed objects to `this` placeholder prior to initialization.
15471545 llvm::SmallDenseMap<const Expr *, til::LiteralPtr *> ConstructedObjects;
15481546 LocalVariableMap::Context LVarCtx;
@@ -1568,11 +1566,9 @@ class BuildLockset : public ConstStmtVisitor<BuildLockset> {
15681566 bool SkipFirstParam = false );
15691567
15701568public:
1571- BuildLockset (ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info,
1572- const FactSet &FunctionExitFSet)
1569+ BuildLockset (ThreadSafetyAnalyzer *Anlzr, CFGBlockInfo &Info)
15731570 : ConstStmtVisitor<BuildLockset>(), Analyzer(Anlzr), FSet(Info.EntrySet),
1574- FunctionExitFSet (FunctionExitFSet), LVarCtx(Info.EntryContext),
1575- CtxIndex (Info.EntryIndex) {}
1571+ LVarCtx (Info.EntryContext), CtxIndex(Info.EntryIndex) {}
15761572
15771573 void VisitUnaryOperator (const UnaryOperator *UO);
15781574 void VisitBinaryOperator (const BinaryOperator *BO);
@@ -1581,7 +1577,6 @@ class BuildLockset : public ConstStmtVisitor<BuildLockset> {
15811577 void VisitCXXConstructExpr (const CXXConstructExpr *Exp);
15821578 void VisitDeclStmt (const DeclStmt *S);
15831579 void VisitMaterializeTemporaryExpr (const MaterializeTemporaryExpr *Exp);
1584- void VisitReturnStmt (const ReturnStmt *S);
15851580};
15861581
15871582} // namespace
@@ -1763,8 +1758,6 @@ void ThreadSafetyAnalyzer::checkPtAccess(const FactSet &FSet, const Expr *Exp,
17631758 // Pass by reference warnings are under a different flag.
17641759 ProtectedOperationKind PtPOK = POK_VarDereference;
17651760 if (POK == POK_PassByRef) PtPOK = POK_PtPassByRef;
1766- if (POK == POK_ReturnByRef)
1767- PtPOK = POK_PtReturnByRef;
17681761
17691762 const ValueDecl *D = getValueDecl (Exp);
17701763 if (!D || !D->hasAttrs ())
@@ -2149,25 +2142,6 @@ void BuildLockset::VisitMaterializeTemporaryExpr(
21492142 }
21502143}
21512144
2152- void BuildLockset::VisitReturnStmt (const ReturnStmt *S) {
2153- if (Analyzer->CurrentFunction == nullptr )
2154- return ;
2155- const Expr *RetVal = S->getRetValue ();
2156- if (!RetVal)
2157- return ;
2158-
2159- // If returning by reference, check that the function requires the appropriate
2160- // capabilities.
2161- const QualType ReturnType =
2162- Analyzer->CurrentFunction ->getReturnType ().getCanonicalType ();
2163- if (ReturnType->isLValueReferenceType ()) {
2164- Analyzer->checkAccess (
2165- FunctionExitFSet, RetVal,
2166- ReturnType->getPointeeType ().isConstQualified () ? AK_Read : AK_Written,
2167- POK_ReturnByRef);
2168- }
2169- }
2170-
21712145// / Given two facts merging on a join point, possibly warn and decide whether to
21722146// / keep or replace.
21732147// /
@@ -2277,7 +2251,8 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
22772251
22782252 CFG *CFGraph = walker.getGraph ();
22792253 const NamedDecl *D = walker.getDecl ();
2280- CurrentFunction = dyn_cast<FunctionDecl>(D);
2254+ const auto *CurrentFunction = dyn_cast<FunctionDecl>(D);
2255+ CurrentMethod = dyn_cast<CXXMethodDecl>(D);
22812256
22822257 if (D->hasAttr <NoThreadSafetyAnalysisAttr>())
22832258 return ;
@@ -2303,7 +2278,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
23032278 PostOrderCFGView::CFGBlockSet VisitedBlocks (CFGraph);
23042279
23052280 CFGBlockInfo &Initial = BlockInfo[CFGraph->getEntry ().getBlockID ()];
2306- CFGBlockInfo &Final = BlockInfo[CFGraph->getExit ().getBlockID ()];
2281+ CFGBlockInfo &Final = BlockInfo[CFGraph->getExit ().getBlockID ()];
23072282
23082283 // Mark entry block as reachable
23092284 Initial.Reachable = true ;
@@ -2373,25 +2348,6 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
23732348 }
23742349 }
23752350
2376- // Compute the expected exit set.
2377- // By default, we expect all locks held on entry to be held on exit.
2378- FactSet ExpectedFunctionExitSet = Initial.EntrySet ;
2379-
2380- // Adjust the expected exit set by adding or removing locks, as declared
2381- // by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then
2382- // issue the appropriate warning.
2383- // FIXME: the location here is not quite right.
2384- for (const auto &Lock : ExclusiveLocksAcquired)
2385- ExpectedFunctionExitSet.addLock (
2386- FactMan, std::make_unique<LockableFactEntry>(Lock, LK_Exclusive,
2387- D->getLocation ()));
2388- for (const auto &Lock : SharedLocksAcquired)
2389- ExpectedFunctionExitSet.addLock (
2390- FactMan,
2391- std::make_unique<LockableFactEntry>(Lock, LK_Shared, D->getLocation ()));
2392- for (const auto &Lock : LocksReleased)
2393- ExpectedFunctionExitSet.removeLock (FactMan, Lock);
2394-
23952351 for (const auto *CurrBlock : *SortedGraph) {
23962352 unsigned CurrBlockID = CurrBlock->getBlockID ();
23972353 CFGBlockInfo *CurrBlockInfo = &BlockInfo[CurrBlockID];
@@ -2451,7 +2407,7 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
24512407 if (!CurrBlockInfo->Reachable )
24522408 continue ;
24532409
2454- BuildLockset LocksetBuilder (this , *CurrBlockInfo, ExpectedFunctionExitSet );
2410+ BuildLockset LocksetBuilder (this , *CurrBlockInfo);
24552411
24562412 // Visit all the statements in the basic block.
24572413 for (const auto &BI : *CurrBlock) {
@@ -2527,8 +2483,24 @@ void ThreadSafetyAnalyzer::runAnalysis(AnalysisDeclContext &AC) {
25272483 if (!Final.Reachable )
25282484 return ;
25292485
2486+ // By default, we expect all locks held on entry to be held on exit.
2487+ FactSet ExpectedExitSet = Initial.EntrySet ;
2488+
2489+ // Adjust the expected exit set by adding or removing locks, as declared
2490+ // by *-LOCK_FUNCTION and UNLOCK_FUNCTION. The intersect below will then
2491+ // issue the appropriate warning.
2492+ // FIXME: the location here is not quite right.
2493+ for (const auto &Lock : ExclusiveLocksAcquired)
2494+ ExpectedExitSet.addLock (FactMan, std::make_unique<LockableFactEntry>(
2495+ Lock, LK_Exclusive, D->getLocation ()));
2496+ for (const auto &Lock : SharedLocksAcquired)
2497+ ExpectedExitSet.addLock (FactMan, std::make_unique<LockableFactEntry>(
2498+ Lock, LK_Shared, D->getLocation ()));
2499+ for (const auto &Lock : LocksReleased)
2500+ ExpectedExitSet.removeLock (FactMan, Lock);
2501+
25302502 // FIXME: Should we call this function for all blocks which exit the function?
2531- intersectAndWarn (ExpectedFunctionExitSet , Final.ExitSet , Final.ExitLoc ,
2503+ intersectAndWarn (ExpectedExitSet , Final.ExitSet , Final.ExitLoc ,
25322504 LEK_LockedAtEndOfFunction, LEK_NotLockedAtEndOfFunction);
25332505
25342506 Handler.leaveFunction (CurrentFunction);
0 commit comments