Hi,

this is a completely different approach at fixing the bug, which overall I like better.

In this case most of the patch touches cp_parser_decltype_expr: instead of using cp_parser_postfix_expression only for member access expressions, we accept all its valid return values (still identifying the member access expressions, of course, because the semantics of decltype is special for those). Thus we can also immediately accept the pseudo destructor calls which are the matter of this bug. Otherwise, as a last resort, if the expression at issue isn't a postfix expression at all, we use cp_parser_expression.

Patch works better than my previous try from the diagnostic point of view (eg, for c++/47277 - type illegal expressions as arguments of the decltype) and seems less "hackish" to me. Also, it seems to me that it's a computational waste to redo the parsing of valid postfix-expressions != member access expression.

Tested x86_64-linux.

Thanks!
Paolo.

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

        PR c++/58633
        * parser.c (cp_parser_decltype_expr): Restructure parsing of
        expressions != id-expressions.
        (cp_parser_postfix_expression, cp_parser_unary_expression): Adjust.

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

        PR c++/58633
        * g++.dg/cpp0x/decltype57.C: New.
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 203308)
+++ cp/parser.c (working copy)
@@ -1857,7 +1857,7 @@ static tree cp_parser_nested_name_specifier
 static tree cp_parser_qualifying_entity
   (cp_parser *, bool, bool, bool, bool, bool);
 static tree cp_parser_postfix_expression
-  (cp_parser *, bool, bool, bool, bool, cp_id_kind *);
+  (cp_parser *, bool, bool, bool, bool&, cp_id_kind *);
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool, bool);
 static tree cp_parser_postfix_dot_deref_expression
@@ -5531,14 +5531,14 @@ cp_parser_qualifying_entity (cp_parser *parser,
    `&' operator.  CAST_P is true if this expression is the target of a
    cast.
 
-   If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are
-   class member access expressions [expr.ref].
+   If IS_MEMBER_ACCESS is false, we are not returning a class member
+   access expression [expr.ref].
 
    Returns a representation of the expression.  */
 
 static tree
 cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
-                              bool member_access_only_p, bool decltype_p,
+                              bool decltype_p, bool& is_member_access,
                              cp_id_kind * pidk_return)
 {
   cp_token *token;
@@ -5546,7 +5546,7 @@ cp_parser_postfix_expression (cp_parser *parser, b
   enum rid keyword;
   cp_id_kind idk = CP_ID_KIND_NONE;
   tree postfix_expression = NULL_TREE;
-  bool is_member_access = false;
+  is_member_access = false;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -6066,10 +6066,7 @@ cp_parser_postfix_expression (cp_parser *parser, b
        default:
          if (pidk_return != NULL)
            * pidk_return = idk;
-          if (member_access_only_p)
-            return is_member_access? postfix_expression : error_mark_node;
-          else
-            return postfix_expression;
+         return postfix_expression;
        }
     }
 
@@ -7003,9 +7000,9 @@ cp_parser_unary_expression (cp_parser *parser, boo
       return expression;
     }
 
+  bool is_member_access;
   return cp_parser_postfix_expression (parser, address_p, cast_p,
-                                       /*member_access_only_p=*/false,
-                                      decltype_p,
+                                      decltype_p, is_member_access,
                                       pidk);
 }
 
@@ -11678,33 +11675,42 @@ cp_parser_decltype_expr (cp_parser *parser,
         id_expression_or_member_access_p = true;
     }
 
-  if (!id_expression_or_member_access_p)
+  if (id_expression_or_member_access_p)
     {
-      /* Abort the id-expression parse.  */
-      cp_parser_abort_tentative_parse (parser);
+      /* We have parsed an id-expression.  */
+      cp_parser_parse_definitely (parser);
+      return expr;
+    }
 
-      /* Parsing tentatively, again.  */
-      cp_parser_parse_tentatively (parser);
+  /* Abort the id-expression parse.  */
+  cp_parser_abort_tentative_parse (parser);
 
-      /* Parse a class member access.  */
-      expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
-                                           /*cast_p=*/false, /*decltype*/true,
-                                           /*member_access_only_p=*/true, 
NULL);
+  /* Parsing tentatively, again.  */
+  cp_parser_parse_tentatively (parser);
 
-      if (expr 
-          && expr != error_mark_node
-          && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
-        /* We have an id-expression.  */
-        id_expression_or_member_access_p = true;
-    }
+  /* Parse a postfix expression.  */
+  bool is_member_access;
+  expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
+                                      /*cast_p=*/false,
+                                      /*decltype_p*/true,
+                                      is_member_access, NULL);
 
-  if (id_expression_or_member_access_p)
-    /* We have parsed the complete id-expression or member access.  */
+  bool postfix_expression_ok_p =
+    (expr && expr != error_mark_node
+     && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN);
+
+  if (postfix_expression_ok_p
+      && is_member_access)
+    id_expression_or_member_access_p = true;
+
+  if (postfix_expression_ok_p)
+    /* We have parsed a member access or a different kind of valid
+       postfix expression, eg, a pseudo destructor call [expr.pseudo]
+       (c++/58633).  */
     cp_parser_parse_definitely (parser);
   else
     {
-      /* Abort our attempt to parse an id-expression or member access
-         expression.  */
+      /* Abort our attempt to parse a postfix-expression.  */
       cp_parser_abort_tentative_parse (parser);
 
       /* Parse a full expression.  */
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