+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>
{
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,
/*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,
--- /dev/null
+// { 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 }