public override void OnExceptionHandler(ExceptionHandler node)
{
if((node.Flags & ExceptionHandlerFlags.Filter) == ExceptionHandlerFlags.Filter)
{
_il.BeginExceptFilterBlock();
Label endLabel = _il.DefineLabel();
// If the filter is not untyped, then test the exception type
// before testing the filter condition
if((node.Flags & ExceptionHandlerFlags.Untyped) == ExceptionHandlerFlags.None)
{
Label filterCondition = _il.DefineLabel();
// Test the type of the exception.
_il.Emit(OpCodes.Isinst, GetSystemType(node.Declaration.Type));
// Duplicate it. If it is null, then it will be used to
// skip the filter.
Dup();
// If the exception is of the right type, branch
// to test the filter condition.
_il.Emit(OpCodes.Brtrue_S, filterCondition);
// Otherwise, clean up the stack and prepare the stack
// to skip the filter.
EmitStoreOrPopException(node);
_il.Emit(OpCodes.Ldc_I4_0);
_il.Emit(OpCodes.Br, endLabel);
_il.MarkLabel(filterCondition);
}
else if((node.Flags & ExceptionHandlerFlags.Anonymous) == ExceptionHandlerFlags.None)
{
// Cast the exception to the default except type
_il.Emit(OpCodes.Isinst, GetSystemType(node.Declaration.Type));
}
EmitStoreOrPopException(node);
// Test the condition and convert to boolean if needed.
node.FilterCondition.Accept(this);
PopType();
EmitToBoolIfNeeded(node.FilterCondition);
// If the type is right and the condition is true,
// proceed with the handler.
_il.MarkLabel(endLabel);
_il.Emit(OpCodes.Ldc_I4_0);
_il.Emit(OpCodes.Cgt_Un);
_il.BeginCatchBlock(null);
}
else
{
// Begin a normal catch block of the appropriate type.
_il.BeginCatchBlock(GetSystemType(node.Declaration.Type));
// Clean up the stack or store the exception if not anonymous.
EmitStoreOrPopException(node);
}
Visit(node.Block);
}