From: Jason Merrill Date: Fri, 20 May 2011 20:39:59 +0000 (-0400) Subject: DR 1073 PR c++/49082 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5e3f417f3efce4a89d7330eed7f4dba99bcbe3bc;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5d93472bba3..4ec657812e1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,12 @@ 2011-05-20 Jason Merrill + 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 d98c62bb940..7791efcaa8f 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 26b9816d548..c2eff9eb6c8 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 a2ccc56f840..c6d5615806b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-05-20 Jason Merrill + + * 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 PR fortran/48706 diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C index 60015e75668..ffbb0919241 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 c759f6fb21d..54e04f3d02d 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 c45033246eb..1df85efff9c 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 00000000000..058a387d778 --- /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 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())), "Error"); +static_assert(!noexcept(Derived(std::declval())), "Error"); // Error + +static_assert(!noexcept(Base(std::declval())), "Error"); +static_assert(!noexcept(Derived(std::declval())), "Error"); // Error + +static_assert(!noexcept(std::declval().~Base()), "Error"); // OK +static_assert(!noexcept(std::declval().~Derived()), "Error"); // Error