aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorManfred Hollstein <manfred@gcc.gnu.org>1998-03-15 03:28:07 +0000
committerManfred Hollstein <manfred@gcc.gnu.org>1998-03-15 03:28:07 +0000
commit4a67c9e985c6961cbc78f0ce1afc19dba2775401 (patch)
tree5dc477a4ae87ddf2829783fba1f5d00999bcb0af /gcc
parentcdcb673e6e6c4b7534fb5b98efda5f8079de8905 (diff)
downloadgcc-4a67c9e985c6961cbc78f0ce1afc19dba2775401.zip
gcc-4a67c9e985c6961cbc78f0ce1afc19dba2775401.tar.gz
gcc-4a67c9e985c6961cbc78f0ce1afc19dba2775401.tar.bz2
cp-tree.h (struct lang_decl_flags): Add needs_final_overrider.
d * cp-tree.h (struct lang_decl_flags): Add needs_final_overrider. (DECL_NEEDS_FINAL_OVERRIDER_P): New macro. * class.c (override_one_vtable): Set DECL_NEEDS_FINAL_OVERRIDER_P. * decl.c (duplicate_decls): Propagate it. * typeck2.c (abstract_virtuals_error): Use two loops to emit abstract virtual functions and virtual functions which need a final overrider separately. From-SVN: r18588
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/class.c1
-rw-r--r--gcc/cp/decl.c1
-rw-r--r--gcc/cp/typeck2.c68
3 files changed, 64 insertions, 6 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f13180f..cb32461 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2725,6 +2725,7 @@ override_one_vtable (binfo, old, t)
fndecl = copy_node (fndecl);
copy_lang_decl (fndecl);
DECL_ABSTRACT_VIRTUAL_P (fndecl) = 1;
+ DECL_NEEDS_FINAL_OVERRIDER_P (fndecl) = 1;
/* Make sure we search for it later. */
if (! CLASSTYPE_ABSTRACT_VIRTUALS (t))
CLASSTYPE_ABSTRACT_VIRTUALS (t) = error_mark_node;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index fdf704c..43a1660 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2740,6 +2740,7 @@ duplicate_decls (newdecl, olddecl)
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_ABSTRACT_VIRTUAL_P (newdecl) |= DECL_ABSTRACT_VIRTUAL_P (olddecl);
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
+ DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
}
/* Deal with C++: must preserve virtual function table size. */
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index f462e79..2a208af 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -130,6 +130,29 @@ abstract_virtuals_error (decl, type)
tree type;
{
tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
+ int has_abstract_virtuals, needs_final_overriders;
+ tree tu;
+
+ /* Count how many abstract methods need to be defined. */
+ for (has_abstract_virtuals = 0, tu = u; tu; tu = TREE_CHAIN (tu))
+ {
+ if (DECL_ABSTRACT_VIRTUAL_P (TREE_VALUE (tu))
+ && ! DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
+ {
+ has_abstract_virtuals = 1;
+ break;
+ }
+ }
+
+ /* Count how many virtual methods need a final overrider. */
+ for (needs_final_overriders = 0, tu = u; tu; tu = TREE_CHAIN (tu))
+ {
+ if (DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
+ {
+ needs_final_overriders = 1;
+ break;
+ }
+ }
if (decl)
{
@@ -151,19 +174,52 @@ abstract_virtuals_error (decl, type)
else if (TREE_CODE (decl) == FUNCTION_DECL)
cp_error ("invalid return type for function `%#D'", decl);
}
- else cp_error ("cannot allocate an object of type `%T'", type);
+ else
+ cp_error ("cannot allocate an object of type `%T'", type);
+
/* Only go through this once. */
if (TREE_PURPOSE (u) == NULL_TREE)
{
- error (" since the following virtual functions are abstract:");
TREE_PURPOSE (u) = error_mark_node;
- while (u)
+
+ if (has_abstract_virtuals)
+ error (" since the following virtual functions are abstract:");
+ tu = u;
+ while (tu)
+ {
+ if (DECL_ABSTRACT_VIRTUAL_P (TREE_VALUE (tu))
+ && ! DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
+ cp_error ("\t%#D", TREE_VALUE (tu));
+ tu = TREE_CHAIN (tu);
+ }
+
+ if (needs_final_overriders)
+ {
+ if (has_abstract_virtuals)
+ error (" and the following virtual functions need a final overrider:");
+ else
+ error (" since the following virtual functions need a final overrider:");
+ }
+ tu = u;
+ while (tu)
{
- cp_error ("\t%#D", TREE_VALUE (u));
- u = TREE_CHAIN (u);
+ if (DECL_NEEDS_FINAL_OVERRIDER_P (TREE_VALUE (tu)))
+ cp_error ("\t%#D", TREE_VALUE (tu));
+ tu = TREE_CHAIN (tu);
}
}
- else cp_error (" since type `%T' has abstract virtual functions", type);
+ else
+ {
+ if (has_abstract_virtuals)
+ {
+ if (needs_final_overriders)
+ cp_error (" since type `%T' has abstract virtual functions and must override virtual functions", type);
+ else
+ cp_error (" since type `%T' has abstract virtual functions", type);
+ }
+ else
+ cp_error (" since type `%T' must override virtual functions", type);
+ }
}
/* Print an error message for invalid use of a signature type.