Patchwork C++ PATCH for c++/46220 (overly strict covariant return checking)

login
register
mail settings
Submitter Jason Merrill
Date March 4, 2011, 4:36 p.m.
Message ID <4D71150A.3080504@redhat.com>
Download mbox | patch
Permalink /patch/85425/
State New
Headers show

Comments

Jason Merrill - March 4, 2011, 4:36 p.m.
When the pointer target type differs in a virtual override, the standard 
requires the type in the derived class method to be complete.  But that 
shouldn't be necessary if the types only differ in cv-quals; this seems 
like a wording bug, and EDG seems to agree.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit 7dfcc5d7e1985a5727a097c2e664b5ded310d509
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Mar 3 16:20:58 2011 -0500

    	PR c++/46220
    	* search.c (check_final_overrider): Allow pointer to same incomplete
    	class type with different cv-quals.

Patch

diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 188f0a5..07ec9ef 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1835,11 +1835,17 @@  check_final_overrider (tree overrider, tree basefn)
 
       if (CLASS_TYPE_P (base_return) && CLASS_TYPE_P (over_return))
 	{
-	  tree binfo = lookup_base (over_return, base_return,
-				    ba_check | ba_quiet, NULL);
+	  /* Strictly speaking, the standard requires the return type to be
+	     complete even if it only differs in cv-quals, but that seems
+	     like a bug in the wording.  */
+	  if (!same_type_ignoring_top_level_qualifiers_p (base_return, over_return))
+	    {
+	      tree binfo = lookup_base (over_return, base_return,
+					ba_check | ba_quiet, NULL);
 
-	  if (!binfo)
-	    fail = 1;
+	      if (!binfo)
+		fail = 1;
+	    }
 	}
       else if (!pedantic
 	       && can_convert (TREE_TYPE (base_type), TREE_TYPE (over_type)))
diff --git a/gcc/testsuite/g++.dg/inherit/covariant19.C b/gcc/testsuite/g++.dg/inherit/covariant19.C
new file mode 100644
index 0000000..22c2b0e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/covariant19.C
@@ -0,0 +1,14 @@ 
+// PR c++/46220
+// According to the letter of the standard this is invalid,
+// but that seems like a bug.
+
+class Baz;
+class Foo {
+public:
+    virtual const Baz* getBaz() = 0;
+};
+class Bar : public Foo {
+public:
+    Baz* getBaz();
+};
+