This is an archive of the discontinued LLVM Phabricator instance.

[clang][dataflow] Add `refreshStructValue()`.
ClosedPublic

Authored by mboehme on Jul 13 2023, 7:24 AM.

Details

Summary

Besides being a useful abstraction, this function will help insulate existing clients of the framework from upcoming changes to the API of StructValue and AggregateStorageLocation.

Depends On D155202

Diff Detail

Event Timeline

mboehme created this revision.Jul 13 2023, 7:24 AM
Herald added a project: Restricted Project. · View Herald Transcript
mboehme requested review of this revision.Jul 13 2023, 7:24 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 13 2023, 7:24 AM
mboehme edited the summary of this revision. (Show Details)
ymandel accepted this revision.Jul 13 2023, 8:26 AM
This revision is now accepted and ready to land.Jul 13 2023, 8:26 AM
xazax.hun accepted this revision.Jul 15 2023, 7:41 AM
xazax.hun added inline comments.
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
704–709

I think this is fine for now, but I wonder if we should come up with an API where errors like this cannot happen. One potential way would be to no longer include these properties in the StructValues, but have a separate mapping StructValue => Properties. So, one can update the mapping in an environment without any unintended consequences in other environments.

mboehme added inline comments.Jul 17 2023, 12:03 AM
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
704–709

I think this is fine for now, but I wonder if we should come up with an API where errors like this cannot happen.

Thanks for bringing this up.

I agree that this needs more improvement in the future. The underlying issue is that StructValue isn't really a very useful concept.

Value works great for scalar values, where we do actually treat it as the immutable value that it's intended to be. Attaching properties to values makes a lot of sense in this context: If we're modelling a property of an immutable value, then that property is presumably itself immutable.

However, the Value concept has never worked well for structs / records because, when we mutate fields, we don't update the StructValue. We could try to change this, but I don't think this would be worth it because StructValue isn't a useful concept in C++ anyway. As the value categories RFC discusses, prvalues of class type are a very niche concept in C++. The only thing you can do with them is to initialize a result object -- you can't otherwise perform any operations on them (i.e. access member variables or call member functions). This has been part of the motivation for reducing their importance as part of the value categories work.

I think we should continue down that path and, ultimately, maybe eliminate StructValue entirely. So while introducing a mapping StructValue => Properties would be a good option, I think an even better one would be to start attaching properties to AggregateStorageLocations instead of StructValues. Because AggregateStorageLocations are in essence, mutable, the mapping of AggregateStorageLocations to property values would need to be reflected in the Environment in some form. I think a natural way to do this would be to model properties in a similar way to fields: An AggregateStorageLocation would have a mapping PropertyName => StorageLocation, and the values of the properties would then be tracked through the existing StorageLocation => Value mapping in the environment.

Benefits:

  • As already noted, this makes properties on AggregateStorageLocations very similar to fields, which is what they are typically used to model
  • If a particular analysis needs a storage location for a property, we already have one. For example, UncheckedOptionalAccessModel.cpp currently models the "value" property as a PointerValue so that it has a StorageLocation that it can use as the return value of optional::value(). Under the approach I'm proposing, the storage location would be available from the framework, and the model for a specific analysis wouldn't have to do anything extra.
  • We don't need any additional logic for joins / widening; the existing join / widening logic for the StorageLocation => Value mapping would also handle properties.

So this is where I think we can go in the future, and I agree that refreshStructValue() should only be a stopgap as we evolve the framework.

This revision was landed with ongoing or failed builds.Jul 17 2023, 12:26 AM
This revision was automatically updated to reflect the committed changes.
xazax.hun added inline comments.Jul 17 2023, 4:57 AM
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
704–709

This sounds great, thanks!