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] Fix 23287


I've installed this patch to fix bug 23287. The problem was that we were parsing the destructor name as an unqualified-id (which it is), but ignoring the object scope. After parsing this, we then have to instantiate it, hence the patch to tsubst_copy_and_build.

built & tested on i686-pc-linux-gnu

nathan
--
Nathan Sidwell    ::   http://www.codesourcery.com   ::         CodeSourcery
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

2006-09-01  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/23287
	* parser.c (cp_parser_id_expression): Add member_p
	argument. Update all callers.
	(cp_parser_unqualified_id): Likewise.  Lookup a destructor name in
	the object's scope, if valid.
	(cp_parser_global_scope_opt): Add object_scope_valid_p.  Update
	callers.
	(cp_parser_postfix_dot_deref_expression): Set object_scope.
	* pt.c (tsubst_copy_and_build): Lookup dependent dtor name here.

2006-09-01  Nathan Sidwell  <nathan@codesourcery.com>

	PR c++/23287
	* g++.dg/parse/dtor12.C: New.

Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 116590)
+++ cp/pt.c	(working copy)
@@ -9200,6 +9200,14 @@ tsubst_copy_and_build (tree t,
 	  member = tsubst_baselink (member,
 				    non_reference (TREE_TYPE (object)),
 				    args, complain, in_decl);
+	else if (TREE_CODE (member) == BIT_NOT_EXPR
+		 && !TYPE_P (TREE_OPERAND (member, 0)))
+	  {
+	    tree id = TREE_OPERAND (member, 0);
+	    id = make_typename_type (object_type, id, typename_type, complain);
+	    gcc_assert (TREE_CODE (id) != TYPENAME_TYPE);
+	    member = build_nt (BIT_NOT_EXPR, id);
+	  }
 	else
 	  member = tsubst_copy (member, args, complain, in_decl);
 	if (member == error_mark_node)
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 116590)
+++ cp/parser.c	(working copy)
@@ -1393,9 +1393,9 @@ static bool cp_parser_translation_unit
 static tree cp_parser_primary_expression
   (cp_parser *, bool, bool, bool, cp_id_kind *);
 static tree cp_parser_id_expression
-  (cp_parser *, bool, bool, bool *, bool, bool);
+  (cp_parser *, bool, bool, bool *, bool, bool, bool);
 static tree cp_parser_unqualified_id
-  (cp_parser *, bool, bool, bool, bool);
+  (cp_parser *, bool, bool, bool, bool, bool);
 static tree cp_parser_nested_name_specifier_opt
   (cp_parser *, bool, bool, bool, bool);
 static tree cp_parser_nested_name_specifier
@@ -1720,7 +1720,7 @@ static bool cp_parser_check_template_par
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
-  (cp_parser *, bool);
+  (cp_parser *, bool, bool);
 static bool cp_parser_constructor_declarator_p
   (cp_parser *, bool);
 static tree cp_parser_function_definition_from_specifiers_and_declarator
@@ -2182,7 +2182,8 @@ cp_parser_parse_and_diagnose_invalid_typ
 				/*check_dependency_p=*/true,
 				/*template_p=*/NULL,
 				/*declarator_p=*/true,
-				/*optional_p=*/false);
+				/*optional_p=*/false,
+				/*member_p=*/false);
   /* After the id-expression, there should be a plain identifier,
      otherwise this is not a simple variable declaration. Also, if
      the scope is dependent, we cannot do much.  */
@@ -3061,7 +3062,8 @@ cp_parser_primary_expression (cp_parser 
 				     /*check_dependency_p=*/true,
 				     &template_p,
 				     /*declarator_p=*/false,
-				     /*optional_p=*/false);
+				     /*optional_p=*/false,
+				     /*member_p=*/false);
 	if (id_expression == error_mark_node)
 	  return error_mark_node;
 	token = cp_lexer_peek_token (parser->lexer);
