This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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();
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]