This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ Patch] PR 11551 (typedef name accepted in destructor declaration)
- From: Scott Brumbaugh <scottb dot lists at verizon dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 19 Aug 2003 12:13:55 -0700 (PDT)
- Subject: [C++ Patch] PR 11551 (typedef name accepted in destructor declaration)
Hi,
This patch fixes PR 11551 where a typedef name is allowed in the
declaration of a destructor. I have also changed the comments for the
function cp_parser_unqualified_id. The original comments say that the
operand of the BIT_NOT_EXPR will be an IDENTIFIER_NODE. This is not
the case as the code will construct a BIT_NOT_EXPR with a type node
as its argument.
2003-08-16 Scott Brumbaugh <scottb.lists@verizon.net>
PR C++/11551
* parser.c (cp_parser_unqualified_id): When parsing a
destructor declaration, make sure that the name is not
a typedef name for a class.
Index: parser.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.101
diff -c -3 -p -r1.101 parser.c
*** parser.c 18 Aug 2003 12:55:03 -0000 1.101
--- parser.c 19 Aug 2003 17:40:57 -0000
*************** cp_parser_id_expression (cp_parser *pars
*** 2615,2624 ****
Returns a representation of unqualified-id. For the `identifier'
production, an IDENTIFIER_NODE is returned. For the `~ class-name'
production a BIT_NOT_EXPR is returned; the operand of the
! BIT_NOT_EXPR is an IDENTIFIER_NODE for the class-name. For the
! other productions, see the documentation accompanying the
! corresponding parsing functions. If CHECK_DEPENDENCY_P is false,
! names are looked up in uninstantiated templates. */
static tree
cp_parser_unqualified_id (cp_parser* parser,
--- 2615,2624 ----
Returns a representation of unqualified-id. For the `identifier'
production, an IDENTIFIER_NODE is returned. For the `~ class-name'
production a BIT_NOT_EXPR is returned; the operand of the
! BIT_NOT_EXPR is a TYPE NODE for the class. For the other
! productions, see the documentation accompanying the corresponding
! parsing functions. If CHECK_DEPENDENCY_P is false, names are
! looked up in uninstantiated templates. */
static tree
cp_parser_unqualified_id (cp_parser* parser,
*************** cp_parser_unqualified_id (cp_parser* par
*** 2655,2661 ****
case CPP_COMPL:
{
! tree type_decl;
tree qualifying_scope;
tree object_scope;
tree scope;
--- 2655,2661 ----
case CPP_COMPL:
{
! tree type_decl = error_mark_node;
tree qualifying_scope;
tree object_scope;
tree scope;
*************** cp_parser_unqualified_id (cp_parser* par
*** 2724,2734 ****
/*type_p=*/false,
/*check_dependency=*/false,
/*class_head_p=*/false);
! if (cp_parser_parse_definitely (parser))
! return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
/* In "N::S::~S", look in "N" as well. */
! if (scope && qualifying_scope)
{
cp_parser_parse_tentatively (parser);
parser->scope = qualifying_scope;
--- 2724,2733 ----
/*type_p=*/false,
/*check_dependency=*/false,
/*class_head_p=*/false);
! cp_parser_parse_definitely (parser);
}
/* In "N::S::~S", look in "N" as well. */
! if (type_decl == error_mark_node && scope && qualifying_scope)
{
cp_parser_parse_tentatively (parser);
parser->scope = qualifying_scope;
*************** cp_parser_unqualified_id (cp_parser* par
*** 2741,2751 ****
/*type_p=*/false,
/*check_dependency=*/false,
/*class_head_p=*/false);
! if (cp_parser_parse_definitely (parser))
! return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
/* In "p->S::~T", look in the scope given by "*p" as well. */
! else if (object_scope)
{
cp_parser_parse_tentatively (parser);
parser->scope = object_scope;
--- 2740,2749 ----
/*type_p=*/false,
/*check_dependency=*/false,
/*class_head_p=*/false);
! cp_parser_parse_definitely (parser);
}
/* In "p->S::~T", look in the scope given by "*p" as well. */
! if (type_decl == error_mark_node && object_scope)
{
cp_parser_parse_tentatively (parser);
parser->scope = object_scope;
*************** cp_parser_unqualified_id (cp_parser* par
*** 2758,2789 ****
/*type_p=*/false,
/*check_dependency=*/false,
/*class_head_p=*/false);
! if (cp_parser_parse_definitely (parser))
! return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
- /* Look in the surrounding context. */
- parser->scope = NULL_TREE;
- parser->object_scope = NULL_TREE;
- parser->qualifying_scope = NULL_TREE;
- type_decl
- = cp_parser_class_name (parser,
- /*typename_keyword_p=*/false,
- /*template_keyword_p=*/false,
- /*type_p=*/false,
- /*check_dependency=*/false,
- /*class_head_p=*/false);
- /* If an error occurred, assume that the name of the
- destructor is the same as the name of the qualifying
- class. That allows us to keep parsing after running
- into ill-formed destructor names. */
- if (type_decl == error_mark_node && scope && TYPE_P (scope))
- return build_nt (BIT_NOT_EXPR, scope);
- else if (type_decl == error_mark_node)
- return error_mark_node;
return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
-
case CPP_KEYWORD:
if (token->keyword == RID_OPERATOR)
{
--- 2756,2817 ----
/*type_p=*/false,
/*check_dependency=*/false,
/*class_head_p=*/false);
! cp_parser_parse_definitely (parser);
! }
! if (type_decl == error_mark_node)
! {
! /* Look in the surrounding context. */
! parser->scope = NULL_TREE;
! parser->object_scope = NULL_TREE;
! parser->qualifying_scope = NULL_TREE;
! type_decl
! = cp_parser_class_name (parser,
! /*typename_keyword_p=*/false,
! /*template_keyword_p=*/false,
! /*type_p=*/false,
! /*check_dependency=*/false,
! /*class_head_p=*/false);
! /* If an error occurred, assume that the name of the
! destructor is the same as the name of the qualifying
! class. That allows us to keep parsing after running
! into ill-formed destructor names. */
! if (type_decl == error_mark_node && scope && TYPE_P (scope))
! return build_nt (BIT_NOT_EXPR, scope);
}
+ if (type_decl == error_mark_node)
+ return error_mark_node;
+
+ /* Check for a destructor name that is a typedef name. It is
+ an error to declare a destructor using a typedef name.
+ However, a typedefname is allowed in an explicit call of a
+ destructor. Example:
+
+ struct S
+ {
+ typedef S S1;
+ ~S(); // ok, destructor
+ ~S1(); // error, typedef name cannot declare
+ // a destructor
+ };
+
+ void f()
+ {
+ S * s = new S;
+ s->~S1(); // ok, calls S::~S()
+ }
+ */
+ if (parser->in_declarator_p
+ && !constructor_name_p (DECL_NAME (type_decl),
+ TREE_TYPE (type_decl)))
+ {
+ error ("destructor %T must match classname", DECL_NAME (type_decl));
+ return error_mark_node;
+ }
+
return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+
}
case CPP_KEYWORD:
if (token->keyword == RID_OPERATOR)
{
*************** cp_parser_direct_declarator (cp_parser*
*** 9772,9777 ****
--- 9800,9806 ----
/* Parse a declarator_id */
if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
cp_parser_parse_tentatively (parser);
+ parser->in_declarator_p = true;
declarator = cp_parser_declarator_id (parser);
if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
{
*************** cp_parser_declarator_id (cp_parser* pars
*** 10089,10095 ****
/*template_p=*/NULL);
/* If the name was qualified, create a SCOPE_REF to represent
that. */
! if (parser->scope)
{
id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
parser->scope = NULL_TREE;
--- 10118,10124 ----
/*template_p=*/NULL);
/* If the name was qualified, create a SCOPE_REF to represent
that. */
! if (parser->scope && id_expression != error_mark_node)
{
id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
parser->scope = NULL_TREE;
// { dg-do compile }
// PR 11551 typedef name used in declaration
// of destructor.
//
struct S
{
typedef struct S S1;
~S1(); // { dg-error "" }
~S();
};
void f()
{
S * s = new S;
s->~S1(); // ok, calls S::~S();
}