aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-08-19 12:59:37 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-08-19 12:59:37 -0400
commit2c5df20f2ee3af837efdcf9a384a5fb600791050 (patch)
treee43271e2f5bde4f31bf2664b89322cd4b225faac
parentfcaa4ca43392cfedaa9ce44dd7280236c1726ed9 (diff)
downloadgcc-2c5df20f2ee3af837efdcf9a384a5fb600791050.zip
gcc-2c5df20f2ee3af837efdcf9a384a5fb600791050.tar.gz
gcc-2c5df20f2ee3af837efdcf9a384a5fb600791050.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/except.c64
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept09.C14
6 files changed, 89 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f8e5354..d93fd4a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+2010-08-19 Jason Merrill <jason@redhat.com>
+
+ * 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 <froydnj@codesourcery.com>
PR c++/45049
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index baa6656..dce28df 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 a768877..fed3452 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 79bab76..20b44e3 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 %<false%> "
+ "because of a call to %qD", fn);
+ warning (OPT_Wnoexcept, "but %q+D does not throw; perhaps "
+ "it should be declared %<noexcept%>", 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 %<false%> "
- "because of a call to %qD", fn);
- warning (OPT_Wnoexcept, "but %q+D does not throw; perhaps "
- "it should be declared %<noexcept%>", 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 8867dee..304a8e8 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2010-08-19 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/noexcept09.C: New.
+
2010-08-19 Daniel Kraft <d@domob.eu>
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 0000000..2a4525c
--- /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 <class T>
+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
+}