aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/ThreadSafety.cpp
AgeCommit message (Collapse)AuthorFilesLines
2022-05-09Thread safety analysis: Handle compound assignment and ->* overloadsAaron Puchert1-7/+18
Like regular assignment, compound assignment operators can be assumed to write to their left-hand side operand. So we strengthen the requirements there. (Previously only the default read access had been required.) Just like operator->, operator->* can also be assumed to dereference the left-hand side argument, so we require read access to the pointee. This will generate new warnings if the left-hand side has a pt_guarded_by attribute. This overload is rarely used, but it was trivial to add, so why not. (Supporting the builtin operator requires changes to the TIL.) Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D124966
2022-04-29Thread safety analysis: Don't pass capability kind where not needed (NFC)Aaron Puchert1-4/+3
If no capability is held, or the capability expression is invalid, there is obviously no capability kind and so none would be reported. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D124132
2022-04-29Thread safety analysis: Store capability kind in CapabilityExprAaron Puchert1-160/+82
This should make us print the right capability kind in many more cases, especially when attributes name multiple capabilities of different kinds. Previously we were trying to deduce the capability kind from the original attribute, but most attributes can name multiple capabilities, which could be of different kinds. So instead we derive the kind when translating the attribute expression, and then store it in the returned CapabilityExpr. Then we can extract the corresponding capability name when we need it, which saves us lots of plumbing and almost guarantees that the name is right. I didn't bother adding any tests for this because it's just a usability improvement and it's pretty much evident from the code that we don't fall back to "mutex" anymore (save for a few cases that I'll address in a separate change). Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D124131
2022-04-29Thread safety analysis: Store CapabilityExprs in ScopedLockableFactEntry (NFC)Aaron Puchert1-25/+23
For now this doesn't make a whole lot of sense, but it will allow us to store the capability kind in a CapabilityExpr and make sure it doesn't get lost. The capabilities managed by a scoped lockable can of course be of different kind, so we'll need to store that per entry. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D124128
2021-12-09Thread safety analysis: Remove unused variable. NFC.Benjamin Kramer1-3/+0
2021-10-24Use llvm::any_of and llvm::none_of (NFC)Kazu Hirata1-5/+3
2021-09-20Thread safety analysis: Drop special block handlingAaron Puchert1-44/+13
Previous changes like D101202 and D104261 have eliminated the special status that break and continue once had, since now we're making decisions purely based on the structure of the CFG without regard for the underlying source code constructs. This means we don't gain anything from defering handling for these blocks. Dropping it moves some diagnostics, though arguably into a better place. We're working around a "quirk" in the CFG that perhaps wasn't visible before: while loops have an empty "transition block" where continue statements and the regular loop exit meet, before continuing to the loop entry. To get a source location for that, we slightly extend our handling for empty blocks. The source location for the transition ends up to be the loop entry then, but formally this isn't a back edge. We pretend it is anyway. (This is safe: we can always treat edges as back edges, it just means we allow less and don't modify the lock set. The other way around it wouldn't be safe.) Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D106715
2021-09-18Thread safety analysis: Warn when demoting locks on back edgesAaron Puchert1-14/+17
Previously in D104261 we warned about dropping locks from back edges, this is the corresponding change for exclusive/shared joins. If we're entering the loop with an exclusive change, which is then relaxed to a shared lock before we loop back, we have already analyzed the loop body with the stronger exclusive lock and thus might have false positives. There is a minor non-observable change: we modify the exit lock set of a function, but since that isn't used further it doesn't change anything. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D106713
2021-06-29Thread safety analysis: Rename parameters of ↵Aaron Puchert1-37/+38
ThreadSafetyAnalyzer::intersectAndWarn (NFC) In D104261 we made the parameters' meaning slightly more specific, this changes their names accordingly. In all uses we're building a new lock set by intersecting existing locksets. The first (modifiable) argument is the new lock set being built, the second (non-modifiable) argument is the exit set of a preceding block. Reviewed By: aaron.ballman, delesley Differential Revision: https://reviews.llvm.org/D104649
2021-06-29Thread safety analysis: Always warn when dropping locks on back edgesAaron Puchert1-5/+6
We allow branches to join where one holds a managed lock but the other doesn't, but we can't do so for back edges: because there we can't drop them from the lockset, as we have already analyzed the loop with the larger lockset. So we can't allow dropping managed locks on back edges. We move the managed() check from handleRemovalFromIntersection up to intersectAndWarn, where we additionally check if we're on a back edge if we're removing from the first lock set (the entry set of the next block) but not if we're removing from the second lock set (the exit set of the previous block). Now that the order of arguments matters, I had to swap them in one invocation, which also causes some minor differences in the tests. Reviewed By: delesley Differential Revision: https://reviews.llvm.org/D104261
2021-06-09[clang] NFC: Rename rvalue to prvalueMatheus Izvekov1-1/+1
This renames the expression value categories from rvalue to prvalue, keeping nomenclature consistent with C++11 onwards. C++ has the most complicated taxonomy here, and every other language only uses a subset of it, so it's less confusing to use the C++ names consistently, and mentally remap to the C names when working on that context (prvalue -> rvalue, no xvalues, etc). Renames: * VK_RValue -> VK_PRValue * Expr::isRValue -> Expr::isPRValue * SK_QualificationConversionRValue -> SK_QualificationConversionPRValue * JSON AST Dumper Expression nodes value category: "rvalue" -> "prvalue" Signed-off-by: Matheus Izvekov <mizvekov@gmail.com> Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D103720
2021-05-27Thread safety analysis: Allow exlusive/shared joins for managed and asserted ↵Aaron Puchert1-3/+10
capabilities Similar to how we allow managed and asserted locks to be held and not held in joining branches, we also allow them to be held shared and exclusive. The scoped lock should restore the original state at the end of the scope in any event, and asserted locks need not be released. We should probably only allow asserted locks to be subsumed by managed, not by (directly) acquired locks, but that's for another change. Reviewed By: delesley Differential Revision: https://reviews.llvm.org/D102026
2021-05-27Thread safety analysis: Factor out function for merging locks (NFC)Aaron Puchert1-13/+18
It's going to become a bit more complicated, so let's have it separate. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D102025
2021-05-06Thread safety analysis: Eliminate parameter from intersectAndWarn (NFC)Aaron Puchert1-22/+15
We were modifying precisely when intersecting the lock sets of multiple predecessors without back edge. That's no coincidence: we can't modify on back edges, it doesn't make sense to modify at the end of a function, and otherwise we always want to intersect on forward edges, because we can build a new lock set for those. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D101755
2021-05-03Thread safety analysis: Fix false negative on breakAaron Puchert1-5/+4
We weren't modifying the lock set when intersecting with one coming from a break-terminated block. This is inconsistent, since break isn't a back edge, and it leads to false negatives with scoped locks. We usually don't warn for those when joining locksets aren't the same, we just silently remove locks that are not in the intersection. But not warning and not removing them isn't right. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D101202
2021-05-03Thread safety analysis: Replace flags in FactEntry by SourceKind (NFC)Aaron Puchert1-41/+46
The motivation here is to make it available in the base class whether a fact is managed or not. That would have meant three flags on the base class, so I had a look whether we really have 8 possible combinations. It turns out we don't: asserted and declared are obviously mutually exclusive. Managed facts are only created when we acquire a capability through a scoped capability. Adopting an asserted or declared lock will not (in fact can not, because Facts are immutable) make them managed. We probably don't want to allow adopting an asserted lock (because then the function should probably have a release attribute, and then the assertion is pointless), but we might at some point decide to replace a declared fact on adoption. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D100801
2021-04-23Thread safety analysis: Simplify intersectAndWarn (NFC)Aaron Puchert1-14/+12
Instead of conditionally overwriting a nullptr and then branching on its nullness, just branch directly on the original condition. Then we can make both pointers (non-null) references instead.
2021-04-06Thread safety analysis: Don't warn about managed locks on join pointsAaron Puchert1-1/+1
We already did so for scoped locks acquired in the constructor, this change extends the treatment to deferred locks and scoped unlocking, so locks acquired outside of the constructor. Obviously this makes things more consistent. Originally I thought this was a bad idea, because obviously it introduces false negatives when it comes to double locking, but these are typically easily found in tests, and the primary goal of the Thread safety analysis is not to find double locks but race conditions. Since the scoped lock will release the mutex anyway when the scope ends, the inconsistent state is just temporary and probably fine. Reviewed By: delesley Differential Revision: https://reviews.llvm.org/D98747
2021-03-27Deduplicate branches and adjust comment [NFC]Aaron Puchert1-8/+4
Currently we want to allow calling non-const methods even when only a shared lock is held, because -Wthread-safety-reference is already quite sensitive and not all code is const-correct. Even if it is, this might require users to add std::as_const around the implicit object argument. See D52395 for a discussion. Fixes PR46963.
2020-10-30Thread safety analysis: Consider static class members as inaccessibleAaron Puchert1-2/+8
This fixes the issue pointed out in D84604#2363134. For now we exclude static members completely, we'll take them into account later.
2020-10-25Thread safety analysis: Nullability improvements in TIL, NFCIAaron Puchert1-3/+2
The constructor of Project asserts that the contained ValueDecl is not null, use that in the ThreadSafetyAnalyzer. In the case of LiteralPtr it's the other way around. Also dyn_cast<> is sufficient if we know something isn't null.
2020-10-25Thread safety analysis: Consider global variables in scopeAaron Puchert1-2/+13
Instead of just mutex members we also consider mutex globals. Unsurprisingly they are always in scope. Now the paper [1] says that > The scope of a class member is assumed to be its enclosing class, > while the scope of a global variable is the translation unit in > which it is defined. But I don't think we should limit this to TUs where a definition is available - a declaration is enough to acquire the mutex, and if a mutex is really limited in scope to a translation unit, it should probably be only declared there. The previous attempt in 9dcc82f34ea was causing false positives because I wrongly assumed that LiteralPtrs were always globals, which they are not. This should be fixed now. [1] https://static.googleusercontent.com/media/research.google.com/en/us/pubs/archive/42958.pdf Fixes PR46354. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D84604
2020-09-09Temporairly revert "Thread safety analysis: Consider global variables in ↵Roman Lebedev1-13/+5
scope" & followup This appears to cause false-positives because it started to warn on local non-global variables. Repro posted to https://reviews.llvm.org/D84604#2262745 This reverts commit 9dcc82f34ea9b623d82d2577b93aaf67d36dabd2. This reverts commit b2ce79ef66157dd752e3864ece57915e23a73f5d.
2020-09-05Thread safety analysis: ValueDecl in Project is non-nullAaron Puchert1-3/+2
The constructor asserts that, use it in the ThreadSafetyAnalyzer. Also note that the result of a cast<> cannot be null.
2020-09-05Thread safety analysis: Consider global variables in scopeAaron Puchert1-2/+11
Instead of just mutex members we also consider mutex globals. Unsurprisingly they are always in scope. Now the paper [1] says that > The scope of a class member is assumed to be its enclosing class, > while the scope of a global variable is the translation unit in > which it is defined. But I don't think we should limit this to TUs where a definition is available - a declaration is enough to acquire the mutex, and if a mutex is really limited in scope to a translation unit, it should probably be only declared there. [1] https://static.googleusercontent.com/media/research.google.com/en/us/pubs/archive/42958.pdf Fixes PR46354. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D84604
2020-09-01Thread safety analysis: More consistent warning messageAaron Puchert1-2/+1
Other warning messages for negative capabilities also mention their kind, and the double space was ugly. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D84603
2020-06-08Thread safety analysis: Add note for double unlockAaron Puchert1-2/+8
Summary: When getting a warning that we release a capability that isn't held it's sometimes not clear why. So just like we do for double locking, we add a note on the previous release operation, which marks the point since when the capability isn't held any longer. We can find this previous release operation by looking up the corresponding negative capability. Reviewers: aaron.ballman, delesley Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D81352
2020-06-08Thread safety analysis: Support deferring locksAaron Puchert1-18/+13
Summary: The standard std::unique_lock can be constructed to manage a lock without initially acquiring it by passing std::defer_lock as second parameter. It can be acquired later by calling lock(). To support this, we use the locks_excluded attribute. This might seem like an odd choice at first, but its consistent with the other annotations we support on scoped capability constructors. By excluding the lock we state that it is currently not in use and the function doesn't change that, which is exactly what the constructor does. Along the way we slightly simplify handling of scoped capabilities. Reviewers: aaron.ballman, delesley Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D81332
2020-03-30[clang analysis] Make mutex guard detection more reliable.Eli Friedman1-5/+7
-Wthread-safety was failing to detect certain AST patterns it should detect. Make the pattern detection a bit more comprehensive. Due to an unrelated bug involving template instantiation, this showed up as a regression in 10.0 vs. 9.0 in the original bug report. The included testcase fails on older versions of clang, though. Fixes https://bugs.llvm.org/show_bug.cgi?id=45323 . Differential Revision: https://reviews.llvm.org/D76943
2020-02-11Use std::foo_t rather than std::foo in clang.Justin Lebar1-4/+2
Summary: No functional change. Reviewers: bkramer, MaskRay, martong, shafik Subscribers: martong, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D74414
2019-10-30Thread safety analysis: Peel away NoOp implicit casts in initializersAaron Puchert1-0/+3
Summary: This happens when someone initializes a variable with guaranteed copy elision and an added const qualifier. Fixes PR43826. Reviewers: aaron.ballman, rsmith Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D69533
2019-08-14[Clang] Migrate llvm::make_unique to std::make_uniqueJonas Devlieghere1-15/+15
Now that we've moved to C++14, we no longer need the llvm::make_unique implementation from STLExtras.h. This patch is a mechanical replacement of (hopefully) all the llvm::make_unique instances across the monorepo. Differential revision: https://reviews.llvm.org/D66259 llvm-svn: 368942
2019-05-24[CFG] NFC: Remove implicit conversion from CFGTerminator to Stmt *.Artem Dergachev1-4/+4
Turn it into a variant class instead. This conversion does indeed save some code but there's a plan to add support for more kinds of terminators that aren't necessarily based on statements, and with those in mind it becomes more and more confusing to have CFGTerminators implicitly convertible to a Stmt *. Differential Revision: https://reviews.llvm.org/D61814 llvm-svn: 361586
2019-03-18Thread safety analysis: Add note for unlock kind mismatchAaron Puchert1-2/+2
Summary: Similar to D56967, we add the existing diag::note_locked_here to tell the user where we saw the locking that isn't matched correctly. Reviewers: aaron.ballman, delesley Reviewed By: aaron.ballman Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D59455 llvm-svn: 356427
2019-01-29Thread safety analysis: Improve diagnostics for double lockingAaron Puchert1-4/+5
Summary: We use the existing diag::note_locked_here to tell the user where we saw the first locking. Reviewers: aaron.ballman, delesley Reviewed By: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D56967 llvm-svn: 352549
2019-01-19Update the file headers across all of the LLVM projects in the monorepoChandler Carruth1-4/+3
to reflect the new license. We understand that people may be surprised that we're moving the header entirely to discuss the new license. We checked this carefully with the Foundation's lawyer and we believe this is the correct approach. Essentially, all code in the project is now made available by the LLVM project under our new license, so you will see that the license headers include that license only. Some of our contributors have contributed code under our old license, and accordingly, we have retained a copy of our old license notice in the top-level files in each project and repository. llvm-svn: 351636
2018-12-21[AST][NFC] Pass the AST context to one of the ctor of DeclRefExpr.Bruno Ricci1-3/+5
All of the other constructors already take a reference to the AST context. This avoids calling Decl::getASTContext in most cases. Additionally move the definition of the constructor from Expr.h to Expr.cpp since it is calling DeclRefExpr::computeDependence. NFC. llvm-svn: 349901
2018-12-16Thread safety analysis: Avoid intermediate copies [NFC]Aaron Puchert1-21/+31
The main reason is to reduce the number of constructor arguments though, especially since many of them had the same type. llvm-svn: 349308
2018-12-16Thread safety analysis: Allow scoped releasing of capabilitiesAaron Puchert1-39/+73
Summary: The pattern is problematic with C++ exceptions, and not as widespread as scoped locks, but it's still used by some, for example Chromium. We are a bit stricter here at join points, patterns that are allowed for scoped locks aren't allowed here. That could still be changed in the future, but I'd argue we should only relax this if people ask for it. Fixes PR36162. Reviewers: aaron.ballman, delesley, pwnall Reviewed By: delesley, pwnall Subscribers: pwnall, cfe-commits Differential Revision: https://reviews.llvm.org/D52578 llvm-svn: 349300
2018-10-31Create ConstantExpr classBill Wendling1-2/+2
A ConstantExpr class represents a full expression that's in a context where a constant expression is required. This class reflects the path the evaluator took to reach the expression rather than the syntactic context in which the expression occurs. In the future, the class will be expanded to cache the result of the evaluated expression so that it's not needlessly re-evaluated Reviewed By: rsmith Differential Revision: https://reviews.llvm.org/D53475 llvm-svn: 345692
2018-10-06Thread safety analysis: Handle conditional expression in getTrylockCallExprAaron Puchert1-1/+13
Summary: We unwrap conditional expressions containing try-lock functions. Additionally we don't acquire on conditional expression branches, since that is usually not helpful. When joining the branches we would almost certainly get a warning then. Hopefully fixes an issue that was raised in D52398. Reviewers: aaron.ballman, delesley, hokein Reviewed By: aaron.ballman Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D52888 llvm-svn: 343902
2018-10-04Thread safety analysis: Examine constructor argumentsAaron Puchert1-51/+49
Summary: Instead of only examining call arguments, we also examine constructor arguments applying the same rules. That was an opportunity for refactoring the examination procedure to work with iterators instead of integer indices. For the case of CallExprs no functional change is intended. Reviewers: aaron.ballman, delesley Reviewed By: delesley Subscribers: JonasToth, cfe-commits Differential Revision: https://reviews.llvm.org/D52443 llvm-svn: 343831
2018-10-03Thread safety analysis: Unwrap __builtin_expect in getTrylockCallExprAaron Puchert1-1/+5
Summary: When people are really sure they'll get the lock they sometimes use __builtin_expect. It's also used by some assertion implementations. Asserting that try-lock succeeded is basically the same as asserting that the lock is not held by anyone else (and acquiring it). Reviewers: aaron.ballman, delesley Reviewed By: aaron.ballman Subscribers: kristina, cfe-commits Differential Revision: https://reviews.llvm.org/D52398 llvm-svn: 343681
2018-09-22Eliminate some unneeded signed/unsigned conversionsAaron Puchert1-5/+5
No functional change is intended, but generally this should be a bit more safe. llvm-svn: 342823
2018-09-21Thread safety analysis: Make printSCFG compile again [NFC]Aaron Puchert1-7/+0
Not used productively, so no observable functional change. Note that printSCFG doesn't yet work reliably, it seems to crash sometimes. llvm-svn: 342790
2018-09-21Thread safety analysis: Make sure FactEntrys stored in FactManager are ↵Aaron Puchert1-12/+12
immutable [NFC] Since FactEntrys are stored in the FactManager, we can't manipulate them anymore when they are stored there. llvm-svn: 342787
2018-08-24Thread safety analysis no longer hands when analyzing a self-referencing ↵Aaron Ballman1-0/+3
initializer. This fixes PR38640. llvm-svn: 340636
2018-08-23Remove more const_casts by using ConstStmtVisitor [NFC]Aaron Puchert1-32/+32
Again, this required adding some const specifiers. llvm-svn: 340580
2018-08-23Remove unnecessary const_cast [NFC]Aaron Puchert1-7/+7
This required adding a few const specifiers on functions. Also a minor formatting fix suggested in D49885. llvm-svn: 340575
2018-08-22Thread safety analysis: Allow relockable scopesAaron Puchert1-2/+28
Summary: It's already allowed to prematurely release a scoped lock, now we also allow relocking it again, possibly even in another mode. This is the second attempt, the first had been merged as r339456 and reverted in r339558 because it caused a crash. Reviewers: delesley, aaron.ballman Reviewed By: delesley, aaron.ballman Subscribers: hokein, cfe-commits Differential Revision: https://reviews.llvm.org/D49885 llvm-svn: 340459