This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
| Other format: | [Raw text] | |
Oops, seems my last email didn't come through anyway. Anyway, here's the stuff: RES is my project to test (at compile time) whether C++ code can throw unhandled exceptions. I tidied up my source, made a patch, wrote and tested some testcases, and wrote some documentation. There should be three attachments here: - res.diff - res.txt - test.tar.gz I've never made patch files before, but hopefully this one is OK. I used [diff -Naur original/gcc-3.4.2/gcc res/gcc-3.4.2/gcc > res.diff] I tested it on a fresh gcc-3.4.2 extract and it worked with [patch -p1 < res.diff] For a quick test, just call gcc with -Wres (or -Wres-debug to add the debug info). I haven't tested on much real-world code, there's a chance it may still have bugs and segfault or something. It's still pre-alpha though. I tried to use GCC coding style but I didn't see an 80 character/line limit anywhere in the document, so I didn't use any limit. Perhaps someone will bite me for this or perhaps you'll all celebrate the beginning of a new era of sensible unlimited lines :) anyway it's pre-alpha so it hardly matters at present - it's just far easier for me to read. Testcases: Unzip test.tar.gz and read test/tests.txt for instructions. All the testcases except the last work as they should.
diff -Naur original/gcc-4.3.2/gcc/c-opts.c res/gcc-4.3.2/gcc/c-opts.c
--- original/gcc-4.3.2/gcc/c-opts.c 2008-01-23 03:11:44.000000000 +1300
+++ res/gcc-4.3.2/gcc/c-opts.c 2008-12-16 17:44:42.000000000 +1300
@@ -40,6 +40,8 @@
#include "mkdeps.h"
#include "target.h"
#include "tm_p.h"
+/* <[SPH]> */
+#include "res.h"
#ifndef DOLLARS_IN_IDENTIFIERS
# define DOLLARS_IN_IDENTIFIERS true
@@ -510,6 +512,21 @@
error ("argument %qs to %<-Wnormalized%> not recognized", arg);
break;
+ /* <[SPH]> */
+ case OPT_Wresl_:
+ res_dwb_add_filelist(arg);
+ case OPT_Wres_cnr:
+ case OPT_Wres_mes:
+ /* Fall through. */
+ case OPT_Wres:
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sWres.", res_intmsg_prefix);
+ res_check_exception_specification = true;
+ warn_restrictive_exception_specification = true;
+ break;
+
+
case OPT_Wreturn_type:
warn_return_type = value;
break;
@@ -530,6 +547,14 @@
cpp_opts->warn_trigraphs = value;
break;
+ /* <[SPH]> */
+ case OPT_Wtt:
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sWtt.", res_intmsg_prefix);
+ res_check_exception_specification = true;
+ break;
+
case OPT_Wundef:
cpp_opts->warn_undef = value;
break;
@@ -552,6 +577,18 @@
warn_write_strings = value;
break;
+ /* <[SPH]> */
+ case OPT_Wxesl_:
+ res_dwb_add_filelist(arg);
+ /* Fall through. */
+ case OPT_Wxes:
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sWxes.", res_intmsg_prefix);
+ res_check_exception_specification = true;
+ warn_excessive_exception_specification = true;
+ break;
+
case OPT_Weffc__:
warn_ecpp = value;
if (value)
@@ -1687,3 +1724,247 @@
break;
}
}
+
+
+
+/* <[SPH]> */
+/* RES: Restrictive Exception Specification. */
+
+bool res_check_exception_specification = FALSE;
+
+/* Internal warning prefix. NULL = no internal warnings. */
+const char* res_intmsg_prefix = RES_INTMSG_PREFIX;
+
+/* RES: Declaration Whitelisting & Blacklisting. */
+
+const char*
+res_system_path = RES_DWB_SYSTEM_DIR;
+
+/* TREE_LISTs of list members. */
+static tree
+res_dwb_filelist = NULL_TREE;
+
+/* Parse the file-list after the command-line option -Wresl=.
+ Save each identified node into res_filelist.
+ Parameters:
+ arg: The null-terminated string argument directly following the command line option. */
+
+void
+res_dwb_add_filelist(const char* arg)
+{
+ tree last_node = NULL_TREE;
+ const char* ch = arg;
+ const char* start = arg;
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%s-Wresl arg = \"%s\".", res_intmsg_prefix, arg);
+
+ /* Parse the file-list.
+ Step through characters one at a time. */
+ while(true)
+ {
+ if(((*ch) == RES_DWB_CHAR_SEPARATOR) || ((*ch) == '\0'))
+ /* New list node. */
+ {
+ bool is_blacklist = false;
+ bool is_system = false;
+ bool is_partial = false;
+ const char* end = ch;
+ int len = end - start;
+
+ /* <TEMP> */
+ /* For disabling verbose debugging output. */
+ if(len > 0)
+ if((*start) == '=')
+ res_intmsg_prefix = NULL;
+
+ if(len > 0)
+ if((*start) == RES_DWB_CHAR_BLACKLIST)
+ /* Blacklist. [-foo.h] makes <foo.h> warnable. */
+ {
+ is_blacklist = true;
+ start++;
+ len--;
+ }
+
+ if(len > 0)
+ if((*start) == RES_DWB_CHAR_SYSTEM)
+ /* System path. [^foo.h] matches <foo.h> not "foo.h". */
+ {
+ is_system = true;
+ start++;
+ len--;
+ }
+
+ if(len > 0)
+ if((*(end - 1)) == RES_DWB_CHAR_PARTIAL)
+ /* Partial match. [foo+] matches any file starting with "foo". */
+ {
+ is_partial = true;
+ end--;
+ len--;
+ }
+
+ /* Build and add the new node to the list. */
+ {
+ tree node;
+ size_t flags = 0;
+
+ if(is_blacklist) flags |= RES_DWB_FLAG_BLACKLIST;
+ if(is_system) flags |= RES_DWB_FLAG_SYSTEM;
+ if(is_partial) flags |= RES_DWB_FLAG_PARTIAL;
+
+ /* Build the new node. */
+ node = tree_cons((tree)start, (tree)end, NULL_TREE);
+ TREE_TYPE(node) = (void*)flags;
+
+ /* Attach the new node to the tail of the list. */
+ if(last_node == NULL_TREE)
+ res_dwb_filelist = node;
+ else
+ TREE_CHAIN(last_node) = node;
+
+ last_node = node;
+ }
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ {
+ char buffer[110];
+ int buffer_len = (len > 100) ? 100 : len;
+ memcpy(buffer, start, buffer_len);
+ buffer[buffer_len] = '\0';
+ /* Eg: [TEST: Added "foo" to blacklist as part user path.] */
+ warning(0l, "%sAdded \"%s\" to %s as %s %s path.", res_intmsg_prefix, buffer, is_blacklist ? "blacklist" : "whitelist", is_partial ? "partial" : "full", is_system ? "system" : "user");
+ }
+
+ start = ch + 1;
+
+ if((*ch) == '\0')
+ break;
+ }
+
+ if((*ch) == RES_DWB_CHAR_ESCAPE)
+ /* Escape character. */
+ {
+ ch++;
+ if((*ch) == '\0')
+ /* Escape without following character. */
+ break;
+ }
+
+ ch++;
+ }
+}
+
+/* Check res_whitelist and res_blacklist to see if calls to items declared in the file should generate -Wres warnings.
+ Parameters:
+ name: The filename to be checked.
+ Return:
+ true: Generate -Wres warnings for calls to this file.
+ false: Do not generate -Wres warnings for calls to this file. */
+
+bool
+res_dwb_file_warnable(const char* name_start)
+{
+ bool is_system = false;
+ const char* name_ch = name_start;
+ const char* system_ch = res_system_path;
+ const char* name_end = name_start + strlen(name_start);
+ tree node;
+
+ /* Check whether "name" is inside the system path.
+ Step through characters one at a time. */
+ while(true)
+ {
+ if((*system_ch) == '\0')
+ /* "name" is inside the system path. */
+ {
+ is_system = true;
+ name_start = name_ch;
+ break;
+ }
+
+ /* If (*name_ch) == '\0', will always break here. */
+ if((*name_ch) != (*system_ch))
+ break;
+
+ system_ch++;
+ name_ch++;
+ }
+
+ /* Check every node on the list to see if it matches. */
+ for(node = res_dwb_filelist; node != NULL_TREE; node = TREE_CHAIN(node))
+ {
+ /* Extract flags. */
+ size_t node_flags = (size_t)TREE_TYPE(node);
+ bool node_is_blacklist = (node_flags & RES_DWB_FLAG_BLACKLIST) != 0;
+ bool node_is_system = (node_flags & RES_DWB_FLAG_SYSTEM) != 0;
+ bool node_is_partial = (node_flags & RES_DWB_FLAG_PARTIAL) != 0;
+ const char* node_start;
+ const char* node_end;
+ const char* node_ch;
+ const char* name_ch;
+
+ /* if(node_is_system ^^ is_system) */
+ if((node_is_system && !is_system) || (!node_is_system && is_system))
+ /* Node is a system path but query isn't, or vice-versa. */
+ continue;
+
+ node_start = (const char*)TREE_PURPOSE(node);
+ node_end = (const char*)TREE_VALUE(node);
+
+ /* Step through characters one at a time. */
+ node_ch = node_start;
+ name_ch = name_start;
+ while(true)
+ {
+ if((*node_ch) == RES_DWB_CHAR_ESCAPE)
+ /* Escape character. */
+ {
+ node_ch++;
+ if(node_ch >= node_end)
+ /* Escape without following character. */
+ break;
+ }
+
+ if(node_ch >= node_end)
+ /* Name matched, at least partially. */
+ {
+ if((name_ch == name_end) || node_is_partial)
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ {
+ char buffer[110];
+ int buffer_len = node_end - node_start;
+ if(buffer_len > 100)
+ buffer_len = 100;
+ memcpy(buffer, node_start, buffer_len);
+ buffer[buffer_len] = '\0';
+ /* Eg: [TEST: "foo" matched "f\o". Blacklisted by partial user path.] */
+ warning(0, "%s\"%s\" matched \"%s\". %s by %s %s path.", res_intmsg_prefix, name_start, buffer, node_is_blacklist ? "Blacklisted" : "Whitelisted", node_is_partial ? "partial" : "full", node_is_system ? "system" : "user");
+ }
+
+ return node_is_blacklist;
+ }
+
+ break;
+ }
+
+ if((*node_ch) != (*name_ch))
+ /* Strings don't match. */
+ break;
+
+ node_ch++;
+ name_ch++;
+ }
+ }
+
+ /* If no list entries match, use the defaults. */
+ if(is_system)
+ return RES_DWB_CHECK_SYSTEM_PATH;
+ else
+ return RES_DWB_CHECK_USER_PATH;
+}
diff -Naur original/gcc-4.3.2/gcc/c.opt res/gcc-4.3.2/gcc/c.opt
--- original/gcc-4.3.2/gcc/c.opt 2008-01-13 13:22:38.000000000 +1300
+++ res/gcc-4.3.2/gcc/c.opt 2008-12-17 01:00:41.000000000 +1300
@@ -393,6 +393,31 @@
C++ ObjC++ Var(warn_reorder) Warning
Warn when the compiler reorders code
+; <[SPH]>
+Wres
+C++ Var(warn_restrictive_exception_specification) Warning
+Warn when an exception may be thrown that isn't listed in the function's exception specifier
+
+; <[SPH]>
+Wres-bl-unk
+C++ Var(warn_res_blacklist_unknown) Warning
+When using -Wres or -Wxes, this forces checks on declarations not in files, such as builtins. This does not enable -Wres
+
+; <[SPH]>
+Wres-cnr
+C++ Var(warn_res_cnr) Warning
+Additional warning for -Wres that warns when a catch(...) has no rethrow. Using this also enables -Wres
+
+; <[SPH]>
+Wres-mes
+C++ Var(warn_res_mes) Warning
+Additional warning for -Wres that warns when a function lacks an exception specification
+
+; <[SPH]>
+Wresl=
+C++ Warning Joined
+-Wresl=<args> Warn when an exception may be thrown that isn't listed in the function's exception specifier. <args> allows whitelisting calls to functions declared in listed files. See <FIXME> for usage
+
Wreturn-type
C ObjC C++ ObjC++ Var(warn_return_type) Warning
Warn whenever a function's return type defaults to \"int\" (C), or about inconsistent return types (C++)
@@ -445,6 +470,11 @@
C ObjC C++ ObjC++ Warning
Warn if trigraphs are encountered that might affect the meaning of the program
+; <[SPH]>
+Wtt
+C++ Var(warn_throw_terminate) Warning
+Warn when an empty throw statement is used outside of a catch block
+
Wundeclared-selector
ObjC ObjC++ Var(warn_undeclared_selector) Warning
Warn about @selector()s without previously declared methods
@@ -473,6 +503,16 @@
C ObjC C++ ObjC++ Var(warn_write_strings) Warning
In C++, nonzero means warn about deprecated conversion from string literals to `char *'. In C, similar warning, except that the conversion is of course not deprecated by the ISO C standard.
+; <[SPH]>
+Wxes
+C++ Var(warn_excessive_exception_specification) Warning
+Warn when a catch block or function exception specifier includes a type that will never be thrown past it.
+
+; <[SPH]>
+Wxesl=
+C++ Warning Joined
+-Wxesl=<args> Warn when a catch block or function exception specifier includes a type that will never be thrown past it. <args> allows whitelisting calls to functions declared in listed files. See <FIXME> for usage.
+
Wpointer-sign
C ObjC Var(warn_pointer_sign) Init(-1) Warning
Warn when a pointer differs in signedness in an assignment
diff -Naur original/gcc-4.3.2/gcc/cp/except.c res/gcc-4.3.2/gcc/cp/except.c
--- original/gcc-4.3.2/gcc/cp/except.c 2007-09-06 15:33:46.000000000 +1200
+++ res/gcc-4.3.2/gcc/cp/except.c 2008-12-17 00:59:59.000000000 +1300
@@ -38,6 +38,8 @@
#include "tree-inline.h"
#include "tree-iterator.h"
#include "target.h"
+/* <[SPH]> */
+#include "res.h"
static void push_eh_cleanup (tree);
static tree prepare_eh_type (tree);
@@ -1015,3 +1017,957 @@
check_handlers_1 (handler, i);
}
}
+
+
+
+/* <[SPH]> */
+/* RES: Restrictive Exception Specification.
+ Code for -Wres, -Wres-wl, -Wres-bl, -Wxes, -Wtt
+ These functions are declared in res.h */
+
+static tree
+res_throwable;
+/* This is the TREE_LIST to which thrown types are added.
+ This list is for the innermost try statement-block being parsed, or the function if the parser is not currently inside any try statement-block. */
+
+static tree
+res_catchable;
+/* This is the list of types thrown inside the previous try block that have not yet been matched by a handler.
+ If the parser is not parsing handlers for a try block this is equal to void_type_node. */
+
+static tree
+res_caught;
+/* Inside catch(type), res_caught = type.
+ Inside catch(...), res_caught = TREE_LIST of remaining throwable types or NULL_TREE if no types.
+ Outside all catch()es, res_caught = void_type_node; */
+
+/* Structure of res_throwable & res_catchable.
+The list nodes have these components:
+- TREE_TYPE(node) = The thrown type.
+- TREE_VALUE(node) = The location where the throw was called.
+ <FIXME>: Currently a size_t typecast to void*.
+- TREE_PURPOSE(node) = The thing throwing the type:
+ If this is a function, this is the function declaration tree.
+ If this is a throw, this is NULL_TREE. <FIXME:Replace with expression?>
+If anything is throwable, there is only one node, whose TREE_TYPE(node) is NULL_TREE.
+If nothing is throwable, the list is empty, equal to NULL_TREE. */
+
+bool
+res_in_function = false;
+/* Indicates whether processing is inside a function. */
+
+
+
+/* Called at the start of a function if res_check_exception_specification is active.
+ Stores the current throwable and catchable lists and catch type, to be recovered when the function ends (useful for function bodies nested inside function bodies).
+ Initialises res_throwable.
+ Parameters:
+ throwable: Pointer to temporary storage for res_throwable.
+ catchable: Pointer to temporary storage for res_catchable.
+ caught: Pointer to temporary storage for res_caught. */
+
+void
+res_on_begin_function(tree* throwable, tree* catchable, tree* caught)
+{
+ /* Temporarily store nested variables. */
+ *throwable = res_throwable;
+ *catchable = res_catchable;
+ *caught = res_caught;
+
+ res_throwable = NULL_TREE;
+ res_catchable = void_type_node;
+ res_caught = void_type_node;
+ res_in_function = true;
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sfunction begins.", res_intmsg_prefix);
+}
+
+/* Called at the end of a function if res_check_exception_specification is active.
+ Checks the exception specification against types that can be thrown.
+ Outputs warnings if any thrown types aren't in the specification.
+ Parameters:
+ throwable: Pointer to where res_throwable was stored by res_on_begin_function().
+ catchable: Pointer to where res_catchable was stored by res_on_begin_function().
+ caught: Pointer to where res_caught was stored by res_on_begin_function().
+ function: The FUNCTION_DECL for the ending function. */
+
+void
+res_on_end_function(tree* throwable, tree* catchable, tree* caught, tree function)
+{
+ tree functype = TREE_TYPE(function);
+ tree exceptions = TYPE_RAISES_EXCEPTIONS(functype);
+
+ /* <FIXME> Unnecessary? */
+ /* Check whether res_on_begin_function() was called for this function.
+ Protects against checking clones. */
+ /*if(!res_in_function)
+ return;
+ else
+ res_in_function = false;*/
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ {
+ warning(0, "%sfunction %q+F ends.", res_intmsg_prefix, function);
+ res_warnlist(res_throwable);
+ }
+
+ /* -Wres, -Wresl= */
+ if(warn_restrictive_exception_specification)
+ res_check_res(function, exceptions);
+
+ /* -Wxes, -Wxesl= */
+ if(warn_excessive_exception_specification)
+ res_check_xes(function, exceptions);
+
+ res_empty(&res_throwable);
+
+ /* Recover previous values. */
+ res_throwable = *throwable;
+ res_catchable = *catchable;
+ res_caught = *caught;
+}
+
+/* Checks the exception specification against types that can be thrown.
+ Warns when thrown types aren't matched by a specification entry.
+ Parameters:
+ function: The FUNCTION_DECL for the ending function.
+ exceptions: The exception specifier for function. */
+
+void
+res_check_res(tree function, tree exceptions)
+{
+ tree list_node;
+ int unmatched = 0;
+
+ /* If the function does not have an exception specification, it may throw any exception. */
+ if(exceptions == NULL_TREE)
+ {
+ /* -Wres-mes */
+ if(warn_res_mes)
+ warning(0, "RES: %q+F has no exception specification.", function);
+
+ return;
+ }
+
+ /* No exceptions can propogate to outside the function. */
+ if(res_throwable == NULL_TREE)
+ return;
+
+ if(TREE_TYPE(res_throwable) == NULL_TREE)
+ /* The function calls another function without an exception specification, and does not catch this. */
+ {
+ tree thrower = TREE_PURPOSE(res_throwable);
+ location_t loc = (size_t)TREE_VALUE(res_throwable);
+
+ if(thrower != NULL_TREE)
+ if(TREE_CODE(thrower) == FUNCTION_DECL)
+ {
+ warning(0, "RES: %q+F may terminate due to the uncaught and unspecified exceptions from calls to %qF, which may throw anything.", function, thrower);
+ inform("RES: %qF called here.%H", thrower, &loc);
+ inform("RES: %q+F declared here.", thrower);
+ return;
+ }
+
+ /* This is unlikely to be called unless RES_CALCULATE_CATCH_ANY_RETHROW is false. */
+ warning(0, "RES: %q+F may terminate due to uncaught and unspecified exceptions, which may be of any type.", function);
+ return;
+ }
+
+ if(TREE_VALUE(exceptions) == NULL_TREE)
+ /* The function is defined as throw(). */
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sCan't throw anything.", res_intmsg_prefix);
+
+ exceptions = NULL_TREE;
+ }
+
+ /* Check all possibly thrown types vs the function's exception specification. */
+ for(list_node = res_throwable; list_node != NULL_TREE; list_node = TREE_CHAIN(list_node))
+ {
+ tree type;
+ tree thrower;
+ location_t loc;
+ tree spec_node;
+
+ type = TREE_TYPE(list_node);
+ thrower = TREE_PURPOSE(list_node);
+ loc = (location_t)(size_t)TREE_VALUE(list_node);
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%s%qT.%H", res_intmsg_prefix, type, &loc);
+
+ /* Step through all types in the exception specification, exiting if a match is found */
+ for(spec_node = exceptions; spec_node != NULL_TREE; spec_node = TREE_CHAIN(spec_node))
+ {
+ tree spec_type = TREE_VALUE(spec_node);
+ if(same_or_base_type_p(spec_type, type))
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%smatched by %qT.", res_intmsg_prefix, spec_type);
+ break;
+ }
+ }
+
+ if(spec_node == NULL_TREE)
+ /* Thrown type isn't part of the exception specification. */
+ {
+ unmatched++;
+
+ if(unmatched == 1)
+ warning(0, "RES: %q+F may terminate due to the following uncaught and unspecified exceptions:", function);
+
+ if(unmatched <= RES_MAX_RES_EXCEPTIONS_LISTED)
+ {
+ if(thrower != NULL_TREE)
+ switch(TREE_CODE(thrower))
+ {
+ case FUNCTION_DECL:
+ {
+ const char* filename = DECL_SOURCE_FILE(thrower);
+ int line = DECL_SOURCE_LINE(thrower);
+ inform("RES: %qT from %qF (declaration at %s:%d).%H", type, thrower, filename, line, &loc);
+ }
+ break;
+ default:
+ inform("RES: %qT from here.%H", type, &loc);
+ }
+ else
+ inform("RES: %qT from here.%H", type, &loc);
+ }
+ }
+ }
+
+ if(unmatched > RES_MAX_RES_EXCEPTIONS_LISTED)
+ {
+ int unlisted;
+ unlisted = unmatched - RES_MAX_RES_EXCEPTIONS_LISTED;
+ inform("RES: %d further unlisted type%s may be thrown.", unlisted, (unlisted == 1) ? "" : "s");
+ }
+}
+
+/* Checks the exception specification against types that can be thrown.
+ Warns when specification entries aren't matched by a thrown type.
+ Parameters:
+ function: The FUNCTION_DECL for the ending function.
+ exceptions: The exception specifier for function. */
+
+void
+res_check_xes(tree function, tree exceptions)
+{
+ int unmatched = 0;
+ tree spec_node;
+
+ if(exceptions == NULL_TREE)
+ /* If the function does not have an exception specifier, it may throw any exception. */
+ {
+ if(res_throwable == NULL_TREE)
+ warning(0, "XES: %q+F has no exception specification yet no exceptions can propagate past it.", function);
+
+ return;
+ }
+
+ if(res_throwable == NULL_TREE)
+ /* No exceptions can propogate to outside the function. */
+ {
+ if(TREE_VALUE(exceptions) != NULL_TREE)
+ warning(0, "XES: %q+F has an exception specification, yet no exceptions can propagate past it.", function);
+
+ return;
+ }
+
+ if(TREE_TYPE(res_throwable) == NULL_TREE)
+ /* Anything is throwable. */
+ return;
+
+ if(TREE_VALUE(exceptions) == NULL_TREE)
+ return;
+
+ for(spec_node = exceptions; spec_node != NULL_TREE; spec_node = TREE_CHAIN(spec_node))
+ {
+ tree spec_type = TREE_VALUE(spec_node);
+
+ tree list_node;
+ for(list_node = res_throwable; list_node != NULL_TREE; list_node = TREE_CHAIN(list_node))
+ {
+ tree list_type = TREE_TYPE(list_node);
+
+ if(same_or_base_type_p(spec_type, list_type))
+ /* Type may be caught. Don't warn. */
+ break;
+
+ if(same_or_base_type_p(list_type, spec_type))
+ /* Type may be caught here too, since more-derived types are removed from lists. */
+ break;
+ }
+
+ if(list_node == NULL_TREE)
+ {
+ unmatched++;
+
+ if(unmatched == 1)
+ warning(0, "XES: %q+F exception specification includes the following types that are unable to propagate past it:", function);
+
+ if(unmatched <= RES_MAX_XES_EXCEPTIONS_LISTED)
+ inform("XES: %qT.", spec_type);
+ }
+ }
+
+ if(unmatched > RES_MAX_XES_EXCEPTIONS_LISTED)
+ {
+ int unlisted;
+ unlisted = unmatched - RES_MAX_XES_EXCEPTIONS_LISTED;
+ inform("XES: There are %d further unlisted type%s on %q+Fs exception specification that can't propagate past it.", unlisted, (unlisted == 1) ? "" : "s", function);
+ }
+}
+
+/* Called at the start of a try-catch segment if res_check_exception_specification is active.
+ Stores the current throwable and catchable lists and catch type, to be recovered when the try-catch block ends.
+ Parameters:
+ throwable: Pointer to temporary storage for res_throwable.
+ catchable: Pointer to temporary storage for res_catchable.
+ caught: Pointer to temporary storage for res_caught. */
+
+void
+res_on_begin_try(tree* throwable, tree* catchable, tree* caught)
+{
+ /* Temporarily store nested variables. */
+ *throwable = res_throwable;
+ *catchable = res_catchable;
+ *caught = res_caught;
+
+ res_throwable = NULL_TREE;
+ res_catchable = void_type_node;
+ res_caught = void_type_node;
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%stry block begins.", res_intmsg_prefix);
+}
+
+/* Called at the start of a try block if res_check_exception_specification is active.
+ Recovers the throwable list stored on entering the try-block.
+ Parameters:
+ throwable: Pointer to where res_throwable was stored by res_on_begin_try(). */
+
+void
+res_on_end_try(tree* throwable)
+{
+ res_catchable = res_throwable;
+
+ /* Recover nested variable. */
+ res_throwable = *throwable;
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%stry block ends.", res_intmsg_prefix);
+}
+
+/* Called at the end of a try-catch segment if res_check_exception_specification is active.
+ Merges the outer throwable list with what can be thrown out of the try-catch block.
+ Recovers the catchable list and catch type stored on entering the segment.
+ Parameters:
+ catchable: Pointer to where res_catchable was stored by res_on_begin_try().
+ caught: Pointer to where res_caught was stored by res_on_begin_try(). */
+
+void
+res_on_end_handlers(tree* catchable, tree* caught)
+{
+ if(res_catchable == void_type_node)
+ res_catchable = NULL_TREE;
+
+ res_merge(&res_throwable, &res_catchable);
+
+ /* Recover nested variables. */
+ res_catchable = *catchable;
+ res_caught = *caught;
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%stry-catch segment ends.", res_intmsg_prefix);
+}
+
+/* Called at the start of a catch block if res_check_exception_specification is active.
+ Sets res_caught to indicate the type(s) caught.
+ If it's a single type, removes the type from the catchable list.
+ If it's catch(...), it can catch any type that is still in the catchable list.
+ Also checks for -Wxes.
+ Parameters:
+ caught: tcc_type caught, or NULL_TREE for catch(...). */
+
+void
+res_on_begin_catch(tree caught)
+{
+ if(res_catchable == void_type_node)
+ /* This shouldn't happen. */
+ res_catchable = NULL_TREE;
+
+ if(caught == NULL_TREE)
+ /* catch(...) */
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%scatch(...) block begins. ", res_intmsg_prefix);
+
+ if((res_catchable == NULL_TREE) && warn_excessive_exception_specification)
+ warning(0, "XES: catch(...) will never catch any types.");
+
+ res_caught = res_catchable;
+
+ /* Indication for -Wres-cnr */
+ res_catchable = void_type_node;
+ }
+ else
+ /* catch(type) */
+ {
+ bool matched;
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%scatch(%qT) block begins.", res_intmsg_prefix, caught);
+
+ res_caught = caught;
+ /* Attempt to remove "caught" from the "res_catchable" list. */
+ matched = res_remove(&res_catchable, caught);
+
+ if((!matched) && warn_excessive_exception_specification)
+ warning(0, "XES: catch(%qT) catches a type never thrown to it.", caught);
+ }
+}
+
+/* Called at the end of a catch block if res_check_exception_specification is active.
+ If ending a catch(...) block, cleans up the TREE_LIST in res_caught. */
+
+void
+res_on_end_catch(void)
+{
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%scatch block ends.", res_intmsg_prefix);
+
+ /* -Wres-cnr */
+ if(warn_res_cnr && (res_catchable == void_type_node))
+ warning(0, "RES: catch(...) has no re-throw.");
+
+ /* Check if res_caught is a TREE_LIST, and if so, empty it. */
+ if(res_caught != NULL_TREE)
+ if(TREE_CODE(res_caught) == TREE_LIST)
+ res_empty(&res_caught);
+}
+
+/* Called on a throw statement if res_check_exception_specification is active.
+ If a type is thrown, adds the thrown type to res_throwable.
+ "type" can be NULL_TREE, indicating a rethrow or throw-terminate.
+ Parameters:
+ expression: The throw expression. */
+
+void
+res_on_throw(tree expression)
+{
+ tree type;
+ location_t loc;
+
+ if(expression == NULL_TREE)
+ type = NULL_TREE;
+ else
+ type = lvalue_type(expression);
+
+ /* <FIXME:Doesn't work.> */
+ /* loc = EXPR_LOCATION(expression); */
+ loc = input_location;
+
+ if(type == NULL_TREE)
+ /* throw; (no type) */
+ res_on_rethrow(NULL_TREE, loc);
+ else
+ /* throw type; */
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sType %qT thrown here.", res_intmsg_prefix, type);
+
+ /* Add "type" to res_throwable. */
+ res_add_type(&res_throwable, type, NULL_TREE, loc);
+ }
+}
+
+/* Called on a throw; statement (with no type) if res_check_exception_specification is active.
+ If outside catch block, or innermost exception block is try {}, this is a throw-terminate. -Wtt will warn here.
+ If innermost exception block is catch(...) block, either adds possibly thrown types to res_throwable, or sets res_throwable to ... (depending on RES_CALCULATE_CATCH_ANY_RETHROW).
+ If innermost exception block is catch(type) block, adds the thrown type to res_throwable.
+ Parameters:
+ thrower: The object rethrowing. <FIXME:Currently NULL_TREE>.
+ loc: The location of the rethrow. */
+
+void
+res_on_rethrow(tree thrower, size_t loc)
+{
+ if(res_caught == void_type_node)
+ {
+ /* -Wtt */
+ if(warn_throw_terminate)
+ warning(0, "TT: Throw-terminate here.");
+ }
+ else
+ /* Innermost exception block is catch. */
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sRe-throw here.", res_intmsg_prefix);
+
+ if(res_caught != NULL_TREE)
+ if(TREE_CODE(res_caught) != TREE_LIST)
+ /* e.g. catch(type) { throw; } */
+ {
+ res_add_type(&res_throwable, res_caught, thrower, loc);
+ return;
+ }
+
+ /* Indication for -Wres-cnr */
+ res_catchable = NULL_TREE;
+
+ /* e.g. catch(...) { throw; } */
+ if(RES_CALCULATE_CATCH_ANY_RETHROW)
+ /* Add all types possibly caught by catch(...) to res_throwable. */
+ res_merge(&res_throwable, &res_caught);
+ else
+ /* Add ... to res_throwable. Empty res_caught. */
+ {
+ res_empty(&res_caught);
+ res_add_any(&res_throwable, thrower, loc);
+ }
+ }
+}
+
+/* Called on a standard function call if res_check_exception_specification is active.
+ Checks blacklists & whitelists from -Wres-wl and -Wres-bl, to see whether to ignore this call.
+ Adds any types thrown by the function to res_throwable.
+ If the function has no exception specification, adds ... .
+ Parameters:
+ function: The FUNCTION_DECL of the called function. */
+
+void
+res_on_call_function(tree function)
+{
+ tree functype;
+ tree exceptions;
+ bool warn;
+ size_t loc = (size_t)input_location;
+ const char* file;
+
+ if(function == NULL_TREE)
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sunknown function called.", res_intmsg_prefix);
+
+ return;
+ }
+
+ /* Retrieve function name string. */
+ file = DECL_SOURCE_FILE(function);
+
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sfunction %qF called (declared in %s).", res_intmsg_prefix, function, file ? file : "unknown file");
+
+ if(file)
+ /* Check whitelist & blacklist. */
+ warn = res_dwb_file_warnable(file);
+ else
+ /* -Wres-bl-unk. */
+ warn = warn_res_blacklist_unknown;
+
+ if(!warn)
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sMuting whitelisted %qF.", res_intmsg_prefix, function);
+
+ return;
+ }
+
+ functype = TREE_TYPE(function);
+ exceptions = TYPE_RAISES_EXCEPTIONS(functype);
+ if(exceptions)
+ /* Call to function with exception specification. */
+ {
+ tree list_node;
+ list_node = exceptions;
+ if(TREE_VALUE(list_node) == NULL_TREE)
+ /* Call to function with empty exception specification. */
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sthrows nothing.", res_intmsg_prefix);
+ }
+ else
+ {
+ /* Step through all thrown types. */
+ while(list_node != NULL_TREE)
+ {
+ tree type;
+ type = TREE_VALUE(list_node);
+
+ if(type == NULL_TREE)
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%scan throw unknown.", res_intmsg_prefix);
+ }
+ else
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%scan throw %qT.", res_intmsg_prefix, type);
+
+ /* Add "type" to res_throwable. */
+ res_add_type(&res_throwable, type, function, loc);
+ }
+
+ list_node = TREE_CHAIN(list_node);
+ }
+ }
+ }
+ else
+ /* Call to function without exception specification. */
+ {
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%s%qF can throw anything.", res_intmsg_prefix, function);
+
+ /* Add ... to res_throwable. */
+ res_add_any(&res_throwable, function, loc);
+ }
+}
+
+
+/* Called on a function-pointer function call.
+ FIXME: gcc doesn't store function-pointer exception specifications yet, although it is required to comply with the C++ spec (15.4 -3- : except.spec).
+ Parameters:
+ pointer: The FUNCTION_DECL of the function pointer. */
+
+void
+res_on_call_function_pointer(tree pointer)
+{
+ /* <TEMP> */
+ if(res_intmsg_prefix)
+ warning(0, "%sfunction pointer called. %qD. <FIXME>", res_intmsg_prefix, pointer);
+}
+
+
+/* Adds a type to a type list.
+ Ensures that no types exist that are derived from other types in the list, as catch(type) catches types derived from "type".
+ Parameters:
+ list: Pointer to the list to which the type is to be added.
+ type: Type to be added.
+ thrower: Object throwing the type, such as a FUNCTION_DECL.
+ loc: Where the throwing occurred. */
+
+void
+res_add_type(tree* list, tree type, tree thrower, size_t loc)
+{
+ tree last_node;
+ tree new_tree;
+
+ if((*list) != NULL_TREE)
+ if(TREE_TYPE(*list) == NULL_TREE)
+ /* list is ... */
+ return;
+
+ if(res_prep_add_type(list, type, &last_node))
+ {
+ /* Build the new node. */
+ new_tree = res_make_node(type, thrower, loc);
+
+ /* Attach the new node. */
+ if(last_node == NULL_TREE)
+ *list = new_tree;
+ else
+ TREE_CHAIN(last_node) = new_tree;
+ }
+}
+
+/* Sets a *list to ... .
+ ... is indicated by a 1-node tree whose TREE_TYPE() is NULL_TREE.
+ Parameters:
+ list: Pointer to the list that is becoming ... .
+ thrower: Object throwing the type, such as a FUNCTION_DECL.
+ loc: Where the throwing occurred. */
+
+void
+res_add_any(tree* list, tree thrower, size_t loc)
+{
+ if(*list == NULL_TREE)
+ *list = res_make_node(NULL_TREE, thrower, loc);
+ else
+ {
+ if(TREE_TYPE(*list) != NULL_TREE)
+ {
+ res_empty(list);
+ *list = res_make_node(NULL_TREE, thrower, loc);
+ }
+ /* else tree is already pointing at a function which may throw anything. */
+ }
+}
+
+/* Merges the contents of two type lists, and sets *from to NULL_TREE.
+ If *into is ..., *from is simply emptied.
+ If *from is ..., *into becomes *from.
+ Ensures that no types exist that are derived from other types in the list.
+ Parameters:
+ into: Pointer to the list to add to.
+ from: Pointer to the list to move from. Equal to NULL_TREE on exit. */
+
+void
+res_merge(tree* into, tree* from)
+{
+ tree list_node;
+
+ if((*from) == NULL_TREE)
+ /* from is empty. */
+ return;
+
+ if((*into) == NULL_TREE)
+ /* into is empty. */
+ {
+ *into = *from;
+ *from = NULL_TREE;
+ return;
+ }
+
+ if(TREE_TYPE(*into) == NULL_TREE)
+ /* into = ... */
+ {
+ res_empty(from);
+ return;
+ }
+
+ if(TREE_TYPE(*from) == NULL_TREE)
+ /* from = ... */
+ {
+ res_empty(into);
+ *into = *from;
+ *from = NULL_TREE;
+ return;
+ }
+
+ list_node = *from;
+ /* Step through all types from *from, adding each to *into. */
+ while(list_node)
+ {
+ tree next = TREE_CHAIN(list_node);
+ tree list_type = TREE_TYPE(list_node);
+ tree last_node;
+
+ if(res_prep_add_type(into, list_type, &last_node))
+ {
+ /* Reuse list_node. */
+ TREE_CHAIN(last_node) = list_node;
+ TREE_CHAIN(list_node) = NULL_TREE;
+ }
+ else
+ /* <FIXME>: else delete list_node. */
+ {}
+
+ list_node = next;
+ }
+
+ *from = NULL_TREE;
+}
+
+/* Internal function for res_add_type() and res_merge().
+ Removes all types derived from "type".
+ Exits if "type" or a less-derived type of "type" is found.
+ Parameters:
+ list: Pointer to the list where the type is to be added.
+ type: The type to be added.
+ last: Return-by-reference. Recieves address of the last node in the list. Allows new node to be added to the back.
+ Return:
+ Indicates whether type needs to be added.
+ false means "type" or a less-derived type of "type" has been found. */
+
+bool
+res_prep_add_type(tree* list, tree type, tree* last)
+{
+ tree list_node;
+ tree prev_node;
+
+ /* Step through list, removing types derived from "type".
+ Exit if "type" or a less-derived base-class of "type" is found. */
+ list_node = *list;
+ prev_node = NULL_TREE;
+ while(list_node != NULL_TREE)
+ {
+ tree list_type = TREE_TYPE(list_node);
+
+ /* Check whether "list_type" is "type", or a less-derived base-class of "type". If so, "type" doesn't need to be added. */
+ if(same_or_base_type_p(list_type, type))
+ return false;
+
+ /* Check whether "type" is a less-derived base-class of "list_type". If so, remove "list_node". */
+ if(same_or_base_type_p(type, list_type))
+ {
+ tree next_node = TREE_CHAIN(list_node);
+ /* <FIXME>: delete list_node */
+
+ if(prev_node == NULL_TREE)
+ *list = next_node;
+ else
+ TREE_CHAIN(prev_node) = next_node;
+
+ list_node = next_node;
+ }
+ else
+ {
+ prev_node = list_node;
+ list_node = TREE_CHAIN(list_node);
+ }
+ }
+
+ *last = prev_node;
+
+ /* "type" needs to be added. */
+ return true;
+}
+
+/* Cleans up a TREE_LIST, deleting all chained nodes.
+ Parameters:
+ list: Pointer to the list to be emptied. */
+
+void
+res_empty(tree* list)
+{
+ tree list_node;
+ list_node = *list;
+ *list = NULL_TREE;
+
+ /* Steps through all types in *list, removing them. */
+ while(list_node != NULL_TREE)
+ {
+ tree next = TREE_CHAIN(list_node);
+ /* <FIXME>: delete list_node */
+ list_node = next;
+ }
+}
+
+/* Attempts to remove "type" or any types derived from "type" from *list.
+ Parameters:
+ list: Pointer to the list to which "type" or its derivatives are to be removed.
+ type: tcc_type to remove.
+ Return:
+ Indicates whether type is matched. */
+
+bool
+res_remove(tree* list, tree type)
+{
+ tree list_node = *list;
+ tree prev_node = NULL_TREE;
+ bool matched = false;
+
+ if((*list) != NULL_TREE)
+ if(TREE_TYPE(*list) == NULL_TREE)
+ /* List is ... */
+ return true;
+
+ /* Step through all listed types.
+ If a more derived type of "type" is found, remove it.
+ If type or a less derived type of "type" is found, exit. */
+ while(list_node != NULL_TREE)
+ {
+ tree next = TREE_CHAIN(list_node);
+ tree list_type = TREE_TYPE(list_node);
+
+ /* Check whether "type" is "list_type", or a less-derived base-class of "list_type". If so, "list_node" is removed. */
+ if(same_or_base_type_p(type, list_type))
+ {
+ matched = true;
+
+ if(prev_node)
+ TREE_CHAIN(prev_node) = next;
+ else
+ *list = next;
+
+ /* <FIXME>: delete list_node */
+ list_node = next;
+ }
+ else
+ {
+ /* Check whether "list_type" is a less-derived base-class of "type". If so, nothing can be done. */
+ if(same_or_base_type_p(list_type, type))
+ return true;
+
+ prev_node = list_node;
+ }
+
+ list_node = next;
+ }
+
+ return matched;
+}
+
+/* Makes a TREE_LIST node, whose TREE_CHAIN() is set to NULL_TREE.
+ Parameters:
+ type: tcc_type. stored in TREE_TYPE().
+ thrower: stored in TREE_PURPOSE().
+ loc: location where type is thrown. Stored via typecast in TREE_VALUE(). <FIXME:This OK?>
+ Return:
+ The newly built TREE_LIST node. */
+
+tree
+res_make_node(tree type, tree thrower, size_t loc)
+{
+ tree new_tree = tree_cons(thrower, (tree)(void*)loc, NULL_TREE);
+ TREE_TYPE(new_tree) = type;
+
+ return new_tree;
+}
+
+/* Dumps the types in list for debugging, as warnings.
+ One line per type.
+ Parameters:
+ list: The list to output. */
+
+void
+res_warnlist(tree list)
+{
+ if(res_intmsg_prefix == NULL)
+ return;
+
+ if(list == NULL_TREE)
+ warning(0, "%sTypelist: No types.", res_intmsg_prefix);
+ else
+ {
+ tree list_node;
+ for(list_node = list; list_node != NULL_TREE; list_node = TREE_CHAIN(list_node))
+ {
+ tree type;
+ tree thrower;
+ location_t loc;
+ type = TREE_TYPE(list_node);
+ thrower = TREE_PURPOSE(list_node);
+ loc = (location_t)(size_t)TREE_VALUE(list_node);
+
+ if(type == NULL_TREE)
+ {
+ if(thrower == NULL_TREE)
+ warning(0, "%sTypelist: Any type.%H", res_intmsg_prefix, &loc);
+ else
+ warning(0, "%sTypelist: Any type. Thrown by %qD.%H", res_intmsg_prefix, thrower, &loc);
+ }
+ else
+ {
+ if(thrower == NULL_TREE)
+ warning(0, "%sTypelist: %qT.%H", res_intmsg_prefix, type, &loc);
+ else
+ warning(0, "%sTypelist: %qT. Thrown by %qD.%H", res_intmsg_prefix, type, thrower, &loc);
+ }
+ }
+ }
+}
diff -Naur original/gcc-4.3.2/gcc/cp/parser.c res/gcc-4.3.2/gcc/cp/parser.c
--- original/gcc-4.3.2/gcc/cp/parser.c 2008-08-08 00:27:48.000000000 +1200
+++ res/gcc-4.3.2/gcc/cp/parser.c 2008-12-15 19:56:06.000000000 +1300
@@ -37,6 +37,8 @@
#include "target.h"
#include "cgraph.h"
#include "c-common.h"
+/* <[SPH]> */
+#include "res.h"
/* The lexer. */
@@ -13782,6 +13784,7 @@
ctor_initializer_p = cp_parser_ctor_initializer_opt (parser);
/* Parse the function-body. */
cp_parser_function_body (parser);
+
/* Finish the function body. */
finish_function_body (body);
@@ -15586,14 +15589,34 @@
cp_parser_try_block (cp_parser* parser)
{
tree try_block;
+ /* <[SPH]> */
+ tree throwable;
+ tree catchable;
+ tree caught;
+
+ /* <[SPH]> */
+ if (res_check_exception_specification)
+ /* Processing for -Wres & -Wxes. */
+ res_on_begin_try (&throwable, &catchable, &caught);
cp_parser_require_keyword (parser, RID_TRY, "`try'");
try_block = begin_try_block ();
cp_parser_compound_statement (parser, NULL, true);
finish_try_block (try_block);
+
+ /* <[SPH]> */
+ if (res_check_exception_specification)
+ /* Processing for -Wres & -Wxes. */
+ res_on_end_try (&throwable);
+
cp_parser_handler_seq (parser);
finish_handler_sequence (try_block);
+ /* <[SPH]> */
+ if (res_check_exception_specification)
+ /* Processing for -Wres & -Wxes. */
+ res_on_end_handlers (&catchable, &caught);
+
return try_block;
}
@@ -15666,8 +15689,19 @@
declaration = cp_parser_exception_declaration (parser);
finish_handler_parms (declaration, handler);
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+ /* <[SPH]> */
+ if (res_check_exception_specification)
+ /* Processing for -Wres & -Wxes. */
+ res_on_begin_catch (HANDLER_TYPE(handler));
+
cp_parser_compound_statement (parser, NULL, false);
finish_handler (handler);
+
+ /* <[SPH]> */
+ if (res_check_exception_specification)
+ /* Processing for -Wres & -Wxes. */
+ res_on_end_catch ();
}
/* Parse an exception-declaration.
@@ -15750,6 +15784,11 @@
expression = cp_parser_assignment_expression (parser,
/*cast_p=*/false);
+ /* <[SPH]> */
+ if (res_check_exception_specification)
+ /* Processing for -Wres & -Wxes. */
+ res_on_throw (expression);
+
return build_throw (expression);
}
@@ -16766,6 +16805,16 @@
bool saved_in_function_body;
unsigned saved_num_template_parameter_lists;
+ /* <[SPH]> */
+ tree throwable;
+ tree catchable;
+ tree caught;
+
+ /* <[SPH]> */
+ if (res_check_exception_specification)
+ /* Processing for -Wres & -Wxes. */
+ res_on_begin_function (&throwable, &catchable, &caught);
+
saved_in_function_body = parser->in_function_body;
parser->in_function_body = true;
/* If the next token is `return', then the code may be trying to
@@ -16823,6 +16872,16 @@
= saved_num_template_parameter_lists;
parser->in_function_body = saved_in_function_body;
+ /* <[SPH]> */
+ if (res_check_exception_specification)
+ {
+ /* <FIX>:Is there a better way? */
+ tree temp_function_decl = current_function_decl;
+ current_function_decl = fn;
+ res_on_end_function (&throwable, &catchable, &caught, fn);
+ current_function_decl = temp_function_decl;
+ }
+
return fn;
}
@@ -19366,6 +19425,7 @@
}
}
+
/* OpenMP 2.5:
variable-list:
identifier
@@ -20455,6 +20515,12 @@
SET_EXPR_LOCATION (stmt, pragma_tok->location);
}
+
+
+
+
+
+
/* The parser. */
static GTY (()) cp_parser *the_parser;
diff -Naur original/gcc-4.3.2/gcc/cp/semantics.c res/gcc-4.3.2/gcc/cp/semantics.c
--- original/gcc-4.3.2/gcc/cp/semantics.c 2008-06-11 18:47:36.000000000 +1200
+++ res/gcc-4.3.2/gcc/cp/semantics.c 2008-12-14 19:56:28.000000000 +1300
@@ -46,6 +46,8 @@
#include "tree-iterator.h"
#include "vec.h"
#include "target.h"
+/* <[SPH]> */
+#include "res.h"
/* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or
@@ -1974,6 +1976,12 @@
result = build_call_list (TREE_TYPE (result), orig_fn, orig_args);
KOENIG_LOOKUP_P (result) = koenig_p;
}
+
+ /* <[SPH]> */
+ if (res_check_exception_specification && (fn != NULL_TREE))
+ /* Processing for -Wres & -Wxes. */
+ res_on_call_function (fn);
+
return result;
}
diff -Naur original/gcc-4.3.2/gcc/res.h res/gcc-4.3.2/gcc/res.h
--- original/gcc-4.3.2/gcc/res.h 1970-01-01 12:00:00.000000000 +1200
+++ res/gcc-4.3.2/gcc/res.h 2008-12-16 17:45:04.000000000 +1300
@@ -0,0 +1,111 @@
+/* C++ Restrictive Exception Specification (RES) warning mechanic.
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Free Software Foundation, Inc.
+ Contributed by Simon Hill. (yacwroy@gmail.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+
+/* <[SPH]> */
+
+/* Internal warning prefix. NULL = no internal warnings. */
+#define RES_INTMSG_PREFIX "------------------------------------: "
+/* #define RES_INTMSG_PREFIX NULL */
+const char*
+res_intmsg_prefix;
+
+
+
+/* Restrictive Exception Specifiers. */
+
+bool
+res_check_exception_specification;
+
+/* Functions called from gcc standard. */
+void
+res_on_begin_function(tree*, tree*, tree*);
+void
+res_on_end_function(tree*, tree*, tree*, tree);
+void
+res_on_begin_try(tree*, tree*, tree*);
+void
+res_on_end_try(tree*);
+void
+res_on_end_handlers(tree*, tree*);
+void
+res_on_begin_catch(tree);
+void
+res_on_end_catch(void);
+void
+res_on_throw(tree);
+void
+res_on_rethrow(tree, size_t);
+void
+res_on_call_function(tree);
+void
+res_on_call_function_pointer(tree);
+
+/* RES and XES checks. */
+void
+res_check_res(tree function, tree exceptions);
+void
+res_check_xes(tree function, tree exceptions);
+
+/* Internal */
+void
+res_add_type(tree*, tree, tree, size_t);
+void
+res_add_any(tree*, tree, size_t);
+bool
+res_prep_add_type(tree*, tree, tree*);
+void
+res_merge(tree*, tree*);
+void
+res_empty(tree*);
+bool
+res_remove(tree*, tree);
+tree
+res_make_node(tree, tree, size_t);
+void
+res_warnlist(tree);
+
+#define RES_MAX_RES_EXCEPTIONS_LISTED 8
+#define RES_MAX_XES_EXCEPTIONS_LISTED 8
+#define RES_CALCULATE_CATCH_ANY_RETHROW true
+
+
+
+/* Blacklists & Whitelists */
+void
+res_dwb_add_filelist(const char*);
+bool
+res_dwb_file_warnable(const char*);
+
+#define RES_DWB_SYSTEM_DIR "/usr/include/"
+#define RES_DWB_CHECK_USER_PATH true
+#define RES_DWB_CHECK_SYSTEM_PATH false
+#define RES_DWB_CHECK_UNKNOWN_PATH false
+
+#define RES_DWB_FLAG_BLACKLIST (1 << 0)
+#define RES_DWB_FLAG_SYSTEM (1 << 1)
+#define RES_DWB_FLAG_PARTIAL (1 << 2)
+
+#define RES_DWB_CHAR_SEPARATOR ','
+#define RES_DWB_CHAR_BLACKLIST '-'
+#define RES_DWB_CHAR_SYSTEM '^'
+#define RES_DWB_CHAR_PARTIAL '+'
+#define RES_DWB_CHAR_ESCAPE '%'
Attachment:
res.txt
Description: Text document
Attachment:
test.tgz
Description: GNU Zip compressed data
| Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
|---|---|---|
| Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |