aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-05-20 16:39:59 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-05-20 16:39:59 -0400
commit5e3f417f3efce4a89d7330eed7f4dba99bcbe3bc (patch)
tree35f1b483465719251a4a4da129ee8d9540173c09 /gcc
parentbce33ab2b4277852496aaebc9bbdbc223ee25164 (diff)
downloadgcc-5e3f417f3efce4a89d7330eed7f4dba99bcbe3bc.zip
gcc-5e3f417f3efce4a89d7330eed7f4dba99bcbe3bc.tar.gz
gcc-5e3f417f3efce4a89d7330eed7f4dba99bcbe3bc.tar.bz2
DR 1073 PR c++/49082
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/typeck.c10
-rw-r--r--gcc/cp/typeck2.c9
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept02.C6
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept03.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept08.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept10.C27
8 files changed, 56 insertions, 29 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5d93472..4ec6578 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d98c62b..7791efc 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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(). */
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 26b9816..c2eff9e 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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))
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a2ccc56..c6d5615 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
index 60015e7..ffbb091 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept03.C b/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
index c759f6f..54e04f3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept03.C
@@ -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 (...) { }
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept08.C b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C
index c450332..1df85ef 100644
--- a/gcc/testsuite/g++.dg/cpp0x/noexcept08.C
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C
@@ -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
index 0000000..058a387
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept10.C
@@ -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