This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] Fix false positive in use-after-move checker
ClosedPublic

Authored by malavikasamak on Aug 9 2022, 2:34 PM.

Details

Summary

The analyzer issues a warning when the destructor is invoked on the moved-from object explicitly. This is a false positive, as this invoking a destructor on a moved-from object is safe.

Example:
``
A* a = new A;
A b = std::move(*a);
a->~A();
``
The patch addresses this false warning.

Diff Detail

Event Timeline

malavikasamak created this revision.Aug 9 2022, 2:34 PM
Herald added a project: Restricted Project. · View Herald TranscriptAug 9 2022, 2:34 PM
malavikasamak requested review of this revision.Aug 9 2022, 2:34 PM
malavikasamak edited the summary of this revision. (Show Details)
xazax.hun accepted this revision.Aug 9 2022, 2:43 PM

Thanks!

This patch looks good to me. While the documentation of CXXDestructorCall will say that it is only used to represent implicit dtor calls, I wonder if the documentation should be made more explicit saying that it will NOT be generated for an explicit dtor call. @NoQ do you think this is OK, or should CXXDestructorCall also be created for explicit calls?

This revision is now accepted and ready to land.Aug 9 2022, 2:43 PM
NoQ added a comment.Aug 9 2022, 2:49 PM

Aha thanks! Interesting that CallEvent was supposed to be a higher-level abstraction but in this case it attracts unnecessary attention to the syntax whereas the purely syntactic Decl does the job perfectly.

clang/test/Analysis/use-after-move.cpp
917

Technically this code is still provably bad because it demonstrates double destructor invocation (one manual, one automatic) which screws with C++ "object lifecycle" rules. So we most likely want to emit a warning here ultimately, it's just not the responibility of this checker to warn. This might be worth pointing out in comments to the test, to let people know why exactly we don't expect the warning. So that when they see the test fail, they knew whether it's a good thing or a bad thing.

The other examples also have a memory leak (and if you simply add a delete operator, it'll again cause double destruction) which probably also deserves a warning but the corresponding checker is disabled in this test. Might also be worth pointing out.

NoQ added a comment.Aug 9 2022, 3:00 PM

@NoQ do you think this is OK, or should CXXDestructorCall also be created for explicit calls?

That's a good question, another example of this problem is CXXAllocatorCall that covers memory allocation with new syntax:

Class *foo = new Class;

but not explicit invocations like

void *foo = Class::operator new(sizeof(Class));

In this other case it's very natural to have CXXAllocatorCall only cover the first case because it has a lot of accessor methods that don't make any sense at all in the second case. In fact, the analysis conducted by the engine to model the first case is completely different from the second case, with all the construction context shenanigans and intermediate hidden variables, so it makes sense for a path-sensitive data structure to discriminate between those cases.

In case of destructors though, maybe it's actually the right call, as destructor invocations aren't all that different from each other.

This update:

  1. Fixes the memory leak in the test case.
  2. Comments about invoking the destructor twice in the test cases.

Moved the comment to the top of the test.

NoQ accepted this revision.Aug 9 2022, 4:29 PM

LGTM!

Herald added a project: Restricted Project. · View Herald TranscriptAug 9 2022, 5:32 PM
Herald added a subscriber: cfe-commits. · View Herald Transcript