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]

Re: [C++ PATCH] Change order of tentative parsing in cp_parser_postfix_dot_deref_expression (PR c++/35138)


On Tue, Feb 12, 2008 at 07:07:18PM +0100, Manuel López-Ibáñez wrote:
> On 12/02/2008, Jakub Jelinek <jakub@redhat.com> wrote:
> > Hi!
> >
> > To fix PR32384, I have changed 3 months ago
> > cp_parser_postfix_dot_deref_expression, if postfix-expression is dependent,
> > to parse it tentatively as pseudo-dtor first and if that fails do what it
> > did before, parse as id-expression.  Unfortunately it turns out that even
> > tentative parsing isn't silent and sometimes emits errors unconditionally,
> > and limiting the PR20293 errors to definitive parse or when committed to
> > tentative parse resulted in many regressions.
> 
> Can't cp_parser_pseudo_destructor_name parse the expression without
> checking types (perhaps even without lookup invocation) and if there
> is no CPP_COMPL token return immediately? Am I missing a case here?

If you mean something like attached patch, then that works too.
To me it looks uglier though, because it repeats part of
cp_parser_type_name/cp_parser_class_name to skip over tokens
cp_parser_type_name would consume.

Regtested on x86_64-linux.

2008-02-12  Jakub Jelinek  <jakub@redhat.com>

	PR c++/35138
	* parser.c (cp_parser_pseudo_destructor_name): If next token
	is not ~, don't call cp_parser_type_name until it is verified
	that ::~ follows the type name.

	* g++.dg/template/member8.C: New test.

--- gcc/cp/parser.c.jj	2008-02-12 14:49:55.000000000 +0100
+++ gcc/cp/parser.c	2008-02-12 20:14:25.000000000 +0100
@@ -5164,11 +5164,43 @@ cp_parser_pseudo_destructor_name (cp_par
      additional qualification.  */
   else if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMPL))
     {
-      /* Look for the type-name.  */
-      *scope = TREE_TYPE (cp_parser_type_name (parser));
+      /* If postfix-expression before . or -> token was dependent,
+	 this might be actually a normal class access rather than
+	 pseudo destructor.  As cp_parser_type_name can report
+	 errors, first make sure the type name is followed
+	 by `::~'.  */
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      if (token->type != CPP_NAME && token->type != CPP_TEMPLATE_ID)
+	{
+	  cp_parser_error (parser, "expected class-name");
+	  return;
+	}
 
-      if (*scope == error_mark_node)
-	return;
+      cp_parser_parse_tentatively (parser);
+
+      if (token->type == CPP_NAME
+	  && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
+	{
+	  tree identifier = cp_parser_identifier (parser);
+	  if (identifier == error_mark_node)
+	    {
+	      cp_parser_abort_tentative_parse (parser);
+	      cp_parser_error (parser, "expected class-name");
+	      return;
+	    }
+	}
+      else
+	{
+	  tree decl = cp_parser_template_id (parser,
+					     /*template_keyword_p=*/false,
+					     /*check_dependency_p=*/true,
+					     /*is_declaration=*/false);
+	  if (decl == error_mark_node)
+	    {
+	      cp_parser_abort_tentative_parse (parser);
+	      return;
+	    }
+	}
 
       /* If we don't have ::~, then something has gone wrong.  Since
 	 the only caller of this function is looking for something
@@ -5178,10 +5210,19 @@ cp_parser_pseudo_destructor_name (cp_par
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE)
 	  || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_COMPL)
 	{
+	  cp_parser_abort_tentative_parse (parser);
 	  cp_parser_error (parser, "request for member of non-aggregate type");
 	  return;
 	}
 
+      cp_parser_abort_tentative_parse (parser);
+
+      /* Look for the type-name.  */
+      *scope = TREE_TYPE (cp_parser_type_name (parser));
+
+      if (*scope == error_mark_node)
+	return;
+
       /* Look for the `::' token.  */
       cp_parser_require (parser, CPP_SCOPE, "`::'");
     }
--- gcc/testsuite/g++.dg/template/member8.C.jj	2008-02-12 18:32:14.000000000 +0100
+++ gcc/testsuite/g++.dg/template/member8.C	2008-02-12 18:19:23.000000000 +0100
@@ -0,0 +1,25 @@
+// PR c++/35138
+// { dg-do compile }
+
+namespace N1 { struct A { }; }
+namespace N2 { struct A { }; }
+using namespace N1;
+using namespace N2;
+
+template <typename T> int
+foo (T const &t)
+{
+  return t.A;
+}
+
+struct B
+{
+  int A;
+};
+
+int
+main ()
+{
+  B b;
+  foo (b);
+}


	Jakub


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