diff mbox

C++0x, fixes for override/final

Message ID 87wrhzzggw.wl%ville@ville-laptop
State New
Headers show

Commit Message

Ville Voutilainen May 9, 2011, 9:55 p.m. UTC
Diagnose final on non-virtuals properly, diagnose override on
virtuals that don't actually override properly. Amend these
cases to the tests. Tested on Linux/X86-32.

2011-05-10 Ville Voutilainen <ville.voutilainen@gmail.com> <ville.voutilainen@symbio.com>
           Fixes for override/final.
           * class.c (check_for_override): Diagnose final on a nonvirtual member function, diagnose override for a virtual with no matching override. Don't fiddle around with DECL_VINDEX.
           * virtual9.C: add tests that cover the aforementioned cases, add a test for a definition of a member function outside its class definition, add a test where cv-qualifiers don't match.

Comments

Jason Merrill May 10, 2011, 4:46 a.m. UTC | #1
On 05/09/2011 05:55 PM, Ville Voutilainen wrote:
> +  overrides_found = look_for_overrides (ctype, decl);
>     if ((DECL_DESTRUCTOR_P (decl)
>          || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl))
>          || DECL_CONV_FN_P (decl))
> -&&  look_for_overrides (ctype, decl)
> +&&  overrides_found
>         &&  !DECL_STATIC_FUNCTION_P (decl))

This is breaking an optimization: before this change we don't bother 
looking for overrides if we've never seen a virtual function with the 
same name.  Just set overrides_found as well as DECL_VINDEX.

Jason
diff mbox

Patch

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 12db2bc..24184d2 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2453,16 +2453,18 @@  get_basefndecls (tree name, tree t)
 void
 check_for_override (tree decl, tree ctype)
 {
+  int overrides_found = 0;
   if (TREE_CODE (decl) == TEMPLATE_DECL)
     /* In [temp.mem] we have:
 
 	 A specialization of a member function template does not
 	 override a virtual function from a base class.  */
     return;
+  overrides_found = look_for_overrides (ctype, decl);
   if ((DECL_DESTRUCTOR_P (decl)
        || IDENTIFIER_VIRTUAL_P (DECL_NAME (decl))
        || DECL_CONV_FN_P (decl))
-      && look_for_overrides (ctype, decl)
+      && overrides_found
       && !DECL_STATIC_FUNCTION_P (decl))
     /* Set DECL_VINDEX to a value that is neither an INTEGER_CST nor
        the error_mark_node so that we know it is an overriding
@@ -2477,11 +2479,11 @@  check_for_override (tree decl, tree ctype)
       if (DECL_DESTRUCTOR_P (decl))
 	TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype) = true;
     }
-  else if (DECL_OVERRIDE_P (decl))
-    {
-      DECL_VINDEX (decl) = error_mark_node;
-      error ("%q+#D marked override, but does not override", decl);
-    }
+  else if (DECL_FINAL_P (decl))
+        error ("%q+#D marked final, but is not virtual", decl);
+  if (DECL_OVERRIDE_P (decl)
+      && !overrides_found)
+    error ("%q+#D marked override, but does not override", decl);
 }
 
 /* Warn about hidden virtual functions that are not overridden in t.
diff --git a/gcc/testsuite/g++.dg/inherit/virtual9.C b/gcc/testsuite/g++.dg/inherit/virtual9.C
index d3175e1..83e0479 100644
--- a/gcc/testsuite/g++.dg/inherit/virtual9.C
+++ b/gcc/testsuite/g++.dg/inherit/virtual9.C
@@ -3,6 +3,7 @@  struct B
 {
   virtual void f() final {}
   virtual void g() {}
+  virtual void x() const {}
 };
 
 struct B2
@@ -20,7 +21,12 @@  template <class T> struct D2 : T
   void h() override {} // { dg-error "marked override, but does not override" }
 };
 
-struct D3 : D
+template <class T> struct D3 : T
+{
+  void h() override {}
+};
+
+struct D4 : D
 {
   void g() {} // { dg-error "virtual function" }
 };
@@ -30,10 +36,25 @@  struct B3
   virtual void f() final final {} // { dg-error "duplicate virt-specifier" }
 };
 
-void g() override {} // { dg-error "virt-specifiers" }
+struct B4
+{
+  void f() final {} // { dg-error "marked final, but is not virtual" }
+};
+
+struct D5 : B
+{
+  void ff() override {} // { dg-error "marked override, but does not override" }
+  virtual void fff() override {} // { dg-error "marked override, but does not override" }
+  virtual void x() override {} // { dg-error "marked override, but does not override" }
+  void g() override;
+};
+
+void D5::g() override {} // { dg-error "not allowed outside a class definition" }
+void g() override {} // { dg-error "not allowed outside a class definition" }
 
 int main()
 {
-  D2<B> d2;
-  D2<B2> d3;
+  D2<B> d;
+  D2<B2> d2;
+  D3<B2> d3;
 }