Added modeling for unique_ptr::operator bool method
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
183–202 | This seems little messy here. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
455 | It's always UnknownVal because the call has not been evaluated yet. This assume() does nothing. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
466 | Since the inner pointer value can be any non-null value, I am not sure what should be the value to be added to the map for tracking. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
455 | Okay. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
183–202 | I agree. isNullAfterMoveMethod is especially confusing as it does not do what the name of the function says. It checks if the Call is a boolean conversion operator. I'd suggest renaming that method to make this code a bit more sensible. Moreover, when ModelSmartPtrDereference is true, we no longer model moves below right? I think a comment that this logic is duplicated handleBoolOperation might make the code cleaner. But yeah, this needs to be cleaned up, hopefully really soon. | |
444 | This looks fine for now, but we often prefer adding a return after each case to avoid executing multiple addTransitions accidentally after refactoring. |
Changes to use conjureSymbolVal if the inner pointer value is missing
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
183–202 |
Hopefully we can clean up once std::move is modeled. | |
444 | Added return | |
466 | Made changes to create the conjured symbol and use that to constrain. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
135 | It seems like a long shot to me. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
135 | That's about right. You're doing exactly what you're asked: grab the template parameter of the class. The problem is indeed that complicated! | |
150 | That's pretty fundamental, right? If it's a specialization, it must have something specialized. It isn't specific to unique pointers, right? Because unique pointers aren't special; technically anybody can define an arbitrary class with name std::unique_ptr and any properties they'd like. It's going to be undefined behavior according to the standard (because namespace std is explicitly reserved for the standard library) but if the compiler *crashes* it'll still be our fault. | |
473 | There's no need to check. You just conjured a brand new symbol out of thin air; you can be sure that it's completely unconstrained and both states are feasible. You can instead assert() that they're both feasible. | |
483–485 | Wait, what happens when the region can't be pretty-printed? Does it print two spaces between "pointer" and "is"? |
Please add a test case, where the unique_ptr is initialized from a pointer parameter that has no assumptions. I think that case is not handled correctly.
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
142 | I'd rather use Decl::isInStdNamespace instead of querying the DeclContext of the decl. The former is more robust with inline namespaces. | |
146 | Inverting this condition would reduce the indentation in the rest of the function. | |
152 | You could return the real inner type here and replace all other returns with return {}; making the code a bit cleaner. | |
438 | Is this actually correct? What if the InnerPtr is an unconstrained symbol. In that case, it is not a zero constant so we will assume that it is constrained to non-zero. As far as I understand. | |
457 | I'd do it the other way around as we discussed during the call.
| |
473 | I think instead of removing this check, this method should be reworked. I think it might have some bugs, see my comment at the beginning of this method. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
429 | I suggest BoolConversion |
- Adding checkLiveSymbols and review comments changes
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
142 | Changed to use Decl::isInStdNamespace | |
146 | inverted the if condition | |
150 | added a check for TemplateArgs.size() == 0 before accessing the first Template argument. | |
152 | Updated to return with {} | |
429 | yeah thats sounds better. | |
438 | Fixed as you suggested in the below comments | |
457 | Made the changes as suggested above | |
473 | Refactored the method as suggested. | |
483–485 | Yes. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
318–321 | Yes, this looks correct, thanks! In the ideal world we'd have checked that I->first is live before marking I->second live. Unfortunately, currently checkLiveSymbols is invoked before RegionStore's live symbols detection, so we can't rely on that and it's a bug; in order to be correct, RegionStore's live symbols detection and checker's live symbols callback should engage in fixpoint iteration. | |
497–499 | Because these note tags aren't specific to the bug report at hand, they have to be marked as prunable (i.e., the optional getNoteTag()'s parameter "IsPrunable" should be set to true). That'd reduce bug report clutter by not bringing in stack frames that aren't otherwise interesting for the bug report. Something like this may act as a test (i didn't try): struct S { std::unique_ptr<int> P; void foo() { if (!P) { // no-note because foo() is pruned return; } } int bar() { P = new int(0); foo(); return 1 / *P; // warning: division by zero } } |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
497–499 | Marked these tags as prunable and added the tests. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
486 | Wait, why are we marking the region interesting here? Not every null smart pointer is interesting, only the ones that are actually dereferenced. | |
500–502 | Also i'm starting to suspect that these notes aren't actually needed when there's no "Assuming..."; in particular, we don't emit such notes for raw pointers, so we probably shouldn't emit them for smart pointers either. There's anyway going to be a note about "Taking true branch..." or something like that, which is sufficient to understand what was the smart pointer. I.e., this note is unnecessary: void foo() { std::unique_ptr<int> P = nullptr; if (P) { // Smart pointer 'P' is null // Taking false branch } } The second note, "Taking false branch", is sufficient for explaining to the user that the smart pointer is known to be null. The user may ask why the smart pointer is null, but the note isn't explaining it. The way you marked the region as interesting (as i noticed in the above inline comment) would have indeed explained why it's null, but at this point we draw the line and believe that if the region isn't already interesting then the user most likely doesn't need to know why it's null (and if it's already interesting then there's no need to mark it again). But this note is necessary: void foo(std::unique_ptr<int> P) { if (P) { // Assuming smart pointer 'P' is null // Taking false branch } } This note conveys the extra information that we don't know for a fact that the smart pointer is null on the current path based on previous analysis, but instead the analyzer is *assuming* that it's possible that it's null due to the presence of the check in the code. That's a big deal. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
486 | This was added to show how the smart pointer, even though it is not dereferenced. But why did we take true/false branch based on this. | |
500–502 | Since the "Taking false branch" is enough to implies the smart pointer in null, removing the notes which are unnecessary. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
556 | Don't we want to actually add InnerPointerVal to TrackedRegionMap in this case? I might be wrong but I cannot find where do we actually record the fact that this freshly conjured symbol belongs to the unique_ptr we are modeling. |
clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp | ||
---|---|---|
556 | Thanks for catching that. |
clang-format not found in user's PATH; not linting file.