[PATCH] D40560: [analyzer] WIP: Get construction into `operator new` running in simple cases.

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 28 08:00:15 PST 2017


NoQ created this revision.
Herald added subscribers: rnkovacs, eraman.

Under the assumption of `-analyzer-config c++-allocator-inlining=true`, which enables evaluation  of `operator new` as a regular function call, this patch shows what it takes to actually inline the constructor into the return value of such operator call.

The CFG for a `new C()` expression looks like:

- `CXXNewAllocator` `new C()` (a special kind of `CFGElement` on which operator new is being evaluated)
- `CXXConstructExpr` `C()` (a regular `CFGStmt` element on which we call the constructor)
- `CXXNewExpr` `new C()` (a regular `CFGStmt` element on which we should ideally have nothing to do)

What i did here is:

1. First, i relax the requirements for constructor regions, as discussed on the mailing list (http://lists.llvm.org/pipermail/cfe-dev/2017-November/056095.html). We can now construct into `ElementRegion` unless it actually represents an array element (we're not dealing with `operator new[]` yet). Also we remove the explicit bailout for constructions that correspond to operator new parent expressions, as long as `-analyzer-config c++-allocator-inlining` is enabled. See changes in `mayInlineCallKind()`.

2. Then, when the constructor is being modeled, we're trying to get back the value returned by `operator new`. This is done similarly to other construction cases - by finding the next (!!) element in the CFG, figuring out that it's a `CXXNewExpr`, and then taking the respective region to construct into from the Environment. The `CXXNewAllocator` element is not relied upon on this phase - for now it only triggers the evaluation of `operator new` at the right moment, so that we had the return value. See changes in `getRegionForConstructedObject()` and `canHaveDirectConstructor()`.

3. When we reach the actual `CXXNewExpr` CFG element (the third one), we need to preserve the value we already have for the `CXXNewExpr` in the environment. The old code that's conjuring a (heap) pointer here would probably still remain to handle the case when an inlined `operator new` has actually returned an `UnknownVal`. Still, this needs polishing, as the FIXME at the top of `VisitCXXNewExpr()` suggests. See the newly added hack in `VisitCXXNewExpr()`.

4. Finally, the `CXXNewExpr` value keeps dying in the Environment. From the point of view of the current liveness analysis, the new-expression is dead (or rather not yet born) until the `CXXNewExpr` statement element is reached, so it immediately gets purged on every step. The really dirty code that prevents this, //that should never be committed//, is in `shouldRemoveDeadBindings()`: for the sake of this proof-of-concept, i've crudely disabled garbage collection on the respective moments of time. I believe that the proper fix would be on the liveness analysis side: mark the new-expression as live between the `CXXNewAllocator` element and `CXXNewExpr` statement element.

My todo list before committing this would be:

1. Fix the live expressions hack.
2. See how reliable is `findElementDirectlyInitializedByCurrentConstructor()` in this case.
3. Understand how my code works for non-object constructors (eg. `new int`).
4. See how much `VisitCXXNewExpr` can be refactored.

Once this lands, i think we should be looking into enabling `-analyzer-config c++-allocator-inlining` by default.


https://reviews.llvm.org/D40560

Files:
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
  test/Analysis/inline.cpp
  test/Analysis/new-ctor.cpp

-------------- next part --------------
A non-text attachment was scrubbed...
Name: D40560.124570.patch
Type: text/x-patch
Size: 8200 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20171128/048d572a/attachment.bin>


More information about the cfe-commits mailing list