OSDN Git Service

* typeck.c (comp_except_specs): Fix ce_derived with noexcept.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Jun 2010 04:36:55 +0000 (04:36 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 22 Jun 2010 04:36:55 +0000 (04:36 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@161130 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 131030e..5d36ad3 100644 (file)
@@ -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.
 
index beef388..4383ef5 100644 (file)
@@ -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;
index 8443f23..54d13fd 100644 (file)
@@ -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 (file)
index 0000000..c450332
--- /dev/null
@@ -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" }
+};