One more EH patch...

This one fixes the case where an exception is thrown inside a @catch() block (GNU runtime).

David

clang.diff (1.96 KB)

And this version now emits code for @synchronized. As with GCC, this code doesn't actually work, because the required functions are not present in the GNU runtime library.

I've also attached the test case I've been using while working on this. The following two commands should produce the same output:

clang -lobjc -fexceptions trycatch.m -g && ./a.out
gcc -lobjc -fobjc-exceptions trycatch.m && ./a.out

I don't know if someone wants to add this to the clang test suite.

At the moment, clang has the same behaviour as gcc when -fexceptions is not specified; it generates code which aborts at runtime if an exception is thrown, rather than handling it. Although this is the same as gcc, it seems like the wrong thing to do. We should probably either:

1) Implicitly turn on -fexceptions when @try/@catch/@throw/@synchronized is encountered, or
2) Emit an error and let the user know at compile-time that they are generating broken code.

My personal preference would be (2), because all of the intervening functions between the @throw and the @catch should be compiled with exception support to work correctly, and it's likely that just turning on exceptions for the files that throw or catch them will introduce subtle failures.

David

clang.diff (3.34 KB)

trycatch.m (1.39 KB)

This one fixes the case where an exception is thrown inside a @catch() block (GNU runtime).

And this version now emits code for @synchronized. As with GCC, this code doesn't actually work, because the required functions are not present in the GNU runtime library.

Thanks David, applied. I don't have an opinion on:

I've also attached the test case I've been using while working on this. The following two commands should produce the same output:

clang -lobjc -fexceptions trycatch.m -g && ./a.out
gcc -lobjc -fobjc-exceptions trycatch.m && ./a.out

I don't know if someone wants to add this to the clang test suite.

At the moment, clang has the same behaviour as gcc when -fexceptions is not specified; it generates code which aborts at runtime if an exception is thrown, rather than handling it. Although this is the same as gcc, it seems like the wrong thing to do. We should probably either:

1) Implicitly turn on -fexceptions when @try/@catch/@throw/@synchronized is encountered, or
2) Emit an error and let the user know at compile-time that they are generating broken code.

My personal preference would be (2), because all of the intervening functions between the @throw and the @catch should be compiled with exception support to work correctly, and it's likely that just turning on exceptions for the files that throw or catch them will introduce subtle failures.

#1 isn't feasible, we don't want mode settings changing depending on what the user wrote. #2 makes the most sense to me.

-Chris

This may make sense for Gnu runtime. But for us, objc runtime library always
supports the eh. Any error reporting should be done on the GNU side.

- Fariborz

Are you sure about this? I just compiled a trivial test function containing @throw, @catch and @finally with -emit-llvm -fnext-runtime and -fobjc2, but without -fexceptions, and it emitted bitcode containing references to the LLVM exception intrinsics in a function marked as nounwind. This is exactly what happens on the GNU runtime without -fexceptions, and it results in LLVM not emitting the unwinding info for the function and the unwind library being unable to unwind into it.

David

ObjC EH on darwin/32 uses setjmp/longjmp, not dwarf exceptions.

-Chris

This may make sense for Gnu runtime. But for us, objc runtime library
always
supports the eh. Any error reporting should be done on the GNU side.

Are you sure about this? I just compiled a trivial test function containing @throw, @catch and @finally with -emit-llvm -fnext-runtime and -fobjc2, but without -fexceptions, and it emitted bitcode containing references to the LLVM exception intrinsics in a function marked as nounwind. This is exactly what happens on the GNU runtime without -fexceptions, and it results in LLVM not emitting the unwinding info for the function and the unwind library being unable to unwind into it.

We are probably on two different systems. On may MacOS system, -fobjc2 is not a valid option and -fexceptions
is always on by default. I think, flagging @try as error should be done based on the system and the supporting
libraries, option settings, etc.

- Fariborz

This one fixes the case where an exception is thrown inside a @catch()
block (GNU runtime).

And this version now emits code for @synchronized. As with GCC, this code
doesn't actually work, because the required functions are not present in the
GNU runtime library.

I've also attached the test case I've been using while working on this. The
following two commands should produce the same output:

clang -lobjc -fexceptions trycatch.m -g && ./a.out
gcc -lobjc -fobjc-exceptions trycatch.m && ./a.out

I don't know if someone wants to add this to the clang test suite.

Right now we don't have executable test cases in the suite, and do
have an active policy to avoid them. I think we should eventually
extend the test infrastructure so that we can have some (optionally
executable) executable tests, but this hasn't really been discussed.

What you can do if you like is add them to the llvm-test suite, with
appropriate Makefile magic to only enable if the platform supports it.
I have already added a few NeXT Objective-C tests there (although
nothing particularly consequential).

At the moment, clang has the same behaviour as gcc when -fexceptions is not
specified; it generates code which aborts at runtime if an exception is
thrown, rather than handling it. Although this is the same as gcc, it seems
like the wrong thing to do. We should probably either:

1) Implicitly turn on -fexceptions when @try/@catch/@throw/@synchronized is
encountered, or
2) Emit an error and let the user know at compile-time that they are
generating broken code.

My personal preference would be (2), because all of the intervening
functions between the @throw and the @catch should be compiled with
exception support to work correctly, and it's likely that just turning on
exceptions for the files that throw or catch them will introduce subtle
failures.

#2, definitely.

- Daniel

This one fixes the case where an exception is thrown inside a
@catch() block (GNU runtime).

And this version now emits code for @synchronized. As with GCC,
this code doesn't actually work, because the required functions are
not present in the GNU runtime library.

Thanks David, applied. I don't have an opinion on:

I've also attached the test case I've been using while working on
this. The following two commands should produce the same output:

clang -lobjc -fexceptions trycatch.m -g && ./a.out
gcc -lobjc -fobjc-exceptions trycatch.m && ./a.out

I don't know if someone wants to add this to the clang test suite.

At the moment, clang has the same behaviour as gcc when -fexceptions
is not specified; it generates code which aborts at runtime if an
exception is thrown, rather than handling it. Although this is the
same as gcc, it seems like the wrong thing to do. We should
probably either:

1) Implicitly turn on -fexceptions when @try/@catch/@throw/
@synchronized is encountered, or
2) Emit an error and let the user know at compile-time that they are
generating broken code.

This may make sense for Gnu runtime. But for us, objc runtime library
always
supports the eh. Any error reporting should be done on the GNU side.

Are you sure about this? I just compiled a trivial test function
containing @throw, @catch and @finally with -emit-llvm -fnext-runtime
and -fobjc2, but without -fexceptions, and it emitted bitcode
containing references to the LLVM exception intrinsics in a function
marked as nounwind. This is exactly what happens on the GNU runtime
without -fexceptions, and it results in LLVM not emitting the
unwinding info for the function and the unwind library being unable to
unwind into it.

I think this is probably a bug, can you file it?

- Daniel

2) Emit an error and let the user know at compile-time that they are
generating broken code.

My personal preference would be (2), because all of the intervening
functions between the @throw and the @catch should be compiled with
exception support to work correctly, and it's likely that just turning on
exceptions for the files that throw or catch them will introduce subtle
failures.

#2, definitely.

If we are going to issue error for @try/@catch and when -fexceptions is not
specified, then it should be done for runtimes which require special libraries to handle
them and at ir-gen time, since ASTs should always be
valid, even with -fno-exceptions. For example, static analyzer should continue to work, regardless.

- Fariborz