DR 1073 PR c++/49082
authorJason Merrill <jason@redhat.com>
Fri, 20 May 2011 20:39:59 +0000 (16:39 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 20 May 2011 20:39:59 +0000 (16:39 -0400)
DR 1073
PR c++/49082
* typeck.c (comp_except_specs): noexcept(false) is not compatible
with throw(type-list).
* typeck2.c (merge_exception_specifiers): noexcept(false)
beats any more limited specification.

From-SVN: r173981

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/noexcept02.C
gcc/testsuite/g++.dg/cpp0x/noexcept03.C
gcc/testsuite/g++.dg/cpp0x/noexcept08.C
gcc/testsuite/g++.dg/cpp0x/noexcept10.C [new file with mode: 0644]

index 5d93472bba3bec330bce35b44d9e65b3c667a574..4ec657812e1841fb47456237039e85cc984347cf 100644 (file)
@@ -1,5 +1,12 @@
 2011-05-20  Jason Merrill  <jason@redhat.com>
 
+       DR 1073
+       PR c++/49082
+       * typeck.c (comp_except_specs): noexcept(false) is not compatible
+       with throw(type-list).
+       * typeck2.c (merge_exception_specifiers): noexcept(false)
+       beats any more limited specification.
+
        PR c++/24163
        PR c++/29131
        * pt.c (tsubst_copy_and_build) [CALL_EXPR]: Avoid repeating
index d98c62bb940a75d68386156c2d6123b0d466110d..7791efcaa8f49f0a1b3b9f756e899ee00117b2c3 100644 (file)
@@ -986,14 +986,14 @@ comp_except_specs (const_tree t1, const_tree t2, int exact)
   /* First handle noexcept.  */
   if (exact < ce_exact)
     {
-      /* noexcept(false) is compatible with any throwing dynamic-exc-spec
+      /* noexcept(false) is compatible with no exception-specification,
         and stricter than any spec.  */
       if (t1 == noexcept_false_spec)
-       return !nothrow_spec_p (t2) || exact == ce_derived;
-      /* Even a derived noexcept(false) is compatible with a throwing
-        dynamic spec.  */
+       return t2 == NULL_TREE || exact == ce_derived;
+      /* Even a derived noexcept(false) is compatible with no
+        exception-specification.  */
       if (t2 == noexcept_false_spec)
-       return !nothrow_spec_p (t1);
+       return t1 == NULL_TREE;
 
       /* Otherwise, if we aren't looking for an exact match, noexcept is
         equivalent to throw().  */
index 26b9816d54807a2df43e9cb977a9c1fd5b42cc1b..c2eff9eb6c890f025d3f47a7aac57d455c415641 100644 (file)
@@ -1756,10 +1756,13 @@ add_exception_specifier (tree list, tree spec, int complain)
 tree
 merge_exception_specifiers (tree list, tree add)
 {
-  if (!list || !add)
-    return NULL_TREE;
+  /* No exception-specifier or noexcept(false) are less strict than
+     anything else.  Prefer the newer variant (LIST).  */
+  if (!list || list == noexcept_false_spec)
+    return list;
+  else if (!add || add == noexcept_false_spec)
+    return add;
   /* For merging noexcept(true) and throw(), take the more recent one (LIST).
-     A throw(type-list) spec takes precedence over a noexcept(false) spec.
      Any other noexcept-spec should only be merged with an equivalent one.
      So the !TREE_VALUE code below is correct for all cases.  */
   else if (!TREE_VALUE (add))
index a2ccc56f84075a2e34af5ea64012dc3022d0d8d4..c6d5615806b571c82332988b25a937c0e5ee0916 100644 (file)
@@ -1,3 +1,10 @@
+2011-05-20  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/noexcept02.C: Fix.
+       * g++.dg/cpp0x/noexcept03.C: Fix.
+       * g++.dg/cpp0x/noexcept08.C: Fix.
+       * g++.dg/cpp0x/noexcept10.C: New.
+
 2011-05-20  Janus Weil  <janus@gcc.gnu.org>
 
        PR fortran/48706
index 60015e756681f4214e72fec206a262fb4c3fe4e0..ffbb091924118b2e3deebde3d5662b4008aeaedc 100644 (file)
@@ -10,9 +10,9 @@ void f();
 
 SA(!noexcept(f()));
 
-void g() throw (int);
-void g() noexcept(false);      // { dg-error "previous declaration" }
-void g();                      // { dg-error "different exception" }
+void g() throw (int);          // { dg-error "previous declaration" }
+void g() noexcept(false);      // { dg-error "different exception" }
+void g();
 
 void h() throw();
 void h() noexcept;
index c759f6fb21d27620023d9933c060fe0ee61d7560..54e04f3d02d8af61e68fa0ea94b2a0d23a2c97e6 100644 (file)
@@ -36,19 +36,6 @@ void f2(T a) noexcept (noexcept (f (a)))
 
 struct A { A() { } };          // { dg-warning "does not throw" }
 
-// throw(int) overrides noexcept(false) in either order.
-void h() throw (int, std::bad_exception);
-void h() noexcept (false)
-{
-  throw 1.0;
-}
-
-void i() noexcept (false);
-void i() throw (int, std::bad_exception)
-{
-  throw 1.0;
-}
-
 int main()
 {
   // noexcept(false) allows throw.
@@ -57,10 +44,6 @@ int main()
   try { f(A()); } catch (int) { }
   try { f2(A()); } catch (int) { }
 
-  std::set_unexpected (my_unexpected);
-  try { h(); } catch (std::bad_exception) { }
-  try { i(); } catch (std::bad_exception) { }
-
   std::set_terminate (my_terminate);
   // noexcept(noexcept(int())) == noexcept(true).
   try { f2(1); } catch (...) { }
index c45033246eba1238267a5ab662876396d7447d5b..1df85efff9c14b34a098d2aeece30b0e8de48a2e 100644 (file)
@@ -34,7 +34,7 @@ struct D: A
   void g() noexcept(false);    // { dg-error "looser" }
   void h() noexcept(false);    // { dg-error "looser" }
   void i() noexcept(false);
-  void j() noexcept(false);    // compatible; treated as throw(int)
+  void j() noexcept(false);    // { dg-error "looser" }
 };
 
 struct E: A
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept10.C b/gcc/testsuite/g++.dg/cpp0x/noexcept10.C
new file mode 100644 (file)
index 0000000..058a387
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/49082
+// { dg-options -std=c++0x }
+
+namespace std { template <class T> T&& declval() noexcept; }
+
+struct Base
+{
+  Base(const Base&) noexcept(false);
+  Base(Base&&) noexcept(false);
+ ~Base() noexcept(false);
+};
+
+struct Derived
+: Base
+{
+  // Derived(const Derived&) = default;
+  // Derived(Derived&&) = default;
+};
+
+static_assert(!noexcept(Base(std::declval<const Base&>())), "Error");
+static_assert(!noexcept(Derived(std::declval<const Derived&>())), "Error"); // Error
+
+static_assert(!noexcept(Base(std::declval<Base&&>())), "Error");
+static_assert(!noexcept(Derived(std::declval<Derived&&>())), "Error"); // Error
+
+static_assert(!noexcept(std::declval<Base&>().~Base()), "Error"); // OK
+static_assert(!noexcept(std::declval<Derived&>().~Derived()), "Error"); // Error