summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-06-22 00:36:55 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-06-22 00:36:55 -0400
commit6d812dd3582299f030ec940c3c513c0653a1a49f (patch)
tree93a38e3444c2c25ffd26aa4f87c19fd13083885a
parentf94ae9875d386e651defd8f8c802cb41e77a6ba0 (diff)
downloadgcc-6d812dd3582299f030ec940c3c513c0653a1a49f.tar.gz
* typeck.c (comp_except_specs): Fix ce_derived with noexcept.
From-SVN: r161130
-rw-r--r--gcc/cp/ChangeLog2
-rw-r--r--gcc/cp/typeck.c52
-rw-r--r--gcc/testsuite/ChangeLog2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept08.C56
4 files changed, 87 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 131030e6a0d..5d36ad3c977 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,7 @@
2010-06-21 Jason Merrill <jason@redhat.com>
+ * typeck.c (comp_except_specs): Fix ce_derived with noexcept.
+
* semantics.c (check_trait_type): Check COMPLETE_TYPE_P for array
element type.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index beef3881291..4383ef560a7 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -993,35 +993,37 @@ comp_except_specs (const_tree t1, const_tree t2, int exact)
const_tree probe;
const_tree base;
int length = 0;
- const_tree noexcept_spec = NULL_TREE;
- const_tree other_spec;
if (t1 == t2)
return true;
- /* First test noexcept compatibility. */
- if (t1 && TREE_PURPOSE (t1))
- noexcept_spec = t1, other_spec = t2;
- else if (t2 && TREE_PURPOSE (t2))
- noexcept_spec = t2, other_spec = t1;
- if (noexcept_spec)
- {
- tree p = TREE_PURPOSE (noexcept_spec);
- /* Two noexcept-specs are equivalent iff their exprs are. */
- if (other_spec && TREE_PURPOSE (other_spec))
- return cp_tree_equal (p, TREE_PURPOSE (other_spec));
- /* noexcept(true) is compatible with throw(). */
- else if (exact < ce_exact && p == boolean_true_node)
- return nothrow_spec_p (other_spec);
- /* noexcept(false) is compatible with any throwing
- dynamic-exception-spec. */
- else if (exact < ce_exact && p == boolean_false_node)
- return !nothrow_spec_p (other_spec);
- /* A dependent noexcept-spec is not compatible with any
- dynamic-exception-spec. */
- else
- return false;
- }
+ /* First handle noexcept. */
+ if (exact < ce_exact)
+ {
+ /* noexcept(false) is compatible with any throwing dynamic-exc-spec
+ 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. */
+ if (t2 == noexcept_false_spec)
+ return !nothrow_spec_p (t1);
+
+ /* Otherwise, if we aren't looking for an exact match, noexcept is
+ equivalent to throw(). */
+ if (t1 == noexcept_true_spec)
+ t1 = empty_except_spec;
+ if (t2 == noexcept_true_spec)
+ t2 = empty_except_spec;
+ }
+
+ /* If any noexcept is left, it is only comparable to itself;
+ either we're looking for an exact match or we're redeclaring a
+ template with dependent noexcept. */
+ if ((t1 && TREE_PURPOSE (t1))
+ || (t2 && TREE_PURPOSE (t2)))
+ return (t1 && t2
+ && cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)));
if (t1 == NULL_TREE) /* T1 is ... */
return t2 == NULL_TREE || exact == ce_derived;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8443f23a7f7..54d13fd22c5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,7 @@
2010-06-21 Jason Merrill <jason@redhat.com>
+ * g++.dg/cpp0x/noexcept08.C: New.
+
* g++.dg/ext/unary_trait_incomplete.C: Adjust.
2010-06-21 H.J. Lu <hongjiu.lu@intel.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept08.C b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C
new file mode 100644
index 00000000000..c45033246eb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C
@@ -0,0 +1,56 @@
+// { dg-options "-std=c++0x" }
+// { dg-prune-output "overriding" }
+
+struct A
+{
+ virtual void f();
+ virtual void g() throw();
+ virtual void h() noexcept;
+ virtual void i() noexcept(false);
+ virtual void j() throw(int);
+};
+
+struct B: A
+{
+ void f() noexcept;
+ void g() noexcept;
+ void h() noexcept;
+ void i() noexcept;
+ void j() noexcept;
+};
+
+struct C: A
+{
+ void f() throw();
+ void g() throw();
+ void h() throw();
+ void i() throw();
+ void j() throw();
+};
+
+struct D: A
+{
+ void f() noexcept(false);
+ 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)
+};
+
+struct E: A
+{
+ void f() throw(int);
+ void g() throw(int); // { dg-error "looser" }
+ void h() throw(int); // { dg-error "looser" }
+ void i() throw(int);
+ void j() throw(int);
+};
+
+struct F: A
+{
+ void f();
+ void g(); // { dg-error "looser" }
+ void h(); // { dg-error "looser" }
+ void i();
+ void j(); // { dg-error "looser" }
+};