This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH] Change order of tentative parsing in cp_parser_postfix_dot_deref_expression (PR c++/35138)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Manuel López-Ibáñez <lopezibanez at gmail dot com>
- Cc: Mark Mitchell <mark at codesourcery dot com>, Jason Merrill <jason at redhat dot com>, gcc-patches at gcc dot gnu dot org
- Date: Tue, 12 Feb 2008 14:41:30 -0500
- Subject: Re: [C++ PATCH] Change order of tentative parsing in cp_parser_postfix_dot_deref_expression (PR c++/35138)
- References: <20080212175402.GG24887@devserv.devel.redhat.com> <6c33472e0802121007g61d7e1c5v8dddd80f28a1d084@mail.gmail.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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