diff mbox

[C++] PR 58633 (Take 2)

Message ID 52553FA7.6000906@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Oct. 9, 2013, 11:36 a.m. UTC
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.carlini@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.carlini@oracle.com>

	PR c++/58633
	* g++.dg/cpp0x/decltype57.C: New.

Comments

Jason Merrill Nov. 23, 2013, 10:45 p.m. UTC | #1
OK.
diff mbox

Patch

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;
+}