From 20c28f711e4f7f210ee1b1307e3ae19436f100cb Mon Sep 17 00:00:00 2001
From: Adam Butcher <dev.lists@jessamine.co.uk>
Date: Thu, 20 Jan 2011 14:11:53 +0000
Subject: [PATCH] [C++0x] Support decltype as base-specifier.

---
 gcc/cp/parser.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 56 insertions(+), 7 deletions(-)

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 41f82ac..d67dd51 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -18221,7 +18221,7 @@ cp_parser_base_clause (cp_parser* parser)
   return nreverse (bases);
 }
 
-/* Parse a base-specifier.
+/* Parse a base-specifier. [gram.derived]
 
    base-specifier:
      :: [opt] nested-name-specifier [opt] class-name
@@ -18230,6 +18230,24 @@ cp_parser_base_clause (cp_parser* parser)
      access-specifier virtual [opt] :: [opt] nested-name-specifier
        [opt] class-name
 
+   C++0x grammar:
+
+   Note: Attribute specifiers are currently unsupported.
+
+   base-specifier:
+     attribute-specifier [opt] base-type-specifier
+     attribute-specifier [opt] `virtual' access-specifier [opt]
+        base-type-specifier
+     attribute-specifier [opt] access-specifier `virtual' [opt]
+        base-type-specifier
+
+   class-or-decltype:
+     :: [opt] nested-name-specifier [opt] class-name
+     decltype-specifier
+
+   base-type-specifier:
+     class-or-decltype
+
    Returns a TREE_LIST.  The TREE_PURPOSE will be one of
    ACCESS_{DEFAULT,PUBLIC,PROTECTED,PRIVATE}_[VIRTUAL]_NODE to
    indicate the specifiers provided.  The TREE_VALUE will be a TYPE
@@ -18247,6 +18265,18 @@ cp_parser_base_specifier (cp_parser* parser)
   tree access = access_default_node;
   tree type;
 
+  /* Decltype could arise at the start of a nested-name-specifier so
+     a lone decltype is looked for on the condition that neither a
+     global-scope operator nor nested-name-specifier is found.  Also,
+     of course, this is C++0x only.
+     XXX: Note, g++ currently does not support decltype appearing in a
+     XXX: a nested-name-specifier but this implementation should be
+     XXX: compatible with future update providing such support. */
+  bool look_for_lone_decltype = cxx_dialect >= cxx0x;
+
+  /* TODO: Support optional `attribute-specifier' when cxx_dialect >=
+     cxx0x. */
+
   /* Process the optional `virtual' and `access-specifier'.  */
   while (!done)
     {
@@ -18313,7 +18343,9 @@ cp_parser_base_specifier (cp_parser* parser)
     }
 
   /* Look for the optional `::' operator.  */
-  cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
+  look_for_lone_decltype &= NULL_TREE == 
+    cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
+
   /* Look for the nested-name-specifier.  The simplest way to
      implement:
 
@@ -18326,11 +18358,28 @@ cp_parser_base_specifier (cp_parser* parser)
 
      is to pretend that we have seen the `typename' keyword at this
      point.  */
-  cp_parser_nested_name_specifier_opt (parser,
-				       /*typename_keyword_p=*/true,
-				       /*check_dependency_p=*/true,
-				       typename_type,
-				       /*is_declaration=*/true);
+  look_for_lone_decltype &= NULL_TREE ==
+    cp_parser_nested_name_specifier_opt (parser,
+				         /*typename_keyword_p=*/true,
+				         /*check_dependency_p=*/true,
+				         typename_type,
+				         /*is_declaration=*/true);
+
+  /* Return early if a lone decltype is found. */
+  if (look_for_lone_decltype)
+    {
+      if (cp_lexer_next_token_is_keyword (parser->lexer,
+					  RID_DECLTYPE))
+	{
+	  type = cp_parser_decltype (parser);
+
+	  if (type == error_mark_node)
+	    return error_mark_node;
+
+	  return finish_base_specifier (type, access, virtual_p);
+	}
+    }
+
   /* If the base class is given by a qualified name, assume that names
      we see are type names or templates, as appropriate.  */
   class_scope_p = (parser->scope && TYPE_P (parser->scope));
-- 
1.7.2

