Skip to content

Flow analysis of try/catch/finally seems to use a conservative join too broadly #4327

@eernstg

Description

@eernstg

The flow analysis feature specification specifies the treatment of a try/catch statement and the treatment of a try/finally statement, but the try/catch/finally statement hasn't been specified yet (I don't think it will work to read any of the two existing rules as a rule that also covers try/catch/finally).

We have an adjusted rule for the try/finally statement:

  • try finally: If N is a try/finally statement of the form try B1 finally B2 then:
    • Let before(B1) = before(N)
    • Let before(B2) = join(after(B1), conservativeJoin(before(N), assignedIn(B1), capturedIn(B1)))
    • Let after(N) = attachFinally(after(B1), before(B2), after(B2)).

The attachFinally function is complex, but it basically compares the before and after of B2 (the finally block) and treats that as a flow model increment which is applied to each of the predecessors in the control flow graph, no matter how they're completing.

This would need to be generalized somewhat in order to handle the case where we have both try, catch, and finally.

The try/catch case is handled as follows:

  • try catch: If N is a try/catch statement of the form try B alternatives then:
    • Let before(B) = before(N)
    • For each catch block on Ti Si in alternatives:
      • Let before(Si) = conservativeJoin(before(N), assignedIn(B), capturedIn(B))
    • Let after(N) = join(after(B), after(C0), ..., after(Ck))

This seems to imply that the conservative join would be used with the try block in order to take into account that this part may have many different control flow edges out of the block and into any of the catch clauses. However, each catch block is subject to normal flow analysis (there is no need for a conservative join here).

We might then be able to use something along these lines:

  • try catch finally: If N is a try/catch/finally statement of the form try B1 alternatives finally F then:
    • Let before(B1) = before(N)
    • Let before(Si) = join(after(B1), conservativeJoin(before(N), assignedIn(B1), capturedIn(B1))), where Si is the body of the i'th alternative
    • Let after(N) = join(attachFinally(after(B1), before(F), after(F)), M1 .. Mk) where Mj = attachFinally(after(Sj), before(F), after(F))

@stereotype441, WDYT? It seems likely to me that using attachFinally first and then join would yield a more precise analysis than the opposite ordering. Is this compatible with the existing implementation?

Metadata

Metadata

Assignees

No one assigned

    Labels

    flow-analysisDiscussions about possible future improvements to flow analysisquestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions