This is an archive of the discontinued LLVM Phabricator instance.

[clang][dataflow] Perform deep copies in copy and move operations.
ClosedPublic

Authored by mboehme on Jun 15 2023, 3:18 AM.

Details

Summary

This serves two purposes:

  • Because, today, we only copy the StructValue, modifying the destination of the copy also modifies the source. This is demonstrated by the new checks added to CopyConstructor and MoveConstructor, which fail without the deep copy.
  • It lays the groundwork for eliminating the redundancy between AggregateStorageLocation and StructValue, which will happen as part of the ongoing migration to strict handling of value categories (seeo https://discourse.llvm.org/t/70086 for details). This will involve turning StructValue into essentially just a wrapper for AggregateStorageLocation; under this scheme, the current "shallow" copy (copying a StructValue from one AggregateStorageLocation to another) will no longer be possible.

Because we now perform deep copies, tests need to perform a deep equality
comparison instead of just comparing for equal identity of the StructValues.
The new function recordsEqual() provides such a deep equality comparison.

Diff Detail

Event Timeline

mboehme created this revision.Jun 15 2023, 3:18 AM
Herald added a project: Restricted Project. · View Herald Transcript
mboehme requested review of this revision.Jun 15 2023, 3:18 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 15 2023, 3:18 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
mboehme updated this revision to Diff 531734.Jun 15 2023, 6:56 AM

Avoid including llvm/Testing/Support/Error.h in clang/unittests/Analysis/FlowSensitive/TestingSupport.h.

This can lead to version conflicts in projects that want to include
TestingSupport.h but use a different version of gtest than the one vendored with
LLVM.

I am not opposed to this solution, but I do anticipate some performance problems in the future. I wonder if copy-on-write, or some persistent data structures where copying is cheap would be a better strategy long term. But getting it right first and fast after sounds like a good strategy :)

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
745–746
xazax.hun added inline comments.Jun 15 2023, 8:41 AM
clang/lib/Analysis/FlowSensitive/RecordOps.cpp
57–58

I know we usually like to mention types at least once, but wonder whether ranges/iterators are actually exceptions.

mboehme updated this revision to Diff 532568.Jun 19 2023, 2:04 AM

Minor style changes in response to review comments.

mboehme marked 2 inline comments as done.Jun 19 2023, 2:08 AM

I am not opposed to this solution, but I do anticipate some performance problems in the future. I wonder if copy-on-write, or some persistent data structures where copying is cheap would be a better strategy long term. But getting it right first and fast after sounds like a good strategy :)

Agreed - I think "right first and fast after" is the way to go here.

Also, we should wait and see whether this really does turn out to be a performance issue. We'll only be doing this for types that are copyable, and by their nature, these tend to have relatively few fields, as programmers try to avoid making types copyable that are expensive to copy at runtime.

clang/lib/Analysis/FlowSensitive/RecordOps.cpp
57–58

I've looked at the style guide, and it seems to support this usage of auto, so done!

mboehme updated this revision to Diff 532604.Jun 19 2023, 4:34 AM
mboehme marked an inline comment as done.

Use cast_or_null instead of cast in VisitCXXOperatorCallExpr. Added a test
that crashes without this change.

mboehme updated this revision to Diff 532812.Jun 20 2023, 1:00 AM

Now that integer literals are associated with Values, use them in tests
instead of using a helper variable.

xazax.hun accepted this revision.Jun 23 2023, 1:59 AM
This revision is now accepted and ready to land.Jun 23 2023, 1:59 AM
MaskRay added inline comments.
mboehme marked an inline comment as done.Jun 26 2023, 9:43 PM
mboehme added inline comments.
clang/lib/Analysis/FlowSensitive/RecordOps.cpp
20

Thanks for pointing this out!

https://reviews.llvm.org/D153833

@mboehme https://lab.llvm.org/buildbot/#/builders/124 is still broken - please can you revert the patch series?

mboehme marked an inline comment as done.Jul 3 2023, 12:24 AM
mboehme added a subscriber: donat.nagy.

@mboehme https://lab.llvm.org/buildbot/#/builders/124 is still broken - please can you revert the patch series?

Sorry, I did not see this in time to revert.

It seems this has been fixed in the meantime by https://github.com/llvm/llvm-project/commit/cec30e2b190bd58a26f54b5fd4232d3828632466. Thank you to @donat.nagy for the fix, and apologies for the breakage.

gribozavr2 added inline comments.
clang/include/clang/Analysis/FlowSensitive/RecordOps.h
26

Shouldn't it go the other way, from Src to Dst?

53

Could you add a caveat that only 'true' return values from this function matter?

That is, "false" means "might or might not be equal at runtime, we don't know".

clang/unittests/Analysis/FlowSensitive/TestingSupport.h
391

Could you change VerifyResultsT to a std::function (like in other overloads above) so that the type signature is clear?

I'm also unsure about the name - why start a new overload set? It seems like another variant of the checkDataflow() functions above.

mboehme marked 3 inline comments as done.Jul 3 2023, 6:09 AM

https://reviews.llvm.org/D154339 has changes in response to post-commit comments.

clang/include/clang/Analysis/FlowSensitive/RecordOps.h
26
53
clang/unittests/Analysis/FlowSensitive/TestingSupport.h
391

Could you change VerifyResultsT to a std::function (like in other overloads above) so that the type signature is clear?

Done in https://reviews.llvm.org/D154339.

I could have sworn that when I moved this from TransferTest.cpp to here that I tried making this change and realized I couldn't for some reason. But obviously I was wrong.

I'm also unsure about the name - why start a new overload set? It seems like another variant of the checkDataflow() functions above.

This is really just moved from TransferTest.cpp -- and it's more closely related to the runDataflow() functions there and in the newly added RecordOps.cpp. (I can't call it runDataflow() because then it would differ only in return type from one of the functions in the overload set.)

Let's continue the discussion on https://reviews.llvm.org/D154339 if necessary.