@@ -3195,7 +3197,8 @@ cp_parser_id_expression (cp_parser *pars
 			 bool check_dependency_p,
 			 bool *template_p,
 			 bool declarator_p,
-			 bool optional_p)
+			 bool optional_p,
+			 bool member_p)
 {
   bool global_scope_p;
   bool nested_name_specifier_p;
@@ -3206,8 +3209,10 @@ cp_parser_id_expression (cp_parser *pars
 
   /* Look for the optional `::' operator.  */
   global_scope_p
-    = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)
+    = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
+				   /*object_scope_valid_p=*/member_p)
        != NULL_TREE);
+  
   /* Look for the optional nested-name-specifier.  */
   nested_name_specifier_p
     = (cp_parser_nested_name_specifier_opt (parser,
@@ -3239,7 +3244,8 @@ cp_parser_id_expression (cp_parser *pars
       unqualified_id = cp_parser_unqualified_id (parser, *template_p,
 						 check_dependency_p,
 						 declarator_p,
-						 /*optional_p=*/false);
+						 /*optional_p=*/false,
+						 /*member_p=*/false);
       /* Restore the SAVED_SCOPE for our caller.  */
       parser->scope = saved_scope;
       parser->object_scope = saved_object_scope;
@@ -3297,8 +3303,7 @@ cp_parser_id_expression (cp_parser *pars
   else
     return cp_parser_unqualified_id (parser, template_keyword_p,
 				     /*check_dependency_p=*/true,
-				     declarator_p,
-				     optional_p);
+				     declarator_p, optional_p, member_p);
 }
 
 /* Parse an unqualified-id.
@@ -3328,7 +3333,8 @@ cp_parser_unqualified_id (cp_parser* par
 			  bool template_keyword_p,
 			  bool check_dependency_p,
 			  bool declarator_p,
-			  bool optional_p)
+			  bool optional_p,
+			  bool member_p)
 {
   cp_token *token;
 
@@ -3456,6 +3462,7 @@ cp_parser_unqualified_id (cp_parser* par
 	    if (cp_parser_parse_definitely (parser))
 	      done = true;
 	  }
+
 	/* In "N::S::~S", look in "N" as well.  */
 	if (!done && scope && qualifying_scope)
 	  {
@@ -3474,24 +3481,56 @@ cp_parser_unqualified_id (cp_parser* par
 	    if (cp_parser_parse_definitely (parser))
 	      done = true;
 	  }
-	/* In "p->S::~T", look in the scope given by "*p" as well.  */
-	else if (!done && object_scope)
+	/* In "p->~T", look in the scope given by "*p" as well.  */
+	else if (!done && member_p)
 	  {
+	    if (!object_scope)
+	      {
+		/* It's a dependent expression, so just parse the
+		   dtor name.  */
+		tree id;
+
+		if (template_keyword_p)
+		  /* It's a template-id.  */
+		  id = cp_parser_template_id (parser, true,
+					      check_dependency_p,
+					      declarator_p);
+		else
+		  {
+		    /* Otherwise, it's an ordinary identifier.  */
+		    id = cp_parser_identifier (parser);
+		    /* If ID is a template type parm, then use that
+		       directly.  */
+		    if (TREE_TYPE (id)
+			&& TREE_CODE (TREE_TYPE (id)) == TEMPLATE_TYPE_PARM)
+		      id = TREE_TYPE (id);
+		  }
+
+		if (id != error_mark_node)
+		  id = build_nt (BIT_NOT_EXPR, id);
+		return id;
+	      }
+
 	    cp_parser_parse_tentatively (parser);
 	    parser->scope = object_scope;
 	    parser->object_scope = NULL_TREE;
 	    parser->qualifying_scope = NULL_TREE;
 	    type_decl
 	      = cp_parser_class_name (parser,
-				      /*typename_keyword_p=*/false,
+					/*typename_keyword_p=*/false,
 				      /*template_keyword_p=*/false,
 				      none_type,
 				      /*check_dependency=*/false,
 				      /*class_head_p=*/false,
 				      declarator_p);
+	    /* The name is not qualified, so reset the parser scopes
+	       so our callers do not get confused.  */
+	    parser->object_scope = object_scope;
+	    parser->scope = NULL_TREE;
 	    if (cp_parser_parse_definitely (parser))
 	      done = true;
 	  }
+	
 	/* Look in the surrounding context.  */
 	if (!done)
 	  {
@@ -4482,11 +4521,12 @@ cp_parser_postfix_dot_deref_expression (
   parser->qualifying_scope = NULL_TREE;
   parser->object_scope = NULL_TREE;
   *idk = CP_ID_KIND_NONE;
+
   /* Enter the scope corresponding to the type of the object
      given by the POSTFIX_EXPRESSION.  */
-  if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
+  scope = TREE_TYPE (postfix_expression);
+  if (!dependent_p && scope)
     {
-      scope = TREE_TYPE (postfix_expression);
       /* According to the standard, no expression should ever have
 	 reference type.  Unfortunately, we do not currently match
 	 the standard in this respect in that our internal representation
@@ -4500,11 +4540,8 @@ cp_parser_postfix_dot_deref_expression (
 	  error ("%qE does not have class type", postfix_expression);
 	  scope = NULL_TREE;
 	}
-      else
+      else if (!dependent_p)
 	scope = complete_type_or_else (scope, NULL_TREE);
-      /* Let the name lookup machinery know that we are processing a
-	 class member access expression.  */
-      parser->context->object_type = scope;
       /* If something went wrong, we want to be able to discern that case,
 	 as opposed to the case where there was no SCOPE due to the type
 	 of expression being dependent.  */
@@ -4516,6 +4553,10 @@ cp_parser_postfix_dot_deref_expression (
       if (scope == error_mark_node)
 	postfix_expression = error_mark_node;
     }
+  /* Let the name lookup machinery know that we are processing a class
+     member access expression.  */
+  parser->context->object_type = scope;
+  parser->object_scope = scope;
 
   /* Assume this expression is not a pseudo-destructor access.  */
   pseudo_destructor_p = false;
@@ -4553,7 +4594,8 @@ cp_parser_postfix_dot_deref_expression (
 	       /*check_dependency_p=*/true,
 	       &template_p,
 	       /*declarator_p=*/false,
-	       /*optional_p=*/false));
+	       /*optional_p=*/false,
+	       /*member_p=*/true));
       /* In general, build a SCOPE_REF if the member name is qualified.
 	 However, if the name was not dependent and has already been
 	 resolved; there is no need to build the SCOPE_REF.  For example;
@@ -4758,7 +4800,9 @@ cp_parser_pseudo_destructor_name (cp_par
   *type = error_mark_node;
 
   /* Look for the optional `::' operator.  */
-  cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true);
+  cp_parser_global_scope_opt (parser,
+			      /*current_scope_valid_p=*/true,
+			      /*object_scop_valid_p=*/true);
   /* Look for the optional nested-name-specifier.  */
   nested_name_specifier_p
     = (cp_parser_nested_name_specifier_opt (parser,
@@ -5069,7 +5113,8 @@ cp_parser_new_expression (cp_parser* par
   /* Look for the optional `::' operator.  */
   global_scope_p
     = (cp_parser_global_scope_opt (parser,
-				   /*current_scope_valid_p=*/false)
+				   /*current_scope_valid_p=*/false,
+				   /*object_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `new' operator.  */
   cp_parser_require_keyword (parser, RID_NEW, "`new'");
@@ -5367,7 +5412,8 @@ cp_parser_delete_expression (cp_parser* 
   /* Look for the optional `::' operator.  */
   global_scope_p
     = (cp_parser_global_scope_opt (parser,
-				   /*current_scope_valid_p=*/false)
+				   /*current_scope_valid_p=*/false,
+				   /*object_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `delete' keyword.  */
   cp_parser_require_keyword (parser, RID_DELETE, "`delete'");
@@ -8022,7 +8068,8 @@ cp_parser_mem_initializer_id (cp_parser*
   /* Look for the optional `::' operator.  */
   global_scope_p
     = (cp_parser_global_scope_opt (parser,
-				   /*current_scope_valid_p=*/false)
+				   /*current_scope_valid_p=*/false,
+				   /*object_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the optional nested-name-specifier.  The simplest way to
      implement:
@@ -8594,7 +8641,8 @@ cp_parser_type_parameter (cp_parser* par
 					 /*check_dependency_p=*/true,
 					 /*template_p=*/&is_template,
 					 /*declarator_p=*/false,
-					 /*optional_p=*/false);
+					 /*optional_p=*/false,
+					 /*member_p=*/false);
 	    if (TREE_CODE (default_argument) == TYPE_DECL)
 	      /* If the id-expression was a template-id that refers to
 		 a template-class, we already have the declaration here,
@@ -9159,7 +9207,8 @@ cp_parser_template_argument (cp_parser* 
 				      /*check_dependency_p=*/true,
 				      &template_p,
 				      /*declarator_p=*/false,
-				      /*optional_p=*/false);
+				      /*optional_p=*/false,
+				      /*member_p=*/false);
   /* If the next token isn't a `,' or a `>', then this argument wasn't
      really finished.  */
   if (!cp_parser_next_token_ends_template_argument_p (parser))
@@ -9799,7 +9848,8 @@ cp_parser_simple_type_specifier (cp_pars
       /* Look for the optional `::' operator.  */
       global_p
 	= (cp_parser_global_scope_opt (parser,
-				       /*current_scope_valid_p=*/false)
+				       /*current_scope_valid_p=*/false,
+				       /*object_scope_valid_p=*/false)
 	   != NULL_TREE);
       /* Look for the nested-name specifier.  */
       qualified_p
@@ -10024,7 +10074,8 @@ cp_parser_elaborated_type_specifier (cp_
 
   /* Look for the `::' operator.  */
   cp_parser_global_scope_opt (parser,
-			      /*current_scope_valid_p=*/false);
+			      /*current_scope_valid_p=*/false,
+			      /*object_scope_valid_p=*/false);
   /* Look for the nested-name-specifier.  */
   if (tag_type == typename_type)
     {
@@ -10559,7 +10610,8 @@ cp_parser_qualified_namespace_specifier 
 {
   /* Look for the optional `::'.  */
   cp_parser_global_scope_opt (parser,
-			      /*current_scope_valid_p=*/false);
+			      /*current_scope_valid_p=*/false,
+			      /*object_scope_valid_p=*/false);
 
   /* Look for the optional nested-name-specifier.  */
   cp_parser_nested_name_specifier_opt (parser,
@@ -10604,7 +10656,8 @@ cp_parser_using_declaration (cp_parser* 
   /* Look for the optional global scope qualification.  */
   global_scope_p
     = (cp_parser_global_scope_opt (parser,
-				   /*current_scope_valid_p=*/false)
+				   /*current_scope_valid_p=*/false,
+				   /*object_scope_valid_p=*/false)
        != NULL_TREE);
 
   /* If we saw `typename', or didn't see `::', then there must be a
@@ -10630,7 +10683,8 @@ cp_parser_using_declaration (cp_parser* 
 					 /*template_keyword_p=*/false,
 					 /*check_dependency_p=*/true,
 					 /*declarator_p=*/true,
-					 /*optional_p=*/false);
+					 /*optional_p=*/false,
+					 /*member_p=*/false);
 
   /* The function we call to handle a using-declaration is different
      depending on what scope we are in.  */
@@ -10684,7 +10738,8 @@ cp_parser_using_directive (cp_parser* pa
   /* And the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
   /* Look for the optional `::' operator.  */
-  cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
+  cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
+			      /*object_scope_valid_p=*/false);
   /* And the optional nested-name-specifier.  */
   cp_parser_nested_name_specifier_opt (parser,
 				       /*typename_keyword_p=*/false,
@@ -11752,7 +11807,8 @@ cp_parser_ptr_operator (cp_parser* parse
       cp_parser_parse_tentatively (parser);
       /* Look for the optional `::' operator.  */
       cp_parser_global_scope_opt (parser,
-				  /*current_scope_valid_p=*/false);
+				  /*current_scope_valid_p=*/false,
+				  /*object_scope_valid_p=*/false);
       /* Look for the nested-name specifier.  */
       cp_parser_nested_name_specifier (parser,
 				       /*typename_keyword_p=*/false,
@@ -11892,7 +11948,8 @@ cp_parser_declarator_id (cp_parser* pars
 				/*check_dependency_p=*/false,
 				/*template_p=*/NULL,
 				/*declarator_p=*/true,
-				optional_p);
+				optional_p,
+				/*member_p=*/false);
   if (id && BASELINK_P (id))
     id = BASELINK_FUNCTIONS (id);
   return id;
@@ -13097,7 +13154,8 @@ cp_parser_class_head (cp_parser* parser,
      issuing an error about it later if this really is a
      class-head.  If it turns out just to be an elaborated type
      specifier, remain silent.  */
-  if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false))
+  if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
+				  /*object_scope_valid_p=*/false))
     qualified_p = true;
 
   push_deferring_access_checks (dk_no_check);
@@ -14083,7 +14141,8 @@ cp_parser_base_specifier (cp_parser* par
     }
 
   /* Look for the optional `::' operator.  */
-  cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
+  cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
+			      /*object_scope_valid_p=*/false);
   /* Look for the nested-name-specifier.  The simplest way to
      implement:
 
@@ -15132,7 +15191,8 @@ cp_parser_check_template_parameters (cp_
    present, and NULL_TREE otherwise.  */
 
 static tree
-cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p)
+cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p,
+			    bool object_scope_valid_p)
 {
   cp_token *token;
 
@@ -15151,12 +15211,15 @@ cp_parser_global_scope_opt (cp_parser* p
 
       return parser->scope;
     }
-  else if (!current_scope_valid_p)
+
+  if (!current_scope_valid_p)
     {
       parser->scope = NULL_TREE;
       parser->qualifying_scope = NULL_TREE;
-      parser->object_scope = NULL_TREE;
     }
+  
+  if (!object_scope_valid_p)
+    parser->object_scope = NULL_TREE;
 
   return NULL_TREE;
 }
