re PR c++/15503 (nested template problem)
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>
Sun, 6 Jun 2004 02:08:18 +0000 (02:08 +0000)
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>
Sun, 6 Jun 2004 02:08:18 +0000 (02:08 +0000)
PR c++/15503
* parser.c (cp_parser_mem_initializer_id): Gracefully reject
'typename', and accept 'template'.

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

From-SVN: r82660

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/meminit2.C [new file with mode: 0644]

index 75aa42f91a87eacb54740ed7eaa575a7f573aaab..8ec1302e035a2057f69662b5d84dec9c136a5ae3 100644 (file)
@@ -1,3 +1,9 @@
+2004-06-06  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
+
+       PR c++/15503
+       * parser.c (cp_parser_mem_initializer_id): Gracefully reject
+       'typename', and accept 'template'.
+
 2004-06-03  Andrew Pinski  <pinskia@physics.uc.edu>
            Jan Hubicka  <jh@suse.cz>
 
index d7253f0a74b9b7a84d722002065d1dd2138529f4..0c94f7102db6fe1254f1320b1a3fccdb4b52e460 100644 (file)
@@ -7383,8 +7383,16 @@ cp_parser_mem_initializer_id (cp_parser* parser)
 {
   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,
@@ -7409,12 +7417,14 @@ cp_parser_mem_initializer_id (cp_parser* parser)
                                            /*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=*/false,
+                                /*template_keyword_p=*/template_p,
                                 /*type_p=*/false,
                                 /*check_dependency_p=*/true,
                                 /*class_head_p=*/false,
index d316dfc61518c199a9cc2f3b974e7e5641ebac3f..197242d2bee90dae9fba828351f22231d7ab4161 100644 (file)
@@ -1,3 +1,8 @@
+2004-06-06  Giovanni Bajo  <giovannibajo@gcc.gnu.org>
+
+       PR c++/15503
+       * g++.dg/template/meminit2.C: New test.
+
 2004-06-04  Paolo Bonzini  <bonzini@gnu.org>
 
        PR target/15822
diff --git a/gcc/testsuite/g++.dg/template/meminit2.C b/gcc/testsuite/g++.dg/template/meminit2.C
new file mode 100644 (file)
index 0000000..6abf2df
--- /dev/null
@@ -0,0 +1,21 @@
+// { 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 }