]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/23287 (Explicitly invoking destructor of template class in a template and...
authorNathan Sidwell <nathan@codesourcery.com>
Fri, 1 Sep 2006 13:46:19 +0000 (13:46 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 1 Sep 2006 13:46:19 +0000 (13:46 +0000)
cp/
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.
testsuite/
PR c++/23287
* g++.dg/parse/dtor12.C: New.

From-SVN: r116623

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/dtor12.C [new file with mode: 0644]

index 5311778db8bdd19433c643f431cca80bc308b30d..bb2e8415f3ae56640acc75f613fce8dbf059b765 100644 (file)
@@ -1,3 +1,15 @@
+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-08-30  Jason Merrill  <jason@redhat.com>
 
        PR c++/26670
index 5271113485a7c2775fa4e2a45e11c543e18af360..2e2885691023a86d2b2edd62471459ac2c94061a 100644 (file)
@@ -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_parameters
 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_type_name (cp_parser *parser)
                                /*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 *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 *parser,
                         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 *parser,
 
   /* 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 *parser,
       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 *parser,
   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* parser,
                          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* parser,
            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* parser,
            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 (cp_parser *parser,
   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 (cp_parser *parser,
          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 (cp_parser *parser,
       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 (cp_parser *parser,
               /*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_parser* parser,
   *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* 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 `new' operator.  */
   cp_parser_require_keyword (parser, RID_NEW, "`new'");
@@ -5367,7 +5412,8 @@ cp_parser_delete_expression (cp_parser* 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* 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* parser)
                                         /*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* 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_parser* parser,
       /* 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_parser* parser,
 
   /* 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 (cp_parser* parser)
 {
   /* 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* 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* 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* parser)
   /* 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* parser,
       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* parser, bool optional_p)
                                /*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* parser)
     }
 
   /* 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_parser* parser,
    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* parser, bool current_scope_valid_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_parser *parser, bool friend_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_parser *parser, enum omp_clause_code kind,
                                      /*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 79d9de4e4ce79fd0134258696318901de197f5f8..c8081f65fb2b1e979c9f149aa6e5bbbc25af6f23 100644 (file)
@@ -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 1a3ecb598edcad16a216d4fa2f66715ddefe387f..cec12fabecb9a5374306f6c4d9cd9107123ae2dd 100644 (file)
@@ -1,3 +1,8 @@
+2006-09-01  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/23287
+       * g++.dg/parse/dtor12.C: New.
+
 2006-08-31  Zdenek Dvorak <dvorakz@suse.cz>
 
        PR tree-optimization/28839
diff --git a/gcc/testsuite/g++.dg/parse/dtor12.C b/gcc/testsuite/g++.dg/parse/dtor12.C
new file mode 100644 (file)
index 0000000..d964662
--- /dev/null
@@ -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> *);
+