Commit 94ccc95d by Paolo Carlini Committed by Paolo Carlini

re PR c++/51184 (Abstract class in function return type)

/cp
2012-05-21  Paolo Carlini  <paolo.carlini@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.carlini@oracle.com>

	PR c++/51184
	* g++.dg/other/abstract4.C: New-

/cp
2012-05-21  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/40821
	* parser.c (cp_parser_attributes_opt): Enforce error checking of
	unbalanced parentheses in the presence of tentative parsing.

/testsuite
2012-05-21  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/40821
	* g++.dg/ext/attrib46.C: New.

From-SVN: r187720
parent cb0c9fc3
2012-05-21 Paolo Carlini <paolo.carlini@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.
2012-05-21 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/40821
* parser.c (cp_parser_attributes_opt): Enforce error checking of
unbalanced parentheses in the presence of tentative parsing.
2012-05-17 Paolo Carlini <paolo.carlini@oracle.com> 2012-05-17 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/39681 PR c++/39681
......
...@@ -1658,6 +1658,10 @@ struct GTY((variable_size)) lang_type { ...@@ -1658,6 +1658,10 @@ struct GTY((variable_size)) lang_type {
#define CLASSTYPE_PURE_VIRTUALS(NODE) \ #define CLASSTYPE_PURE_VIRTUALS(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->pure_virtuals) (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. */ /* Nonzero means that this type has an X() constructor. */
#define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \ #define TYPE_HAS_DEFAULT_CONSTRUCTOR(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor) (LANG_TYPE_CLASS_CHECK (NODE)->h.has_default_ctor)
......
...@@ -9194,6 +9194,11 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -9194,6 +9194,11 @@ grokdeclarator (const cp_declarator *declarator,
error ("%qs declared as function returning an array", name); error ("%qs declared as function returning an array", name);
return error_mark_node; 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'. */ /* Pick up type qualifiers which should be applied to `this'. */
memfn_quals = declarator->u.function.qualifiers; memfn_quals = declarator->u.function.qualifiers;
......
...@@ -974,7 +974,7 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw) ...@@ -974,7 +974,7 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
/* 10.4/3 An abstract class shall not be used as a parameter type, /* 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 as a function return type or as type of an explicit
conversion. */ conversion. */
else if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type)) else if (ABSTRACT_CLASS_TYPE_P (type))
{ {
if (is_throw) if (is_throw)
error ("expression %qE of abstract class type %qT cannot " error ("expression %qE of abstract class type %qT cannot "
......
...@@ -20052,6 +20052,7 @@ cp_parser_attributes_opt (cp_parser* parser) ...@@ -20052,6 +20052,7 @@ cp_parser_attributes_opt (cp_parser* parser)
{ {
cp_token *token; cp_token *token;
tree attribute_list; tree attribute_list;
bool ok = true;
/* Peek at the next token. */ /* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer); token = cp_lexer_peek_token (parser->lexer);
...@@ -20076,8 +20077,12 @@ cp_parser_attributes_opt (cp_parser* parser) ...@@ -20076,8 +20077,12 @@ cp_parser_attributes_opt (cp_parser* parser)
attribute_list = NULL; attribute_list = NULL;
/* Look for the two `)' tokens. */ /* Look for the two `)' tokens. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); ok = false;
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
ok = false;
if (!ok)
cp_parser_skip_to_end_of_statement (parser);
/* Add these new attributes to the list. */ /* Add these new attributes to the list. */
attributes = chainon (attributes, attribute_list); attributes = chainon (attributes, attribute_list);
......
...@@ -11646,7 +11646,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -11646,7 +11646,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
error ("creating array of %qT", type); error ("creating array of %qT", type);
return error_mark_node; return error_mark_node;
} }
if (CLASS_TYPE_P (type) && CLASSTYPE_PURE_VIRTUALS (type)) if (ABSTRACT_CLASS_TYPE_P (type))
{ {
if (complain & tf_error) if (complain & tf_error)
error ("creating array of %qT, which is an abstract class type", error ("creating array of %qT, which is an abstract class type",
......
...@@ -5441,7 +5441,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) ...@@ -5441,7 +5441,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
return type_has_virtual_destructor (type1); return type_has_virtual_destructor (type1);
case CPTK_IS_ABSTRACT: case CPTK_IS_ABSTRACT:
return (CLASS_TYPE_P (type1) && CLASSTYPE_PURE_VIRTUALS (type1)); return (ABSTRACT_CLASS_TYPE_P (type1));
case CPTK_IS_BASE_OF: case CPTK_IS_BASE_OF:
return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2)
......
2012-05-21 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/51184
* g++.dg/other/abstract4.C: New-
2012-05-21 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/40821
* g++.dg/ext/attrib46.C: New.
2012-05-21 Joseph Myers <joseph@codesourcery.com> 2012-05-21 Joseph Myers <joseph@codesourcery.com>
PR c/53148 PR c/53148
......
// PR c++/40821
struct __attribute__((aligned(8)) S1 { int i; }; // { dg-error "expected" }
struct __attribute__( aligned(8) S2 { int i; }; // { dg-error "expected" }
// 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" }
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment