Bug 168828

Summary: The -fno-enforce-eh-specs option does not behave properly when the function explicitly cannot throw exceptions
Product: Red Hat Enterprise Linux 4 Reporter: Josef Bacik <jbacik>
Component: gcc3Assignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: 4.0CC: jason
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2006-03-15 15:05:16 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---
Description Flags
Patch that fixes the problem none

Description Josef Bacik 2005-09-20 15:15:43 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.10) Gecko/20050719 Red Hat/1.0.6-1.4.1 Firefox/1.0.6

Description of problem:
The g++ option -fno-enforce-eh-specs with RHEL 4's GCC does not work properly with the following test case

#include <iostream>
#include <exception>

using namespace std;

class Exception1 {};

void func1() throw(){ throw Exception1();}

int main()
      cout << "*" << endl;
   catch (...)
      cout << "Exception caught" << endl;

If you compile this with

g++ -Wall -fno-enforce-eh-specs 

and then run it, it will exit with SIGABRT, instead of allowing the exception to be thrown.

Now, what I found is that the only place that the flag_enforce_eh_specs option is invocked is in gcc/cp/decl.c, first around 10620 (depending which build you are looking at) in static void store_parm_decls (tree current_function_parms) with the following code

/* Do the starting of the exception specifications, if we have any. */
if (flag_exceptions && !processing_template_decl
    && flag_enforce_eh_specs
    && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
   current_eh_spec_block = begin_eh_spec_block ();

and then again at 10880 in tree finish_function (int flags)

/* Finish dealing with exception specifiers. */
if (flag_exceptions && !processing_template_decl
    && flag_enforce_eh_specs
    && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
   finish_eh_spec_block (TYPE_RAISES_EXCEPTIONS
                        (TREE_TYPE (current_function_decl)),

So from this, if this option is set and I'm reading it properly, then the throw() part of a function declaration is never processed, basically stripping the function declaration of its throw() restrictions. This works if you do something like

void foo() throw(int)
   throw myClass;

and compile it with -fno-enforce-eh-specs. However, if you use the case provided , with just throw(), the program aborts. The reason for this is because later down in tree finish_function (int flags), there is the following section

/* If this function can't throw any exceptions, remember that. */
if (!processing_template_decl
    && !cp_function_chain->can_throw
    && !flag_non_call_exceptions)
   TREE_NOTHROW (fndecl) = 1;

and cp_function_chain->can_throw gets set in bool maybe_clone_body (tree fn) in gcc/cp/optimize.c, so the TREE_NOTHROW flag gets set since this function has been declared in such a way so that it is not supposed to throw exceptions.

I've written a patch for this issue and tested it, and it works, I will attach it to this bugzilla.

Version-Release number of selected component (if applicable):

How reproducible:

Steps to Reproduce:
1.Make a function definition with throw() in it 
2.compile it with the -fno-enforce-eh-specs option
3.run the program

Actual Results:  The program exits with sigabrt and dumps a core

Expected Results:  It should run fine

Additional info:

Comment 1 Josef Bacik 2005-09-20 15:17:18 UTC
Created attachment 119030 [details]
Patch that fixes the problem

This patch basically checks to see if flag_enforce_eh_specs is set, and if its
not it doesn't allow g++ to note the fact that the function explicitly doesn't
allow exception throwing.

Comment 2 Josef Bacik 2005-09-20 19:23:44 UTC
Hmm, seems I used the wrong test case to test this patch, so it doesn't work.  I
think its because TREE_NOTHROW is set to 1 by default, and is never set back to
0.  I'm rebuilding GCC with some debug information, and as soon as I
verify/prove this wrong I'll work out another patch that should fix this.