@@ -15194,7 +15257,8 @@ cp_parser_constructor_declarator_p (cp_p
 
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser,
-			      /*current_scope_valid_p=*/false);
+			      /*current_scope_valid_p=*/false,
+			      /*object_scope_valid_p=*/false);
   /* Look for the nested-name-specifier.  */
   nested_name_p
     = (cp_parser_nested_name_specifier_opt (parser,
@@ -17901,7 +17965,8 @@ cp_parser_omp_var_list_no_open (cp_parse
 				      /*check_dependency_p=*/true,
 				      /*template_p=*/NULL,
 				      /*declarator_p=*/false,
-				      /*optional_p=*/false);
+				      /*optional_p=*/false,
+				      /*member_p=*/false);
       if (name == error_mark_node)
 	goto skip_comma;
 
Index: testsuite/g++.dg/parse/dtor12.C
===================================================================
--- testsuite/g++.dg/parse/dtor12.C	(revision 0)
+++ testsuite/g++.dg/parse/dtor12.C	(revision 0)
@@ -0,0 +1,15 @@
+// Copyright (C) 2006 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 1 Sep 2006 <nathan@codesourcery.com>
+
+// PR 23287: Failure to parse dependent dtor name
+// Origin:Wolfgang Bangerth  <bangerth@dealii.org>
+
+
+template <class T> struct A {}; 
+ 
+template <class T> void f(A<T> *ptr) { 
+  ptr->~A(); 
+}
+
+template void f<void> (A<void> *);
+

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