[PATCH] D77229: [Analyzer][WIP] Avoid handling of LazyCompundVals in IteratorModeling

Artem Dergachev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 27 07:29:44 PDT 2020


NoQ added a comment.

In D77229#2004964 <https://reviews.llvm.org/D77229#2004964>, @baloghadamsoftware wrote:

> This is not the proper way, `MemRegion`s for parameters in inlined functions should remain `VarRegion`s because parameters **are** variables inside. On the other hand, from outside it does not matter what kind of regions they are. We mainly need the region there to use it as key for `GDM` maps. That is why `ParamRegion`s should only be created for functions that are not inlined. If they have no definition then they cannot be inlined so a `ParamRegion` is OK for them. However, if they have a definition then there is no problem finding the same `Decl` because the definition is that same `Decl` that we use everywhere so it can and should remain a `VarRegion`.


I'm not opposed to this solution. I'm not sure it's actually easier; i agree that it may even be less code but because i already tried to do this and failed, i'm worried that the tail of regressions may actually be longer.

That said, as of now you cannot know in advance whether the function will be inlined or not. "Having a definition" is probably the best approximation that you'll ever get.

Also it complicates the construction of the region, given that in order to figure out whether we have a definition you suddenly need access to the `Environment` (in case of inlined calls by function pointers you cannot figure out from the AST whether we have a definition or not) which is a fairly unfortunate layering violation. Is such information always available in all the places in which we want to reconstruct the region? Will it always be available? How will you ensure that?

Also please check if the following example behaves correctly:

  class C { ... };
  
  void foo(C, int) {}
  
  int set_foo_ptr(void (**func)(C, int)) {
    *func = foo;
    return 0;
  }
  
  void bar() {
    void (*func)(C, int);
    func(C(), set_foo_ptr(&func));
  }

What's the evaluation order here? Do we actually invoke `foo()` from `bar()` here or do we read from the `func` variable before assigning into it thus causing a call to uninitialized pointer? In the former case your plan is doomed because you need a region into which `C()` lands earlier than you get to know any `Decl` at all.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D77229/new/

https://reviews.llvm.org/D77229





More information about the cfe-commits mailing list