Hi,

in this ICE on valid, 4.7/4.8/4.9 Regression, the ICE happens in the second half of cp_parser_decltype_expr, when cp_parser_abort_tentative_parse is called in an inconstent status: tentative parsing is committed and no errors. The reason is the following: in its main loop cp_parser_postfix_expression calls cp_parser_postfix_dot_deref_expression which in turns calls cp_parser_pseudo_destructor_name and everything appears to be fine, thus the latter commits the tentative parse, but member_access_only_p is *true* in the first half of cp_parser_decltype_expr and even if cp_parser_postfix_expression later also finds valid () following the pseudo dtor expression has to return error_mark_node anyway.

A possible way to resolve the inconsistency is propagating member_access_only_p past cp_parser_postfix_expression to cp_parser_pseudo_destructor_name and in the latter not committing the tentative parse when the flag is true.

Tested x86_64-linux.

Thanks,
Paolo.

///////////////////////////
/cp
2013-10-08  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/58633
        * parser.c (cp_parser_postfix_dot_deref_expression,
        cp_parser_pseudo_destructor_name): Add bool parameter.
        (cp_parser_postfix_expression, cp_parser_builtin_offsetof):
        Adjust.

/testsuite
2013-10-08  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/58633
        * g++.dg/cpp0x/decltype57.C: New.
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 203274)
+++ cp/parser.c (working copy)
@@ -1861,13 +1861,13 @@ static tree cp_parser_postfix_expression
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool, bool);
 static tree cp_parser_postfix_dot_deref_expression
-  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
+  (cp_parser *, enum cpp_ttype, tree, bool, bool, cp_id_kind *, location_t);
 static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
   (cp_parser *, int, bool, bool, bool *);
 /* Values for the second parameter of cp_parser_parenthesized_expression_list. 
 */
 enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
-  (cp_parser *, tree, tree *, tree *);
+  (cp_parser *, tree, tree *, tree *, bool);
 static tree cp_parser_unary_expression
   (cp_parser *, bool, bool, cp_id_kind *);
 static enum tree_code cp_parser_unary_operator
@@ -6028,7 +6028,9 @@ cp_parser_postfix_expression (cp_parser *parser, b
          postfix_expression
            = cp_parser_postfix_dot_deref_expression (parser, token->type,
                                                      postfix_expression,
-                                                     false, &idk, loc);
+                                                     false,
+                                                     member_access_only_p,
+                                                     &idk, loc);
 
           is_member_access = true;
          break;
@@ -6261,7 +6263,9 @@ static tree
 cp_parser_postfix_dot_deref_expression (cp_parser *parser,
                                        enum cpp_ttype token_type,
                                        tree postfix_expression,
-                                       bool for_offsetof, cp_id_kind *idk,
+                                       bool for_offsetof,
+                                       bool member_access_only_p,
+                                       cp_id_kind *idk,
                                        location_t location)
 {
   tree name;
@@ -6337,7 +6341,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser
       /* Parse the pseudo-destructor-name.  */
       s = NULL_TREE;
       cp_parser_pseudo_destructor_name (parser, postfix_expression,
-                                       &s, &type);
+                                       &s, &type, member_access_only_p);
       if (dependent_p
          && (cp_parser_error_occurred (parser)
              || !SCALAR_TYPE_P (type)))
@@ -6610,7 +6614,8 @@ static void
 cp_parser_pseudo_destructor_name (cp_parser* parser,
                                  tree object,
                                  tree* scope,
-                                 tree* type)
+                                 tree* type,
+                                 bool member_access_only_p)
 {
   bool nested_name_specifier_p;
 
@@ -6692,7 +6697,15 @@ cp_parser_pseudo_destructor_name (cp_parser* parse
   cp_parser_require (parser, CPP_COMPL, RT_COMPL);
 
   /* Once we see the ~, this has to be a pseudo-destructor.  */
-  if (!processing_template_decl && !cp_parser_error_occurred (parser))
+  if (!processing_template_decl && !cp_parser_error_occurred (parser)
+      /* ... but we don't want to prematurely commit when only
+        member access expressions are allowed.  This happens
+        when parsing a decltype, because pseudo destructor
+        calls (5.2.4) are handled by cp_parser_decltype_expr
+        via the final cp_parser_expression (which eventually
+        calls cp_parser_postfix_expression with a false
+        member_access_only_p) (c++/58633).  */
+      && !member_access_only_p)
     cp_parser_commit_to_tentative_parse (parser);
 
   /* Look for the type-name again.  We are not responsible for
@@ -8258,8 +8271,9 @@ cp_parser_builtin_offsetof (cp_parser *parser)
                             tf_warning_or_error);
 
   /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
-  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
-                                                true, &dummy, token->location);
+  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr, true,
+                                                /*member_access_only_p=*/false,
+                                                &dummy, token->location);
   while (true)
     {
       token = cp_lexer_peek_token (parser->lexer);
@@ -8280,9 +8294,9 @@ cp_parser_builtin_offsetof (cp_parser *parser)
        case CPP_DOT:
          /* offsetof-member-designator "." identifier */
          cp_lexer_consume_token (parser->lexer);
-         expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT,
-                                                        expr, true, &dummy,
-                                                        token->location);
+         expr = (cp_parser_postfix_dot_deref_expression
+                 (parser, CPP_DOT, expr, true, /*member_access_only_p=*/false,
+                  &dummy, token->location));
          break;
 
        case CPP_CLOSE_PAREN:
Index: testsuite/g++.dg/cpp0x/decltype57.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype57.C (revision 0)
+++ testsuite/g++.dg/cpp0x/decltype57.C (working copy)
@@ -0,0 +1,8 @@
+// PR c++/58633
+// { dg-do compile { target c++11 } }
+
+void foo(int i)
+{
+  typedef int I;
+  decltype(i.I::~I())* p;
+}

Reply via email to