Hi,
a simple diagnostic issue: we aren't diagnosing functions returning
abstract class types as typenames.
In grokdeclarator we already have a place where we do such checks on the
return types, and I'm adding this one too, with the following details:
1- I'm not immediately returning with error_mark_node: I think that by
now we have solid enough evidence that the rest of the compiler can cope
with such types without crashing and in this way the error message
doesn't end up including more redundant lines about semicolons etc.
Additionally, in this way we can also produce further useful error
messages, for example no function types in sizeofs.
2- I'm only handling TYPENAME, because normal FUNCTION_DECL, etc, are
handled later, by abstract_virtuals_error and the error messages are
more verbose but also more complete in such cases (eg, always include
the complete signature of the function)
Tested x86_64-linux.
Thanks,
Paolo.
//////////////////////
/cp
2012-05-21 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/51184
* decl.c (grokdeclarator): Diagnose functions returning abstract
class types as TYPENAME.
* cp-tree.h (ABSTRACT_CLASS_TYPE_P): Add.
* except.c (is_admissible_throw_operand_or_catch_parameter): Use it.
* pt.c (tsubst): Likewise.
* semantics.c (trait_expr_value): Likewise.
/testsuite
2012-05-21 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/51184
* g++.dg/other/abstract4.C: New-
Index: testsuite/g++.dg/other/abstract4.C
===================================================================
--- testsuite/g++.dg/other/abstract4.C (revision 0)
+++ testsuite/g++.dg/other/abstract4.C (revision 0)
@@ -0,0 +1,18 @@
+// PR c++/51184
+
+template<typename T>
+struct S { };
+
+template<typename T>
+void foo();
+
+struct Abs
+{
+ virtual void bar() = 0;
+};
+
+int main()
+{
+ S<Abs(int)> s; // { dg-error "abstract" }
+ foo<Abs(int)>(); // { dg-error "abstract" }
+}
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 187694)
+++ cp/decl.c (working copy)
@@ -9194,6 +9194,11 @@ grokdeclarator (const cp_declarator *declarator,
error ("%qs declared as function returning an array", name);
return error_mark_node;
}
+ /* When decl_context == NORMAL we emit a better error message
+ later in abstract_virtuals_error. */
+ if (decl_context == TYPENAME && ABSTRACT_CLASS_TYPE_P (type))
+ error ("%qs declared as function returning an abstract "
+ "class type", name);
/* Pick up type qualifiers which should be applied to `this'. */
memfn_quals = declarator->u.function.qualifiers;
Index: cp/except.c
===================================================================
--- cp/except.c (revision 187694)
+++ cp/except.c (working copy)
@@ -974,7 +974,7 @@ is_admissible_throw_operand_or_catch_parameter (tr
/* 10.4/3 An abstract class shall not be used as a parameter type,
as a function return type or as type of an explicit
conversion. */
- else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
+ else if (ABSTRACT_CLASS_TYPE_P (type))
{
if (is_throw)
error ("expression %qE of abstract class type %qT cannot "
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 187694)
+++ cp/pt.c (working copy)
@@ -11646,7 +11646,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain
error ("creating array of %qT", type);
return error_mark_node;
}
- if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type))
+ if (ABSTRACT_CLASS_TYPE_P (type))
{
if (complain & tf_error)
error ("creating array of %qT, which is an abstract class type",
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 187694)
+++ cp/semantics.c (working copy)
@@ -5441,7 +5441,7 @@ trait_expr_value (cp_trait_kind kind, tree type1,
return type_has_virtual_destructor (type1);
case CPTK_IS_ABSTRACT:
- return (CLASS_TYPE_P (type1) && CLASSTYPE_PURE_VIRTUALS (type1));
+ return (ABSTRACT_CLASS_TYPE_P (type1));
case CPTK_IS_BASE_OF:
return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h (revision 187694)
+++ cp/cp-tree.h (working copy)
@@ -1658,6 +1658,10 @@ struct GTY((variable_size)) lang_type {
#define CLASSTYPE_PURE_VIRTUALS(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->pure_virtuals)
+/* Nonzero means that this type is an abstract class type. */
+#define ABSTRACT_CLASS_TYPE_P(NODE) \
+ (CLASS_TYPE_P (NODE) && CLASSTYPE_PURE_VIRTUALS(NODE))
+
/* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor)