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]

[C++ PATCH] [PR15503] Accept 'template' in mem-initializer-id


Hello,

PR 15503 is about DR 343, which is about allowing 'template' in
mem-initializer-id expressions. The testcase attacched to this bug shows a
situation where there is no legal way to do what the user wants, given the
current standard. The DR is still open but we need to take a decision now,
since we have a regression from previous GCC versions where we used to accept
the code. It is common understanding that the committee will allow the code to
be *legal* one way or the other: Mark suggests in the PR that probably both the
version with 'template' and the version without will be made legal.

As a stop-gap for the release branch, I'm proposing this patch which makes the
version with 'template' legal. At least, we give the user one way to do what
she wants. If we want to experiment with the DR supposed resolution, we can do
it on mainline.

While doing this, I also exposed a latent bug in the code that skips to the end
of the expression (which must be probably tuned for the member initializer
case), in case the 'template' keyword is needed but missing: it results in too
eager skipping which makes the parser unable to continue its job. I didn't
bother investigating this at this point, so I handled it with dg-bogus,
xfailed.

Moreover, since I was at it, I also improved the error message to reject the
'typename' keyword in member initializers, as mandated by [temp.res]/5.

Tested on i686-pc-linux-gnu, OK for mainline and 3.4.1?

Giovanni Bajo


cp/
        PR c++/15503
        * parser.c (cp_parser_mem_initializer_id): Gracefully reject
        'typename', and accept 'template'.

testsuite/
        PR c++/15503
        * g++.dg/template/meminit2.C: New test.


Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.192
diff -c -3 -p -r1.192 parser.c
*** parser.c 13 May 2004 06:40:19 -0000 1.192
--- parser.c 1 Jun 2004 02:05:03 -0000
*************** cp_parser_mem_initializer_id (cp_parser*
*** 7279,7286 ****
--- 7281,7296 ----
  {
    bool global_scope_p;
    bool nested_name_specifier_p;
+   bool template_p = false;
    tree id;

+   /* `typename' is not allowed in this context ([temp.res]).  */
+   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
+     {
+       error ("keyword `typename' not allowed in this context (a qualified "
+       "member initializer is implicitly a type)");
+       cp_lexer_consume_token (parser->lexer);
+     }
    /* Look for the optional `::' operator.  */
    global_scope_p
      = (cp_parser_global_scope_opt (parser,
*************** cp_parser_mem_initializer_id (cp_parser*
*** 7305,7316 ****
           /*type_p=*/true,
           /*is_declaration=*/true)
         != NULL_TREE);
    /* If there is a `::' operator or a nested-name-specifier, then we
       are definitely looking for a class-name.  */
    if (global_scope_p || nested_name_specifier_p)
      return cp_parser_class_name (parser,
       /*typename_keyword_p=*/true,
!      /*template_keyword_p=*/false,
       /*type_p=*/false,
       /*check_dependency_p=*/true,
       /*class_head_p=*/false,
--- 7315,7328 ----
           /*type_p=*/true,
           /*is_declaration=*/true)
         != NULL_TREE);
+   if (nested_name_specifier_p)
+     template_p = cp_parser_optional_template_keyword (parser);
    /* If there is a `::' operator or a nested-name-specifier, then we
       are definitely looking for a class-name.  */
    if (global_scope_p || nested_name_specifier_p)
      return cp_parser_class_name (parser,
       /*typename_keyword_p=*/true,
!      /*template_keyword_p=*/template_p,
       /*type_p=*/false,
       /*check_dependency_p=*/true,
       /*class_head_p=*/false,



// { dg-do compile }
// Origin: Mark Anders <mark dot a dot anders at intel dot com>
// PR c++/15503: disambiguators in base classes and mem-initializers

template <typename K1> struct O {
  template <typename K2> struct I {};
};

template <typename T>
struct A : typename O<T>::template I<int> {   // { dg-error "keyword `typename'
not allowed" }
  A() :    typename O<T>::template I<int>()   // { dg-error "keyword `typename'
not allowed" }
  {};
};

template <typename T>
struct B : O<T>::template I<int> {
  B() :    O<T>::I<int>()   // { dg-error "used as template|it is a template"
"" }
  {};
};

// { dg-bogus "end of input" "bogus token skipping in the parser" { xfail
*-*-* } 17 }



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