-
Couldn't load subscription status.
- Fork 45
trycatch support #101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
trycatch support #101
Conversation
|
Hi @nikic, @ircmaxell |
|
So, one issue: technically now every sub-block within the try-catch needs to keep a reference back to the wrapping try in-case there’s an exception. In essence: The block for Where this gets tricky is when blocks can be entered by multiple paths (via goto, etc), the parser needs to be careful to attach the TryContextOp of the code parent, not the CFG entry point (which may or may not be the same). In an analysis context, seeing as every expression (well, most) could theoretically throw an exception, when analyzing code flow, the expression would look to the block it resides in for the context. Which raises the question: should the Op or Expr keep a reference to the Block it is a member of, or to the nearest |
|
The issue is: That should return |
|
Thanks for the detailed answer. Is this really specific to the But statically and only with the CFG, we don't know this, unless we track the value of |
|
The difference is that with the information currently contained in the CFG, you could transform that via constant propagation passes, and reduce it down fully to just With try/catch, there is a subtle difference in that it's actually overlaying a separate graph on top. Without that separate graph, there's no real way of knowing where an exception would bubble. Without try/catch support that doesn't matter in practice since you could just walk back up to the wrapping Func/Script and you're done. But once you have try/catch that walking now has potential intermediaries it needs to visit. And we definitely need to track the type of exceptions. I don't know if we can track thrown types generally, but we should be able to track caught types generally (your current |
|
I will take this code as an example to better understand the objective: Generated cfg for the first Generated cfg for the second then for the Am I correct? |
|
So, this turned out to be much deeper than I expected. I created #102 to attempt an implementation. There are multiple issues with it, but it should give you an idea of the direction and what's needed. Gives us
And Note: I know Traverser is broken as it won't traverse any Blocks inside the |
|
Thank you, I think I understand, except for this sentence: "I know Traverser is broken as it won't traverse any Blocks inside the catchTarget". I can clean a bit the PR but I don't have the necessary permissions on the repository. This information about catch/finally targets certainly helps, but is it really the CFG's responsibility to offer this kind of "semantic information"? My use case may be very specific, but in the case of interprocedural analysis on top of the CFG: Obviously, the |
I think so (but am open to other ideas), since control flow is determined by semantics of try/catch/finally, so without encoding the semantics analysis can be incorrect (not just in edge cases like exceptions, but even in semantic cases). Take the following code: In this code, the return is 100% always guaranteed to be The catch target is likely less useful for most analysis types, but there are definitely some where it's going to be handy. Finally is definitely useful though.
That only really matters if inlining In your interprocedural analysis case, you'd need to keep track of what can throw (literally anything with ErrorExceptions) and then wire together. But the key is you only need to keep track of the potential call graphs, and only walk those call graph edges backwards to determine where a catch or finally would occur.
I'd suggest just throwing away my PR. Maybe fork from it and continue to develop and update this one? |
The problem is that Looking at it deeper, realistically this should likely be refactored to have Also, Thinking about it a bit more, I think each of the And yeah, this gets super complex super quickly, which is why it wasn't implemented before. But this is definitely getting close. Thanks!!! |

No description provided.