This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Exception Specifications & code quality
- To: egcs at cygnus dot com
- Subject: Exception Specifications & code quality
- From: Nathan Sidwell <nathan at acm dot org>
- Date: Fri, 04 Sep 1998 17:15:06 +0100
- Organization: Computer Science Dept, Bristol University
Last month there was a thread about checking exception specifications
and warning on any leaked exceptions
(http://www.cygnus.com/ml/egcs/1998-Aug/0252.html) I've noticed
something about the exception unwind code, which is related
Consider the following piece of code,
void fn_char() throw(char);
void fn_char1() throw(char)
{fn_char();}
fn_char1 produces exception unwinding code which checks if it's going to
throw an object outside the set of its exception specification. (I've
attached the sparc assembler produced at -O2). This is, of course, not
possible.
The code I'm talking about is between LL3 and LL16. I must say, I'm a
little surprised about the exception unwind blocks LLEHB14, LLEHB7 and
LLEHB10 around this, surely the routines __cp_eh_info, __tfc,
__check_eh_spec cannot throw?
This isn't an execution speed problem, because this is the exception
path, but it is a code size issue.
As with checking exception specifications, you need to scan over the
function body creating the union of all uncaught thrown types (from
throw statements and function calls). Then if this is a subset of the
function's throw specification no runtime check is required. Solving
this problem gives the oportunity for the warning, if you really want
it. Like the 'this var may be used uninitialized' warning, you'd only
get it when optimizing (and you asked for it!).
Just thought I'd share this with you.
nathan
--
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
You can up the bandwidth, but you can't up the speed of light
nathan@acm.org http://www.cs.bris.ac.uk/~nathan/ nathan@cs.bris.ac.uk
.file "e1.ii"
gcc2_compiled.:
.global __throw
.section ".text"
.align 4
.global fn_char1__Fv
.type fn_char1__Fv,#function
.proc 020
fn_char1__Fv:
.LLFB1:
!#PROLOGUE# 0
save %sp,-120,%sp
.LLCFI0:
!#PROLOGUE# 1
.LLEHB3:
call fn_char__Fv,0
nop
.LLEHE3:
b,a .LL16
.LL2:
call __throw,0
nop
.LLEHB14:
.LLEHB7:
.LL3:
call __cp_eh_info,0
nop
mov %o0,%l0
ld [%l0+28],%o1
add %o1,1,%o1
st %o1,[%l0+28]
.LLEHB10:
mov 1,%o2
call __tfc,0
st %o2,[%l0+20]
st %o0,[%fp-20]
mov 1,%o0
call __check_eh_spec,0
add %fp,-20,%o1
.LLEHE10:
.LL9:
call __throw,0
nop
.LLEHE7:
.LL10:
call __cp_pop_exception,0
mov %l0,%o0
b,a .LL9
.LL7:
b,a .LL2
.LLEHE14:
.LL14:
call terminate__Fv,0
nop
.LL16:
ret
restore
.LLFE1:
.LLfe1:
.size fn_char1__Fv,.LLfe1-fn_char1__Fv
.section ".gcc_except_table",#alloc,#write
.align 4
__EXCEPTION_TABLE__:
.uaword .LLEHB3
.uaword .LLEHE3
.uaword .LL3
.uaword .LLEHB14
.uaword .LLEHE14
.uaword .LL14
.uaword .LLEHB7
.uaword .LLEHE7
.uaword .LL7
.uaword .LLEHB10
.uaword .LLEHE10
.uaword .LL10
.uaword -1
.uaword -1
.section ".eh_frame",#alloc,#write
__FRAME_BEGIN__:
.uaword .LLECIE1-.LLSCIE1
.LLSCIE1:
.uaword 0x0
.byte 0x1
.asciz "eh"
.uaword __EXCEPTION_TABLE__
.byte 0x1
.byte 0x7c
.byte 0x65
.byte 0xc
.byte 0xe
.byte 0x0
.byte 0x9
.byte 0x65
.byte 0xf
.align 4
.LLECIE1:
.uaword .LLEFDE1-.LLSFDE1
.LLSFDE1:
.uaword .LLSFDE1-__FRAME_BEGIN__
.uaword .LLFB1
.uaword .LLFE1-.LLFB1
.byte 0x4
.uaword .LLCFI0-.LLFB1
.byte 0xd
.byte 0x1e
.byte 0x2d
.byte 0x9
.byte 0x65
.byte 0x1f
.align 4
.LLEFDE1:
.ident "GCC: (GNU) egcs-2.91.55 19980824 (gcc2 ss-980609 experimental)"