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
This commit is contained in:
parent
bce33ab2b4
commit
5e3f417f3e
|
@ -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
|
||||
|
|
|
@ -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(). */
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 (...) { }
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue