This is an archive of the discontinued LLVM Phabricator instance.

[Static Analyzer][CFG] Introducing the source array in the CFG of DecompositionDecl
ClosedPublic

Authored by isuckatcs on Jun 16 2022, 11:19 AM.

Details

Summary

Before this patch the array being decomposed was not present in the CFG, which lead to liveness issues.

Consider this snippet:

int uninit[2];
int init[2] = {0};

uninit[0] = init[0];  <-- init is marked as a dead symbol and gets removed

auto [i, j] = init;   <-- init is not referenced in the CFG

This patch makes sure, that the required array is referenced in the CFG, so the liveness of the variable is handled properly.

The AST of auto [i, j] = init; and the solution looks like the following:

`-DecompositionDecl 
  |-ArrayInitLoopExpr 
  | |-OpaqueValueExpr          <-- ignore this OpaqueValueExpr
  | | `-DeclRefExpr 'int[2]'   <-- put this DeclRefExpr to the CFG
  | `-ImplicitCastExpr
  |   `-ArraySubscriptExpr
  |     |-ImplicitCastExpr 
  |     | `-OpaqueValueExpr
  |     |   `-DeclRefExpr
  |     `-ArrayInitIndexExpr
  ` ...

Comparing the old and the new CFG of DecompositionDecl:

                         Old CFG                         |                           New CFG                        
                                                         |   
15: init (ImplicitCastExpr, ArrayToPointerDecay, int *)  |  15: init
16: *                                                    |  16: [B1.15] (ImplicitCastExpr, ArrayToPointerDecay, int *)
17: [B1.15][[B1.16]]                                     |  17: *
18: [B1.17] (ImplicitCastExpr, LValueToRValue, int)      |  18: [B1.16][[B1.17]]
19: {[B1.18]}                                            |  19: [B1.18] (ImplicitCastExpr, LValueToRValue, int)
20: auto = {init[*]};                                    |  20: {[B1.19]}
                                                         |  21: auto = {init[*]};

Diff Detail

Event Timeline

isuckatcs created this revision.Jun 16 2022, 11:19 AM
Herald added a project: Restricted Project. · View Herald TranscriptJun 16 2022, 11:19 AM
isuckatcs requested review of this revision.Jun 16 2022, 11:19 AM
isuckatcs edited the summary of this revision. (Show Details)

Applied clang-format

I think a unit test would be nice. We have some CFG tests here: https://github.com/llvm/llvm-project/blob/main/clang/unittests/Analysis/CFGTest.cpp

clang/lib/Analysis/CFG.cpp
3866

I think visiting the children we want explicitly would be cleaner. I.e., instead of using a loop, querying each child using getters like getCommonExpr.

NoQ added a comment.Jun 16 2022, 12:47 PM

There are also LIT tests in test/Analysis/cfg.cpp etc. which are easier to write and maintain so we usually do them until we have something very specific we want to test.

I see you're still omitting OpaqueValueExpr. I don't remember whether this is the right thing to do, somebody has to eventually omit them but I don't remember whether it's traditionally CFG's responsibility or the consumer (eg. static analyzer)'s responsibility. I think we'll cross this bridge when we get to it.

There are also LIT tests in test/Analysis/cfg.cpp etc. which are easier to write and maintain so we usually do them until we have something very specific we want to test.

I see you're still omitting OpaqueValueExpr. I don't remember whether this is the right thing to do, somebody has to eventually omit them but I don't remember whether it's traditionally CFG's responsibility or the consumer (eg. static analyzer)'s responsibility. I think we'll cross this bridge when we get to it.

OpaqueValueExpr terminates the CFG building, the expression it contains is not visited at all. My initial idea was that if we encounter the OpaqueValueExpr, just take the Expr is contains and visit it, however that resulted in 30+ failing testcases in analysis. I think this situation when the DeclRefExpr we need is wrapped in an OpaqueValueExpr is unique to ArrayInitLoopExpr, so there is no good general solution here.

We either handle it separately in the CFG, or in liveness analysis.

NoQ added a comment.Jun 16 2022, 3:04 PM

Aha great, sounds like this is the right thing to do then!

isuckatcs updated this revision to Diff 437859.Jun 17 2022, 5:34 AM

Addressed comments.

It seems unit tests are focusing more on the features of the CFG itself, and not on CFGs built from snippets.
As this change only affects how a specific expression is evaluated, and doesn't influence the core of the CFG,
I decided to only add a LIT test.

isuckatcs marked an inline comment as done.Jun 17 2022, 5:35 AM
xazax.hun accepted this revision.Jun 17 2022, 9:19 AM

Looks good to me, thanks!

This revision is now accepted and ready to land.Jun 17 2022, 9:19 AM
This revision was landed with ongoing or failed builds.Jun 17 2022, 9:35 AM
This revision was automatically updated to reflect the committed changes.