NoQ added inline comments.
================ Comment at: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp:112 +Optional<SVal> ExprEngine::retrieveFromConstructionContext( + ProgramStateRef State, const LocationContext *LCtx, ---------------- balazske wrote: > baloghadamsoftware wrote: > > baloghadamsoftware wrote: > > > baloghadamsoftware wrote: > > > > baloghadamsoftware wrote: > > > > > NoQ wrote: > > > > > > baloghadamsoftware wrote: > > > > > > > NoQ wrote: > > > > > > > > Please instead re-use the code that computes the object under > > > > > > > > construction. That'll save you ~50 lines of code and will be > > > > > > > > more future-proof (eg., standalone temporaries without > > > > > > > > destructor technically have a construction context with 0 items > > > > > > > > so when we implement them correctly your procedure will stop > > > > > > > > working). > > > > > > > That was so my first thought. However, > > > > > > > `handleConstructionContext()` is private and non-static. Now I > > > > > > > tried to merge the two methods: if the value is already in the > > > > > > > construction context, we return it, if not then we add it. Is > > > > > > > this what you suggest? Or did I misunderstand you? At the very > > > > > > > beginning I tried to simply use `handleConstructionContext()`, > > > > > > > but it asserted because the value was already in the map. > > > > > > I'd like to preserve the assertion that objects-under-construction > > > > > > are never filled twice; it's a very useful sanity check. What you > > > > > > need in your checker is a function that computes > > > > > > object-under-construction but doesn't put it into the > > > > > > objects-under-construction map. So you have to separate the > > > > > > computation from filling in the state. > > > > > OK, so I (fortunately) misundertood you. Thus I should refactor this > > > > > function to a calculation and a storing part? > > > > OK, I see what you are speaking about, but I have no idea how to do it > > > > properly. The problem is that the control logic of filling in the state > > > > also depends on the kind of the construction context. For some kinds we > > > > do not fill at all. Every way I try it becomes more complex and less > > > > correct: > > > > > > > > 1) `NewAllocatedObjectKind`: we do not add this to the state, we only > > > > retrieve the original. > > > > 2) `SimpleReturnedValueKind` and `CXX17ElidedCopyReturnedValueKind`: > > > > depending on whether we are in top frame we handle this case > > > > recursively or we do not fill at all, just return the value. What is > > > > the construction context item here? Maybe the `ReturnStmt`? > > > > 3) `ElidedTemporaryObjectKind`: this is the most problematic: we first > > > > handle it recursively for the construction context after elision, then > > > > we also fill it for the elided temporary object construction context as > > > > well. > > > > > > > > The only thing I can (maybe) do is to retrieve the construction context > > > > item. But then the switch is still duplicated for filling, because of > > > > the different control logic for different construction context kinds. > > > > The only thing I can (maybe) do is to retrieve the construction context > > > > item. > > > > > > This does not help even for retrieving the value, because its control > > > logic also depends on the construction context kind. If I do it, it will > > > be code triplication instead of duplication and results in a code that is > > > worse to understand than the current one. > > > > > > > > > Please instead re-use the code that computes the object under > > > construction. That'll save you ~50 lines of code and will be more > > > future-proof (eg., standalone temporaries without destructor technically > > > have a construction context with 0 items so when we implement them > > > correctly your procedure will stop working). > > > > Any solution I can come up with rather adds 100 to 150 lines to the code > > instead of saving 50. For retrieving we only have to determine the > > construction context item (the key). For storing we also have to calculate > > the value. It sounds good to calculate these things in separate functions > > and then have a simple retriever and store function but there are lots of > > recursions, double strores, non-stores, retrieving in the store function > > that make it too complicated. > > > > Also retrieving is more complex than just determining the item and getting > > the value from the context: if you look at `SimpleReturnedValueKind` and > > `CXX17ElidedCopyReturnedValueKind` you can see that we do not use the > > construction context we got in the parameter (the construction context of > > the return value) but the construction context of the call instead. For > > `ElidedTemporaryObjectKind` we take the construction context before the > > elusion. > > > > Future proofness: I agree, this is a problem to solve. In cases where the > > construction context is empty maybe we can move the calculation of the > > values to a separate function that is called by both the "handler" and the > > "retriever". > Do I think correctly that `retrieveFromConstructionContext` (in the previous > version) should return the same value as second part of > `handleConstructionContext`? It does not look obvious at first. Or do we need > a function with that purpose? If yes it looks a difficult task because the > similar "logic" to get the value and update the state. Probably it is enough > to add a flag to `handleConstructionContext` to not make new state. The > current code looks bad because calling a "handle" type of function (that was > private before) only to compute a value. > > Any solution I can come up with rather adds 100 to 150 lines to the code > instead of saving 50. I think the following is a fairly literal implementation of my suggestion: {F12020285} It's 26 lines shorter than your `retrieveFromConstructionContext()` (ok, not 50, duplicating the switch was more annoying than i expected), it adds zero new logic (the only new piece of logic is to track constructors that were modeled correctly but their elision wasn't; previously we could fit it into control flow), it no longer tries to reverse-engineer the original behavior by duplicating its logic, and it's more future-proof for the reasons explained above. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D80366/new/ https://reviews.llvm.org/D80366 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits