1. A system comprising: at least one processor of a computing device; a memory of the computing device; and at least one module loaded into the memory causing the at least one processor to: for each function in a computer program: receive intermediate representation from a compiler for a function: capture summary information for the function, the summary information comprising: a structure capturing nesting of try and catch statements within the function, the function comprising a plurality of regions; for each region of the plurality of regions of the function, types of exceptions thrown by the region; for each catch region of the plurality of regions of the function, types of exceptions caught by the catch region; for each region of the plurality of regions of the function, an indicator that indicates that re-throw statements are found within the region; for each region of the plurality of regions of the function, functions called by the region; for each region of the plurality of regions of the function, an indicator that indicates that the region calls unknown functions or does not call unknown functions; and add the summary information to a call-graph node for the function; and at least one module loaded into the memory causing the at least one processor to: compute a set of live exception types thrown by each function by iteratively propagating types of thrown exceptions from a callee function to a caller function in the call-graph in a bottom-up direction and propagating types of in-flight exceptions from a caller function to a callee function in the call-graph in a top-down direction until a fixpoint is reached; attempt to match catch handlers of each function with a corresponding set of thrown exceptions; and identify a dead catch handler by failing to find a thrown exception of a type caught by the dead catch handler.