[cfe-dev] CFG temporary objects destructors

Ted Kremenek kremenek at apple.com
Sun Oct 24 11:13:58 PDT 2010


On Oct 22, 2010, at 10:41 PM, Zhongxing Xu <xuzhongxing at gmail.com> wrote:

> 
> 
> 2010/10/23 Ted Kremenek <kremenek at apple.com>
> On Oct 17, 2010, at 3:06 PM, Marcin Świderski wrote:
> 
> > Blocks structure that is constructed is fine, but I don't know what to use for terminator of block initiating the branch and for first element in block closing the branch (I didn't check this yet, but I think that it could be used during backward analysis). Could I use fake if/else statement for this? Similar solution is used to make every declaration into separate statement.
> 
> What we could do is generalize terminators in the same way we did with CFGElements.  Right now terminators are Stmt*, but they could be something like CFGTerminator, which could discriminate between regular terminators and those used for blocks guarding destructor calls.  The CFGTerminator for those blocks could essentially be the same Stmt* as the terminator guarding the block with the constructor, but with a special bit indicating it is for the matching destructor(s).  The nice thing about this approach is that it naturally ties the two blocks together, they can share the same condition values, etc.
> 
> We need a way to convey the branch information to the second logical op used as terminator. At first we bind logical op to a UndefinedVal which indicates which branch is taken. Then the logical op is bound to its real value. At the second terminator where the logical op appears, we still need the taken branch information to decide which branch to take.

Indeed.  After thinking about this some more, we can't just keep a reference the original block-level expression that represented the branch condition and hope that is enough.  That expression's SVal should still be in the Environment (since it would still be live), and we could use it a second time when deciding the branch.  That only works, however, if we only took a single branch (not both of them) and the SVal didn't reference any symbolic values (which depend on state).  Thus recording the branch taken seems to be the most accurate and simplest approach.

We could possibly insert this information into the Environment (possibly using some bit mangling for the Stmt* key value), have the data value represent the branch taken, and then have the liveness of that entry be the same as the liveness of the original condition expression.

For example, in A || B, the expression 'A' is used to determine the first branch.  For that, we have a block-level expression (a Stmt*) which serves as a condition for the terminator '||'.  That value gets inserted into the Environment as part of regular evaluation, and stays live until after we are done with evaluating the '||' terminator (LiveVariables analysis does this for us).  In addition, we could insert another entry whose key is similar to the one for the block-level expression but instead has a bit twiddled (e.g., we take the Stmt* for 'A', which represents the condition value used for the first branch, and then bit-mangle it).  We could use that to record what branch we took, and keep that entry around as long as the original block-level expression (e.g., the Stmt* for 'A') would stay in the Environment.  That value's lifetime would get extended by having a special CFGTerminator that referenced that block-level expression and represented the terminator for jumping to the block with the destructor calls.  We then consult the branch value when choosing what block to jump to for the destructors.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20101024/1fa0fba0/attachment.html>


More information about the cfe-dev mailing list