From 2c5df20f2ee3af837efdcf9a384a5fb600791050 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 19 Aug 2010 12:59:37 -0400 Subject: [PATCH] except.c (pending_noexcept, [...]): New. * except.c (pending_noexcept, pending_noexcept_checks): New. (perform_deferred_noexcept_checks): New. (maybe_noexcept_warning): Split from... (finish_noexcept_expr): ...here. Adjust. * decl2.c (cp_write_global_declarations): Call perform_deferred_noexcept_checks. * cp-tree.h: And declare it. From-SVN: r163379 --- gcc/cp/ChangeLog | 10 ++++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl2.c | 2 + gcc/cp/except.c | 64 ++++++++++++++++++++++--- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/g++.dg/cpp0x/noexcept09.C | 14 ++++++ 6 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept09.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f8e53540382..d93fd4a0ecf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2010-08-19 Jason Merrill + + * except.c (pending_noexcept, pending_noexcept_checks): New. + (perform_deferred_noexcept_checks): New. + (maybe_noexcept_warning): Split from... + (finish_noexcept_expr): ...here. Adjust. + * decl2.c (cp_write_global_declarations): Call + perform_deferred_noexcept_checks. + * cp-tree.h: And declare it. + 2010-08-18 Nathan Froyd PR c++/45049 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index baa66562031..dce28dfcaaf 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4883,6 +4883,7 @@ extern tree build_throw (tree); extern int nothrow_libfn_p (const_tree); extern void check_handlers (tree); extern tree finish_noexcept_expr (tree, tsubst_flags_t); +extern void perform_deferred_noexcept_checks (void); extern bool nothrow_spec_p (const_tree); extern bool type_noexcept_p (const_tree); extern bool type_throw_all_p (const_tree); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a768877b1a8..fed345246a6 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -3934,6 +3934,8 @@ cp_write_global_declarations (void) VEC_length (tree, pending_statics)); } + perform_deferred_noexcept_checks (); + /* Generate hidden aliases for Java. */ if (candidates) { diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 79bab76cc5a..20b44e3ed04 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -1069,6 +1069,51 @@ check_noexcept_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, return NULL_TREE; } +/* If a function that causes a noexcept-expression to be false isn't + defined yet, remember it and check it for TREE_NOTHROW again at EOF. */ + +typedef struct GTY(()) pending_noexcept { + tree fn; + location_t loc; +} pending_noexcept; +DEF_VEC_O(pending_noexcept); +DEF_VEC_ALLOC_O(pending_noexcept,gc); +static GTY(()) VEC(pending_noexcept,gc) *pending_noexcept_checks; + +/* FN is a FUNCTION_DECL that caused a noexcept-expr to be false. Warn if + it can't throw. */ + +static void +maybe_noexcept_warning (tree fn) +{ + if (TREE_NOTHROW (fn)) + { + warning (OPT_Wnoexcept, "noexcept-expression evaluates to % " + "because of a call to %qD", fn); + warning (OPT_Wnoexcept, "but %q+D does not throw; perhaps " + "it should be declared %", fn); + } +} + +/* Check any functions that weren't defined earlier when they caused a + noexcept expression to evaluate to false. */ + +void +perform_deferred_noexcept_checks (void) +{ + int i; + pending_noexcept *p; + location_t saved_loc = input_location; + for (i = 0; + VEC_iterate (pending_noexcept, pending_noexcept_checks, i, p); + ++i) + { + input_location = p->loc; + maybe_noexcept_warning (p->fn); + } + input_location = saved_loc; +} + /* Evaluate noexcept ( EXPR ). */ tree @@ -1082,13 +1127,20 @@ finish_noexcept_expr (tree expr, tsubst_flags_t complain) fn = cp_walk_tree_without_duplicates (&expr, check_noexcept_r, 0); if (fn) { - if ((complain & tf_warning) && TREE_CODE (fn) == FUNCTION_DECL - && TREE_NOTHROW (fn) && !DECL_ARTIFICIAL (fn)) + if ((complain & tf_warning) && warn_noexcept + && TREE_CODE (fn) == FUNCTION_DECL) { - warning (OPT_Wnoexcept, "noexcept-expression evaluates to % " - "because of a call to %qD", fn); - warning (OPT_Wnoexcept, "but %q+D does not throw; perhaps " - "it should be declared %", fn); + if (!DECL_INITIAL (fn)) + { + /* Not defined yet; check again at EOF. */ + pending_noexcept *p + = VEC_safe_push (pending_noexcept, gc, + pending_noexcept_checks, NULL); + p->fn = fn; + p->loc = input_location; + } + else + maybe_noexcept_warning (fn); } return boolean_false_node; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8867dee32f5..304a8e89f22 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2010-08-19 Jason Merrill + + * g++.dg/cpp0x/noexcept09.C: New. + 2010-08-19 Daniel Kraft PR fortran/29785 diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept09.C b/gcc/testsuite/g++.dg/cpp0x/noexcept09.C new file mode 100644 index 00000000000..2a4525cbd6c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept09.C @@ -0,0 +1,14 @@ +// Test that -Wnoexcept works with templates +// { dg-options "-std=c++0x -Wnoexcept" } + +template +T f (T t) { return t; } // { dg-warning "does not throw" } + +#define SA(X) static_assert(X, #X) + +SA (!noexcept(f(1))); // { dg-warning "noexcept" } + +int main() +{ + f(1); // Use f(int) so it gets instantiated +}