except.c (pending_noexcept, [...]): New.
authorJason Merrill <jason@redhat.com>
Thu, 19 Aug 2010 16:59:37 +0000 (12:59 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 19 Aug 2010 16:59:37 +0000 (12:59 -0400)
* 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
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/except.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/noexcept09.C [new file with mode: 0644]

index f8e5354..d93fd4a 100644 (file)
@@ -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
index baa6656..dce28df 100644 (file)
@@ -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);
index a768877..fed3452 100644 (file)
@@ -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)
     {
index 79bab76..20b44e3 100644 (file)
@@ -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;
     }
index 8867dee..304a8e8 100644 (file)
@@ -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 (file)
index 0000000..2a4525c
--- /dev/null
@@ -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
+}