Repository navigation
Codegen Patterns EH
MSVC's exception metadata records object lifetimes and source ordering. When instruction bytes are close but unwind data or stack layout differs, inspect scopes and catch types before adding artificial locals.
Symptom: The executable's unwind map returns to the initial state (toState = -1) after each pointer cleanup, but the candidate has nested states. Likely source: each smart-pointer local has its own block and is destroyed immediately after its use.
{
Ptr first = createFirst();
if (first) use(first);
}
{
Ptr second = createSecond();
if (second) use(second);
}Symptom: Code bytes match, but the exception-state table (ip2state) maps temporaries in a different order. Likely source: the same expressions occur in another source order, even if optimization lays out branches differently. Map each state to the relevant temporary or literal and preserve the inferred statement order.
if (condition) makeA(); else makeB();
makeC();The state numbering can reflect source order rather than basic-block layout.
Symptom: In a function with try/catch, the only frame difference is a security-cookie slot shifted by eight bytes. Likely source: the executable catches a named typed reference, which needs a catch-object slot, rather than using catch (...).
try {
work();
} catch (const Error& error) {
handle(error);
}Symptom: A destructor's code lacks the expected terminate/unwind frame even though the source appears non-throwing. Likely source: the language mode and specialization form affect how the compiler interprets exception specifications. Probe with the project's C++14 mode and match the declaration form used by the target code.
template<class T> struct Holder { ~Holder() throw(); };Do not infer behavior from a newer language mode; compile probes with the actual toolchain and flags.