OSDN Git Service

* class.c (finish_struct_methods): Remove unncessary code.
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index fe3a3de..c60158c 100644 (file)
@@ -34,6 +34,7 @@
 #include "diagnostic.h"
 #include "toplev.h"
 #include "output.h"
+#include "target.h"
 
 \f
 /* The lexer.  */
@@ -58,7 +59,7 @@
 
    The parser routinely peeks at the next token, and then consumes it
    later.  That also requires a buffer in which to store the tokens.
-     
+
    In order to easily permit adding tokens to the end of the buffer,
    while removing them from the beginning of the buffer, we use a
    circular buffer.  */
@@ -72,6 +73,8 @@ typedef struct cp_token GTY (())
   /* If this token is a keyword, this value indicates which keyword.
      Otherwise, this value is RID_MAX.  */
   ENUM_BITFIELD (rid) keyword : 8;
+  /* Token flags.  */
+  unsigned char flags;
   /* The value associated with this token, if any.  */
   tree value;
   /* The location at which this token was found.  */
@@ -87,7 +90,7 @@ typedef struct cp_token GTY (())
    large numbers of tokens.  (For example, a token block is created
    when the body of an inline member function is first encountered;
    the tokens are processed later after the class definition is
-   complete.)  
+   complete.)
 
    This somewhat ungainly data structure (as opposed to, say, a
    variable-length array), is used due to constraints imposed by the
@@ -118,7 +121,7 @@ typedef struct cp_token_cache GTY (())
 
 /* Prototypes.  */
 
-static cp_token_cache *cp_token_cache_new 
+static cp_token_cache *cp_token_cache_new
   (void);
 static void cp_token_cache_push_token
   (cp_token_cache *, cp_token *);
@@ -165,19 +168,19 @@ typedef struct cp_lexer GTY (())
   /* The memory allocated for the buffer.  Never NULL.  */
   cp_token * GTY ((length ("(%h.buffer_end - %h.buffer)"))) buffer;
   /* A pointer just past the end of the memory allocated for the buffer.  */
-  cp_token * GTY ((skip (""))) buffer_end;
+  cp_token * GTY ((skip)) buffer_end;
   /* The first valid token in the buffer, or NULL if none.  */
-  cp_token * GTY ((skip (""))) first_token;
+  cp_token * GTY ((skip)) first_token;
   /* The next available token.  If NEXT_TOKEN is NULL, then there are
      no more available tokens.  */
-  cp_token * GTY ((skip (""))) next_token;
+  cp_token * GTY ((skip)) next_token;
   /* A pointer just past the last available token.  If FIRST_TOKEN is
      NULL, however, there are no available tokens, and then this
      location is simply the place in which the next token read will be
      placed.  If LAST_TOKEN == FIRST_TOKEN, then the buffer is full.
      When the LAST_TOKEN == BUFFER, then the last token is at the
      highest memory address in the BUFFER.  */
-  cp_token * GTY ((skip (""))) last_token;
+  cp_token * GTY ((skip)) last_token;
 
   /* A stack indicating positions at which cp_lexer_save_tokens was
      called.  The top entry is the most recent position at which we
@@ -221,7 +224,7 @@ static cp_token *cp_lexer_next_token
   (cp_lexer *, cp_token *);
 static cp_token *cp_lexer_prev_token
   (cp_lexer *, cp_token *);
-static ptrdiff_t cp_lexer_token_difference 
+static ptrdiff_t cp_lexer_token_difference
   (cp_lexer *, cp_token *, cp_token *);
 static cp_token *cp_lexer_read_token
   (cp_lexer *);
@@ -239,7 +242,7 @@ static bool cp_lexer_next_token_is_not
   (cp_lexer *, enum cpp_ttype);
 static bool cp_lexer_next_token_is_keyword
   (cp_lexer *, enum rid);
-static cp_token *cp_lexer_consume_token 
+static cp_token *cp_lexer_consume_token
   (cp_lexer *);
 static void cp_lexer_purge_token
   (cp_lexer *);
@@ -251,11 +254,11 @@ static void cp_lexer_commit_tokens
   (cp_lexer *);
 static void cp_lexer_rollback_tokens
   (cp_lexer *);
-static inline void cp_lexer_set_source_position_from_token 
+static inline void cp_lexer_set_source_position_from_token
   (cp_lexer *, const cp_token *);
 static void cp_lexer_print_token
   (FILE *, cp_token *);
-static inline bool cp_lexer_debugging_p 
+static inline bool cp_lexer_debugging_p
   (cp_lexer *);
 static void cp_lexer_start_debugging
   (cp_lexer *) ATTRIBUTE_UNUSED;
@@ -325,7 +328,7 @@ cp_lexer_new_main (void)
 
   /* Create the SAVED_TOKENS stack.  */
   VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
-  
+
   /* Create the STRINGS array.  */
   VARRAY_TREE_INIT (lexer->string_tokens, 32, "strings");
 
@@ -355,7 +358,7 @@ cp_lexer_new_from_tokens (cp_token_cache *tokens)
     num_tokens += block->num_tokens;
   lexer->buffer = ggc_alloc (num_tokens * sizeof (cp_token));
   lexer->buffer_end = lexer->buffer + num_tokens;
-  
+
   /* Install the tokens.  */
   token = lexer->buffer;
   for (block = tokens->first; block != NULL; block = block->next)
@@ -376,7 +379,7 @@ cp_lexer_new_from_tokens (cp_token_cache *tokens)
 
   /* Create the SAVED_TOKENS stack.  */
   VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
-  
+
   /* Create the STRINGS array.  */
   VARRAY_TREE_INIT (lexer->string_tokens, 32, "strings");
 
@@ -499,15 +502,25 @@ cp_lexer_read_token (cp_lexer* lexer)
   if ((token->type == CPP_STRING || token->type == CPP_WSTRING)
       && flag_const_strings)
     {
-      tree type;
+      if (c_lex_string_translate)
+       {
+         tree value = token->value;
+         tree type;
 
-      /* Get the current type.  It will be an ARRAY_TYPE.  */
-      type = TREE_TYPE (token->value);
-      /* Use build_cplus_array_type to rebuild the array, thereby
-        getting the right type.  */
-      type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type));
-      /* Reset the type of the token.  */
-      TREE_TYPE (token->value) = type;
+         /* We might as well go ahead and release the chained
+            translated string such that we can reuse its memory.  */
+         if (TREE_CHAIN (value))
+           value = TREE_CHAIN (token->value);
+
+         /* Get the current type.  It will be an ARRAY_TYPE.  */
+         type = TREE_TYPE (value);
+         /* Use build_cplus_array_type to rebuild the array, thereby
+            getting the right type.  */
+         type = build_cplus_array_type (TREE_TYPE (type),
+                                        TYPE_DOMAIN (type));
+         /* Reset the type of the token.  */
+         TREE_TYPE (value) = type;
+       }
     }
 
   return token;
@@ -534,9 +547,9 @@ cp_lexer_maybe_grow_buffer (cp_lexer* lexer)
       /* Compute the current buffer size.  */
       buffer_length = lexer->buffer_end - lexer->buffer;
       /* Allocate a buffer twice as big.  */
-      new_buffer = ggc_realloc (lexer->buffer, 
+      new_buffer = ggc_realloc (lexer->buffer,
                                2 * buffer_length * sizeof (cp_token));
-      
+
       /* Because the buffer is circular, logically consecutive tokens
         are not necessarily placed consecutively in memory.
         Therefore, we must keep move the tokens that were before
@@ -548,11 +561,11 @@ cp_lexer_maybe_grow_buffer (cp_lexer* lexer)
              num_tokens_to_copy * sizeof (cp_token));
       /* Clear the rest of the buffer.  We never look at this storage,
         but the garbage collector may.  */
-      memset (new_buffer + buffer_length + num_tokens_to_copy, 0, 
+      memset (new_buffer + buffer_length + num_tokens_to_copy, 0,
              (buffer_length - num_tokens_to_copy) * sizeof (cp_token));
 
       /* Now recompute all of the buffer pointers.  */
-      new_first_token 
+      new_first_token
        = new_buffer + (lexer->first_token - old_buffer);
       if (lexer->next_token != NULL)
        {
@@ -561,7 +574,7 @@ cp_lexer_maybe_grow_buffer (cp_lexer* lexer)
          if (lexer->next_token > lexer->first_token)
            next_token_delta = lexer->next_token - lexer->first_token;
          else
-           next_token_delta = 
+           next_token_delta =
              buffer_length - (lexer->first_token - lexer->next_token);
          lexer->next_token = new_first_token + next_token_delta;
        }
@@ -574,7 +587,7 @@ cp_lexer_maybe_grow_buffer (cp_lexer* lexer)
 
 /* Store the next token from the preprocessor in *TOKEN.  */
 
-static void 
+static void
 cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
                                  cp_token *token)
 {
@@ -584,8 +597,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
   if (lexer != NULL && !lexer->main_lexer_p)
     {
       token->type = CPP_EOF;
-      token->location.line = 0;
-      token->location.file = NULL;
+      token->location = UNKNOWN_LOCATION;
       token->value = NULL_TREE;
       token->keyword = RID_MAX;
 
@@ -597,7 +609,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
   while (!done)
     {
       /* Get a new token from the preprocessor.  */
-      token->type = c_lex (&token->value);
+      token->type = c_lex_with_flags (&token->value, &token->flags);
       /* Issue messages about tokens we cannot process.  */
       switch (token->type)
        {
@@ -617,7 +629,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
   token->location = input_location;
 
   /* Check to see if this token is a keyword.  */
-  if (token->type == CPP_NAME 
+  if (token->type == CPP_NAME
       && C_IS_RESERVED_WORD (token->value))
     {
       /* Mark this token as a keyword.  */
@@ -744,7 +756,7 @@ cp_lexer_consume_token (cp_lexer* lexer)
   token = lexer->next_token;
 
   /* Increment NEXT_TOKEN.  */
-  lexer->next_token = cp_lexer_next_token (lexer, 
+  lexer->next_token = cp_lexer_next_token (lexer,
                                           lexer->next_token);
   /* Check to see if we're all out of tokens.  */
   if (lexer->next_token == lexer->last_token)
@@ -782,7 +794,7 @@ cp_lexer_purge_token (cp_lexer *lexer)
   cp_token *next_token;
 
   token = lexer->next_token;
-  while (true) 
+  while (true)
     {
       next_token = cp_lexer_next_token (lexer, token);
       if (next_token == lexer->last_token)
@@ -885,7 +897,7 @@ cp_lexer_rollback_tokens (cp_lexer* lexer)
   delta = VARRAY_TOP_INT(lexer->saved_tokens);
   /* Make it the next token again now.  */
   lexer->next_token = cp_lexer_advance_token (lexer,
-                                             lexer->first_token, 
+                                             lexer->first_token,
                                              delta);
   /* It might be the case that there were no tokens when we started
      saving tokens, but that there are some tokens now.  */
@@ -958,10 +970,10 @@ cp_lexer_print_token (FILE * stream, cp_token* token)
   else
     fprintf (stream, "%d", token->type);
   /* And, for an identifier, print the identifier name.  */
-  if (token->type == CPP_NAME 
+  if (token->type == CPP_NAME
       /* Some keywords have a value that is not an IDENTIFIER_NODE.
         For example, `struct' is mapped to an INTEGER_CST.  */
-      || (token->type == CPP_KEYWORD 
+      || (token->type == CPP_KEYWORD
          && TREE_CODE (token->value) == IDENTIFIER_NODE))
     fprintf (stream, " %s", IDENTIFIER_POINTER (token->value));
 }
@@ -973,7 +985,7 @@ cp_lexer_start_debugging (cp_lexer* lexer)
 {
   ++lexer->debugging_p;
 }
-  
+
 /* Stop emitting debugging information.  */
 
 static void
@@ -983,6 +995,197 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
 }
 
 \f
+/* Decl-specifiers.  */
+
+static void clear_decl_specs
+  (cp_decl_specifier_seq *);
+
+/* Set *DECL_SPECS to represent an empty decl-specifier-seq.  */
+
+static void
+clear_decl_specs (cp_decl_specifier_seq *decl_specs)
+{
+  memset (decl_specs, 0, sizeof (cp_decl_specifier_seq));
+}
+
+/* Declarators.  */
+
+/* Nothing other than the parser should be creating declarators;
+   declarators are a semi-syntactic representation of C++ entities.
+   Other parts of the front end that need to create entities (like
+   VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
+
+static cp_declarator *make_id_declarator
+  (tree);
+static cp_declarator *make_call_declarator
+  (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree);
+static cp_declarator *make_array_declarator
+  (cp_declarator *, tree);
+static cp_declarator *make_pointer_declarator
+  (cp_cv_quals, cp_declarator *);
+static cp_declarator *make_reference_declarator
+  (cp_cv_quals, cp_declarator *);
+static cp_parameter_declarator *make_parameter_declarator
+  (cp_decl_specifier_seq *, cp_declarator *, tree);
+static cp_declarator *make_ptrmem_declarator
+  (cp_cv_quals, tree, cp_declarator *);
+
+cp_declarator *cp_error_declarator;
+
+/* The obstack on which declarators and related data structures are
+   allocated.  */
+static struct obstack declarator_obstack;
+
+/* Alloc BYTES from the declarator memory pool.  */
+
+static inline void *
+alloc_declarator (size_t bytes)
+{
+  return obstack_alloc (&declarator_obstack, bytes);
+}
+
+/* Allocate a declarator of the indicated KIND.  Clear fields that are
+   common to all declarators.  */
+
+static cp_declarator *
+make_declarator (cp_declarator_kind kind)
+{
+  cp_declarator *declarator;
+
+  declarator = (cp_declarator *) alloc_declarator (sizeof (cp_declarator));
+  declarator->kind = kind;
+  declarator->attributes = NULL_TREE;
+  declarator->declarator = NULL;
+
+  return declarator;
+}
+
+/* Make a declarator for a generalized identifier.  */
+
+cp_declarator *
+make_id_declarator (tree id)
+{
+  cp_declarator *declarator;
+
+  declarator = make_declarator (cdk_id);
+  declarator->u.id.name = id;
+  declarator->u.id.sfk = sfk_none;
+
+  return declarator;
+}
+
+/* Make a declarator for a pointer to TARGET.  CV_QUALIFIERS is a list
+   of modifiers such as const or volatile to apply to the pointer
+   type, represented as identifiers.  */
+
+cp_declarator *
+make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
+{
+  cp_declarator *declarator;
+
+  declarator = make_declarator (cdk_pointer);
+  declarator->declarator = target;
+  declarator->u.pointer.qualifiers = cv_qualifiers;
+  declarator->u.pointer.class_type = NULL_TREE;
+
+  return declarator;
+}
+
+/* Like make_pointer_declarator -- but for references.  */
+
+cp_declarator *
+make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
+{
+  cp_declarator *declarator;
+
+  declarator = make_declarator (cdk_reference);
+  declarator->declarator = target;
+  declarator->u.pointer.qualifiers = cv_qualifiers;
+  declarator->u.pointer.class_type = NULL_TREE;
+
+  return declarator;
+}
+
+/* Like make_pointer_declarator -- but for a pointer to a non-static
+   member of CLASS_TYPE.  */
+
+cp_declarator *
+make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
+                       cp_declarator *pointee)
+{
+  cp_declarator *declarator;
+
+  declarator = make_declarator (cdk_ptrmem);
+  declarator->declarator = pointee;
+  declarator->u.pointer.qualifiers = cv_qualifiers;
+  declarator->u.pointer.class_type = class_type;
+
+  return declarator;
+}
+
+/* Make a declarator for the function given by TARGET, with the
+   indicated PARMS.  The CV_QUALIFIERS aply to the function, as in
+   "const"-qualified member function.  The EXCEPTION_SPECIFICATION
+   indicates what exceptions can be thrown.  */
+
+cp_declarator *
+make_call_declarator (cp_declarator *target,
+                     cp_parameter_declarator *parms,
+                     cp_cv_quals cv_qualifiers,
+                      tree exception_specification)
+{
+  cp_declarator *declarator;
+
+  declarator = make_declarator (cdk_function);
+  declarator->declarator = target;
+  declarator->u.function.parameters = parms;
+  declarator->u.function.qualifiers = cv_qualifiers;
+  declarator->u.function.exception_specification = exception_specification;
+
+  return declarator;
+}
+
+/* Make a declarator for an array of BOUNDS elements, each of which is
+   defined by ELEMENT.  */
+
+cp_declarator *
+make_array_declarator (cp_declarator *element, tree bounds)
+{
+  cp_declarator *declarator;
+
+  declarator = make_declarator (cdk_array);
+  declarator->declarator = element;
+  declarator->u.array.bounds = bounds;
+
+  return declarator;
+}
+
+cp_parameter_declarator *no_parameters;
+
+/* Create a parameter declarator with the indicated DECL_SPECIFIERS,
+   DECLARATOR and DEFAULT_ARGUMENT.  */
+
+cp_parameter_declarator *
+make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
+                          cp_declarator *declarator,
+                          tree default_argument)
+{
+  cp_parameter_declarator *parameter;
+
+  parameter = ((cp_parameter_declarator *)
+              alloc_declarator (sizeof (cp_parameter_declarator)));
+  parameter->next = NULL;
+  if (decl_specifiers)
+    parameter->decl_specifiers = *decl_specifiers;
+  else
+    clear_decl_specs (&parameter->decl_specifiers);
+  parameter->declarator = declarator;
+  parameter->default_argument = default_argument;
+  parameter->ellipsis_p = false;
+
+  return parameter;
+}
+
 /* The parser.  */
 
 /* Overview
@@ -998,7 +1201,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
 
    The parser invokes routines elsewhere in the compiler to perform
    semantic analysis and to build up the abstract syntax tree for the
-   code processed.  
+   code processed.
 
    The parser (and the template instantiation code, which is, in a
    way, a close relative of parsing) are the only parts of the
@@ -1011,7 +1214,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
 
    Methodology
    -----------
-   
+
    The parser is of the standard recursive-descent variety.  Upcoming
    tokens in the token stream are examined in order to determine which
    production to use when parsing a non-terminal.  Some C++ constructs
@@ -1031,7 +1234,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
 
    Future Improvements
    -------------------
-   
+
    The performance of the parser could probably be improved
    substantially.  Some possible improvements include:
 
@@ -1063,7 +1266,7 @@ typedef enum cp_parser_flags
 
 typedef enum cp_parser_declarator_kind
 {
-  /* We want an abstract declartor.  */
+  /* We want an abstract declarator.  */
   CP_PARSER_DECLARATOR_ABSTRACT,
   /* We want a named declarator.  */
   CP_PARSER_DECLARATOR_NAMED,
@@ -1124,7 +1327,7 @@ static cp_parser_context *cp_parser_context_new
 
 /* Class variables.  */
 
-static GTY((deletable (""))) cp_parser_context* cp_parser_context_free_list;
+static GTY((deletable)) cp_parser_context* cp_parser_context_free_list;
 
 /* Constructors and destructors.  */
 
@@ -1172,7 +1375,7 @@ typedef struct cp_parser GTY(())
   /* The scope in which names should be looked up.  If NULL_TREE, then
      we look up names in the scope that is currently open in the
      source program.  If non-NULL, this is either a TYPE or
-     NAMESPACE_DECL for the scope in which we should look.  
+     NAMESPACE_DECL for the scope in which we should look.
 
      This value is not cleared automatically after a name is looked
      up, so we must be careful to clear it before starting a new look
@@ -1186,7 +1389,7 @@ typedef struct cp_parser GTY(())
   /* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the
      last lookup took place.  OBJECT_SCOPE is used if an expression
      like "x->y" or "x.y" was used; it gives the type of "*x" or "x",
-     respectively.  QUALIFYING_SCOPE is used for an expression of the 
+     respectively.  QUALIFYING_SCOPE is used for an expression of the
      form "X::Y"; it refers to X.  */
   tree object_scope;
   tree qualifying_scope;
@@ -1215,7 +1418,7 @@ typedef struct cp_parser GTY(())
      that starts at this point. FALSE if only a gnu extension makes
      them permissible.  */
   bool default_arg_ok_p;
-  
+
   /* TRUE if we are parsing an integral constant-expression.  See
      [expr.const] for a precise definition.  */
   bool integral_constant_expression_p;
@@ -1230,9 +1433,6 @@ typedef struct cp_parser GTY(())
      been seen that makes the expression non-constant.  */
   bool non_integral_constant_expression_p;
 
-  /* TRUE if we are parsing the argument to "__offsetof__".  */
-  bool in_offsetof_p;
-
   /* TRUE if local variable names and `this' are forbidden in the
      current context.  */
   bool local_variables_forbidden_p;
@@ -1302,7 +1502,7 @@ typedef tree (*cp_parser_expression_fn) (cp_parser *);
 static cp_parser *cp_parser_new
   (void);
 
-/* Routines to parse various constructs.  
+/* Routines to parse various constructs.
 
    Those that return `tree' will return the error_mark_node (rather
    than NULL_TREE) if a parse error occurs, unless otherwise noted.
@@ -1340,6 +1540,10 @@ static tree cp_parser_class_or_namespace_name
   (cp_parser *, bool, bool, bool, bool, bool);
 static tree cp_parser_postfix_expression
   (cp_parser *, bool);
+static tree cp_parser_postfix_open_square_expression
+  (cp_parser *, tree, bool);
+static tree cp_parser_postfix_dot_deref_expression
+  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
 static tree cp_parser_parenthesized_expression_list
   (cp_parser *, bool, bool *);
 static void cp_parser_pseudo_destructor_name
@@ -1353,16 +1557,16 @@ static tree cp_parser_new_expression
 static tree cp_parser_new_placement
   (cp_parser *);
 static tree cp_parser_new_type_id
+  (cp_parser *, tree *);
+static cp_declarator *cp_parser_new_declarator_opt
   (cp_parser *);
-static tree cp_parser_new_declarator_opt
-  (cp_parser *);
-static tree cp_parser_direct_new_declarator
+static cp_declarator *cp_parser_direct_new_declarator
   (cp_parser *);
 static tree cp_parser_new_initializer
   (cp_parser *);
 static tree cp_parser_delete_expression
   (cp_parser *);
-static tree cp_parser_cast_expression 
+static tree cp_parser_cast_expression
   (cp_parser *, bool);
 static tree cp_parser_pm_expression
   (cp_parser *);
@@ -1384,7 +1588,7 @@ static tree cp_parser_inclusive_or_expression
   (cp_parser *);
 static tree cp_parser_logical_and_expression
   (cp_parser *);
-static tree cp_parser_logical_or_expression 
+static tree cp_parser_logical_or_expression
   (cp_parser *);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
@@ -1396,19 +1600,21 @@ static tree cp_parser_expression
   (cp_parser *);
 static tree cp_parser_constant_expression
   (cp_parser *, bool, bool *);
+static tree cp_parser_builtin_offsetof
+  (cp_parser *);
 
 /* Statements [gram.stmt.stmt]  */
 
 static void cp_parser_statement
-  (cp_parser *, bool);
+  (cp_parser *, tree);
 static tree cp_parser_labeled_statement
-  (cp_parser *, bool);
+  (cp_parser *, tree);
 static tree cp_parser_expression_statement
-  (cp_parser *, bool);
+  (cp_parser *, tree);
 static tree cp_parser_compound_statement
-  (cp_parser *, bool);
+  (cp_parser *, tree, bool);
 static void cp_parser_statement_seq_opt
-  (cp_parser *, bool);
+  (cp_parser *, tree);
 static tree cp_parser_selection_statement
   (cp_parser *);
 static tree cp_parser_condition
@@ -1437,16 +1643,17 @@ static void cp_parser_block_declaration
   (cp_parser *, bool);
 static void cp_parser_simple_declaration
   (cp_parser *, bool);
-static tree cp_parser_decl_specifier_seq 
-  (cp_parser *, cp_parser_flags, tree *, int *);
+static void cp_parser_decl_specifier_seq
+  (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *);
 static tree cp_parser_storage_class_specifier_opt
   (cp_parser *);
 static tree cp_parser_function_specifier_opt
-  (cp_parser *);
+  (cp_parser *, cp_decl_specifier_seq *);
 static tree cp_parser_type_specifier
-  (cp_parser *, cp_parser_flags, bool, bool, int *, bool *);
+  (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, bool,
+   int *, bool *);
 static tree cp_parser_simple_type_specifier
-  (cp_parser *, cp_parser_flags, bool);
+  (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
 static tree cp_parser_type_name
   (cp_parser *);
 static tree cp_parser_elaborated_type_specifier
@@ -1455,7 +1662,7 @@ static tree cp_parser_enum_specifier
   (cp_parser *);
 static void cp_parser_enumerator_list
   (cp_parser *, tree);
-static void cp_parser_enumerator_definition 
+static void cp_parser_enumerator_definition
   (cp_parser *, tree);
 static tree cp_parser_namespace_name
   (cp_parser *);
@@ -1479,28 +1686,26 @@ static void cp_parser_linkage_specification
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
-  (cp_parser *, tree, tree, bool, bool, int, bool *);
-static tree cp_parser_declarator
+  (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *);
+static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool *);
-static tree cp_parser_direct_declarator
+static cp_declarator *cp_parser_direct_declarator
   (cp_parser *, cp_parser_declarator_kind, int *);
 static enum tree_code cp_parser_ptr_operator
-  (cp_parser *, tree *, tree *);
-static tree cp_parser_cv_qualifier_seq_opt
-  (cp_parser *);
-static tree cp_parser_cv_qualifier_opt
+  (cp_parser *, tree *, cp_cv_quals *);
+static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
 static tree cp_parser_declarator_id
   (cp_parser *);
 static tree cp_parser_type_id
   (cp_parser *);
-static tree cp_parser_type_specifier_seq
+static void cp_parser_type_specifier_seq
+  (cp_parser *, cp_decl_specifier_seq *);
+static cp_parameter_declarator *cp_parser_parameter_declaration_clause
   (cp_parser *);
-static tree cp_parser_parameter_declaration_clause
-  (cp_parser *);
-static tree cp_parser_parameter_declaration_list
-  (cp_parser *);
-static tree cp_parser_parameter_declaration
+static cp_parameter_declarator *cp_parser_parameter_declaration_list
+  (cp_parser *, bool *);
+static cp_parameter_declarator *cp_parser_parameter_declaration
   (cp_parser *, bool, bool *);
 static void cp_parser_function_body
   (cp_parser *);
@@ -1521,7 +1726,7 @@ static tree cp_parser_class_name
 static tree cp_parser_class_specifier
   (cp_parser *);
 static tree cp_parser_class_head
-  (cp_parser *, bool *);
+  (cp_parser *, bool *, tree *);
 static enum tag_types cp_parser_class_key
   (cp_parser *);
 static void cp_parser_member_specification_opt
@@ -1546,7 +1751,7 @@ static tree cp_parser_conversion_function_id
   (cp_parser *);
 static tree cp_parser_conversion_type_id
   (cp_parser *);
-static tree cp_parser_conversion_declarator_opt
+static cp_declarator *cp_parser_conversion_declarator_opt
   (cp_parser *);
 static bool cp_parser_ctor_initializer_opt
   (cp_parser *);
@@ -1571,7 +1776,7 @@ static void cp_parser_template_declaration
 static tree cp_parser_template_parameter_list
   (cp_parser *);
 static tree cp_parser_template_parameter
-  (cp_parser *);
+  (cp_parser *, bool *);
 static tree cp_parser_type_parameter
   (cp_parser *);
 static tree cp_parser_template_id
@@ -1589,7 +1794,7 @@ static void cp_parser_explicit_specialization
 
 /* Exception handling [gram.exception] */
 
-static tree cp_parser_try_block 
+static tree cp_parser_try_block
   (cp_parser *);
 static bool cp_parser_function_try_block
   (cp_parser *);
@@ -1632,7 +1837,7 @@ static tree cp_parser_lookup_name_simple
 static tree cp_parser_maybe_treat_template_as_class
   (tree, bool);
 static bool cp_parser_check_declarator_template_parameters
-  (cp_parser *, tree);
+  (cp_parser *, cp_declarator *);
 static bool cp_parser_check_template_parameters
   (cp_parser *, unsigned);
 static tree cp_parser_simple_cast_expression
@@ -1644,7 +1849,7 @@ static tree cp_parser_global_scope_opt
 static bool cp_parser_constructor_declarator_p
   (cp_parser *, bool);
 static tree cp_parser_function_definition_from_specifiers_and_declarator
-  (cp_parser *, tree, tree, tree);
+  (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *);
 static tree cp_parser_function_definition_after_declarator
   (cp_parser *, bool);
 static void cp_parser_template_declaration_after_export
@@ -1654,7 +1859,7 @@ static tree cp_parser_single_declaration
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
-  (cp_parser *, tree, tree, tree);
+  (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree);
 static tree cp_parser_enclosed_template_argument_list
   (cp_parser *);
 static void cp_parser_save_default_args
@@ -1667,20 +1872,24 @@ static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
-static tree cp_parser_fold_non_dependent_expr
-  (tree);
+static void cp_parser_set_storage_class
+  (cp_decl_specifier_seq *, cp_storage_class);
+static void cp_parser_set_decl_spec_type
+  (cp_decl_specifier_seq *, tree, bool);
 static bool cp_parser_friend_p
-  (tree);
+  (const cp_decl_specifier_seq *);
 static cp_token *cp_parser_require
   (cp_parser *, enum cpp_ttype, const char *);
 static cp_token *cp_parser_require_keyword
   (cp_parser *, enum rid, const char *);
-static bool cp_parser_token_starts_function_definition_p 
+static bool cp_parser_token_starts_function_definition_p
   (cp_token *);
 static bool cp_parser_next_token_starts_class_definition_p
   (cp_parser *);
 static bool cp_parser_next_token_ends_template_argument_p
   (cp_parser *);
+static bool cp_parser_nth_token_starts_template_argument_list_p
+  (cp_parser *, size_t);
 static enum tag_types cp_parser_token_is_class_key
   (cp_token *);
 static void cp_parser_check_class_key
@@ -1689,11 +1898,11 @@ static void cp_parser_check_access_in_redeclaration
   (tree type);
 static bool cp_parser_optional_template_keyword
   (cp_parser *);
-static void cp_parser_pre_parsed_nested_name_specifier 
+static void cp_parser_pre_parsed_nested_name_specifier
   (cp_parser *);
 static void cp_parser_cache_group
   (cp_parser *, cp_token_cache *, enum cpp_ttype, unsigned);
-static void cp_parser_parse_tentatively 
+static void cp_parser_parse_tentatively
   (cp_parser *);
 static void cp_parser_commit_to_tentative_parse
   (cp_parser *);
@@ -1714,12 +1923,14 @@ static bool cp_parser_simulate_error
 static void cp_parser_check_type_definition
   (cp_parser *);
 static void cp_parser_check_for_definition_in_return_type
-  (tree, int);
+  (cp_declarator *, int);
 static void cp_parser_check_for_invalid_template_id
   (cp_parser *, tree);
-static tree cp_parser_non_integral_constant_expression
-  (const char *);
-static bool cp_parser_diagnose_invalid_type_name
+static bool cp_parser_non_integral_constant_expression
+  (cp_parser *, const char *);
+static void cp_parser_diagnose_invalid_type_name
+  (cp_parser *, tree, tree);
+static bool cp_parser_parse_and_diagnose_invalid_type_name
   (cp_parser *);
 static int cp_parser_skip_to_closing_parenthesis
   (cp_parser *, bool, bool, bool);
@@ -1739,8 +1950,10 @@ static bool cp_parser_allow_gnu_extensions_p
   (cp_parser *);
 static bool cp_parser_is_string_literal
   (cp_token *);
-static bool cp_parser_is_keyword 
+static bool cp_parser_is_keyword
   (cp_token *, enum rid);
+static tree cp_parser_make_typename_type
+  (cp_parser *, tree, tree);
 
 /* Returns nonzero if we are parsing tentatively.  */
 
@@ -1776,11 +1989,11 @@ cp_parser_error (cp_parser* parser, const char* message)
     {
       cp_token *token;
       token = cp_lexer_peek_token (parser->lexer);
-      c_parse_error (message, 
+      c_parse_error (message,
                     /* Because c_parser_error does not understand
                        CPP_KEYWORD, keywords are treated like
                        identifiers.  */
-                    (token->type == CPP_KEYWORD ? CPP_NAME : token->type), 
+                    (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
                     token->value);
     }
 }
@@ -1801,7 +2014,7 @@ cp_parser_name_lookup_error (cp_parser* parser,
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-       error ("`%D::%D' has not been declared", 
+       error ("`%D::%D' has not been declared",
               parser->scope, name);
       else if (parser->scope == global_namespace)
        error ("`::%D' has not been declared", name);
@@ -1818,7 +2031,7 @@ cp_parser_name_lookup_error (cp_parser* parser,
 
 /* If we are parsing tentatively, remember that an error has occurred
    during this tentative parse.  Returns true if the error was
-   simulated; false if a messgae should be issued by the caller.  */
+   simulated; false if a message should be issued by the caller.  */
 
 static bool
 cp_parser_simulate_error (cp_parser* parser)
@@ -1852,18 +2065,19 @@ cp_parser_check_type_definition (cp_parser* parser)
    then an error is issued.  */
 
 static void
-cp_parser_check_for_definition_in_return_type (tree declarator, 
+cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
                                               int declares_class_or_enum)
 {
   /* [dcl.fct] forbids type definitions in return types.
      Unfortunately, it's not easy to know whether or not we are
      processing a return type until after the fact.  */
   while (declarator
-        && (TREE_CODE (declarator) == INDIRECT_REF
-            || TREE_CODE (declarator) == ADDR_EXPR))
-    declarator = TREE_OPERAND (declarator, 0);
+        && (declarator->kind == cdk_pointer
+            || declarator->kind == cdk_reference
+            || declarator->kind == cdk_ptrmem))
+    declarator = declarator->declarator;
   if (declarator
-      && TREE_CODE (declarator) == CALL_EXPR 
+      && declarator->kind == cdk_function
       && declares_class_or_enum & 2)
     error ("new types may not be defined in a return type");
 }
@@ -1874,7 +2088,7 @@ cp_parser_check_for_definition_in_return_type (tree declarator,
    invalid attempt to form a template-id.  */
 
 static void
-cp_parser_check_for_invalid_template_id (cp_parser* parser, 
+cp_parser_check_for_invalid_template_id (cp_parser* parser,
                                         tree type)
 {
   ptrdiff_t start;
@@ -1885,7 +2099,7 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
       if (TYPE_P (type))
        error ("`%T' is not a template", type);
       else if (TREE_CODE (type) == IDENTIFIER_NODE)
-       error ("`%s' is not a template", IDENTIFIER_POINTER (type));
+       error ("`%E' is not a template", type);
       else
        error ("invalid template-id");
       /* Remember the location of the invalid "<".  */
@@ -1916,40 +2130,48 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
     }
 }
 
-/* Issue an error message about the fact that THING appeared in a
-   constant-expression.  Returns ERROR_MARK_NODE.  */
-
-static tree
-cp_parser_non_integral_constant_expression (const char *thing)
-{
-  error ("%s cannot appear in a constant-expression", thing);
-  return error_mark_node;
-}
-
-/* Check for a common situation where a type-name should be present,
-   but is not, and issue a sensible error message.  Returns true if an
-   invalid type-name was detected.  */
+/* If parsing an integral constant-expression, issue an error message
+   about the fact that THING appeared and return true.  Otherwise,
+   return false, marking the current expression as non-constant.  */
 
 static bool
-cp_parser_diagnose_invalid_type_name (cp_parser *parser)
+cp_parser_non_integral_constant_expression (cp_parser  *parser,
+                                           const char *thing)
 {
-  /* If the next two tokens are both identifiers, the code is
-     erroneous. The usual cause of this situation is code like:
+  if (parser->integral_constant_expression_p)
+    {
+      if (!parser->allow_non_integral_constant_expression_p)
+       {
+         error ("%s cannot appear in a constant-expression", thing);
+         return true;
+       }
+      parser->non_integral_constant_expression_p = true;
+    }
+  return false;
+}
 
-       T t;
+/* Emit a diagnostic for an invalid type name. Consider also if it is
+   qualified or not and the result of a lookup, to provide a better
+   message.  */
 
-     where "T" should name a type -- but does not.  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
-      && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME)
+static void
+cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
+{
+  tree decl, old_scope;
+  /* Try to lookup the identifier.  */
+  old_scope = parser->scope;
+  parser->scope = scope;
+  decl = cp_parser_lookup_name_simple (parser, id);
+  parser->scope = old_scope;
+  /* If the lookup found a template-name, it means that the user forgot
+  to specify an argument list. Emit an useful error message.  */
+  if (TREE_CODE (decl) == TEMPLATE_DECL)
+    error ("invalid use of template-name `%E' without an argument list",
+      decl);
+  else if (!parser->scope)
     {
-      tree name;
-
-      /* If parsing tentatively, we should commit; we really are
-        looking at a declaration.  */
-      /* Consume the first identifier.  */
-      name = cp_lexer_consume_token (parser->lexer)->value;
       /* Issue an error message.  */
-      error ("`%s' does not name a type", IDENTIFIER_POINTER (name));
+      error ("`%E' does not name a type", id);
       /* If we're in a template class, it's possible that the user was
         referring to a type from a base class.  For example:
 
@@ -1966,7 +2188,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser)
               b = TREE_CHAIN (b))
            {
              tree base_type = BINFO_TYPE (b);
-             if (CLASS_TYPE_P (base_type) 
+             if (CLASS_TYPE_P (base_type)
                  && dependent_type_p (base_type))
                {
                  tree field;
@@ -1978,10 +2200,10 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser)
                       field;
                       field = TREE_CHAIN (field))
                    if (TREE_CODE (field) == TYPE_DECL
-                       && DECL_NAME (field) == name)
+                       && DECL_NAME (field) == id)
                      {
-                       error ("(perhaps `typename %T::%s' was intended)",
-                              BINFO_TYPE (b), IDENTIFIER_POINTER (name));
+                       inform ("(perhaps `typename %T::%E' was intended)",
+                               BINFO_TYPE (b), id);
                        break;
                      }
                  if (field)
@@ -1989,58 +2211,130 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser)
                }
            }
        }
-      /* Skip to the end of the declaration; there's no point in
-        trying to process it.  */
-      cp_parser_skip_to_end_of_statement (parser);
-      
-      return true;
     }
+  /* Here we diagnose qualified-ids where the scope is actually correct,
+     but the identifier does not resolve to a valid type name.  */
+  else
+    {
+      if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
+       error ("`%E' in namespace `%E' does not name a type",
+              id, parser->scope);
+      else if (TYPE_P (parser->scope))
+       error ("`%E' in class `%T' does not name a type",
+              id, parser->scope);
+      else
+       abort();
+    }
+}
 
-  return false;
+/* Check for a common situation where a type-name should be present,
+   but is not, and issue a sensible error message.  Returns true if an
+   invalid type-name was detected.
+
+   The situation handled by this function are variable declarations of the
+   form `ID a', where `ID' is an id-expression and `a' is a plain identifier.
+   Usually, `ID' should name a type, but if we got here it means that it
+   does not. We try to emit the best possible error message depending on
+   how exactly the id-expression looks like.
+*/
+
+static bool
+cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
+{
+  tree id;
+
+  cp_parser_parse_tentatively (parser);
+  id = cp_parser_id_expression (parser,
+                               /*template_keyword_p=*/false,
+                               /*check_dependency_p=*/true,
+                               /*template_p=*/NULL,
+                               /*declarator_p=*/true);
+  /* After the id-expression, there should be a plain identifier,
+     otherwise this is not a simple variable declaration. Also, if
+     the scope is dependent, we cannot do much.  */
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+      || (parser->scope && TYPE_P (parser->scope)
+         && dependent_type_p (parser->scope)))
+    {
+      cp_parser_abort_tentative_parse (parser);
+      return false;
+    }
+  if (!cp_parser_parse_definitely (parser))
+    return false;
+
+  /* If we got here, this cannot be a valid variable declaration, thus
+     the cp_parser_id_expression must have resolved to a plain identifier
+     node (not a TYPE_DECL or TEMPLATE_ID_EXPR).  */
+  my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 20030203);
+  /* Emit a diagnostic for the invalid type.  */
+  cp_parser_diagnose_invalid_type_name (parser, parser->scope, id);
+  /* Skip to the end of the declaration; there's no point in
+     trying to process it.  */
+  cp_parser_skip_to_end_of_block_or_statement (parser);
+  return true;
 }
 
-/* Consume tokens up to, and including, the next non-nested closing `)'. 
+/* Consume tokens up to, and including, the next non-nested closing `)'.
    Returns 1 iff we found a closing `)'.  RECOVERING is true, if we
    are doing error recovery. Returns -1 if OR_COMMA is true and we
    found an unnested comma.  */
 
 static int
 cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
-                                      bool recovering, 
+                                      bool recovering,
                                       bool or_comma,
                                       bool consume_paren)
 {
   unsigned paren_depth = 0;
   unsigned brace_depth = 0;
+  int saved_c_lex_string_translate = c_lex_string_translate;
+  int result;
 
   if (recovering && !or_comma && cp_parser_parsing_tentatively (parser)
       && !cp_parser_committed_to_tentative_parse (parser))
     return 0;
-  
+
+  if (! recovering)
+    /* If we're looking ahead, keep both translated and untranslated
+       strings.  */
+    c_lex_string_translate = -1;
+
   while (true)
     {
       cp_token *token;
-      
+
       /* If we've run out of tokens, then there is no closing `)'.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
-       return 0;
+       {
+         result = 0;
+         break;
+       }
 
       token = cp_lexer_peek_token (parser->lexer);
-      
+
       /* This matches the processing in skip_to_end_of_statement.  */
       if (token->type == CPP_SEMICOLON && !brace_depth)
-       return 0;
+       {
+         result = 0;
+         break;
+       }
       if (token->type == CPP_OPEN_BRACE)
        ++brace_depth;
       if (token->type == CPP_CLOSE_BRACE)
        {
          if (!brace_depth--)
-           return 0;
+           {
+             result = 0;
+             break;
+           }
        }
       if (recovering && or_comma && token->type == CPP_COMMA
          && !brace_depth && !paren_depth)
-       return -1;
-      
+       {
+         result = -1;
+         break;
+       }
+
       if (!brace_depth)
        {
          /* If it is an `(', we have entered another level of nesting.  */
@@ -2051,13 +2345,19 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
            {
              if (consume_paren)
                cp_lexer_consume_token (parser->lexer);
-             return 1;
+             {
+               result = 1;
+               break;
+             }
            }
        }
-      
+
       /* Consume the token.  */
       cp_lexer_consume_token (parser->lexer);
     }
+
+  c_lex_string_translate = saved_c_lex_string_translate;
+  return result;
 }
 
 /* Consume tokens until we reach the end of the current statement.
@@ -2089,7 +2389,7 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
          /* If this is a non-nested `}', stop before consuming it.
             That way, when confronted with something like:
 
-              { 3 + } 
+              { 3 + }
 
             we stop before consuming the closing `}', even though we
             have not yet reached a `;'.  */
@@ -2168,7 +2468,7 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
       token = cp_lexer_consume_token (parser->lexer);
       /* If the next token is a non-nested `}', then we have reached
         the end of the current block.  */
-      if (token->type == CPP_CLOSE_BRACE 
+      if (token->type == CPP_CLOSE_BRACE
          && (nesting_depth == 0 || --nesting_depth == 0))
        break;
       /* If it the next token is a `{', then we are entering a new
@@ -2208,6 +2508,25 @@ cp_parser_skip_to_closing_brace (cp_parser *parser)
     }
 }
 
+/* This is a simple wrapper around make_typename_type. When the id is
+   an unresolved identifier node, we can provide a superior diagnostic
+   using cp_parser_diagnose_invalid_type_name.  */
+
+static tree
+cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
+{
+  tree result;
+  if (TREE_CODE (id) == IDENTIFIER_NODE)
+    {
+      result = make_typename_type (scope, id, /*complain=*/0);
+      if (result == error_mark_node)
+       cp_parser_diagnose_invalid_type_name (parser, scope, id);
+      return result;
+    }
+  return make_typename_type (scope, id, tf_error);
+}
+
+
 /* Create a new C++ parser.  */
 
 static cp_parser *
@@ -2232,15 +2551,12 @@ cp_parser_new (void)
   parser->greater_than_is_operator_p = true;
 
   parser->default_arg_ok_p = true;
-  
+
   /* We are not parsing a constant-expression.  */
   parser->integral_constant_expression_p = false;
   parser->allow_non_integral_constant_expression_p = false;
   parser->non_integral_constant_expression_p = false;
 
-  /* We are not parsing offsetof.  */
-  parser->in_offsetof_p = false;
-
   /* Local variable names are not forbidden.  */
   parser->local_variables_forbidden_p = false;
 
@@ -2279,7 +2595,7 @@ cp_parser_new (void)
 /* Parse an identifier.  Returns an IDENTIFIER_NODE representing the
    identifier.  */
 
-static tree 
+static tree
 cp_parser_identifier (cp_parser* parser)
 {
   cp_token *token;
@@ -2295,34 +2611,62 @@ cp_parser_identifier (cp_parser* parser)
 /* Parse a translation-unit.
 
    translation-unit:
-     declaration-seq [opt]  
+     declaration-seq [opt]
 
    Returns TRUE if all went well.  */
 
 static bool
 cp_parser_translation_unit (cp_parser* parser)
 {
+  /* The address of the first non-permanent object on the declarator
+     obstack.  */
+  static void *declarator_obstack_base;
+
+  bool success;
+
+  /* Create the declarator obstack, if necessary.  */
+  if (!cp_error_declarator)
+    {
+      gcc_obstack_init (&declarator_obstack);
+      /* Create the error declarator.  */
+      cp_error_declarator = make_declarator (cdk_error);
+      /* Create the empty parameter list.  */
+      no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE);
+      /* Remember where the base of the declarator obstack lies.  */
+      declarator_obstack_base = obstack_next_free (&declarator_obstack);
+    }
+
   while (true)
     {
       cp_parser_declaration_seq_opt (parser);
 
       /* If there are no tokens left then all went well.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
-       break;
-      
-      /* Otherwise, issue an error message.  */
-      cp_parser_error (parser, "expected declaration");
-      return false;
+       {
+         /* Consume the EOF token.  */
+         cp_parser_require (parser, CPP_EOF, "end-of-file");
+
+         /* Finish up.  */
+         finish_translation_unit ();
+
+         success = true;
+         break;
+       }
+      else
+       {
+         cp_parser_error (parser, "expected declaration");
+         success = false;
+         break;
+       }
     }
 
-  /* Consume the EOF token.  */
-  cp_parser_require (parser, CPP_EOF, "end-of-file");
-  
-  /* Finish up.  */
-  finish_translation_unit ();
+  /* Make sure the declarator obstack was fully cleaned up.  */
+  my_friendly_assert (obstack_next_free (&declarator_obstack) ==
+                     declarator_obstack_base,
+                     20040621);
 
   /* All went well.  */
-  return true;
+  return success;
 }
 
 /* Expressions [gram.expr] */
@@ -2344,9 +2688,9 @@ cp_parser_translation_unit (cp_parser* parser)
    literal:
      __null
 
-   Returns a representation of the expression.  
+   Returns a representation of the expression.
 
-   *IDK indicates what kind of id-expression (if any) was present.  
+   *IDK indicates what kind of id-expression (if any) was present.
 
    *QUALIFYING_CLASS is set to a non-NULL value if the id-expression can be
    used as the operand of a pointer-to-member.  In that case,
@@ -2354,7 +2698,7 @@ cp_parser_translation_unit (cp_parser* parser)
    class in the pointer-to-member.  */
 
 static tree
-cp_parser_primary_expression (cp_parser *parser, 
+cp_parser_primary_expression (cp_parser *parser,
                              cp_id_kind *idk,
                              tree *qualifying_class)
 {
@@ -2377,12 +2721,18 @@ cp_parser_primary_expression (cp_parser *parser,
           boolean-literal  */
     case CPP_CHAR:
     case CPP_WCHAR:
-    case CPP_STRING:
-    case CPP_WSTRING:
     case CPP_NUMBER:
       token = cp_lexer_consume_token (parser->lexer);
       return token->value;
 
+    case CPP_STRING:
+    case CPP_WSTRING:
+      token = cp_lexer_consume_token (parser->lexer);
+      if (TREE_CHAIN (token->value))
+       return TREE_CHAIN (token->value);
+      else
+       return token->value;
+
     case CPP_OPEN_PAREN:
       {
        tree expr;
@@ -2392,7 +2742,7 @@ cp_parser_primary_expression (cp_parser *parser,
        cp_lexer_consume_token (parser->lexer);
        /* Within a parenthesized expression, a `>' token is always
           the greater-than operator.  */
-       saved_greater_than_is_operator_p 
+       saved_greater_than_is_operator_p
          = parser->greater_than_is_operator_p;
        parser->greater_than_is_operator_p = true;
        /* If we see `( { ' then we are looking at the beginning of
@@ -2402,20 +2752,20 @@ cp_parser_primary_expression (cp_parser *parser,
          {
            /* Statement-expressions are not allowed by the standard.  */
            if (pedantic)
-             pedwarn ("ISO C++ forbids braced-groups within expressions");  
-           
+             pedwarn ("ISO C++ forbids braced-groups within expressions");
+
            /* And they're not allowed outside of a function-body; you
               cannot, for example, write:
-              
+
                 int i = ({ int j = 3; j + 1; });
-              
+
               at class or namespace scope.  */
            if (!at_function_scope_p ())
              error ("statement-expressions are allowed only inside functions");
            /* Start the statement-expression.  */
            expr = begin_stmt_expr ();
            /* Parse the compound-statement.  */
-           cp_parser_compound_statement (parser, true);
+           cp_parser_compound_statement (parser, expr, false);
            /* Finish up.  */
            expr = finish_stmt_expr (expr, false);
          }
@@ -2432,7 +2782,7 @@ cp_parser_primary_expression (cp_parser *parser,
          }
        /* The `>' token might be the end of a template-id or
           template-parameter-list now.  */
-       parser->greater_than_is_operator_p 
+       parser->greater_than_is_operator_p
          = saved_greater_than_is_operator_p;
        /* Consume the `)'.  */
        if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
@@ -2451,7 +2801,7 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_FALSE:
          cp_lexer_consume_token (parser->lexer);
          return boolean_false_node;
-         
+
          /* The `__null' literal.  */
        case RID_NULL:
          cp_lexer_consume_token (parser->lexer);
@@ -2466,12 +2816,9 @@ cp_parser_primary_expression (cp_parser *parser,
              return error_mark_node;
            }
          /* Pointers cannot appear in constant-expressions.  */
-         if (parser->integral_constant_expression_p)
-           {
-             if (!parser->allow_non_integral_constant_expression_p)
-               return cp_parser_non_integral_constant_expression ("`this'");
-             parser->non_integral_constant_expression_p = true;
-           }
+         if (cp_parser_non_integral_constant_expression (parser,
+                                                         "`this'"))
+           return error_mark_node;
          return finish_this_expr ();
 
          /* The `operator' keyword can be the beginning of an
@@ -2486,7 +2833,7 @@ cp_parser_primary_expression (cp_parser *parser,
             __func__ are the names of variables -- but they are
             treated specially.  Therefore, they are handled here,
             rather than relying on the generic id-expression logic
-            below.  Grammatically, these names are id-expressions.  
+            below.  Grammatically, these names are id-expressions.
 
             Consume the token.  */
          token = cp_lexer_consume_token (parser->lexer);
@@ -2513,37 +2860,14 @@ cp_parser_primary_expression (cp_parser *parser,
            cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
            /* Using `va_arg' in a constant-expression is not
               allowed.  */
-           if (parser->integral_constant_expression_p)
-             {
-               if (!parser->allow_non_integral_constant_expression_p)
-                 return cp_parser_non_integral_constant_expression ("`va_arg'");
-               parser->non_integral_constant_expression_p = true;
-             }
+           if (cp_parser_non_integral_constant_expression (parser,
+                                                           "`va_arg'"))
+             return error_mark_node;
            return build_x_va_arg (expression, type);
          }
 
        case RID_OFFSETOF:
-         {
-           tree expression;
-           bool saved_in_offsetof_p;
-
-           /* Consume the "__offsetof__" token.  */
-           cp_lexer_consume_token (parser->lexer);
-           /* Consume the opening `('.  */
-           cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
-           /* Parse the parenthesized (almost) constant-expression.  */
-           saved_in_offsetof_p = parser->in_offsetof_p;
-           parser->in_offsetof_p = true;
-           expression 
-             = cp_parser_constant_expression (parser,
-                                              /*allow_non_constant_p=*/false,
-                                              /*non_constant_p=*/NULL);
-           parser->in_offsetof_p = saved_in_offsetof_p;
-           /* Consume the closing ')'.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-
-           return expression;
-         }
+         return cp_parser_builtin_offsetof (parser);
 
        default:
          cp_parser_error (parser, "expected primary-expression");
@@ -2564,8 +2888,8 @@ cp_parser_primary_expression (cp_parser *parser,
 
       id_expression:
        /* Parse the id-expression.  */
-       id_expression 
-         = cp_parser_id_expression (parser, 
+       id_expression
+         = cp_parser_id_expression (parser,
                                     /*template_keyword_p=*/false,
                                     /*check_dependency_p=*/true,
                                     /*template_p=*/NULL,
@@ -2579,7 +2903,7 @@ cp_parser_primary_expression (cp_parser *parser,
            || TREE_CODE (id_expression) == TYPE_DECL)
          decl = id_expression;
        /* Look up the name.  */
-       else 
+       else
          {
            decl = cp_parser_lookup_name_simple (parser, id_expression);
            /* If name lookup gives us a SCOPE_REF, then the
@@ -2606,7 +2930,7 @@ cp_parser_primary_expression (cp_parser *parser,
                       extern void f(int j = i);
                     }
 
-                  Here, name look up will originally find the out 
+                  Here, name look up will originally find the out
                   of scope `i'.  We need to issue a warning message,
                   but then use the global `i'.  */
                decl = check_for_out_of_scope_variable (decl);
@@ -2618,8 +2942,8 @@ cp_parser_primary_expression (cp_parser *parser,
                  }
              }
          }
-       
-       decl = finish_id_expression (id_expression, decl, parser->scope, 
+
+       decl = finish_id_expression (id_expression, decl, parser->scope,
                                     idk, qualifying_class,
                                     parser->integral_constant_expression_p,
                                     parser->allow_non_integral_constant_expression_p,
@@ -2662,11 +2986,11 @@ cp_parser_primary_expression (cp_parser *parser,
    `template' keyword.
 
    If CHECK_DEPENDENCY_P is false, then names are looked up inside
-   uninstantiated templates.  
+   uninstantiated templates.
 
    If *TEMPLATE_P is non-NULL, it is set to true iff the
    `template' keyword is used to explicitly indicate that the entity
-   named is a template.  
+   named is a template.
 
    If DECLARATOR_P is true, the id-expression is appearing as part of
    a declarator, rather than as part of an expression.  */
@@ -2686,11 +3010,11 @@ cp_parser_id_expression (cp_parser *parser,
     *template_p = false;
 
   /* Look for the optional `::' operator.  */
-  global_scope_p 
-    = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false) 
+  global_scope_p
+    = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the optional nested-name-specifier.  */
-  nested_name_specifier_p 
+  nested_name_specifier_p
     = (cp_parser_nested_name_specifier_opt (parser,
                                            /*typename_keyword_p=*/false,
                                            check_dependency_p,
@@ -2740,13 +3064,14 @@ cp_parser_id_expression (cp_parser *parser,
       /* If it's an identifier, and the next token is not a "<", then
         we can avoid the template-id case.  This is an optimization
         for this common case.  */
-      if (token->type == CPP_NAME 
-         && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
+      if (token->type == CPP_NAME
+         && !cp_parser_nth_token_starts_template_argument_list_p
+              (parser, 2))
        return cp_parser_identifier (parser);
 
       cp_parser_parse_tentatively (parser);
       /* Try a template-id.  */
-      id = cp_parser_template_id (parser, 
+      id = cp_parser_template_id (parser,
                                  /*template_keyword_p=*/false,
                                  /*check_dependency_p=*/true,
                                  declarator_p);
@@ -2767,7 +3092,7 @@ cp_parser_id_expression (cp_parser *parser,
          if (token->keyword == RID_OPERATOR)
            return cp_parser_operator_function_id (parser);
          /* Fall through.  */
-         
+
        default:
          cp_parser_error (parser, "expected id-expression");
          return error_mark_node;
@@ -2802,7 +3127,7 @@ cp_parser_id_expression (cp_parser *parser,
    rather than as part of an expression.  */
 
 static tree
-cp_parser_unqualified_id (cp_parser* parser, 
+cp_parser_unqualified_id (cp_parser* parser,
                           bool template_keyword_p,
                          bool check_dependency_p,
                          bool declarator_p)
@@ -2811,7 +3136,7 @@ cp_parser_unqualified_id (cp_parser* parser,
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
-  
+
   switch (token->type)
     {
     case CPP_NAME:
@@ -2859,11 +3184,11 @@ cp_parser_unqualified_id (cp_parser* parser,
 
             template <typename T> void f(T t) {
               t.T::~T();
-            } 
+            }
 
           Here, it is not possible to look up `T' in the scope of `T'
           itself.  We must look in both the current scope, and the
-          scope of the containing complete expression.  
+          scope of the containing complete expression.
 
           Yet another issue is:
 
@@ -2888,9 +3213,9 @@ cp_parser_unqualified_id (cp_parser* parser,
        /* If the name is of the form "X::~X" it's OK.  */
        if (scope && TYPE_P (scope)
            && cp_lexer_next_token_is (parser->lexer, CPP_NAME)
-           && (cp_lexer_peek_nth_token (parser->lexer, 2)->type 
+           && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
                == CPP_OPEN_PAREN)
-           && (cp_lexer_peek_token (parser->lexer)->value 
+           && (cp_lexer_peek_token (parser->lexer)->value
                == TYPE_IDENTIFIER (scope)))
          {
            cp_lexer_consume_token (parser->lexer);
@@ -2902,7 +3227,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        if (scope)
          {
            cp_parser_parse_tentatively (parser);
-           type_decl = cp_parser_class_name (parser, 
+           type_decl = cp_parser_class_name (parser,
                                              /*typename_keyword_p=*/false,
                                              /*template_keyword_p=*/false,
                                              /*type_p=*/false,
@@ -2919,8 +3244,8 @@ cp_parser_unqualified_id (cp_parser* parser,
            parser->scope = qualifying_scope;
            parser->object_scope = NULL_TREE;
            parser->qualifying_scope = NULL_TREE;
-           type_decl 
-             = cp_parser_class_name (parser, 
+           type_decl
+             = cp_parser_class_name (parser,
                                      /*typename_keyword_p=*/false,
                                      /*template_keyword_p=*/false,
                                      /*type_p=*/false,
@@ -2937,8 +3262,8 @@ cp_parser_unqualified_id (cp_parser* parser,
            parser->scope = object_scope;
            parser->object_scope = NULL_TREE;
            parser->qualifying_scope = NULL_TREE;
-           type_decl 
-             = cp_parser_class_name (parser, 
+           type_decl
+             = cp_parser_class_name (parser,
                                      /*typename_keyword_p=*/false,
                                      /*template_keyword_p=*/false,
                                      /*type_p=*/false,
@@ -2952,8 +3277,8 @@ cp_parser_unqualified_id (cp_parser* parser,
        parser->scope = NULL_TREE;
        parser->object_scope = NULL_TREE;
        parser->qualifying_scope = NULL_TREE;
-       type_decl 
-         = cp_parser_class_name (parser, 
+       type_decl
+         = cp_parser_class_name (parser,
                                  /*typename_keyword_p=*/false,
                                  /*template_keyword_p=*/false,
                                  /*type_p=*/false,
@@ -2973,7 +3298,7 @@ cp_parser_unqualified_id (cp_parser* parser,
 
           A typedef-name that names a class shall not be used as the
           identifier in the declarator for a destructor declaration.  */
-       if (declarator_p 
+       if (declarator_p
            && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
            && !DECL_SELF_REFERENCE_P (type_decl))
          error ("typedef-name `%D' used as destructor declarator",
@@ -3029,14 +3354,14 @@ cp_parser_unqualified_id (cp_parser* parser,
    Sets PARSER->SCOPE to the class (TYPE) or namespace
    (NAMESPACE_DECL) specified by the nested-name-specifier, or leaves
    it unchanged if there is no nested-name-specifier.  Returns the new
-   scope iff there is a nested-name-specifier, or NULL_TREE otherwise.  
+   scope iff there is a nested-name-specifier, or NULL_TREE otherwise.
 
    If IS_DECLARATION is TRUE, the nested-name-specifier is known to be
    part of a declaration and/or decl-specifier.  */
 
 static tree
-cp_parser_nested_name_specifier_opt (cp_parser *parser, 
-                                    bool typename_keyword_p, 
+cp_parser_nested_name_specifier_opt (cp_parser *parser,
+                                    bool typename_keyword_p,
                                     bool check_dependency_p,
                                     bool type_p,
                                     bool is_declaration)
@@ -3048,7 +3373,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
 
   /* If the next token corresponds to a nested name specifier, there
      is no need to reparse it.  However, if CHECK_DEPENDENCY_P is
-     false, it may have been true before, in which case something 
+     false, it may have been true before, in which case something
      like `A<X>::B<Y>::C' may have resulted in a nested-name-specifier
      of `A<X>::', where it should now be `A<X>::B<Y>::'.  So, when
      CHECK_DEPENDENCY_P is false, we have to fall through into the
@@ -3113,7 +3438,9 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
             template-id), nor a `::', then we are not looking at a
             nested-name-specifier.  */
          token = cp_lexer_peek_nth_token (parser->lexer, 2);
-         if (token->type != CPP_LESS && token->type != CPP_SCOPE)
+         if (token->type != CPP_SCOPE
+             && !cp_parser_nth_token_starts_template_argument_list_p
+                 (parser, 2))
            break;
        }
 
@@ -3133,7 +3460,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
       old_scope = parser->scope;
       saved_qualifying_scope = parser->qualifying_scope;
       /* Parse the qualifying entity.  */
-      new_scope 
+      new_scope
        = cp_parser_class_or_namespace_name (parser,
                                             typename_keyword_p,
                                             template_keyword_p,
@@ -3158,13 +3485,13 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
             that is a `::', then any valid interpretation would have
             found a class-or-namespace-name.  */
          while (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
-                && (cp_lexer_peek_nth_token (parser->lexer, 2)->type 
+                && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
                     == CPP_SCOPE)
-                && (cp_lexer_peek_nth_token (parser->lexer, 3)->type 
+                && (cp_lexer_peek_nth_token (parser->lexer, 3)->type
                     != CPP_COMPL))
            {
              token = cp_lexer_consume_token (parser->lexer);
-             if (!error_p) 
+             if (!error_p)
                {
                  tree decl;
 
@@ -3173,8 +3500,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                    error ("`%D' used without template parameters",
                           decl);
                  else
-                   cp_parser_name_lookup_error 
-                     (parser, token->value, decl, 
+                   cp_parser_name_lookup_error
+                     (parser, token->value, decl,
                       "is not a class or namespace");
                  parser->scope = NULL_TREE;
                  error_p = true;
@@ -3197,7 +3524,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
       success = true;
       /* Make sure we look in the right scope the next time through
         the loop.  */
-      parser->scope = (TREE_CODE (new_scope) == TYPE_DECL 
+      parser->scope = (TREE_CODE (new_scope) == TYPE_DECL
                       ? TREE_TYPE (new_scope)
                       : new_scope);
       /* If it is a class scope, try to complete it; we are about to
@@ -3224,7 +3551,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
     {
       /* Find the token that corresponds to the start of the
         template-id.  */
-      token = cp_lexer_advance_token (parser->lexer, 
+      token = cp_lexer_advance_token (parser->lexer,
                                      parser->lexer->first_token,
                                      start);
 
@@ -3249,8 +3576,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
    is present.  */
 
 static tree
-cp_parser_nested_name_specifier (cp_parser *parser, 
-                                bool typename_keyword_p, 
+cp_parser_nested_name_specifier (cp_parser *parser,
+                                bool typename_keyword_p,
                                 bool check_dependency_p,
                                 bool type_p,
                                 bool is_declaration)
@@ -3292,7 +3619,7 @@ cp_parser_nested_name_specifier (cp_parser *parser,
    ERROR_MARK_NODE is returned.  */
 
 static tree
-cp_parser_class_or_namespace_name (cp_parser *parser, 
+cp_parser_class_or_namespace_name (cp_parser *parser,
                                   bool typename_keyword_p,
                                   bool template_keyword_p,
                                   bool check_dependency_p,
@@ -3316,7 +3643,7 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
   only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope));
   if (!only_class_p)
     cp_parser_parse_tentatively (parser);
-  scope = cp_parser_class_name (parser, 
+  scope = cp_parser_class_name (parser,
                                typename_keyword_p,
                                template_keyword_p,
                                type_p,
@@ -3350,7 +3677,7 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
      postfix-expression [ expression ]
      postfix-expression ( expression-list [opt] )
      simple-type-specifier ( expression-list [opt] )
-     typename :: [opt] nested-name-specifier identifier 
+     typename :: [opt] nested-name-specifier identifier
        ( expression-list [opt] )
      typename :: [opt] nested-name-specifier template [opt] template-id
        ( expression-list [opt] )
@@ -3368,7 +3695,7 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
      typeid ( type-id )
 
    GNU Extension:
-     
+
    postfix-expression:
      ( type-id ) { initializer-list , [opt] }
 
@@ -3412,7 +3739,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
           of view of parsing.  Begin by consuming the token
           identifying the cast.  */
        cp_lexer_consume_token (parser->lexer);
-       
+
        /* New types cannot be defined in the cast.  */
        saved_message = parser->type_definition_forbidden_message;
        parser->type_definition_forbidden_message
@@ -3437,16 +3764,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
        if (parser->integral_constant_expression_p
            && !dependent_type_p (type)
            && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
-           /* A cast to pointer or reference type is allowed in the
-              implementation of "offsetof".  */
-           && !(parser->in_offsetof_p && POINTER_TYPE_P (type)))
-         {
-           if (!parser->allow_non_integral_constant_expression_p)
-             return (cp_parser_non_integral_constant_expression 
-                     ("a cast to a type other than an integral or "
-                      "enumeration type"));
-           parser->non_integral_constant_expression_p = true;
-         }
+           && (cp_parser_non_integral_constant_expression
+               (parser,
+                "a cast to a type other than an integral or "
+                "enumeration type")))
+         return error_mark_node;
 
        switch (keyword)
          {
@@ -3513,12 +3835,15 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            /* Look for the `)' token.  */
            cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
          }
-
+       /* `typeid' may not appear in an integral constant expression.  */
+       if (cp_parser_non_integral_constant_expression(parser,
+                                                      "`typeid' operator"))
+         return error_mark_node;
        /* Restore the saved message.  */
        parser->type_definition_forbidden_message = saved_message;
       }
       break;
-      
+
     case RID_TYPENAME:
       {
        bool template_p = false;
@@ -3528,7 +3853,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
        /* Consume the `typename' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Look for the optional `::' operator.  */
-       cp_parser_global_scope_opt (parser, 
+       cp_parser_global_scope_opt (parser,
                                    /*current_scope_valid_p=*/false);
        /* Look for the nested-name-specifier.  */
        cp_parser_nested_name_specifier (parser,
@@ -3548,10 +3873,16 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
        /* If that didn't work, try an identifier.  */
        if (!cp_parser_parse_definitely (parser))
          id = cp_parser_identifier (parser);
+       /* If we look up a template-id in a non-dependent qualifying
+          scope, there's no need to create a dependent type.  */
+       if (TREE_CODE (id) == TYPE_DECL
+           && !dependent_type_p (parser->scope))
+         type = TREE_TYPE (id);
        /* Create a TYPENAME_TYPE to represent the type to which the
           functional cast is being performed.  */
-       type = make_typename_type (parser->scope, id, 
-                                  /*complain=*/1);
+       else
+         type = make_typename_type (parser->scope, id,
+                                    /*complain=*/1);
 
        postfix_expression = cp_parser_functional_cast (parser, type);
       }
@@ -3567,12 +3898,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
           that doesn't work we fall back to the primary-expression.  */
        cp_parser_parse_tentatively (parser);
        /* Look for the simple-type-specifier.  */
-       type = cp_parser_simple_type_specifier (parser, 
-                                               CP_PARSER_FLAGS_NONE,
-                                               /*identifier_p=*/false);
+       type = cp_parser_simple_type_specifier (parser,
+                                               /*decl_specs=*/NULL,
+                                               CP_PARSER_FLAGS_NONE);
        /* Parse the cast itself.  */
        if (!cp_parser_error_occurred (parser))
-         postfix_expression 
+         postfix_expression
            = cp_parser_functional_cast (parser, type);
        /* If that worked, we're done.  */
        if (cp_parser_parse_definitely (parser))
@@ -3604,7 +3935,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
              {
                bool non_constant_p;
                /* Parse the initializer-list.  */
-               initializer_list 
+               initializer_list
                  = cp_parser_initializer_list (parser, &non_constant_p);
                /* Allow a trailing `,'.  */
                if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
@@ -3621,14 +3952,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                if (pedantic)
                  pedwarn ("ISO C++ forbids compound-literals");
                /* Form the representation of the compound-literal.  */
-               postfix_expression 
+               postfix_expression
                  = finish_compound_literal (type, initializer_list);
                break;
              }
          }
 
        /* It must be a primary-expression.  */
-       postfix_expression = cp_parser_primary_expression (parser, 
+       postfix_expression = cp_parser_primary_expression (parser,
                                                           &idk,
                                                           &qualifying_class);
       }
@@ -3666,47 +3997,27 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
          && TREE_CODE (postfix_expression) == IDENTIFIER_NODE
          && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
        /* It is not a Koenig lookup function call.  */
-       postfix_expression 
+       postfix_expression
          = unqualified_name_lookup_error (postfix_expression);
-      
+
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
 
       switch (token->type)
        {
        case CPP_OPEN_SQUARE:
-         /* postfix-expression [ expression ] */
-         {
-           tree index;
-
-           /* Consume the `[' token.  */
-           cp_lexer_consume_token (parser->lexer);
-           /* Parse the index expression.  */
-           index = cp_parser_expression (parser);
-           /* Look for the closing `]'.  */
-           cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
-
-           /* Build the ARRAY_REF.  */
-           postfix_expression 
-             = grok_array_decl (postfix_expression, index);
-           idk = CP_ID_KIND_NONE;
-           /* Array references are not permitted in
-              constant-expressions.  */
-           if (parser->integral_constant_expression_p)
-             {
-               if (!parser->allow_non_integral_constant_expression_p)
-                 postfix_expression 
-                   = cp_parser_non_integral_constant_expression ("an array reference");
-               parser->non_integral_constant_expression_p = true;
-             }
-         }
+         postfix_expression
+           = cp_parser_postfix_open_square_expression (parser,
+                                                       postfix_expression,
+                                                       false);
+         idk = CP_ID_KIND_NONE;
          break;
 
        case CPP_OPEN_PAREN:
          /* postfix-expression ( expression-list [opt] ) */
          {
            bool koenig_p;
-           tree args = (cp_parser_parenthesized_expression_list 
+           tree args = (cp_parser_parenthesized_expression_list
                         (parser, false, /*non_constant_p=*/NULL));
 
            if (args == error_mark_node)
@@ -3714,37 +4025,35 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                postfix_expression = error_mark_node;
                break;
              }
-           
+
            /* Function calls are not permitted in
               constant-expressions.  */
-           if (parser->integral_constant_expression_p)
+           if (cp_parser_non_integral_constant_expression (parser,
+                                                           "a function call"))
              {
-               if (!parser->allow_non_integral_constant_expression_p)
-                 {
-                   postfix_expression 
-                     = cp_parser_non_integral_constant_expression ("a function call");
-                   break;
-                 }
-               parser->non_integral_constant_expression_p = true;
+               postfix_expression = error_mark_node;
+               break;
              }
 
            koenig_p = false;
            if (idk == CP_ID_KIND_UNQUALIFIED)
              {
+               /* We do not perform argument-dependent lookup if
+                  normal lookup finds a non-function, in accordance
+                  with the expected resolution of DR 218.  */
                if (args
                    && (is_overloaded_fn (postfix_expression)
-                       || DECL_P (postfix_expression)
                        || TREE_CODE (postfix_expression) == IDENTIFIER_NODE))
                  {
                    koenig_p = true;
-                   postfix_expression 
+                   postfix_expression
                      = perform_koenig_lookup (postfix_expression, args);
                  }
                else if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
                  postfix_expression
                    = unqualified_fn_lookup_error (postfix_expression);
              }
-         
+
            if (TREE_CODE (postfix_expression) == COMPONENT_REF)
              {
                tree instance = TREE_OPERAND (postfix_expression, 0);
@@ -3758,15 +4067,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                        || any_type_dependent_arguments_p (args)))
                  {
                    postfix_expression
-                     = build_min_nt (CALL_EXPR, postfix_expression, args);
+                     = build_min_nt (CALL_EXPR, postfix_expression,
+                                     args, NULL_TREE);
                    break;
                  }
-                 
-               postfix_expression
-                 = (build_new_method_call 
-                    (instance, fn, args, NULL_TREE, 
-                     (idk == CP_ID_KIND_QUALIFIED 
-                      ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
+
+               if (BASELINK_P (fn))
+                 postfix_expression
+                   = (build_new_method_call
+                      (instance, fn, args, NULL_TREE,
+                       (idk == CP_ID_KIND_QUALIFIED
+                        ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
+               else
+                 postfix_expression
+                   = finish_call_expr (postfix_expression, args,
+                                       /*disallow_virtual=*/false,
+                                       /*koenig_p=*/false);
              }
            else if (TREE_CODE (postfix_expression) == OFFSET_REF
                     || TREE_CODE (postfix_expression) == MEMBER_REF
@@ -3782,8 +4098,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
                                    koenig_p);
            else
              /* All other function calls.  */
-             postfix_expression 
-               = finish_call_expr (postfix_expression, args, 
+             postfix_expression
+               = finish_call_expr (postfix_expression, args,
                                    /*disallow_virtual=*/false,
                                    koenig_p);
 
@@ -3791,135 +4107,21 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            idk = CP_ID_KIND_NONE;
          }
          break;
-         
+
        case CPP_DOT:
        case CPP_DEREF:
-         /* postfix-expression . template [opt] id-expression  
-            postfix-expression . pseudo-destructor-name 
+         /* postfix-expression . template [opt] id-expression
+            postfix-expression . pseudo-destructor-name
             postfix-expression -> template [opt] id-expression
             postfix-expression -> pseudo-destructor-name */
-         {
-           tree name;
-           bool dependent_p;
-           bool template_p;
-           tree scope = NULL_TREE;
-           enum cpp_ttype token_type = token->type;
-
-           /* If this is a `->' operator, dereference the pointer.  */
-           if (token->type == CPP_DEREF)
-             postfix_expression = build_x_arrow (postfix_expression);
-           /* Check to see whether or not the expression is
-              type-dependent.  */
-           dependent_p = type_dependent_expression_p (postfix_expression);
-           /* The identifier following the `->' or `.' is not
-              qualified.  */
-           parser->scope = NULL_TREE;
-           parser->qualifying_scope = NULL_TREE;
-           parser->object_scope = NULL_TREE;
-           idk = CP_ID_KIND_NONE;
-           /* Enter the scope corresponding to the type of the object
-              given by the POSTFIX_EXPRESSION.  */
-           if (!dependent_p 
-               && TREE_TYPE (postfix_expression) != NULL_TREE)
-             {
-               scope = TREE_TYPE (postfix_expression);
-               /* According to the standard, no expression should
-                  ever have reference type.  Unfortunately, we do not
-                  currently match the standard in this respect in
-                  that our internal representation of an expression
-                  may have reference type even when the standard says
-                  it does not.  Therefore, we have to manually obtain
-                  the underlying type here.  */
-               scope = non_reference (scope);
-               /* The type of the POSTFIX_EXPRESSION must be
-                  complete.  */
-               scope = complete_type_or_else (scope, NULL_TREE);
-               /* Let the name lookup machinery know that we are
-                  processing a class member access expression.  */
-               parser->context->object_type = scope;
-               /* If something went wrong, we want to be able to
-                  discern that case, as opposed to the case where
-                  there was no SCOPE due to the type of expression
-                  being dependent.  */
-               if (!scope)
-                 scope = error_mark_node;
-             }
 
-           /* Consume the `.' or `->' operator.  */
-           cp_lexer_consume_token (parser->lexer);
-           /* If the SCOPE is not a scalar type, we are looking at an
-              ordinary class member access expression, rather than a
-              pseudo-destructor-name.  */
-           if (!scope || !SCALAR_TYPE_P (scope))
-             {
-               template_p = cp_parser_optional_template_keyword (parser);
-               /* Parse the id-expression.  */
-               name = cp_parser_id_expression (parser,
-                                               template_p,
-                                               /*check_dependency_p=*/true,
-                                               /*template_p=*/NULL,
-                                               /*declarator_p=*/false);
-               /* In general, build a SCOPE_REF if the member name is
-                  qualified.  However, if the name was not dependent
-                  and has already been resolved; there is no need to
-                  build the SCOPE_REF.  For example;
-
-                     struct X { void f(); };
-                     template <typename T> void f(T* t) { t->X::f(); }
-                   Even though "t" is dependent, "X::f" is not and has
-                  been resolved to a BASELINK; there is no need to
-                  include scope information.  */
-
-               /* But we do need to remember that there was an explicit
-                  scope for virtual function calls.  */
-               if (parser->scope)
-                 idk = CP_ID_KIND_QUALIFIED;
-
-               if (name != error_mark_node 
-                   && !BASELINK_P (name)
-                   && parser->scope)
-                 {
-                   name = build_nt (SCOPE_REF, parser->scope, name);
-                   parser->scope = NULL_TREE;
-                   parser->qualifying_scope = NULL_TREE;
-                   parser->object_scope = NULL_TREE;
-                 }
-               postfix_expression 
-                 = finish_class_member_access_expr (postfix_expression, name);
-             }
-           /* Otherwise, try the pseudo-destructor-name production.  */
-           else
-             {
-               tree s = NULL_TREE;
-               tree type;
-
-               /* Parse the pseudo-destructor-name.  */
-               cp_parser_pseudo_destructor_name (parser, &s, &type);
-               /* Form the call.  */
-               postfix_expression 
-                 = finish_pseudo_destructor_expr (postfix_expression,
-                                                  s, TREE_TYPE (type));
-             }
+         /* Consume the `.' or `->' operator.  */
+         cp_lexer_consume_token (parser->lexer);
 
-           /* We no longer need to look up names in the scope of the
-              object on the left-hand side of the `.' or `->'
-              operator.  */
-           parser->context->object_type = NULL_TREE;
-           /* These operators may not appear in constant-expressions.  */
-           if (parser->integral_constant_expression_p
-               /* The "->" operator is allowed in the implementation
-                  of "offsetof".  The "." operator may appear in the
-                  name of the member.  */
-               && !parser->in_offsetof_p)
-             {
-               if (!parser->allow_non_integral_constant_expression_p)
-                 postfix_expression 
-                   = (cp_parser_non_integral_constant_expression 
-                      (token_type == CPP_DEREF ? "'->'" : "`.'"));
-               parser->non_integral_constant_expression_p = true;
-             }
-         }
+         postfix_expression
+           = cp_parser_postfix_dot_deref_expression (parser, token->type,
+                                                     postfix_expression,
+                                                     false, &idk);
          break;
 
        case CPP_PLUS_PLUS:
@@ -3927,17 +4129,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
          /* Consume the `++' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Generate a representation for the complete expression.  */
-         postfix_expression 
-           = finish_increment_expr (postfix_expression, 
+         postfix_expression
+           = finish_increment_expr (postfix_expression,
                                     POSTINCREMENT_EXPR);
          /* Increments may not appear in constant-expressions.  */
-         if (parser->integral_constant_expression_p)
-           {
-             if (!parser->allow_non_integral_constant_expression_p)
-               postfix_expression 
-                 = cp_parser_non_integral_constant_expression ("an increment");
-             parser->non_integral_constant_expression_p = true;
-           }
+         if (cp_parser_non_integral_constant_expression (parser,
+                                                         "an increment"))
+           postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
          break;
 
@@ -3946,17 +4144,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
          /* Consume the `--' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Generate a representation for the complete expression.  */
-         postfix_expression 
-           = finish_increment_expr (postfix_expression, 
+         postfix_expression
+           = finish_increment_expr (postfix_expression,
                                     POSTDECREMENT_EXPR);
          /* Decrements may not appear in constant-expressions.  */
-         if (parser->integral_constant_expression_p)
-           {
-             if (!parser->allow_non_integral_constant_expression_p)
-               postfix_expression 
-                 = cp_parser_non_integral_constant_expression ("a decrement");
-             parser->non_integral_constant_expression_p = true;
-           }
+         if (cp_parser_non_integral_constant_expression (parser,
+                                                         "a decrement"))
+           postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
          break;
 
@@ -3970,6 +4164,183 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
   return error_mark_node;
 }
 
+/* A subroutine of cp_parser_postfix_expression that also gets hijacked
+   by cp_parser_builtin_offsetof.  We're looking for
+
+     postfix-expression [ expression ]
+
+   FOR_OFFSETOF is set if we're being called in that context, which
+   changes how we deal with integer constant expressions.  */
+
+static tree
+cp_parser_postfix_open_square_expression (cp_parser *parser,
+                                         tree postfix_expression,
+                                         bool for_offsetof)
+{
+  tree index;
+
+  /* Consume the `[' token.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  /* Parse the index expression.  */
+  /* ??? For offsetof, there is a question of what to allow here.  If
+     offsetof is not being used in an integral constant expression context,
+     then we *could* get the right answer by computing the value at runtime.
+     If we are in an integral constant expression context, then we might
+     could accept any constant expression; hard to say without analysis.
+     Rather than open the barn door too wide right away, allow only integer
+     constant expresions here.  */
+  if (for_offsetof)
+    index = cp_parser_constant_expression (parser, false, NULL);
+  else
+    index = cp_parser_expression (parser);
+
+  /* Look for the closing `]'.  */
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+
+  /* Build the ARRAY_REF.  */
+  postfix_expression = grok_array_decl (postfix_expression, index);
+
+  /* When not doing offsetof, array references are not permitted in
+     constant-expressions.  */
+  if (!for_offsetof
+      && (cp_parser_non_integral_constant_expression
+         (parser, "an array reference")))
+    postfix_expression = error_mark_node;
+
+  return postfix_expression;
+}
+
+/* A subroutine of cp_parser_postfix_expression that also gets hijacked
+   by cp_parser_builtin_offsetof.  We're looking for
+
+     postfix-expression . template [opt] id-expression
+     postfix-expression . pseudo-destructor-name
+     postfix-expression -> template [opt] id-expression
+     postfix-expression -> pseudo-destructor-name
+
+   FOR_OFFSETOF is set if we're being called in that context.  That sorta
+   limits what of the above we'll actually accept, but nevermind.
+   TOKEN_TYPE is the "." or "->" token, which will already have been
+   removed from the stream.  */
+
+static tree
+cp_parser_postfix_dot_deref_expression (cp_parser *parser,
+                                       enum cpp_ttype token_type,
+                                       tree postfix_expression,
+                                       bool for_offsetof, cp_id_kind *idk)
+{
+  tree name;
+  bool dependent_p;
+  bool template_p;
+  tree scope = NULL_TREE;
+
+  /* If this is a `->' operator, dereference the pointer.  */
+  if (token_type == CPP_DEREF)
+    postfix_expression = build_x_arrow (postfix_expression);
+  /* Check to see whether or not the expression is type-dependent.  */
+  dependent_p = type_dependent_expression_p (postfix_expression);
+  /* The identifier following the `->' or `.' is not qualified.  */
+  parser->scope = NULL_TREE;
+  parser->qualifying_scope = NULL_TREE;
+  parser->object_scope = NULL_TREE;
+  *idk = CP_ID_KIND_NONE;
+  /* Enter the scope corresponding to the type of the object
+     given by the POSTFIX_EXPRESSION.  */
+  if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
+    {
+      scope = TREE_TYPE (postfix_expression);
+      /* According to the standard, no expression should ever have
+        reference type.  Unfortunately, we do not currently match
+        the standard in this respect in that our internal representation
+        of an expression may have reference type even when the standard
+        says it does not.  Therefore, we have to manually obtain the
+        underlying type here.  */
+      scope = non_reference (scope);
+      /* The type of the POSTFIX_EXPRESSION must be complete.  */
+      scope = complete_type_or_else (scope, NULL_TREE);
+      /* Let the name lookup machinery know that we are processing a
+        class member access expression.  */
+      parser->context->object_type = scope;
+      /* If something went wrong, we want to be able to discern that case,
+        as opposed to the case where there was no SCOPE due to the type
+        of expression being dependent.  */
+      if (!scope)
+       scope = error_mark_node;
+      /* If the SCOPE was erroneous, make the various semantic analysis
+        functions exit quickly -- and without issuing additional error
+        messages.  */
+      if (scope == error_mark_node)
+       postfix_expression = error_mark_node;
+    }
+
+  /* If the SCOPE is not a scalar type, we are looking at an
+     ordinary class member access expression, rather than a
+     pseudo-destructor-name.  */
+  if (!scope || !SCALAR_TYPE_P (scope))
+    {
+      template_p = cp_parser_optional_template_keyword (parser);
+      /* Parse the id-expression.  */
+      name = cp_parser_id_expression (parser, template_p,
+                                     /*check_dependency_p=*/true,
+                                     /*template_p=*/NULL,
+                                     /*declarator_p=*/false);
+      /* In general, build a SCOPE_REF if the member name is qualified.
+        However, if the name was not dependent and has already been
+        resolved; there is no need to build the SCOPE_REF.  For example;
+
+             struct X { void f(); };
+             template <typename T> void f(T* t) { t->X::f(); }
+
+        Even though "t" is dependent, "X::f" is not and has been resolved
+        to a BASELINK; there is no need to include scope information.  */
+
+      /* But we do need to remember that there was an explicit scope for
+        virtual function calls.  */
+      if (parser->scope)
+       *idk = CP_ID_KIND_QUALIFIED;
+
+      if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
+       {
+         name = build_nt (SCOPE_REF, parser->scope, name);
+         parser->scope = NULL_TREE;
+         parser->qualifying_scope = NULL_TREE;
+         parser->object_scope = NULL_TREE;
+       }
+      if (scope && name && BASELINK_P (name))
+       adjust_result_of_qualified_name_lookup
+         (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
+      postfix_expression
+       = finish_class_member_access_expr (postfix_expression, name);
+    }
+  /* Otherwise, try the pseudo-destructor-name production.  */
+  else
+    {
+      tree s = NULL_TREE;
+      tree type;
+
+      /* Parse the pseudo-destructor-name.  */
+      cp_parser_pseudo_destructor_name (parser, &s, &type);
+      /* Form the call.  */
+      postfix_expression
+       = finish_pseudo_destructor_expr (postfix_expression,
+                                        s, TREE_TYPE (type));
+    }
+
+  /* We no longer need to look up names in the scope of the object on
+     the left-hand side of the `.' or `->' operator.  */
+  parser->context->object_type = NULL_TREE;
+
+  /* Outside of offsetof, these operators may not appear in
+     constant-expressions.  */
+  if (!for_offsetof
+      && (cp_parser_non_integral_constant_expression
+         (parser, token_type == CPP_DEREF ? "'->'" : "`.'")))
+    postfix_expression = error_mark_node;
+
+  return postfix_expression;
+}
+
 /* Parse a parenthesized expression-list.
 
    expression-list:
@@ -3992,7 +4363,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
    constant.  */
 
 static tree
-cp_parser_parenthesized_expression_list (cp_parser* parser, 
+cp_parser_parenthesized_expression_list (cp_parser* parser,
                                         bool is_attribute_list,
                                         bool *non_constant_p)
 {
@@ -4005,20 +4376,20 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
     return error_mark_node;
-  
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
       {
        tree expr;
-       
+
        /* At the beginning of attribute lists, check to see if the
           next token is an identifier.  */
        if (is_attribute_list
            && cp_lexer_peek_token (parser->lexer)->type == CPP_NAME)
          {
            cp_token *token;
-           
+
            /* Consume the identifier.  */
            token = cp_lexer_consume_token (parser->lexer);
            /* Save the identifier.  */
@@ -4030,7 +4401,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
            if (non_constant_p)
              {
                bool expr_non_constant_p;
-               expr = (cp_parser_constant_expression 
+               expr = (cp_parser_constant_expression
                        (parser, /*allow_non_constant_p=*/true,
                         &expr_non_constant_p));
                if (expr_non_constant_p)
@@ -4052,7 +4423,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
        /* After the first item, attribute lists look the same as
           expression lists.  */
        is_attribute_list = false;
-       
+
       get_comma:;
        /* If the next token isn't a `,', then we are done.  */
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
@@ -4061,16 +4432,16 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
        /* Otherwise, consume the `,' and keep going.  */
        cp_lexer_consume_token (parser->lexer);
       }
-  
+
   if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
     {
       int ending;
-      
+
     skip_comma:;
       /* We try and resync to an unnested comma, as that will give the
         user better diagnostics.  */
-      ending = cp_parser_skip_to_closing_parenthesis (parser, 
-                                                     /*recovering=*/true, 
+      ending = cp_parser_skip_to_closing_parenthesis (parser,
+                                                     /*recovering=*/true,
                                                      /*or_comma=*/true,
                                                      /*consume_paren=*/true);
       if (ending < 0)
@@ -4083,7 +4454,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
   expression_list = nreverse (expression_list);
   if (identifier)
     expression_list = tree_cons (NULL_TREE, identifier, expression_list);
-  
+
   return expression_list;
 }
 
@@ -4097,11 +4468,11 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
    If either of the first two productions is used, sets *SCOPE to the
    TYPE specified before the final `::'.  Otherwise, *SCOPE is set to
    NULL_TREE.  *TYPE is set to the TYPE_DECL for the final type-name,
-   or ERROR_MARK_NODE if no type-name is present.  */
+   or ERROR_MARK_NODE if the parse fails.  */
 
 static void
-cp_parser_pseudo_destructor_name (cp_parser* parser, 
-                                  tree* scope, 
+cp_parser_pseudo_destructor_name (cp_parser* parser,
+                                  tree* scope,
                                   tree* type)
 {
   bool nested_name_specifier_p;
@@ -4109,22 +4480,22 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true);
   /* Look for the optional nested-name-specifier.  */
-  nested_name_specifier_p 
+  nested_name_specifier_p
     = (cp_parser_nested_name_specifier_opt (parser,
                                            /*typename_keyword_p=*/false,
                                            /*check_dependency_p=*/true,
                                            /*type_p=*/false,
-                                           /*is_declaration=*/true) 
+                                           /*is_declaration=*/true)
        != NULL_TREE);
   /* Now, if we saw a nested-name-specifier, we might be doing the
      second production.  */
-  if (nested_name_specifier_p 
+  if (nested_name_specifier_p
       && cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
     {
       /* Consume the `template' keyword.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the template-id.  */
-      cp_parser_template_id (parser, 
+      cp_parser_template_id (parser,
                             /*template_keyword_p=*/true,
                             /*check_dependency_p=*/false,
                             /*is_declaration=*/true);
@@ -4137,6 +4508,21 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
     {
       /* Look for the type-name.  */
       *scope = TREE_TYPE (cp_parser_type_name (parser));
+
+      /* If we didn't get an aggregate type, or we don't have ::~,
+        then something has gone wrong.  Since the only caller of this
+        function is looking for something after `.' or `->' after a
+        scalar type, most likely the program is trying to get a
+        member of a non-aggregate type.  */
+      if (*scope == error_mark_node
+         || cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE)
+         || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_COMPL)
+       {
+         cp_parser_error (parser, "request for member of non-aggregate type");
+         *type = error_mark_node;
+         return;
+       }
+
       /* Look for the `::' token.  */
       cp_parser_require (parser, CPP_SCOPE, "`::'");
     }
@@ -4197,7 +4583,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
          {
            tree operand;
            enum tree_code op;
-           
+
            op = keyword == RID_ALIGNOF ? ALIGNOF_EXPR : SIZEOF_EXPR;
            /* Consume the token.  */
            cp_lexer_consume_token (parser->lexer);
@@ -4215,7 +4601,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
 
        case RID_DELETE:
          return cp_parser_delete_expression (parser);
-         
+
        case RID_EXTENSION:
          {
            /* The saved value of the PEDANTIC flag.  */
@@ -4305,7 +4691,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
       /* Consume the operator token.  */
       token = cp_lexer_consume_token (parser->lexer);
       /* Parse the cast-expression.  */
-      cast_expression 
+      cast_expression
        = cp_parser_cast_expression (parser, unary_operator == ADDR_EXPR);
       /* Now, build an appropriate representation.  */
       switch (unary_operator)
@@ -4316,10 +4702,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
          break;
 
        case ADDR_EXPR:
-         /* The "&" operator is allowed in the implementation of
-            "offsetof".  */
-         if (!parser->in_offsetof_p)
-           non_constant_p = "`&'";
+         non_constant_p = "`&'";
          /* Fall through.  */
        case BIT_NOT_EXPR:
          expression = build_x_unary_op (unary_operator, cast_expression);
@@ -4340,12 +4723,10 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
          abort ();
        }
 
-      if (non_constant_p && parser->integral_constant_expression_p)
-       {
-         if (!parser->allow_non_integral_constant_expression_p)
-           return cp_parser_non_integral_constant_expression (non_constant_p);
-         parser->non_integral_constant_expression_p = true;
-       }
+      if (non_constant_p
+         && cp_parser_non_integral_constant_expression (parser,
+                                                        non_constant_p))
+       expression = error_mark_node;
 
       return expression;
     }
@@ -4375,7 +4756,7 @@ cp_parser_unary_operator (cp_token* token)
 
     case CPP_NOT:
       return TRUTH_NOT_EXPR;
-      
+
     case CPP_COMPL:
       return BIT_NOT_EXPR;
 
@@ -4399,9 +4780,10 @@ cp_parser_new_expression (cp_parser* parser)
   tree placement;
   tree type;
   tree initializer;
+  tree nelts;
 
   /* Look for the optional `::' operator.  */
-  global_scope_p 
+  global_scope_p
     = (cp_parser_global_scope_opt (parser,
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
@@ -4426,10 +4808,20 @@ cp_parser_new_expression (cp_parser* parser)
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      /* There should not be a direct-new-declarator in this production,
+         but GCC used to allowed this, so we check and emit a sensible error
+        message for this case.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
+       {
+         error ("array bound forbidden after parenthesized type-id");
+         inform ("try removing the parentheses around the type-id");
+         cp_parser_direct_new_declarator (parser);
+       }
+      nelts = integer_one_node;
     }
   /* Otherwise, there must be a new-type-id.  */
   else
-    type = cp_parser_new_type_id (parser);
+    type = cp_parser_new_type_id (parser, &nelts);
 
   /* If the next token is a `(', then we have a new-initializer.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
@@ -4437,8 +4829,13 @@ cp_parser_new_expression (cp_parser* parser)
   else
     initializer = NULL_TREE;
 
+  /* A new-expression may not appear in an integral constant
+     expression.  */
+  if (cp_parser_non_integral_constant_expression (parser, "`new'"))
+    return error_mark_node;
+
   /* Create a representation of the new-expression.  */
-  return build_new (placement, type, initializer, global_scope_p);
+  return build_new (placement, type, nelts, initializer, global_scope_p);
 }
 
 /* Parse a new-placement.
@@ -4454,7 +4851,7 @@ cp_parser_new_placement (cp_parser* parser)
   tree expression_list;
 
   /* Parse the expression-list.  */
-  expression_list = (cp_parser_parenthesized_expression_list 
+  expression_list = (cp_parser_parenthesized_expression_list
                     (parser, false, /*non_constant_p=*/NULL));
 
   return expression_list;
@@ -4465,15 +4862,19 @@ cp_parser_new_placement (cp_parser* parser)
    new-type-id:
      type-specifier-seq new-declarator [opt]
 
-   Returns a TREE_LIST whose TREE_PURPOSE is the type-specifier-seq,
-   and whose TREE_VALUE is the new-declarator.  */
+   Returns the TYPE allocated.  If the new-type-id indicates an array
+   type, *NELTS is set to the number of elements in the last array
+   bound; the TYPE will not include the last array bound.  */
 
 static tree
-cp_parser_new_type_id (cp_parser* parser)
+cp_parser_new_type_id (cp_parser* parser, tree *nelts)
 {
-  tree type_specifier_seq;
-  tree declarator;
+  cp_decl_specifier_seq type_specifier_seq;
+  cp_declarator *new_declarator;
+  cp_declarator *declarator;
+  cp_declarator *outer_declarator;
   const char *saved_message;
+  tree type;
 
   /* The type-specifier sequence must not contain type definitions.
      (It cannot contain declarations of new types either, but if they
@@ -4483,13 +4884,60 @@ cp_parser_new_type_id (cp_parser* parser)
   parser->type_definition_forbidden_message
     = "types may not be defined in a new-type-id";
   /* Parse the type-specifier-seq.  */
-  type_specifier_seq = cp_parser_type_specifier_seq (parser);
+  cp_parser_type_specifier_seq (parser, &type_specifier_seq);
   /* Restore the old message.  */
   parser->type_definition_forbidden_message = saved_message;
   /* Parse the new-declarator.  */
-  declarator = cp_parser_new_declarator_opt (parser);
+  new_declarator = cp_parser_new_declarator_opt (parser);
 
-  return build_tree_list (type_specifier_seq, declarator);
+  /* Determine the number of elements in the last array dimension, if
+     any.  */
+  *nelts = NULL_TREE;
+  /* Skip down to the last array dimension.  */
+  declarator = new_declarator;
+  outer_declarator = NULL;
+  while (declarator && (declarator->kind == cdk_pointer
+                       || declarator->kind == cdk_ptrmem))
+    {
+      outer_declarator = declarator;
+      declarator = declarator->declarator;
+    }
+  while (declarator
+        && declarator->kind == cdk_array
+        && declarator->declarator
+        && declarator->declarator->kind == cdk_array)
+    {
+      outer_declarator = declarator;
+      declarator = declarator->declarator;
+    }
+
+  if (declarator && declarator->kind == cdk_array)
+    {
+      *nelts = declarator->u.array.bounds;
+      if (*nelts == error_mark_node)
+       *nelts = integer_one_node;
+      else if (!processing_template_decl)
+       {
+         if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, *nelts,
+                                          false))
+           pedwarn ("size in array new must have integral type");
+         *nelts = save_expr (cp_convert (sizetype, *nelts));
+         if (*nelts == integer_zero_node)
+           warning ("zero size array reserves no space");
+       }
+      if (outer_declarator)
+       outer_declarator->declarator = declarator->declarator;
+      else
+       new_declarator = NULL;
+    }
+
+  type = groktypename (&type_specifier_seq, new_declarator);
+  if (TREE_CODE (type) == ARRAY_TYPE && *nelts == NULL_TREE)
+    {
+      *nelts = array_type_nelts_top (type);
+      type = TREE_TYPE (type);
+    }
+  return type;
 }
 
 /* Parse an (optional) new-declarator.
@@ -4498,39 +4946,34 @@ cp_parser_new_type_id (cp_parser* parser)
      ptr-operator new-declarator [opt]
      direct-new-declarator
 
-   Returns a representation of the declarator.  See
-   cp_parser_declarator for the representations used.  */
+   Returns the declarator.  */
 
-static tree
+static cp_declarator *
 cp_parser_new_declarator_opt (cp_parser* parser)
 {
   enum tree_code code;
   tree type;
-  tree cv_qualifier_seq;
+  cp_cv_quals cv_quals;
 
   /* We don't know if there's a ptr-operator next, or not.  */
   cp_parser_parse_tentatively (parser);
   /* Look for a ptr-operator.  */
-  code = cp_parser_ptr_operator (parser, &type, &cv_qualifier_seq);
+  code = cp_parser_ptr_operator (parser, &type, &cv_quals);
   /* If that worked, look for more new-declarators.  */
   if (cp_parser_parse_definitely (parser))
     {
-      tree declarator;
+      cp_declarator *declarator;
 
       /* Parse another optional declarator.  */
       declarator = cp_parser_new_declarator_opt (parser);
 
       /* Create the representation of the declarator.  */
-      if (code == INDIRECT_REF)
-       declarator = make_pointer_declarator (cv_qualifier_seq,
-                                             declarator);
+      if (type)
+       declarator = make_ptrmem_declarator (cv_quals, type, declarator);
+      else if (code == INDIRECT_REF)
+       declarator = make_pointer_declarator (cv_quals, declarator);
       else
-       declarator = make_reference_declarator (cv_qualifier_seq,
-                                               declarator);
-
-     /* Handle the pointer-to-member case.  */
-     if (type)
-       declarator = build_nt (SCOPE_REF, type, declarator);
+       declarator = make_reference_declarator (cv_quals, declarator);
 
       return declarator;
     }
@@ -4539,22 +4982,21 @@ cp_parser_new_declarator_opt (cp_parser* parser)
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
     return cp_parser_direct_new_declarator (parser);
 
-  return NULL_TREE;
+  return NULL;
 }
 
 /* Parse a direct-new-declarator.
 
    direct-new-declarator:
      [ expression ]
-     direct-new-declarator [constant-expression]  
+     direct-new-declarator [constant-expression]
 
-   Returns an ARRAY_REF, following the same conventions as are
-   documented for cp_parser_direct_declarator.  */
+   */
 
-static tree
+static cp_declarator *
 cp_parser_direct_new_declarator (cp_parser* parser)
 {
-  tree declarator = NULL_TREE;
+  cp_declarator *declarator = NULL;
 
   while (true)
     {
@@ -4574,7 +5016,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
             enumeration type.  */
          if (!processing_template_decl)
            {
-             expression 
+             expression
                = build_expr_type_conversion (WANT_INT | WANT_ENUM,
                                              expression,
                                              /*complain=*/true);
@@ -4587,15 +5029,15 @@ cp_parser_direct_new_declarator (cp_parser* parser)
        }
       /* But all the other expressions must be.  */
       else
-       expression 
-         = cp_parser_constant_expression (parser, 
+       expression
+         = cp_parser_constant_expression (parser,
                                           /*allow_non_constant=*/false,
                                           NULL);
       /* Look for the closing `]'.  */
       cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
 
       /* Add this bound to the declarator.  */
-      declarator = build_nt (ARRAY_REF, declarator, expression);
+      declarator = make_array_declarator (declarator, expression);
 
       /* If the next token is not a `[', then there are no more
         bounds.  */
@@ -4619,7 +5061,7 @@ cp_parser_new_initializer (cp_parser* parser)
 {
   tree expression_list;
 
-  expression_list = (cp_parser_parenthesized_expression_list 
+  expression_list = (cp_parser_parenthesized_expression_list
                     (parser, false, /*non_constant_p=*/NULL));
   if (!expression_list)
     expression_list = void_zero_node;
@@ -4665,6 +5107,11 @@ cp_parser_delete_expression (cp_parser* parser)
   /* Parse the cast-expression.  */
   expression = cp_parser_simple_cast_expression (parser);
 
+  /* A delete-expression may not appear in an integral constant
+     expression.  */
+  if (cp_parser_non_integral_constant_expression (parser, "`delete'"))
+    return error_mark_node;
+
   return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
 }
 
@@ -4706,18 +5153,18 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
         the type-id, and it happens to be a class-specifier, then we
         will commit to the parse at that point, because we cannot
         undo the action that is done when creating a new class.  So,
-        then we cannot back up and do a postfix-expression.  
+        then we cannot back up and do a postfix-expression.
 
         Therefore, we scan ahead to the closing `)', and check to see
         if the token after the `)' is a `{'.  If so, we are not
-        looking at a cast-expression.  
+        looking at a cast-expression.
 
         Save tokens so that we can put them back.  */
       cp_lexer_save_tokens (parser->lexer);
       /* Skip tokens until the next token is a closing parenthesis.
         If we find the closing `)', and the next token is a `{', then
         we are looking at a compound-literal.  */
-      compound_literal_p 
+      compound_literal_p
        = (cp_parser_skip_to_closing_parenthesis (parser, false, false,
                                                  /*consume_paren=*/true)
           && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
@@ -4752,9 +5199,9 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
       if (cp_parser_parse_definitely (parser))
        {
          /* Warn about old-style casts, if so requested.  */
-         if (warn_old_style_cast 
-             && !in_system_header 
-             && !VOID_TYPE_P (type) 
+         if (warn_old_style_cast
+             && !in_system_header
+             && !VOID_TYPE_P (type)
              && current_lang_name != lang_name_c)
            warning ("use of old-style cast");
 
@@ -4762,14 +5209,13 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
             can be used in constant-expressions.  */
          if (parser->integral_constant_expression_p
              && !dependent_type_p (type)
-             && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-           {
-             if (!parser->allow_non_integral_constant_expression_p)
-               return (cp_parser_non_integral_constant_expression 
-                       ("a casts to a type other than an integral or "
-                        "enumeration type"));
-             parser->non_integral_constant_expression_p = true;
-           }
+             && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+             && (cp_parser_non_integral_constant_expression
+                 (parser,
+                  "a cast to a type other than an integral or "
+                  "enumeration type")))
+           return error_mark_node;
+
          /* Perform the cast.  */
          expr = build_c_cast (type, expr);
          return expr;
@@ -4799,13 +5245,13 @@ cp_parser_pm_expression (cp_parser* parser)
     { CPP_EOF, ERROR_MARK }
   };
 
-  return cp_parser_binary_expression (parser, map, 
+  return cp_parser_binary_expression (parser, map,
                                      cp_parser_simple_cast_expression);
 }
 
 /* Parse a multiplicative-expression.
 
-   mulitplicative-expression:
+   multiplicative-expression:
      pm-expression
      multiplicative-expression * pm-expression
      multiplicative-expression / pm-expression
@@ -5046,9 +5492,9 @@ cp_parser_logical_or_expression (cp_parser* parser)
    This routine is used by cp_parser_assignment_expression.
 
      ? expression : assignment-expression
-   
+
    GNU Extensions:
-   
+
      ? : assignment-expression */
 
 static tree
@@ -5066,7 +5512,7 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
   else
     /* Parse the expression.  */
     expr = cp_parser_expression (parser);
-  
+
   /* The next token should be a `:'.  */
   cp_parser_require (parser, CPP_COLON, "`:'");
   /* Parse the assignment-expression.  */
@@ -5106,13 +5552,13 @@ cp_parser_assignment_expression (cp_parser* parser)
         conditional-expression.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
        return cp_parser_question_colon_clause (parser, expr);
-      else 
+      else
        {
          enum tree_code assignment_operator;
 
          /* If it's an assignment-operator, we're using the second
             production.  */
-         assignment_operator 
+         assignment_operator
            = cp_parser_assignment_operator_opt (parser);
          if (assignment_operator != ERROR_MARK)
            {
@@ -5122,15 +5568,12 @@ cp_parser_assignment_expression (cp_parser* parser)
              rhs = cp_parser_assignment_expression (parser);
              /* An assignment may not appear in a
                 constant-expression.  */
-             if (parser->integral_constant_expression_p)
-               {
-                 if (!parser->allow_non_integral_constant_expression_p)
-                   return cp_parser_non_integral_constant_expression ("an assignment");
-                 parser->non_integral_constant_expression_p = true;
-               }
+             if (cp_parser_non_integral_constant_expression (parser,
+                                                             "an assignment"))
+               return error_mark_node;
              /* Build the assignment expression.  */
-             expr = build_x_modify_expr (expr, 
-                                         assignment_operator, 
+             expr = build_x_modify_expr (expr,
+                                         assignment_operator,
                                          rhs);
            }
        }
@@ -5141,11 +5584,11 @@ cp_parser_assignment_expression (cp_parser* parser)
 
 /* Parse an (optional) assignment-operator.
 
-   assignment-operator: one of 
-     = *= /= %= += -= >>= <<= &= ^= |=  
+   assignment-operator: one of
+     = *= /= %= += -= >>= <<= &= ^= |=
 
    GNU Extension:
-   
+
    assignment-operator: one of
      <?= >?=
 
@@ -5219,7 +5662,7 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
       op = MAX_EXPR;
       break;
 
-    default: 
+    default:
       /* Nothing else is an assignment operator.  */
       op = ERROR_MARK;
     }
@@ -5249,7 +5692,7 @@ cp_parser_expression (cp_parser* parser)
       tree assignment_expression;
 
       /* Parse the next assignment-expression.  */
-      assignment_expression 
+      assignment_expression
        = cp_parser_assignment_expression (parser);
       /* If this is the first assignment-expression, we can just
         save it away.  */
@@ -5265,22 +5708,18 @@ cp_parser_expression (cp_parser* parser)
       /* Consume the `,'.  */
       cp_lexer_consume_token (parser->lexer);
       /* A comma operator cannot appear in a constant-expression.  */
-      if (parser->integral_constant_expression_p)
-       {
-         if (!parser->allow_non_integral_constant_expression_p)
-           expression 
-             = cp_parser_non_integral_constant_expression ("a comma operator");
-         parser->non_integral_constant_expression_p = true;
-       }
+      if (cp_parser_non_integral_constant_expression (parser,
+                                                     "a comma operator"))
+       expression = error_mark_node;
     }
 
   return expression;
 }
 
-/* Parse a constant-expression. 
+/* Parse a constant-expression.
 
    constant-expression:
-     conditional-expression  
+     conditional-expression
 
   If ALLOW_NON_CONSTANT_P a non-constant expression is silently
   accepted.  If ALLOW_NON_CONSTANT_P is true and the expression is not
@@ -5288,7 +5727,7 @@ cp_parser_expression (cp_parser* parser)
   is false, NON_CONSTANT_P should be NULL.  */
 
 static tree
-cp_parser_constant_expression (cp_parser* parser, 
+cp_parser_constant_expression (cp_parser* parser,
                               bool allow_non_constant_p,
                               bool *non_constant_p)
 {
@@ -5316,7 +5755,7 @@ cp_parser_constant_expression (cp_parser* parser,
 
   /* Save the old settings.  */
   saved_integral_constant_expression_p = parser->integral_constant_expression_p;
-  saved_allow_non_integral_constant_expression_p 
+  saved_allow_non_integral_constant_expression_p
     = parser->allow_non_integral_constant_expression_p;
   saved_non_integral_constant_expression_p = parser->non_integral_constant_expression_p;
   /* We are now parsing a constant-expression.  */
@@ -5335,7 +5774,7 @@ cp_parser_constant_expression (cp_parser* parser,
   expression = cp_parser_assignment_expression (parser);
   /* Restore the old settings.  */
   parser->integral_constant_expression_p = saved_integral_constant_expression_p;
-  parser->allow_non_integral_constant_expression_p 
+  parser->allow_non_integral_constant_expression_p
     = saved_allow_non_integral_constant_expression_p;
   if (allow_non_constant_p)
     *non_constant_p = parser->non_integral_constant_expression_p;
@@ -5344,9 +5783,96 @@ cp_parser_constant_expression (cp_parser* parser,
   return expression;
 }
 
+/* Parse __builtin_offsetof.
+
+   offsetof-expression:
+     "__builtin_offsetof" "(" type-id "," offsetof-member-designator ")"
+
+   offsetof-member-designator:
+     id-expression
+     | offsetof-member-designator "." id-expression
+     | offsetof-member-designator "[" expression "]"
+*/
+
+static tree
+cp_parser_builtin_offsetof (cp_parser *parser)
+{
+  int save_ice_p, save_non_ice_p;
+  tree type, expr;
+  cp_id_kind dummy;
+
+  /* We're about to accept non-integral-constant things, but will
+     definitely yield an integral constant expression.  Save and
+     restore these values around our local parsing.  */
+  save_ice_p = parser->integral_constant_expression_p;
+  save_non_ice_p = parser->non_integral_constant_expression_p;
+
+  /* Consume the "__builtin_offsetof" token.  */
+  cp_lexer_consume_token (parser->lexer);
+  /* Consume the opening `('.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  /* Parse the type-id.  */
+  type = cp_parser_type_id (parser);
+  /* Look for the `,'.  */
+  cp_parser_require (parser, CPP_COMMA, "`,'");
+
+  /* Build the (type *)null that begins the traditional offsetof macro.  */
+  expr = build_static_cast (build_pointer_type (type), null_pointer_node);
+
+  /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
+  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
+                                                true, &dummy);
+  while (true)
+    {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      switch (token->type)
+       {
+       case CPP_OPEN_SQUARE:
+         /* offsetof-member-designator "[" expression "]" */
+         expr = cp_parser_postfix_open_square_expression (parser, expr, true);
+         break;
+
+       case CPP_DOT:
+         /* offsetof-member-designator "." identifier */
+         cp_lexer_consume_token (parser->lexer);
+         expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
+                                                        true, &dummy);
+         break;
+
+       case CPP_CLOSE_PAREN:
+         /* Consume the ")" token.  */
+         cp_lexer_consume_token (parser->lexer);
+         goto success;
+
+       default:
+         /* Error.  We know the following require will fail, but
+            that gives the proper error message.  */
+         cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+         cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
+         expr = error_mark_node;
+         goto failure;
+       }
+    }
+
+ success:
+  /* We've finished the parsing, now finish with the semantics.  At present
+     we're just mirroring the traditional macro implementation.  Better
+     would be to do the lowering of the ADDR_EXPR to flat pointer arithmetic
+     here rather than in build_x_unary_op.  */
+  expr = build_reinterpret_cast (build_reference_type (char_type_node), expr);
+  expr = build_x_unary_op (ADDR_EXPR, expr);
+  expr = build_reinterpret_cast (size_type_node, expr);
+
+ failure:
+  parser->integral_constant_expression_p = save_ice_p;
+  parser->non_integral_constant_expression_p = save_non_ice_p;
+
+  return expr;
+}
+
 /* Statements [gram.stmt.stmt]  */
 
-/* Parse a statement.  
+/* Parse a statement.
 
    statement:
      labeled-statement
@@ -5359,18 +5885,18 @@ cp_parser_constant_expression (cp_parser* parser,
      try-block  */
 
 static void
-cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
+cp_parser_statement (cp_parser* parser, tree in_statement_expr)
 {
   tree statement;
   cp_token *token;
-  int statement_line_number;
+  location_t statement_location;
 
   /* There is no statement yet.  */
   statement = NULL_TREE;
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
-  /* Remember the line number of the first token in the statement.  */
-  statement_line_number = token->location.line;
+  /* Remember the location of the first token in the statement.  */
+  statement_location = token->location;
   /* If this is a keyword, then that will often determine what kind of
      statement we have.  */
   if (token->type == CPP_KEYWORD)
@@ -5382,7 +5908,7 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
        case RID_CASE:
        case RID_DEFAULT:
          statement = cp_parser_labeled_statement (parser,
-                                                  in_statement_expr_p);
+                                                  in_statement_expr);
          break;
 
        case RID_IF:
@@ -5419,14 +5945,14 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
         labeled-statement.  */
       token = cp_lexer_peek_nth_token (parser->lexer, 2);
       if (token->type == CPP_COLON)
-       statement = cp_parser_labeled_statement (parser, in_statement_expr_p);
+       statement = cp_parser_labeled_statement (parser, in_statement_expr);
     }
   /* Anything that starts with a `{' must be a compound-statement.  */
   else if (token->type == CPP_OPEN_BRACE)
-    statement = cp_parser_compound_statement (parser, false);
+    statement = cp_parser_compound_statement (parser, NULL, false);
 
   /* Everything else must be a declaration-statement or an
-     expression-statement.  Try for the declaration-statement 
+     expression-statement.  Try for the declaration-statement
      first, unless we are looking at a `;', in which case we know that
      we have an expression-statement.  */
   if (!statement)
@@ -5441,12 +5967,12 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
            return;
        }
       /* Look for an expression-statement instead.  */
-      statement = cp_parser_expression_statement (parser, in_statement_expr_p);
+      statement = cp_parser_expression_statement (parser, in_statement_expr);
     }
 
   /* Set the line number for the statement.  */
   if (statement && STATEMENT_CODE_P (TREE_CODE (statement)))
-    STMT_LINENO (statement) = statement_line_number;
+    SET_EXPR_LOCATION (statement, statement_location);
 }
 
 /* Parse a labeled-statement.
@@ -5454,13 +5980,18 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
    labeled-statement:
      identifier : statement
      case constant-expression : statement
-     default : statement  
+     default : statement
 
-   Returns the new CASE_LABEL, for a `case' or `default' label.  For
-   an ordinary label, returns a LABEL_STMT.  */
+   GNU Extension:
+
+   labeled-statement:
+     case constant-expression ... constant-expression : statement
+
+   Returns the new CASE_LABEL_EXPR, for a `case' or `default' label.
+   For an ordinary label, returns a LABEL_EXPR.  */
 
 static tree
-cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
+cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
 {
   cp_token *token;
   tree statement = error_mark_node;
@@ -5478,18 +6009,35 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
     {
     case RID_CASE:
       {
-       tree expr;
+       tree expr, expr_hi;
+       cp_token *ellipsis;
 
        /* Consume the `case' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Parse the constant-expression.  */
-       expr = cp_parser_constant_expression (parser, 
+       expr = cp_parser_constant_expression (parser,
                                              /*allow_non_constant_p=*/false,
                                              NULL);
+
+       ellipsis = cp_lexer_peek_token (parser->lexer);
+       if (ellipsis->type == CPP_ELLIPSIS)
+         {
+            /* Consume the `...' token.  */
+           cp_lexer_consume_token (parser->lexer);
+           expr_hi =
+             cp_parser_constant_expression (parser,
+                                            /*allow_non_constant_p=*/false,
+                                            NULL);
+           /* We don't need to emit warnings here, as the common code
+              will do this for us.  */
+         }
+       else
+         expr_hi = NULL_TREE;
+
        if (!parser->in_switch_statement_p)
          error ("case label `%E' not within a switch statement", expr);
        else
-         statement = finish_case_label (expr, NULL_TREE);
+         statement = finish_case_label (expr, expr_hi);
       }
       break;
 
@@ -5511,7 +6059,7 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
   /* Require the `:' token.  */
   cp_parser_require (parser, CPP_COLON, "`:'");
   /* Parse the labeled statement.  */
-  cp_parser_statement (parser, in_statement_expr_p);
+  cp_parser_statement (parser, in_statement_expr);
 
   /* Return the label, in the case of a `case' or `default' label.  */
   return statement;
@@ -5528,7 +6076,7 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
    expression statement.  */
 
 static tree
-cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p)
+cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
 {
   tree statement = NULL_TREE;
 
@@ -5536,22 +6084,22 @@ cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p)
      statement.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     statement = cp_parser_expression (parser);
-  
+
   /* Consume the final `;'.  */
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
-  if (in_statement_expr_p
+  if (in_statement_expr
       && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
     {
       /* This is the final expression statement of a statement
         expression.  */
-      statement = finish_stmt_expr_expr (statement);
+      statement = finish_stmt_expr_expr (statement, in_statement_expr);
     }
   else if (statement)
     statement = finish_expr_stmt (statement);
   else
     finish_stmt ();
-  
+
   return statement;
 }
 
@@ -5559,11 +6107,12 @@ cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p)
 
    compound-statement:
      { statement-seq [opt] }
-     
-   Returns a COMPOUND_STMT representing the statement.  */
+
+   Returns a tree representing the statement.  */
 
 static tree
-cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p)
+cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
+                             bool in_try)
 {
   tree compound_stmt;
 
@@ -5571,9 +6120,9 @@ cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p)
   if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
     return error_mark_node;
   /* Begin the compound-statement.  */
-  compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+  compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
   /* Parse an (optional) statement-seq.  */
-  cp_parser_statement_seq_opt (parser, in_statement_expr_p);
+  cp_parser_statement_seq_opt (parser, in_statement_expr);
   /* Finish the compound-statement.  */
   finish_compound_stmt (compound_stmt);
   /* Consume the `}'.  */
@@ -5589,7 +6138,7 @@ cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p)
      statement-seq [opt] statement  */
 
 static void
-cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p)
+cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
 {
   /* Scan statements until there aren't any more.  */
   while (true)
@@ -5600,7 +6149,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p)
        break;
 
       /* Parse the statement.  */
-      cp_parser_statement (parser, in_statement_expr_p);
+      cp_parser_statement (parser, in_statement_expr);
     }
 }
 
@@ -5609,7 +6158,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p)
    selection-statement:
      if ( condition ) statement
      if ( condition ) statement else statement
-     switch ( condition ) statement  
+     switch ( condition ) statement
 
    Returns the new IF_STMT or SWITCH_STMT.  */
 
@@ -5654,35 +6203,30 @@ cp_parser_selection_statement (cp_parser* parser)
 
        if (keyword == RID_IF)
          {
-           tree then_stmt;
-
            /* Add the condition.  */
            finish_if_stmt_cond (condition, statement);
 
            /* Parse the then-clause.  */
-           then_stmt = cp_parser_implicitly_scoped_statement (parser);
+           cp_parser_implicitly_scoped_statement (parser);
            finish_then_clause (statement);
 
            /* If the next token is `else', parse the else-clause.  */
            if (cp_lexer_next_token_is_keyword (parser->lexer,
                                                RID_ELSE))
              {
-               tree else_stmt;
-
                /* Consume the `else' keyword.  */
                cp_lexer_consume_token (parser->lexer);
+               begin_else_clause (statement);
                /* Parse the else-clause.  */
-               else_stmt 
-                 = cp_parser_implicitly_scoped_statement (parser);
+               cp_parser_implicitly_scoped_statement (parser);
                finish_else_clause (statement);
              }
 
            /* Now we're all done with the if-statement.  */
-           finish_if_stmt ();
+           finish_if_stmt (statement);
          }
        else
          {
-           tree body;
            bool in_switch_statement_p;
 
            /* Add the condition.  */
@@ -5691,7 +6235,7 @@ cp_parser_selection_statement (cp_parser* parser)
            /* Parse the body of the switch-statement.  */
            in_switch_statement_p = parser->in_switch_statement_p;
            parser->in_switch_statement_p = true;
-           body = cp_parser_implicitly_scoped_statement (parser);
+           cp_parser_implicitly_scoped_statement (parser);
            parser->in_switch_statement_p = in_switch_statement_p;
 
            /* Now we're all done with the switch-statement.  */
@@ -5708,24 +6252,24 @@ cp_parser_selection_statement (cp_parser* parser)
     }
 }
 
-/* Parse a condition. 
+/* Parse a condition.
 
    condition:
      expression
-     type-specifier-seq declarator = assignment-expression  
+     type-specifier-seq declarator = assignment-expression
 
    GNU Extension:
-   
+
    condition:
-     type-specifier-seq declarator asm-specification [opt] 
+     type-specifier-seq declarator asm-specification [opt]
        attributes [opt] = assignment-expression
+
    Returns the expression that should be tested.  */
 
 static tree
 cp_parser_condition (cp_parser* parser)
 {
-  tree type_specifiers;
+  cp_decl_specifier_seq type_specifiers;
   const char *saved_message;
 
   /* Try the declaration first.  */
@@ -5736,7 +6280,7 @@ cp_parser_condition (cp_parser* parser)
   parser->type_definition_forbidden_message
     = "types may not be defined in conditions";
   /* Parse the type-specifier-seq.  */
-  type_specifiers = cp_parser_type_specifier_seq (parser);
+  cp_parser_type_specifier_seq (parser, &type_specifiers);
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
   /* If all is well, we might be looking at a declaration.  */
@@ -5745,9 +6289,9 @@ cp_parser_condition (cp_parser* parser)
       tree decl;
       tree asm_specification;
       tree attributes;
-      tree declarator;
+      cp_declarator *declarator;
       tree initializer = NULL_TREE;
-      
+
       /* Parse the declarator.  */
       declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                                         /*ctor_dtor_or_conv_p=*/NULL,
@@ -5758,9 +6302,9 @@ cp_parser_condition (cp_parser* parser)
       asm_specification = cp_parser_asm_specification_opt (parser);
       /* If the next token is not an `=', then we might still be
         looking at an expression.  For example:
-        
+
           if (A(a).x)
-         
+
         looks like a decl-specifier-seq and a declarator -- but then
         there is no `=', so this is an expression.  */
       cp_parser_require (parser, CPP_EQ, "`='");
@@ -5769,18 +6313,18 @@ cp_parser_condition (cp_parser* parser)
       if (cp_parser_parse_definitely (parser))
        {
          /* Create the declaration.  */
-         decl = start_decl (declarator, type_specifiers, 
+         decl = start_decl (declarator, &type_specifiers,
                             /*initialized_p=*/true,
                             attributes, /*prefix_attributes=*/NULL_TREE);
          /* Parse the assignment-expression.  */
          initializer = cp_parser_assignment_expression (parser);
-         
+
          /* Process the initializer.  */
-         cp_finish_decl (decl, 
-                         initializer, 
-                         asm_specification, 
+         cp_finish_decl (decl,
+                         initializer,
+                         asm_specification,
                          LOOKUP_ONLYCONVERTING);
-         
+
          return convert_from_reference (decl);
        }
     }
@@ -5818,7 +6362,7 @@ cp_parser_iteration_statement (cp_parser* parser)
     return error_mark_node;
 
   /* Remember whether or not we are already within an iteration
-     statement.  */ 
+     statement.  */
   in_iteration_statement_p = parser->in_iteration_statement_p;
 
   /* See what kind of keyword it is.  */
@@ -5898,7 +6442,7 @@ cp_parser_iteration_statement (cp_parser* parser)
          expression = cp_parser_expression (parser);
        finish_for_expr (expression, statement);
        /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`;'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
        /* Parse the body of the for-statement.  */
        parser->in_iteration_statement_p = true;
@@ -5957,15 +6501,14 @@ cp_parser_for_init_statement (cp_parser* parser)
      break ;
      continue ;
      return expression [opt] ;
-     goto identifier ;  
+     goto identifier ;
 
    GNU extension:
 
    jump-statement:
      goto * expression ;
 
-   Returns the new BREAK_STMT, CONTINUE_STMT, RETURN_STMT, or
-   GOTO_STMT.  */
+   Returns the new BREAK_STMT, CONTINUE_STMT, RETURN_EXPR, or GOTO_EXPR.  */
 
 static tree
 cp_parser_jump_statement (cp_parser* parser)
@@ -6010,7 +6553,7 @@ cp_parser_jump_statement (cp_parser* parser)
       {
        tree expr;
 
-       /* If the next token is a `;', then there is no 
+       /* If the next token is a `;', then there is no
           expression.  */
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
          expr = cp_parser_expression (parser);
@@ -6057,9 +6600,17 @@ cp_parser_jump_statement (cp_parser* parser)
 static void
 cp_parser_declaration_statement (cp_parser* parser)
 {
-  /* Parse the block-declaration.  */
+  void *p;
+
+  /* Get the high-water mark for the DECLARATOR_OBSTACK.  */
+  p = obstack_alloc (&declarator_obstack, 0);
+
+ /* Parse the block-declaration.  */
   cp_parser_block_declaration (parser, /*statement_p=*/true);
 
+  /* Free any declarators allocated.  */
+  obstack_free (&declarator_obstack, p);
+
   /* Finish off the statement.  */
   finish_stmt ();
 }
@@ -6071,7 +6622,7 @@ cp_parser_declaration_statement (cp_parser* parser)
    declarations appearing in the dependent statement are out of scope
    after control passes that point.  This function parses a statement,
    but ensures that is in its own scope, even if it is not a
-   compound-statement.  
+   compound-statement.
 
    Returns the new statement.  */
 
@@ -6084,7 +6635,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
     {
       /* Create a compound-statement.  */
-      statement = begin_compound_stmt (/*has_no_scope=*/false);
+      statement = begin_compound_stmt (0);
       /* Parse the dependent-statement.  */
       cp_parser_statement (parser, false);
       /* Finish the dummy compound-statement.  */
@@ -6092,7 +6643,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
     }
   /* Otherwise, we simply parse the statement directly.  */
   else
-    statement = cp_parser_compound_statement (parser, false);
+    statement = cp_parser_compound_statement (parser, NULL, false);
 
   /* Return the statement.  */
   return statement;
@@ -6106,21 +6657,17 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
 static void
 cp_parser_already_scoped_statement (cp_parser* parser)
 {
-  /* If the token is not a `{', then we must take special action.  */
-  if (cp_lexer_next_token_is_not(parser->lexer, CPP_OPEN_BRACE))
+  /* If the token is a `{', then we must take special action.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+    cp_parser_statement (parser, false);
+  else
     {
-      tree statement;
-
-      /* Create a compound-statement.  */
-      statement = begin_compound_stmt (/*has_no_scope=*/true);
-      /* Parse the dependent-statement.  */
-      cp_parser_statement (parser, false);
-      /* Finish the dummy compound-statement.  */
-      finish_compound_stmt (statement);
+      /* Avoid calling cp_parser_compound_statement, so that we
+        don't create a new scope.  Do everything else by hand.  */
+      cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+      cp_parser_statement_seq_opt (parser, false);
+      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
     }
-  /* Otherwise, we simply parse the statement directly.  */
-  else
-    cp_parser_statement (parser, false);
 }
 
 /* Declarations [gram.dcl.dcl] */
@@ -6144,7 +6691,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
          || token->type == CPP_EOF)
        break;
 
-      if (token->type == CPP_SEMICOLON) 
+      if (token->type == CPP_SEMICOLON)
        {
          /* A declaration consisting of a single semicolon is
             invalid.  Allow it unless we're being pedantic.  */
@@ -6181,7 +6728,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
      explicit-instantiation
      explicit-specialization
      linkage-specification
-     namespace-definition    
+     namespace-definition
 
    GNU extension:
 
@@ -6194,6 +6741,11 @@ cp_parser_declaration (cp_parser* parser)
   cp_token token1;
   cp_token token2;
   int saved_pedantic;
+  void *p;
+
+  /* Set this here since we can be called after
+     pushing the linkage specification.  */
+  c_lex_string_translate = 1;
 
   /* Check for the `__extension__' keyword.  */
   if (cp_parser_extension_opt (parser, &saved_pedantic))
@@ -6208,9 +6760,19 @@ cp_parser_declaration (cp_parser* parser)
 
   /* Try to figure out what kind of declaration is present.  */
   token1 = *cp_lexer_peek_token (parser->lexer);
+
+  /* Don't translate the CPP_STRING in extern "C".  */
+  if (token1.keyword == RID_EXTERN)
+    c_lex_string_translate = 0;
+
   if (token1.type != CPP_EOF)
     token2 = *cp_lexer_peek_nth_token (parser->lexer, 2);
 
+  c_lex_string_translate = 1;
+
+  /* Get the high-water mark for the DECLARATOR_OBSTACK.  */
+  p = obstack_alloc (&declarator_obstack, 0);
+
   /* If the next token is `extern' and the following token is a string
      literal, then we have a linkage specification.  */
   if (token1.keyword == RID_EXTERN
@@ -6250,7 +6812,7 @@ cp_parser_declaration (cp_parser* parser)
   else if (token1.keyword == RID_NAMESPACE
           && (/* A named namespace definition.  */
               (token2.type == CPP_NAME
-               && (cp_lexer_peek_nth_token (parser->lexer, 3)->type 
+               && (cp_lexer_peek_nth_token (parser->lexer, 3)->type
                    == CPP_OPEN_BRACE))
               /* An unnamed namespace definition.  */
               || token2.type == CPP_OPEN_BRACE))
@@ -6260,28 +6822,31 @@ cp_parser_declaration (cp_parser* parser)
   else
     /* Try to parse a block-declaration, or a function-definition.  */
     cp_parser_block_declaration (parser, /*statement_p=*/false);
+
+  /* Free any declarators allocated.  */
+  obstack_free (&declarator_obstack, p);
 }
 
-/* Parse a block-declaration.  
+/* Parse a block-declaration.
 
    block-declaration:
      simple-declaration
      asm-definition
      namespace-alias-definition
      using-declaration
-     using-directive  
+     using-directive
 
    GNU Extension:
 
    block-declaration:
-     __extension__ block-declaration 
+     __extension__ block-declaration
      label-declaration
 
    If STATEMENT_P is TRUE, then this block-declaration is occurring as
    part of a declaration-statement.  */
 
 static void
-cp_parser_block_declaration (cp_parser *parser, 
+cp_parser_block_declaration (cp_parser *parser,
                             bool      statement_p)
 {
   cp_token *token1;
@@ -6345,21 +6910,20 @@ cp_parser_block_declaration (cp_parser *parser,
 /* Parse a simple-declaration.
 
    simple-declaration:
-     decl-specifier-seq [opt] init-declarator-list [opt] ;  
+     decl-specifier-seq [opt] init-declarator-list [opt] ;
 
    init-declarator-list:
      init-declarator
-     init-declarator-list , init-declarator 
+     init-declarator-list , init-declarator
 
    If FUNCTION_DEFINITION_ALLOWED_P is TRUE, then we also recognize a
    function-definition as a simple-declaration.  */
 
 static void
-cp_parser_simple_declaration (cp_parser* parser, 
+cp_parser_simple_declaration (cp_parser* parser,
                               bool function_definition_allowed_p)
 {
-  tree decl_specifiers;
-  tree attributes;
+  cp_decl_specifier_seq decl_specifiers;
   int declares_class_or_enum;
   bool saw_declarator;
 
@@ -6371,7 +6935,7 @@ cp_parser_simple_declaration (cp_parser* parser,
   /* Parse the decl-specifier-seq.  We have to keep track of whether
      or not the decl-specifier-seq declares a named class or
      enumeration type, since that is the only case in which the
-     init-declarator-list is allowed to be empty.  
+     init-declarator-list is allowed to be empty.
 
      [dcl.dcl]
 
@@ -6379,18 +6943,18 @@ cp_parser_simple_declaration (cp_parser* parser,
      omitted only when declaring a class or enumeration, that is when
      the decl-specifier-seq contains either a class-specifier, an
      elaborated-type-specifier, or an enum-specifier.  */
-  decl_specifiers
-    = cp_parser_decl_specifier_seq (parser, 
-                                   CP_PARSER_FLAGS_OPTIONAL,
-                                   &attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_OPTIONAL,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
   /* We no longer need to defer access checks.  */
   stop_deferring_access_checks ();
 
   /* In a block scope, a valid declaration must always have a
      decl-specifier-seq.  By not trying to parse declarators, we can
      resolve the declaration/expression ambiguity more quickly.  */
-  if (!function_definition_allowed_p && !decl_specifiers)
+  if (!function_definition_allowed_p
+      && !decl_specifiers.any_specifiers_p)
     {
       cp_parser_error (parser, "expected declaration");
       goto done;
@@ -6402,7 +6966,7 @@ cp_parser_simple_declaration (cp_parser* parser,
        T t;
 
      where "T" should name a type -- but does not.  */
-  if (cp_parser_diagnose_invalid_type_name (parser))
+  if (cp_parser_parse_and_diagnose_invalid_type_name (parser))
     {
       /* If parsing tentatively, we should commit; we really are
         looking at a declaration.  */
@@ -6414,7 +6978,7 @@ cp_parser_simple_declaration (cp_parser* parser,
   /* Keep going until we hit the `;' at the end of the simple
      declaration.  */
   saw_declarator = false;
-  while (cp_lexer_next_token_is_not (parser->lexer, 
+  while (cp_lexer_next_token_is_not (parser->lexer,
                                     CPP_SEMICOLON))
     {
       cp_token *token;
@@ -6423,7 +6987,7 @@ cp_parser_simple_declaration (cp_parser* parser,
 
       saw_declarator = true;
       /* Parse the init-declarator.  */
-      decl = cp_parser_init_declarator (parser, decl_specifiers, attributes,
+      decl = cp_parser_init_declarator (parser, &decl_specifiers,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
                                        declares_class_or_enum,
@@ -6466,6 +7030,9 @@ cp_parser_simple_declaration (cp_parser* parser,
          cp_parser_error (parser, "expected `,' or `;'");
          /* Skip tokens until we reach the end of the statement.  */
          cp_parser_skip_to_end_of_statement (parser);
+         /* If the next token is now a `;', consume it.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+           cp_lexer_consume_token (parser->lexer);
          goto done;
        }
       /* After the first time around, a function-definition is not
@@ -6483,7 +7050,7 @@ cp_parser_simple_declaration (cp_parser* parser,
   if (!saw_declarator)
     {
       if (cp_parser_declares_only_class_p (parser))
-       shadow_tag (decl_specifiers);
+       shadow_tag (&decl_specifiers);
       /* Perform any deferred access checks.  */
       perform_deferred_access_checks ();
     }
@@ -6505,27 +7072,20 @@ cp_parser_simple_declaration (cp_parser* parser,
      type-specifier
      function-specifier
      friend
-     typedef  
+     typedef
 
    GNU Extension:
 
-   decl-specifier-seq:
-     decl-specifier-seq [opt] attributes
-
-   Returns a TREE_LIST, giving the decl-specifiers in the order they
-   appear in the source code.  The TREE_VALUE of each node is the
-   decl-specifier.  For a keyword (such as `auto' or `friend'), the
-   TREE_VALUE is simply the corresponding TREE_IDENTIFIER.  For the
-   representation of a type-specifier, see cp_parser_type_specifier.  
+   decl-specifier:
+     attributes
 
-   If there are attributes, they will be stored in *ATTRIBUTES,
-   represented as described above cp_parser_attributes.  
+   Set *DECL_SPECS to a representation of the decl-specifier-seq.
 
    If FRIEND_IS_NOT_CLASS_P is non-NULL, and the `friend' specifier
    appears, and the entity that will be a friend is not going to be a
    class, then *FRIEND_IS_NOT_CLASS_P will be set to TRUE.  Note that
    even if *FRIEND_IS_NOT_CLASS_P is FALSE, the entity to which
-   friendship is granted might not be a class.  
+   friendship is granted might not be a class.
 
    *DECLARES_CLASS_OR_ENUM is set to the bitwise or of the following
    flags:
@@ -6537,27 +7097,25 @@ cp_parser_simple_declaration (cp_parser* parser,
 
    */
 
-static tree
-cp_parser_decl_specifier_seq (cp_parser* parser, 
-                              cp_parser_flags flags, 
-                              tree* attributes,
+static void
+cp_parser_decl_specifier_seq (cp_parser* parser,
+                             cp_parser_flags flags,
+                             cp_decl_specifier_seq *decl_specs,
                              int* declares_class_or_enum)
 {
-  tree decl_specs = NULL_TREE;
-  bool friend_p = false;
   bool constructor_possible_p = !parser->in_declarator_p;
-  
+
+  /* Clear DECL_SPECS.  */
+  clear_decl_specs (decl_specs);
+
   /* Assume no class or enumeration type is declared.  */
   *declares_class_or_enum = 0;
 
-  /* Assume there are no attributes.  */
-  *attributes = NULL_TREE;
-
   /* Keep reading specifiers until there are no more to read.  */
   while (true)
     {
-      tree decl_spec = NULL_TREE;
       bool constructor_p;
+      bool found_decl_spec;
       cp_token *token;
 
       /* Peek at the next token.  */
@@ -6566,25 +7124,22 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       if (token->keyword == RID_ATTRIBUTE)
        {
          /* Parse the attributes.  */
-         decl_spec = cp_parser_attributes_opt (parser);
-         /* Add them to the list.  */
-         *attributes = chainon (*attributes, decl_spec);
+         decl_specs->attributes
+           = chainon (decl_specs->attributes,
+                      cp_parser_attributes_opt (parser));
          continue;
        }
+      /* Assume we will find a decl-specifier keyword.  */
+      found_decl_spec = true;
       /* If the next token is an appropriate keyword, we can simply
         add it to the list.  */
       switch (token->keyword)
        {
-       case RID_FRIEND:
          /* decl-specifier:
               friend  */
-         if (friend_p)
+       case RID_FRIEND:
+         if (decl_specs->specs[(int) ds_friend]++)
            error ("duplicate `friend'");
-         else
-           friend_p = true;
-         /* The representation of the specifier is simply the
-            appropriate TREE_IDENTIFIER node.  */
-         decl_spec = token->value;
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
          break;
@@ -6596,15 +7151,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
        case RID_INLINE:
        case RID_VIRTUAL:
        case RID_EXPLICIT:
-         decl_spec = cp_parser_function_specifier_opt (parser);
+         cp_parser_function_specifier_opt (parser, decl_specs);
          break;
-         
+
          /* decl-specifier:
               typedef  */
        case RID_TYPEDEF:
-         /* The representation of the specifier is simply the
-            appropriate TREE_IDENTIFIER node.  */
-         decl_spec = token->value;
+         ++decl_specs->specs[(int) ds_typedef];
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
          /* A constructor declarator cannot appear in a typedef.  */
@@ -6619,40 +7172,76 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
               register
               static
               extern
-              mutable  
+              mutable
 
              GNU Extension:
               thread  */
        case RID_AUTO:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_set_storage_class (decl_specs, sc_auto);
+         break;
        case RID_REGISTER:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_set_storage_class (decl_specs, sc_register);
+         break;
        case RID_STATIC:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         if (decl_specs->specs[(int) ds_thread])
+           {
+             error ("`__thread' before `static'");
+             decl_specs->specs[(int) ds_thread] = 0;
+           }
+         cp_parser_set_storage_class (decl_specs, sc_static);
+         break;
        case RID_EXTERN:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         if (decl_specs->specs[(int) ds_thread])
+           {
+             error ("`__thread' before `extern'");
+             decl_specs->specs[(int) ds_thread] = 0;
+           }
+         cp_parser_set_storage_class (decl_specs, sc_extern);
+         break;
        case RID_MUTABLE:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_set_storage_class (decl_specs, sc_mutable);
+         break;
        case RID_THREAD:
-         decl_spec = cp_parser_storage_class_specifier_opt (parser);
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         ++decl_specs->specs[(int) ds_thread];
          break;
-         
+
        default:
+         /* We did not yet find a decl-specifier yet.  */
+         found_decl_spec = false;
          break;
        }
 
       /* Constructors are a special case.  The `S' in `S()' is not a
         decl-specifier; it is the beginning of the declarator.  */
-      constructor_p = (!decl_spec 
-                      && constructor_possible_p
-                      && cp_parser_constructor_declarator_p (parser,
-                                                             friend_p));
+      constructor_p
+       = (!found_decl_spec
+          && constructor_possible_p
+          && (cp_parser_constructor_declarator_p
+              (parser, decl_specs->specs[(int) ds_friend] != 0)));
 
       /* If we don't have a DECL_SPEC yet, then we must be looking at
         a type-specifier.  */
-      if (!decl_spec && !constructor_p)
+      if (!found_decl_spec && !constructor_p)
        {
          int decl_spec_declares_class_or_enum;
          bool is_cv_qualifier;
+         tree type_spec;
 
-         decl_spec
+         type_spec
            = cp_parser_type_specifier (parser, flags,
-                                       friend_p,
+                                       decl_specs,
                                        /*is_declaration=*/true,
                                        &decl_spec_declares_class_or_enum,
                                        &is_cv_qualifier);
@@ -6677,7 +7266,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
             only exceptions are the following:
 
             -- const or volatile can be combined with any other
-               type-specifier. 
+               type-specifier.
 
             -- signed or unsigned can be combined with char, long,
                short, or int.
@@ -6695,54 +7284,41 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
             user-defined types.  We *do* still allow things like `int
             int' to be considered a decl-specifier-seq, and issue the
             error message later.  */
-         if (decl_spec && !is_cv_qualifier)
+         if (type_spec && !is_cv_qualifier)
            flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
          /* A constructor declarator cannot follow a type-specifier.  */
-         if (decl_spec)
-           constructor_possible_p = false;
-       }
-
-      /* If we still do not have a DECL_SPEC, then there are no more
-        decl-specifiers.  */
-      if (!decl_spec)
-       {
-         /* Issue an error message, unless the entire construct was
-             optional.  */
-         if (!(flags & CP_PARSER_FLAGS_OPTIONAL))
+         if (type_spec)
            {
-             cp_parser_error (parser, "expected decl specifier");
-             return error_mark_node;
+             constructor_possible_p = false;
+             found_decl_spec = true;
            }
-
-         break;
        }
 
-      /* Add the DECL_SPEC to the list of specifiers.  */
-      if (decl_specs == NULL || TREE_VALUE (decl_specs) != error_mark_node)
-       decl_specs = tree_cons (NULL_TREE, decl_spec, decl_specs);
+      /* If we still do not have a DECL_SPEC, then there are no more
+        decl-specifiers.  */
+      if (!found_decl_spec)
+       break;
 
+      decl_specs->any_specifiers_p = true;
       /* After we see one decl-specifier, further decl-specifiers are
         always optional.  */
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
   /* Don't allow a friend specifier with a class definition.  */
-  if (friend_p && (*declares_class_or_enum & 2))
+  if (decl_specs->specs[(int) ds_friend] != 0
+      && (*declares_class_or_enum & 2))
     error ("class definition may not be declared a friend");
-
-  /* We have built up the DECL_SPECS in reverse order.  Return them in
-     the correct order.  */
-  return nreverse (decl_specs);
 }
 
-/* Parse an (optional) storage-class-specifier. 
+/* Parse an (optional) storage-class-specifier.
 
    storage-class-specifier:
      auto
      register
      static
      extern
-     mutable  
+     mutable
 
    GNU Extension:
 
@@ -6750,7 +7326,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
      thread
 
    Returns an IDENTIFIER_NODE corresponding to the keyword used.  */
-   
+
 static tree
 cp_parser_storage_class_specifier_opt (cp_parser* parser)
 {
@@ -6770,29 +7346,43 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
     }
 }
 
-/* Parse an (optional) function-specifier. 
+/* Parse an (optional) function-specifier.
 
    function-specifier:
      inline
      virtual
      explicit
 
-   Returns an IDENTIFIER_NODE corresponding to the keyword used.  */
-   
+   Returns an IDENTIFIER_NODE corresponding to the keyword used.
+   Updates DECL_SPECS, if it is non-NULL.  */
+
 static tree
-cp_parser_function_specifier_opt (cp_parser* parser)
+cp_parser_function_specifier_opt (cp_parser* parser,
+                                 cp_decl_specifier_seq *decl_specs)
 {
   switch (cp_lexer_peek_token (parser->lexer)->keyword)
     {
     case RID_INLINE:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_inline];
+      break;
+
     case RID_VIRTUAL:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_virtual];
+      break;
+
     case RID_EXPLICIT:
-      /* Consume the token.  */
-      return cp_lexer_consume_token (parser->lexer)->value;
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_explicit];
+      break;
 
     default:
       return NULL_TREE;
     }
+
+  /* Consume the token.  */
+  return cp_lexer_consume_token (parser->lexer)->value;
 }
 
 /* Parse a linkage-specification.
@@ -6832,6 +7422,10 @@ cp_parser_linkage_specification (cp_parser* parser)
       /* Assume C++ linkage.  */
       linkage = get_identifier ("c++");
     }
+  /* If the string is chained to another string, take the latter,
+     that's the untranslated string.  */
+  else if (TREE_CHAIN (token->value))
+    linkage = get_identifier (TREE_STRING_POINTER (TREE_CHAIN (token->value)));
   /* If it's a simple string constant, things are easier.  */
   else
     linkage = get_identifier (TREE_STRING_POINTER (token->value));
@@ -6855,13 +7449,13 @@ cp_parser_linkage_specification (cp_parser* parser)
     {
       bool saved_in_unbraced_linkage_specification_p;
 
-      saved_in_unbraced_linkage_specification_p 
+      saved_in_unbraced_linkage_specification_p
        = parser->in_unbraced_linkage_specification_p;
       parser->in_unbraced_linkage_specification_p = true;
       have_extern_spec = true;
       cp_parser_declaration (parser);
       have_extern_spec = false;
-      parser->in_unbraced_linkage_specification_p 
+      parser->in_unbraced_linkage_specification_p
        = saved_in_unbraced_linkage_specification_p;
     }
 
@@ -6874,17 +7468,18 @@ cp_parser_linkage_specification (cp_parser* parser)
 /* Parse a conversion-function-id.
 
    conversion-function-id:
-     operator conversion-type-id  
+     operator conversion-type-id
 
    Returns an IDENTIFIER_NODE representing the operator.  */
 
-static tree 
+static tree
 cp_parser_conversion_function_id (cp_parser* parser)
 {
   tree type;
   tree saved_scope;
   tree saved_qualifying_scope;
   tree saved_object_scope;
+  bool pop_p = false;
 
   /* Look for the `operator' token.  */
   if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'"))
@@ -6899,7 +7494,7 @@ cp_parser_conversion_function_id (cp_parser* parser)
      entities declared within the class are available in the
      conversion-type-id.  For example, consider:
 
-       struct S { 
+       struct S {
          typedef int I;
         operator I();
        };
@@ -6909,11 +7504,11 @@ cp_parser_conversion_function_id (cp_parser* parser)
      In order to see that `I' is a type-name in the definition, we
      must be in the scope of `S'.  */
   if (saved_scope)
-    push_scope (saved_scope);
+    pop_p = push_scope (saved_scope);
   /* Parse the conversion-type-id.  */
   type = cp_parser_conversion_type_id (parser);
   /* Leave the scope of the class, if any.  */
-  if (saved_scope)
+  if (pop_p)
     pop_scope (saved_scope);
   /* Restore the saved scope.  */
   parser->scope = saved_scope;
@@ -6936,73 +7531,68 @@ static tree
 cp_parser_conversion_type_id (cp_parser* parser)
 {
   tree attributes;
-  tree type_specifiers;
-  tree declarator;
+  cp_decl_specifier_seq type_specifiers;
+  cp_declarator *declarator;
 
   /* Parse the attributes.  */
   attributes = cp_parser_attributes_opt (parser);
   /* Parse the type-specifiers.  */
-  type_specifiers = cp_parser_type_specifier_seq (parser);
+  cp_parser_type_specifier_seq (parser, &type_specifiers);
   /* If that didn't work, stop.  */
-  if (type_specifiers == error_mark_node)
+  if (type_specifiers.type == error_mark_node)
     return error_mark_node;
   /* Parse the conversion-declarator.  */
   declarator = cp_parser_conversion_declarator_opt (parser);
 
-  return grokdeclarator (declarator, type_specifiers, TYPENAME,
+  return grokdeclarator (declarator, &type_specifiers, TYPENAME,
                         /*initialized=*/0, &attributes);
 }
 
 /* Parse an (optional) conversion-declarator.
 
    conversion-declarator:
-     ptr-operator conversion-declarator [opt]  
+     ptr-operator conversion-declarator [opt]
 
-   Returns a representation of the declarator.  See
-   cp_parser_declarator for details.  */
+   */
 
-static tree
+static cp_declarator *
 cp_parser_conversion_declarator_opt (cp_parser* parser)
 {
   enum tree_code code;
   tree class_type;
-  tree cv_qualifier_seq;
+  cp_cv_quals cv_quals;
 
   /* We don't know if there's a ptr-operator next, or not.  */
   cp_parser_parse_tentatively (parser);
   /* Try the ptr-operator.  */
-  code = cp_parser_ptr_operator (parser, &class_type, 
-                                &cv_qualifier_seq);
+  code = cp_parser_ptr_operator (parser, &class_type, &cv_quals);
   /* If it worked, look for more conversion-declarators.  */
   if (cp_parser_parse_definitely (parser))
     {
-     tree declarator;
+      cp_declarator *declarator;
 
-     /* Parse another optional declarator.  */
-     declarator = cp_parser_conversion_declarator_opt (parser);
+      /* Parse another optional declarator.  */
+      declarator = cp_parser_conversion_declarator_opt (parser);
 
-     /* Create the representation of the declarator.  */
-     if (code == INDIRECT_REF)
-       declarator = make_pointer_declarator (cv_qualifier_seq,
+      /* Create the representation of the declarator.  */
+      if (class_type)
+       declarator = make_ptrmem_declarator (cv_quals, class_type,
                                             declarator);
-     else
-       declarator =  make_reference_declarator (cv_qualifier_seq,
-                                               declarator);
-
-     /* Handle the pointer-to-member case.  */
-     if (class_type)
-       declarator = build_nt (SCOPE_REF, class_type, declarator);
+      else if (code == INDIRECT_REF)
+       declarator = make_pointer_declarator (cv_quals, declarator);
+      else
+       declarator = make_reference_declarator (cv_quals, declarator);
 
-     return declarator;
+      return declarator;
    }
 
-  return NULL_TREE;
+  return NULL;
 }
 
 /* Parse an (optional) ctor-initializer.
 
    ctor-initializer:
-     : mem-initializer-list  
+     : mem-initializer-list
 
    Returns TRUE iff the ctor-initializer was actually present.  */
 
@@ -7072,10 +7662,10 @@ cp_parser_mem_initializer_list (cp_parser* parser)
 /* Parse a mem-initializer.
 
    mem-initializer:
-     mem-initializer-id ( expression-list [opt] )  
+     mem-initializer-id ( expression-list [opt] )
 
    GNU extension:
-  
+
    mem-initializer:
      ( expression-list [opt] )
 
@@ -7089,7 +7679,7 @@ cp_parser_mem_initializer (cp_parser* parser)
   tree mem_initializer_id;
   tree expression_list;
   tree member;
-  
+
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
@@ -7102,14 +7692,14 @@ cp_parser_mem_initializer (cp_parser* parser)
   if (member && !DECL_P (member))
     in_base_initializer = 1;
 
-  expression_list 
+  expression_list
     = cp_parser_parenthesized_expression_list (parser, false,
                                               /*non_constant_p=*/NULL);
   if (!expression_list)
     expression_list = void_type_node;
 
   in_base_initializer = 0;
-  
+
   return member ? build_tree_list (member, expression_list) : NULL_TREE;
 }
 
@@ -7117,7 +7707,7 @@ cp_parser_mem_initializer (cp_parser* parser)
 
    mem-initializer-id:
      :: [opt] nested-name-specifier [opt] class-name
-     identifier  
+     identifier
 
    Returns a TYPE indicating the class to be initializer for the first
    production.  Returns an IDENTIFIER_NODE indicating the data member
@@ -7128,12 +7718,20 @@ 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, 
-                                  /*current_scope_valid_p=*/false) 
+  global_scope_p
+    = (cp_parser_global_scope_opt (parser,
+                                  /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the optional nested-name-specifier.  The simplest way to
      implement:
@@ -7147,19 +7745,21 @@ cp_parser_mem_initializer_id (cp_parser* parser)
 
      is to assume that we have seen the `typename' keyword at this
      point.  */
-  nested_name_specifier_p 
+  nested_name_specifier_p
     = (cp_parser_nested_name_specifier_opt (parser,
                                            /*typename_keyword_p=*/true,
                                            /*check_dependency_p=*/true,
                                            /*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,
@@ -7167,7 +7767,7 @@ cp_parser_mem_initializer_id (cp_parser* parser)
   /* Otherwise, we could also be looking for an ordinary identifier.  */
   cp_parser_parse_tentatively (parser);
   /* Try a class-name.  */
-  id = cp_parser_class_name (parser, 
+  id = cp_parser_class_name (parser,
                             /*typename_keyword_p=*/true,
                             /*template_keyword_p=*/false,
                             /*type_p=*/false,
@@ -7186,12 +7786,12 @@ cp_parser_mem_initializer_id (cp_parser* parser)
 /* Parse an operator-function-id.
 
    operator-function-id:
-     operator operator  
+     operator operator
 
    Returns an IDENTIFIER_NODE for the operator which is a
    human-readable spelling of the identifier, e.g., `operator +'.  */
 
-static tree 
+static tree
 cp_parser_operator_function_id (cp_parser* parser)
 {
   /* Look for the `operator' keyword.  */
@@ -7209,13 +7809,13 @@ cp_parser_operator_function_id (cp_parser* parser)
      || ++ -- , ->* -> () []
 
    GNU Extensions:
-   
+
    operator:
      <? >? <?= >?=
 
    Returns an IDENTIFIER_NODE for the operator which is a
    human-readable spelling of the identifier, e.g., `operator +'.  */
-   
+
 static tree
 cp_parser_operator (cp_parser* parser)
 {
@@ -7252,7 +7852,7 @@ cp_parser_operator (cp_parser* parser)
            cp_lexer_consume_token (parser->lexer);
            /* Look for the `]' token.  */
            cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
-           id = ansi_opname (op == NEW_EXPR 
+           id = ansi_opname (op == NEW_EXPR
                              ? VEC_NEW_EXPR : VEC_DELETE_EXPR);
          }
        /* Otherwise, we have the non-array variant.  */
@@ -7297,7 +7897,7 @@ cp_parser_operator (cp_parser* parser)
     case CPP_COMPL:
       id = ansi_opname (BIT_NOT_EXPR);
       break;
-      
+
     case CPP_NOT:
       id = ansi_opname (TRUTH_NOT_EXPR);
       break;
@@ -7385,7 +7985,7 @@ cp_parser_operator (cp_parser* parser)
     case CPP_OR_OR:
       id = ansi_opname (TRUTH_ORIF_EXPR);
       break;
-      
+
     case CPP_PLUS_PLUS:
       id = ansi_opname (POSTINCREMENT_EXPR);
       break;
@@ -7459,18 +8059,18 @@ cp_parser_operator (cp_parser* parser)
 /* Parse a template-declaration.
 
    template-declaration:
-     export [opt] template < template-parameter-list > declaration  
+     export [opt] template < template-parameter-list > declaration
 
    If MEMBER_P is TRUE, this template-declaration occurs within a
-   class-specifier.  
+   class-specifier.
 
    The grammar rule given by the standard isn't correct.  What
    is really meant is:
 
    template-declaration:
-     export [opt] template-parameter-list-seq 
+     export [opt] template-parameter-list-seq
        decl-specifier-seq [opt] init-declarator [opt] ;
-     export [opt] template-parameter-list-seq 
+     export [opt] template-parameter-list-seq
        function-definition
 
    template-parameter-list-seq:
@@ -7510,13 +8110,14 @@ cp_parser_template_parameter_list (cp_parser* parser)
     {
       tree parameter;
       cp_token *token;
+      bool is_non_type;
 
       /* Parse the template-parameter.  */
-      parameter = cp_parser_template_parameter (parser);
+      parameter = cp_parser_template_parameter (parser, &is_non_type);
       /* Add it to the list.  */
       parameter_list = process_template_parm (parameter_list,
-                                             parameter);
-
+                                             parameter,
+                                             is_non_type);
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
       /* If it's not a `,', we're done.  */
@@ -7536,13 +8137,17 @@ cp_parser_template_parameter_list (cp_parser* parser)
      parameter-declaration
 
    Returns a TREE_LIST.  The TREE_VALUE represents the parameter.  The
-   TREE_PURPOSE is the default value, if any.  */
+   TREE_PURPOSE is the default value, if any.  *IS_NON_TYPE is set to
+   true iff this parameter is a non-type parameter.  */
 
 static tree
-cp_parser_template_parameter (cp_parser* parser)
+cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
 {
   cp_token *token;
+  cp_parameter_declarator *parameter_declarator;
 
+  /* Assume it is a type parameter or a template parameter.  */
+  *is_non_type = false;
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* If it is `class' or `template', we have a type-parameter.  */
@@ -7554,7 +8159,7 @@ cp_parser_template_parameter (cp_parser* parser)
        template <typename T, typename T::X X> ...
 
      or:
-     
+
        template <class C, class D*> ...
 
      Here, the first parameter is a type parameter, and the second is
@@ -7570,13 +8175,13 @@ cp_parser_template_parameter (cp_parser* parser)
        token = cp_lexer_peek_nth_token (parser->lexer, 3);
       /* Now, see if the token looks like the end of a template
         parameter.  */
-      if (token->type == CPP_COMMA 
+      if (token->type == CPP_COMMA
          || token->type == CPP_EQ
          || token->type == CPP_GREATER)
        return cp_parser_type_parameter (parser);
     }
 
-  /* Otherwise, it is a non-type parameter.  
+  /* Otherwise, it is a non-type parameter.
 
      [temp.param]
 
@@ -7584,9 +8189,16 @@ cp_parser_template_parameter (cp_parser* parser)
      template-parameter, the first non-nested `>' is taken as the end
      of the template parameter-list rather than a greater-than
      operator.  */
-  return 
-    cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
-                                    /*parenthesized_p=*/NULL);
+  *is_non_type = true;
+  parameter_declarator
+     = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
+                                       /*parenthesized_p=*/NULL);
+  return (build_tree_list
+         (parameter_declarator->default_argument,
+          grokdeclarator (parameter_declarator->declarator,
+                          &parameter_declarator->decl_specifiers,
+                          PARM, /*initialized=*/0,
+                          /*attrlist=*/NULL)));
 }
 
 /* Parse a type-parameter.
@@ -7597,8 +8209,8 @@ cp_parser_template_parameter (cp_parser* parser)
      typename identifier [opt]
      typename identifier [opt] = type-id
      template < template-parameter-list > class identifier [opt]
-     template < template-parameter-list > class identifier [opt] 
-       = id-expression  
+     template < template-parameter-list > class identifier [opt]
+       = id-expression
 
    Returns a TREE_LIST.  The TREE_VALUE is itself a TREE_LIST.  The
    TREE_PURPOSE is the default-argument, if any.  The TREE_VALUE is
@@ -7611,7 +8223,7 @@ cp_parser_type_parameter (cp_parser* parser)
   tree parameter;
 
   /* Look for a keyword to tell us what kind of parameter this is.  */
-  token = cp_parser_require (parser, CPP_KEYWORD, 
+  token = cp_parser_require (parser, CPP_KEYWORD,
                             "`class', `typename', or `template'");
   if (!token)
     return error_mark_node;
@@ -7661,7 +8273,7 @@ cp_parser_type_parameter (cp_parser* parser)
        cp_parser_require (parser, CPP_LESS, "`<'");
        /* Parse the template-parameter-list.  */
        begin_template_parm_list ();
-       parameter_list 
+       parameter_list
          = cp_parser_template_parameter_list (parser);
        parameter_list = end_template_parm_list (parameter_list);
        /* Look for the `>'.  */
@@ -7681,7 +8293,7 @@ cp_parser_type_parameter (cp_parser* parser)
        /* Create the template parameter.  */
        parameter = finish_template_template_parm (class_type_node,
                                                   identifier);
-                                                  
+
        /* If the next token is an `=', then there is a
           default-argument.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
@@ -7691,19 +8303,25 @@ cp_parser_type_parameter (cp_parser* parser)
            /* Consume the `='.  */
            cp_lexer_consume_token (parser->lexer);
            /* Parse the id-expression.  */
-           default_argument 
+           default_argument
              = cp_parser_id_expression (parser,
                                         /*template_keyword_p=*/false,
                                         /*check_dependency_p=*/true,
                                         /*template_p=*/&is_template,
                                         /*declarator_p=*/false);
-           /* Look up the name.  */
-           default_argument 
-             = cp_parser_lookup_name (parser, default_argument,
-                                      /*is_type=*/false,
-                                      /*is_template=*/is_template,
-                                      /*is_namespace=*/false,
-                                      /*check_dependency=*/true);
+           if (TREE_CODE (default_argument) == TYPE_DECL)
+             /* If the id-expression was a template-id that refers to
+                a template-class, we already have the declaration here,
+                so no further lookup is needed.  */
+                ;
+           else
+             /* Look up the name.  */
+             default_argument
+               = cp_parser_lookup_name (parser, default_argument,
+                                       /*is_type=*/false,
+                                       /*is_template=*/is_template,
+                                       /*is_namespace=*/false,
+                                       /*check_dependency=*/true);
            /* See if the default argument is valid.  */
            default_argument
              = check_template_template_default_arg (default_argument);
@@ -7723,7 +8341,7 @@ cp_parser_type_parameter (cp_parser* parser)
                       "expected `class', `typename', or `template'");
       parameter = error_mark_node;
     }
-  
+
   return parameter;
 }
 
@@ -7736,14 +8354,14 @@ cp_parser_type_parameter (cp_parser* parser)
    `template' keyword.  In this case, a TEMPLATE_ID_EXPR will be
    returned.  Otherwise, if the template-name names a function, or set
    of functions, returns a TEMPLATE_ID_EXPR.  If the template-name
-   names a class, returns a TYPE_DECL for the specialization.  
+   names a class, returns a TYPE_DECL for the specialization.
 
    If CHECK_DEPENDENCY_P is FALSE, names are looked up in
    uninstantiated templates.  */
 
 static tree
-cp_parser_template_id (cp_parser *parser, 
-                      bool template_keyword_p, 
+cp_parser_template_id (cp_parser *parser,
+                      bool template_keyword_p,
                       bool check_dependency_p,
                       bool is_declaration)
 {
@@ -7752,7 +8370,7 @@ cp_parser_template_id (cp_parser *parser,
   tree template_id;
   ptrdiff_t start_of_id;
   tree access_check = NULL_TREE;
-  cp_token *next_token;
+  cp_token *next_token, *next_token_2;
   bool is_identifier;
 
   /* If the next token corresponds to a template-id, there is no need
@@ -7777,7 +8395,8 @@ cp_parser_template_id (cp_parser *parser,
      finding a template-id.  */
   if ((next_token->type != CPP_NAME && next_token->keyword != RID_OPERATOR)
       || (next_token->type == CPP_NAME
-         && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS))
+         && !cp_parser_nth_token_starts_template_argument_list_p
+              (parser, 2)))
     {
       cp_parser_error (parser, "expected template-id");
       return error_mark_node;
@@ -7809,24 +8428,69 @@ cp_parser_template_id (cp_parser *parser,
       return template;
     }
 
-  /* Look for the `<' that starts the template-argument-list.  */
-  if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+  /* If we find the sequence `[:' after a template-name, it's probably
+     a digraph-typo for `< ::'. Substitute the tokens and check if we can
+     parse correctly the argument list.  */
+  next_token = cp_lexer_peek_nth_token (parser->lexer, 1);
+  next_token_2 = cp_lexer_peek_nth_token (parser->lexer, 2);
+  if (next_token->type == CPP_OPEN_SQUARE
+      && next_token->flags & DIGRAPH
+      && next_token_2->type == CPP_COLON
+      && !(next_token_2->flags & PREV_WHITE))
     {
-      pop_deferring_access_checks ();
-      return error_mark_node;
+      cp_parser_parse_tentatively (parser);
+      /* Change `:' into `::'.  */
+      next_token_2->type = CPP_SCOPE;
+      /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
+         CPP_LESS.  */
+      cp_lexer_consume_token (parser->lexer);
+      /* Parse the arguments.  */
+      arguments = cp_parser_enclosed_template_argument_list (parser);
+      if (!cp_parser_parse_definitely (parser))
+       {
+         /* If we couldn't parse an argument list, then we revert our changes
+            and return simply an error. Maybe this is not a template-id
+            after all.  */
+         next_token_2->type = CPP_COLON;
+         cp_parser_error (parser, "expected `<'");
+         pop_deferring_access_checks ();
+         return error_mark_node;
+       }
+      /* Otherwise, emit an error about the invalid digraph, but continue
+         parsing because we got our argument list.  */
+      pedwarn ("`<::' cannot begin a template-argument list");
+      inform ("`<:' is an alternate spelling for `['. Insert whitespace "
+             "between `<' and `::'");
+      if (!flag_permissive)
+       {
+         static bool hint;
+         if (!hint)
+           {
+             inform ("(if you use `-fpermissive' G++ will accept your code)");
+             hint = true;
+           }
+       }
+    }
+  else
+    {
+      /* Look for the `<' that starts the template-argument-list.  */
+      if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+       {
+         pop_deferring_access_checks ();
+         return error_mark_node;
+       }
+      /* Parse the arguments.  */
+      arguments = cp_parser_enclosed_template_argument_list (parser);
     }
-
-  /* Parse the arguments.  */
-  arguments = cp_parser_enclosed_template_argument_list (parser);
 
   /* Build a representation of the specialization.  */
   if (TREE_CODE (template) == IDENTIFIER_NODE)
     template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
   else if (DECL_CLASS_TEMPLATE_P (template)
           || DECL_TEMPLATE_TEMPLATE_PARM_P (template))
-    template_id 
-      = finish_template_type (template, arguments, 
-                             cp_lexer_next_token_is (parser->lexer, 
+    template_id
+      = finish_template_type (template, arguments,
+                             cp_lexer_next_token_is (parser->lexer,
                                                      CPP_SCOPE));
   else
     {
@@ -7836,10 +8500,10 @@ cp_parser_template_id (cp_parser *parser,
                           || TREE_CODE (template) == OVERLOAD
                           || BASELINK_P (template)),
                          20010716);
-      
+
       template_id = lookup_template_function (template, arguments);
     }
-  
+
   /* Retrieve any deferred checks.  Do not pop this access checks yet
      so the memory will not be reclaimed during token replacing below.  */
   access_check = get_deferred_access_checks ();
@@ -7856,7 +8520,7 @@ cp_parser_template_id (cp_parser *parser,
 
       /* Find the token that corresponds to the start of the
         template-id.  */
-      token = cp_lexer_advance_token (parser->lexer, 
+      token = cp_lexer_advance_token (parser->lexer,
                                      parser->lexer->first_token,
                                      start_of_id);
 
@@ -7876,16 +8540,25 @@ cp_parser_template_id (cp_parser *parser,
 
    template-name:
      identifier
+
    The standard should actually say:
 
    template-name:
      identifier
      operator-function-id
-     conversion-function-id
 
    A defect report has been filed about this issue.
 
+   A conversion-function-id cannot be a template name because they cannot
+   be part of a template-id. In fact, looking at this code:
+
+   a.operator K<int>()
+
+   the conversion-function-id is "operator K<int>", and K<int> is a type-id.
+   It is impossible to call a templated conversion-function-id with an
+   explicit argument list, since the only allowed template parameter is
+   the type to which it is converting.
+
    If TEMPLATE_KEYWORD_P is true, then we have just seen the
    `template' keyword, in a construction like:
 
@@ -7901,8 +8574,8 @@ cp_parser_template_id (cp_parser *parser,
    names are looked up inside uninstantiated templates.  */
 
 static tree
-cp_parser_template_name (cp_parser* parser, 
-                         bool template_keyword_p, 
+cp_parser_template_name (cp_parser* parser,
+                         bool template_keyword_p,
                          bool check_dependency_p,
                         bool is_declaration,
                         bool *is_identifier)
@@ -7922,12 +8595,15 @@ cp_parser_template_name (cp_parser* parser,
       identifier = cp_parser_operator_function_id (parser);
       /* If that didn't work, try a conversion-function-id.  */
       if (!cp_parser_parse_definitely (parser))
-       identifier = cp_parser_conversion_function_id (parser);
+        {
+         cp_parser_error (parser, "expected template-name");
+         return error_mark_node;
+        }
     }
   /* Look for the identifier.  */
   else
     identifier = cp_parser_identifier (parser);
-  
+
   /* If we didn't find an identifier, we don't have a template-id.  */
   if (identifier == error_mark_node)
     return error_mark_node;
@@ -7945,26 +8621,29 @@ cp_parser_template_name (cp_parser* parser,
      -- but we do not if there is no `<'.  */
 
   if (processing_template_decl
-      && cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+      && cp_parser_nth_token_starts_template_argument_list_p (parser, 1))
     {
       /* In a declaration, in a dependent context, we pretend that the
         "template" keyword was present in order to improve error
         recovery.  For example, given:
-        
+
           template <typename T> void f(T::X<int>);
-        
+
         we want to treat "X<int>" as a template-id.  */
-      if (is_declaration 
-         && !template_keyword_p 
+      if (is_declaration
+         && !template_keyword_p
          && parser->scope && TYPE_P (parser->scope)
-         && dependent_type_p (parser->scope))
+         && dependent_type_p (parser->scope)
+         /* Do not do this for dtors (or ctors), since they never
+            need the template keyword before their name.  */
+         && !constructor_name_p (identifier, parser->scope))
        {
          ptrdiff_t start;
          cp_token* token;
          /* Explain what went wrong.  */
          error ("non-template `%D' used as template", identifier);
-         error ("(use `%T::template %D' to indicate that it is a template)",
-                parser->scope, identifier);
+         inform ("use `%T::template %D' to indicate that it is a template",
+                 parser->scope, identifier);
          /* If parsing tentatively, find the location of the "<"
             token.  */
          if (cp_parser_parsing_tentatively (parser)
@@ -8004,7 +8683,15 @@ cp_parser_template_name (cp_parser* parser,
            *is_identifier = true;
          return identifier;
        }
-      if (template_keyword_p)
+
+      /* If the "template" keyword is present, then there is generally
+        no point in doing name-lookup, so we just return IDENTIFIER.
+        But, if the qualifying scope is non-dependent then we can
+        (and must) do name-lookup normally.  */
+      if (template_keyword_p
+         && (!parser->scope
+             || (TYPE_P (parser->scope)
+                 && dependent_type_p (parser->scope))))
        return identifier;
     }
 
@@ -8019,7 +8706,7 @@ cp_parser_template_name (cp_parser* parser,
   /* If DECL is a template, then the name was a template-name.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
     ;
-  else 
+  else
     {
       /* The standard does not explicitly indicate whether a name that
         names a set of overloaded declarations, some of which are
@@ -8030,7 +8717,7 @@ cp_parser_template_name (cp_parser* parser,
       if (TREE_CODE (fns) == OVERLOAD)
        {
          tree fn;
-         
+
          for (fn = fns; fn; fn = OVL_NEXT (fn))
            if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
              break;
@@ -8082,13 +8769,13 @@ cp_parser_template_argument_list (cp_parser* parser)
       if (n_args)
        /* Consume the comma.  */
        cp_lexer_consume_token (parser->lexer);
-      
+
       /* Parse the template-argument.  */
       argument = cp_parser_template_argument (parser);
       if (n_args == alloced)
        {
          alloced *= 2;
-         
+
          if (arg_ary == fixed_args)
            {
              arg_ary = xmalloc (sizeof (tree) * alloced);
@@ -8105,7 +8792,7 @@ cp_parser_template_argument_list (cp_parser* parser)
 
   while (n_args--)
     TREE_VEC_ELT (vec, n_args) = arg_ary[n_args];
-  
+
   if (arg_ary != fixed_args)
     free (arg_ary);
   parser->in_template_argument_list_p = saved_in_template_argument_list_p;
@@ -8122,7 +8809,7 @@ cp_parser_template_argument_list (cp_parser* parser)
    The representation is that of an assignment-expression, type-id, or
    id-expression -- except that the qualified id-expression is
    evaluated, so that the value returned is either a DECL or an
-   OVERLOAD.  
+   OVERLOAD.
 
    Although the standard says "assignment-expression", it forbids
    throw-expressions or assignments in the template argument.
@@ -8140,19 +8827,19 @@ cp_parser_template_argument (cp_parser* parser)
   tree qualifying_class;
 
   /* There's really no way to know what we're looking at, so we just
-     try each alternative in order.  
+     try each alternative in order.
 
        [temp.arg]
 
        In a template-argument, an ambiguity between a type-id and an
        expression is resolved to a type-id, regardless of the form of
-       the corresponding template-parameter.  
+       the corresponding template-parameter.
 
      Therefore, we try a type-id first.  */
   cp_parser_parse_tentatively (parser);
   argument = cp_parser_type_id (parser);
   /* If there was no error parsing the type-id but the next token is a '>>',
-     we probably found a typo for '> >'. But there are type-id which are 
+     we probably found a typo for '> >'. But there are type-id which are
      also valid expressions. For instance:
 
      struct X { int operator >> (int); };
@@ -8183,7 +8870,7 @@ cp_parser_template_argument (cp_parser* parser)
   /* We're still not sure what the argument will be.  */
   cp_parser_parse_tentatively (parser);
   /* Try a template.  */
-  argument = cp_parser_id_expression (parser, 
+  argument = cp_parser_id_expression (parser,
                                      /*template_keyword_p=*/false,
                                      /*check_dependency_p=*/true,
                                      &template_p,
@@ -8194,12 +8881,16 @@ cp_parser_template_argument (cp_parser* parser)
     cp_parser_error (parser, "expected template-argument");
   if (!cp_parser_error_occurred (parser))
     {
-      /* Figure out what is being referred to.  */
-      argument = cp_parser_lookup_name (parser, argument,
-                                       /*is_type=*/false,
-                                       /*is_template=*/template_p,
-                                       /*is_namespace=*/false,
-                                       /*check_dependency=*/true);
+      /* Figure out what is being referred to.  If the id-expression
+        was for a class template specialization, then we will have a
+        TYPE_DECL at this point.  There is no need to do name lookup
+        at this point in that case.  */
+      if (TREE_CODE (argument) != TYPE_DECL)
+       argument = cp_parser_lookup_name (parser, argument,
+                                         /*is_type=*/false,
+                                         /*is_template=*/template_p,
+                                         /*is_namespace=*/false,
+                                         /*check_dependency=*/true);
       if (TREE_CODE (argument) != TEMPLATE_DECL
          && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
        cp_parser_error (parser, "expected template-name");
@@ -8273,7 +8964,7 @@ cp_parser_template_argument (cp_parser* parser)
               later.  */
            ;
          else if (address_p
-                  && (TREE_CODE (argument) == OFFSET_REF 
+                  && (TREE_CODE (argument) == OFFSET_REF
                       || TREE_CODE (argument) == SCOPE_REF))
            /* A pointer-to-member.  */
            ;
@@ -8296,15 +8987,15 @@ cp_parser_template_argument (cp_parser* parser)
       return error_mark_node;
     }
   /* If the argument wasn't successfully parsed as a type-id followed
-     by '>>', the argument can only be a constant expression now.  
+     by '>>', the argument can only be a constant expression now.
      Otherwise, we try parsing the constant-expression tentatively,
      because the argument could really be a type-id.  */
   if (maybe_type_id)
     cp_parser_parse_tentatively (parser);
-  argument = cp_parser_constant_expression (parser, 
+  argument = cp_parser_constant_expression (parser,
                                            /*allow_non_constant_p=*/false,
                                            /*non_constant_p=*/NULL);
-  argument = cp_parser_fold_non_dependent_expr (argument);
+  argument = fold_non_dependent_expr (argument);
   if (!maybe_type_id)
     return argument;
   if (!cp_parser_next_token_ends_template_argument_p (parser))
@@ -8313,7 +9004,7 @@ cp_parser_template_argument (cp_parser* parser)
     return argument;
   /* We did our best to parse the argument as a non type-id, but that
      was the only alternative that matched (albeit with a '>' after
-     it). We can assume it's just a typo from the user, and a 
+     it). We can assume it's just a typo from the user, and a
      diagnostic will then be issued.  */
   return cp_parser_type_id (parser);
 }
@@ -8321,41 +9012,42 @@ cp_parser_template_argument (cp_parser* parser)
 /* Parse an explicit-instantiation.
 
    explicit-instantiation:
-     template declaration  
+     template declaration
 
    Although the standard says `declaration', what it really means is:
 
    explicit-instantiation:
-     template decl-specifier-seq [opt] declarator [opt] ; 
+     template decl-specifier-seq [opt] declarator [opt] ;
 
    Things like `template int S<int>::i = 5, int S<double>::j;' are not
    supposed to be allowed.  A defect report has been filed about this
-   issue.  
+   issue.
 
    GNU Extension:
-  
+
    explicit-instantiation:
-     storage-class-specifier template 
+     storage-class-specifier template
        decl-specifier-seq [opt] declarator [opt] ;
-     function-specifier template 
+     function-specifier template
        decl-specifier-seq [opt] declarator [opt] ;  */
 
 static void
 cp_parser_explicit_instantiation (cp_parser* parser)
 {
   int declares_class_or_enum;
-  tree decl_specifiers;
-  tree attributes;
+  cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
 
   /* Look for an (optional) storage-class-specifier or
      function-specifier.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
-      extension_specifier 
+      extension_specifier
        = cp_parser_storage_class_specifier_opt (parser);
       if (!extension_specifier)
-       extension_specifier = cp_parser_function_specifier_opt (parser);
+       extension_specifier
+         = cp_parser_function_specifier_opt (parser,
+                                             /*decl_specs=*/NULL);
     }
 
   /* Look for the `template' keyword.  */
@@ -8367,11 +9059,10 @@ cp_parser_explicit_instantiation (cp_parser* parser)
      control while processing explicit instantiation directives.  */
   push_deferring_access_checks (dk_no_check);
   /* Parse a decl-specifier-seq.  */
-  decl_specifiers 
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_OPTIONAL,
-                                   &attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_OPTIONAL,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
   /* If there was exactly one decl-specifier, and it declared a class,
      and there's no declarator, then we have an explicit type
      instantiation.  */
@@ -8379,7 +9070,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     {
       tree type;
 
-      type = check_tag_decl (decl_specifiers);
+      type = check_tag_decl (&decl_specifiers);
       /* Turn access control back on for names used during
         template instantiation.  */
       pop_deferring_access_checks ();
@@ -8388,19 +9079,19 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     }
   else
     {
-      tree declarator;
+      cp_declarator *declarator;
       tree decl;
 
       /* Parse the declarator.  */
-      declarator 
+      declarator
        = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                                /*ctor_dtor_or_conv_p=*/NULL,
                                /*parenthesized_p=*/NULL);
-      cp_parser_check_for_definition_in_return_type (declarator, 
+      cp_parser_check_for_definition_in_return_type (declarator,
                                                     declares_class_or_enum);
-      if (declarator != error_mark_node)
+      if (declarator != cp_error_declarator)
        {
-         decl = grokdeclarator (declarator, decl_specifiers, 
+         decl = grokdeclarator (declarator, &decl_specifiers,
                                 NORMAL, 0, NULL);
          /* Turn access control back on for names used during
             template instantiation.  */
@@ -8424,13 +9115,13 @@ cp_parser_explicit_instantiation (cp_parser* parser)
 /* Parse an explicit-specialization.
 
    explicit-specialization:
-     template < > declaration  
+     template < > declaration
 
    Although the standard says `declaration', what it really means is:
 
    explicit-specialization:
      template <> decl-specifier [opt] init-declarator [opt] ;
-     template <> function-definition 
+     template <> function-definition
      template <> explicit-specialization
      template <> template-declaration  */
 
@@ -8461,7 +9152,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
     }
   else
     /* Parse the dependent declaration.  */
-    cp_parser_single_declaration (parser, 
+    cp_parser_single_declaration (parser,
                                  /*member_p=*/false,
                                  /*friend_p=*/NULL);
 
@@ -8485,11 +9176,9 @@ cp_parser_explicit_specialization (cp_parser* parser)
    type-specifier:
      __complex__
 
-   Returns a representation of the type-specifier.  If the
-   type-specifier is a keyword (like `int' or `const', or
-   `__complex__') then the corresponding IDENTIFIER_NODE is returned.
-   For a class-specifier, enum-specifier, or elaborated-type-specifier
-   a TREE_TYPE is returned; otherwise, a TYPE_DECL is returned.
+   Returns a representation of the type-specifier.  For a
+   class-specifier, enum-specifier, or elaborated-type-specifier, a
+   TREE_TYPE is returned; otherwise, a TYPE_DECL is returned.
 
    If IS_FRIEND is TRUE then this type-specifier is being declared a
    `friend'.  If IS_DECLARATION is TRUE, then this type-specifier is
@@ -8506,9 +9195,9 @@ cp_parser_explicit_specialization (cp_parser* parser)
    is set to FALSE.  */
 
 static tree
-cp_parser_type_specifier (cp_parser* parser, 
-                         cp_parser_flags flags, 
-                         bool is_friend,
+cp_parser_type_specifier (cp_parser* parser,
+                         cp_parser_flags flags,
+                         cp_decl_specifier_seq *decl_specs,
                          bool is_declaration,
                          int* declares_class_or_enum,
                          bool* is_cv_qualifier)
@@ -8516,6 +9205,7 @@ cp_parser_type_specifier (cp_parser* parser,
   tree type_spec = NULL_TREE;
   cp_token *token;
   enum rid keyword;
+  cp_decl_spec ds = ds_last;
 
   /* Assume this type-specifier does not declare a new type.  */
   if (declares_class_or_enum)
@@ -8551,6 +9241,10 @@ cp_parser_type_specifier (cp_parser* parser,
        {
          if (declares_class_or_enum)
            *declares_class_or_enum = 2;
+         if (decl_specs)
+           cp_parser_set_decl_spec_type (decl_specs,
+                                         type_spec,
+                                         /*user_defined_p=*/true);
          return type_spec;
        }
 
@@ -8558,40 +9252,64 @@ cp_parser_type_specifier (cp_parser* parser,
 
     case RID_TYPENAME:
       /* Look for an elaborated-type-specifier.  */
-      type_spec = cp_parser_elaborated_type_specifier (parser,
-                                                      is_friend,
-                                                      is_declaration);
+      type_spec
+       = (cp_parser_elaborated_type_specifier
+          (parser,
+           decl_specs && decl_specs->specs[(int) ds_friend],
+           is_declaration));
       /* We're declaring a class or enum -- unless we're using
         `typename'.  */
       if (declares_class_or_enum && keyword != RID_TYPENAME)
        *declares_class_or_enum = 1;
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs,
+                                     type_spec,
+                                     /*user_defined_p=*/true);
       return type_spec;
 
     case RID_CONST:
+      ds = ds_const;
+      if (is_cv_qualifier)
+       *is_cv_qualifier = true;
+      break;
+
     case RID_VOLATILE:
-    case RID_RESTRICT:
-      type_spec = cp_parser_cv_qualifier_opt (parser);
-      /* Even though we call a routine that looks for an optional
-        qualifier, we know that there should be one.  */
-      my_friendly_assert (type_spec != NULL, 20000328);
-      /* This type-specifier was a cv-qualified.  */
+      ds = ds_volatile;
       if (is_cv_qualifier)
        *is_cv_qualifier = true;
+      break;
 
-      return type_spec;
+    case RID_RESTRICT:
+      ds = ds_restrict;
+      if (is_cv_qualifier)
+       *is_cv_qualifier = true;
+      break;
 
     case RID_COMPLEX:
       /* The `__complex__' keyword is a GNU extension.  */
-      return cp_lexer_consume_token (parser->lexer)->value;
+      ds = ds_complex;
+      break;
 
     default:
       break;
     }
 
+  /* Handle simple keywords.  */
+  if (ds != ds_last)
+    {
+      if (decl_specs)
+       {
+         ++decl_specs->specs[(int)ds];
+         decl_specs->any_specifiers_p = true;
+       }
+      return cp_lexer_consume_token (parser->lexer)->value;
+    }
+
   /* If we do not already have a type-specifier, assume we are looking
      at a simple-type-specifier.  */
-  type_spec = cp_parser_simple_type_specifier (parser, flags, 
-                                              /*identifier_p=*/true);
+  type_spec = cp_parser_simple_type_specifier (parser,
+                                              decl_specs,
+                                              flags);
 
   /* If we didn't find a type-specifier, and a type-specifier was not
      optional in this context, issue an error message.  */
@@ -8619,7 +9337,7 @@ cp_parser_type_specifier (cp_parser* parser,
      unsigned
      float
      double
-     void  
+     void
 
    GNU Extension:
 
@@ -8627,14 +9345,13 @@ cp_parser_type_specifier (cp_parser* parser,
      __typeof__ unary-expression
      __typeof__ ( type-id )
 
-   For the various keywords, the value returned is simply the
-   TREE_IDENTIFIER representing the keyword if IDENTIFIER_P is true.
-   For the first two productions, and if IDENTIFIER_P is false, the
-   value returned is the indicated TYPE_DECL.  */
+   Returns the indicated TYPE_DECL.  If DECL_SPECS is not NULL, it is
+   appropriately updated.  */
 
 static tree
-cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
-                                bool identifier_p)
+cp_parser_simple_type_specifier (cp_parser* parser,
+                                cp_decl_specifier_seq *decl_specs,
+                                cp_parser_flags flags)
 {
   tree type = NULL_TREE;
   cp_token *token;
@@ -8646,6 +9363,8 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
   switch (token->keyword)
     {
     case RID_CHAR:
+      if (decl_specs)
+       decl_specs->explicit_char_p = true;
       type = char_type_node;
       break;
     case RID_WCHAR:
@@ -8655,18 +9374,28 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
       type = boolean_type_node;
       break;
     case RID_SHORT:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_short];
       type = short_integer_type_node;
       break;
     case RID_INT:
+      if (decl_specs)
+       decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
     case RID_LONG:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_long];
       type = long_integer_type_node;
       break;
     case RID_SIGNED:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_signed];
       type = integer_type_node;
       break;
     case RID_UNSIGNED:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_unsigned];
       type = unsigned_type_node;
       break;
     case RID_FLOAT:
@@ -8680,19 +9409,19 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
       break;
 
     case RID_TYPEOF:
-      {
-       tree operand;
+      /* Consume the `typeof' token.  */
+      cp_lexer_consume_token (parser->lexer);
+      /* Parse the operand to `typeof'.  */
+      type = cp_parser_sizeof_operand (parser, RID_TYPEOF);
+      /* If it is not already a TYPE, take its type.  */
+      if (!TYPE_P (type))
+       type = finish_typeof (type);
 
-       /* Consume the `typeof' token.  */
-       cp_lexer_consume_token (parser->lexer);
-       /* Parse the operand to `typeof'.  */
-       operand = cp_parser_sizeof_operand (parser, RID_TYPEOF);
-       /* If it is not already a TYPE, take its type.  */
-       if (!TYPE_P (operand))
-         operand = finish_typeof (operand);
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     /*user_defined_p=*/true);
 
-       return operand;
-      }
+      return type;
 
     default:
       break;
@@ -8703,14 +9432,34 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
     {
       tree id;
 
+      /* Record the type.  */
+      if (decl_specs
+         && (token->keyword != RID_SIGNED
+             && token->keyword != RID_UNSIGNED
+             && token->keyword != RID_SHORT
+             && token->keyword != RID_LONG))
+       cp_parser_set_decl_spec_type (decl_specs,
+                                     type,
+                                     /*user_defined=*/false);
+      if (decl_specs)
+       decl_specs->any_specifiers_p = true;
+
       /* Consume the token.  */
       id = cp_lexer_consume_token (parser->lexer)->value;
-      return identifier_p ? id : TYPE_NAME (type);
+
+      /* There is no valid C++ program where a non-template type is
+        followed by a "<".  That usually indicates that the user thought
+        that the type was a template.  */
+      cp_parser_check_for_invalid_template_id (parser, type);
+
+      return TYPE_NAME (type);
     }
 
   /* The type-specifier must be a user-defined type.  */
-  if (!(flags & CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES)) 
+  if (!(flags & CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES))
     {
+      bool qualified_p;
+
       /* Don't gobble tokens or issue error messages if this is an
         optional type-specifier.  */
       if (flags & CP_PARSER_FLAGS_OPTIONAL)
@@ -8720,18 +9469,20 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
       cp_parser_global_scope_opt (parser,
                                  /*current_scope_valid_p=*/false);
       /* Look for the nested-name specifier.  */
-      cp_parser_nested_name_specifier_opt (parser,
-                                          /*typename_keyword_p=*/false,
-                                          /*check_dependency_p=*/true,
-                                          /*type_p=*/false,
-                                          /*is_declaration=*/false);
+      qualified_p
+       = (cp_parser_nested_name_specifier_opt (parser,
+                                               /*typename_keyword_p=*/false,
+                                               /*check_dependency_p=*/true,
+                                               /*type_p=*/false,
+                                               /*is_declaration=*/false)
+          != NULL_TREE);
       /* If we have seen a nested-name-specifier, and the next token
         is `template', then we are using the template-id production.  */
-      if (parser->scope 
+      if (parser->scope
          && cp_parser_optional_template_keyword (parser))
        {
          /* Look for the template-id.  */
-         type = cp_parser_template_id (parser, 
+         type = cp_parser_template_id (parser,
                                        /*template_keyword_p=*/true,
                                        /*check_dependency_p=*/true,
                                        /*is_declaration=*/false);
@@ -8746,10 +9497,19 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
       /* Otherwise, look for a type-name.  */
       else
        type = cp_parser_type_name (parser);
+      /* Keep track of all name-lookups performed in class scopes.  */
+      if (type
+         && !qualified_p
+         && TREE_CODE (type) == TYPE_DECL
+         && TREE_CODE (DECL_NAME (type)) == IDENTIFIER_NODE)
+       maybe_note_name_used_in_class (DECL_NAME (type), type);
       /* If it didn't work out, we don't have a TYPE.  */
-      if ((flags & CP_PARSER_FLAGS_OPTIONAL) 
+      if ((flags & CP_PARSER_FLAGS_OPTIONAL)
          && !cp_parser_parse_definitely (parser))
        type = NULL_TREE;
+      if (type && decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     /*user_defined=*/true);
     }
 
   /* If we didn't get a type-name, issue an error message.  */
@@ -8773,13 +9533,13 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
    type-name:
      class-name
      enum-name
-     typedef-name  
+     typedef-name
 
    enum-name:
      identifier
 
    typedef-name:
-     identifier 
+     identifier
 
    Returns a TYPE_DECL for the the type.  */
 
@@ -8792,7 +9552,7 @@ cp_parser_type_name (cp_parser* parser)
   /* We can't know yet whether it is a class-name or not.  */
   cp_parser_parse_tentatively (parser);
   /* Try a class-name.  */
-  type_decl = cp_parser_class_name (parser, 
+  type_decl = cp_parser_class_name (parser,
                                    /*typename_keyword_p=*/false,
                                    /*template_keyword_p=*/false,
                                    /*type_p=*/false,
@@ -8806,14 +9566,14 @@ cp_parser_type_name (cp_parser* parser)
       identifier = cp_parser_identifier (parser);
       if (identifier == error_mark_node)
        return error_mark_node;
-      
+
       /* Look up the type-name.  */
       type_decl = cp_parser_lookup_name_simple (parser, identifier);
       /* Issue an error if we did not find a type-name.  */
       if (TREE_CODE (type_decl) != TYPE_DECL)
        {
          if (!cp_parser_simulate_error (parser))
-           cp_parser_name_lookup_error (parser, identifier, type_decl, 
+           cp_parser_name_lookup_error (parser, identifier, type_decl,
                                         "is not a type");
          type_decl = error_mark_node;
        }
@@ -8825,7 +9585,7 @@ cp_parser_type_name (cp_parser* parser)
               && !parser->scope)
        maybe_note_name_used_in_class (identifier, type_decl);
     }
-  
+
   return type_decl;
 }
 
@@ -8838,14 +9598,14 @@ cp_parser_type_name (cp_parser* parser)
      class-key :: [opt] nested-name-specifier [opt] template [opt] template-id
      enum :: [opt] nested-name-specifier [opt] identifier
      typename :: [opt] nested-name-specifier identifier
-     typename :: [opt] nested-name-specifier template [opt] 
-       template-id 
+     typename :: [opt] nested-name-specifier template [opt]
+       template-id
 
    GNU extension:
 
    elaborated-type-specifier:
      class-key attributes :: [opt] nested-name-specifier [opt] identifier
-     class-key attributes :: [opt] nested-name-specifier [opt] 
+     class-key attributes :: [opt] nested-name-specifier [opt]
                template [opt] template-id
      enum attributes :: [opt] nested-name-specifier [opt] identifier
 
@@ -8857,8 +9617,8 @@ cp_parser_type_name (cp_parser* parser)
    Returns the TYPE specified.  */
 
 static tree
-cp_parser_elaborated_type_specifier (cp_parser* parser, 
-                                     bool is_friend, 
+cp_parser_elaborated_type_specifier (cp_parser* parser,
+                                     bool is_friend,
                                      bool is_declaration)
 {
   enum tag_types tag_type;
@@ -8899,7 +9659,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
     }
 
   /* Look for the `::' operator.  */
-  cp_parser_global_scope_opt (parser, 
+  cp_parser_global_scope_opt (parser,
                              /*current_scope_valid_p=*/false);
   /* Look for the nested-name-specifier.  */
   if (tag_type == typename_type)
@@ -8908,7 +9668,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
                                           /*typename_keyword_p=*/true,
                                           /*check_dependency_p=*/true,
                                           /*type_p=*/true,
-                                          is_declaration) 
+                                          is_declaration)
          == error_mark_node)
        return error_mark_node;
     }
@@ -8948,7 +9708,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
               && tag_type == typename_type)
        type = make_typename_type (parser->scope, decl,
                                   /*complain=*/1);
-      else 
+      else
        type = TREE_TYPE (decl);
     }
 
@@ -8965,8 +9725,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
       /* For a `typename', we needn't call xref_tag.  */
       if (tag_type == typename_type)
-       return make_typename_type (parser->scope, identifier, 
-                                  /*complain=*/1);
+       return cp_parser_make_typename_type (parser, parser->scope,
+                                            identifier);
       /* Look up a qualified name in the usual way.  */
       if (parser->scope)
        {
@@ -8975,7 +9735,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
          /* In an elaborated-type-specifier, names are assumed to name
             types, so we set IS_TYPE to TRUE when calling
             cp_parser_lookup_name.  */
-         decl = cp_parser_lookup_name (parser, identifier, 
+         decl = cp_parser_lookup_name (parser, identifier,
                                        /*is_type=*/true,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
@@ -9002,7 +9762,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
             processing_template_decl does not work here since it is
             always 1 for the above two cases.  */
 
-         decl = (cp_parser_maybe_treat_template_as_class 
+         decl = (cp_parser_maybe_treat_template_as_class
                  (decl, /*tag_name_p=*/is_friend
                         && parser->num_template_parameter_lists));
 
@@ -9013,14 +9773,14 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
            }
 
          if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
-           check_elaborated_type_specifier 
+           check_elaborated_type_specifier
              (tag_type, decl,
               (parser->num_template_parameter_lists
                || DECL_SELF_REFERENCE_P (decl)));
 
          type = TREE_TYPE (decl);
        }
-      else 
+      else
        {
          /* An elaborated-type-specifier sometimes introduces a new type and
             sometimes names an existing type.  Normally, the rule is that it
@@ -9032,7 +9792,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
             the `struct S' in the body of `f' is the same `struct S' as in
             the global scope; the existing definition is used.  However, if
-            there were no global declaration, this would introduce a new 
+            there were no global declaration, this would introduce a new
             local class named `S'.
 
             An exception to this rule applies to the following code:
@@ -9045,7 +9805,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
             This exception only applies if the elaborated-type-specifier
             forms the complete declaration:
 
-              [class.name] 
+              [class.name]
 
               A declaration consisting solely of `class-key identifier ;' is
               either a redeclaration of the name in the current scope or a
@@ -9059,17 +9819,20 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
               struct S { friend struct T; };
 
-            `T' is not a new type in the scope of `S'.  
+            `T' is not a new type in the scope of `S'.
 
             Also, `new struct S' or `sizeof (struct S)' never results in the
             definition of a new type; a new type can only be declared in a
             declaration context.  */
 
-         type = xref_tag (tag_type, identifier, 
-                          attributes,
-                          (is_friend 
+         /* Warn about attributes. They are ignored.  */
+         if (attributes)
+           warning ("type attributes are honored only at type definition");
+
+         type = xref_tag (tag_type, identifier,
+                          (is_friend
                            || !is_declaration
-                           || cp_lexer_next_token_is_not (parser->lexer, 
+                           || cp_lexer_next_token_is_not (parser->lexer,
                                                           CPP_SEMICOLON)),
                           parser->num_template_parameter_lists);
        }
@@ -9137,7 +9900,7 @@ cp_parser_enum_specifier (cp_parser* parser)
 }
 
 /* Parse an enumerator-list.  The enumerators all have the indicated
-   TYPE.  
+   TYPE.
 
    enumerator-list:
      enumerator-definition
@@ -9154,7 +9917,7 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
       cp_parser_enumerator_definition (parser, type);
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
-      /* If it's not a `,', then we've reached the end of the 
+      /* If it's not a `,', then we've reached the end of the
         list.  */
       if (token->type != CPP_COMMA)
        break;
@@ -9176,7 +9939,7 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
    enumerator-definition:
      enumerator
      enumerator = constant-expression
-    
+
    enumerator:
      identifier  */
 
@@ -9191,7 +9954,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
     return;
-  
+
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* If it's an `=', then there's an explicit value.  */
@@ -9200,7 +9963,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
       /* Consume the `=' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the value.  */
-      value = cp_parser_constant_expression (parser, 
+      value = cp_parser_constant_expression (parser,
                                             /*allow_non_constant_p=*/false,
                                             NULL);
     }
@@ -9236,14 +9999,14 @@ cp_parser_namespace_name (cp_parser* parser)
        [basic.lookup.udir]
 
        When looking up a namespace-name in a using-directive or alias
-       definition, only namespace names are considered.  
+       definition, only namespace names are considered.
 
      And:
 
        [basic.lookup.qual]
 
        During the lookup of a name preceding the :: scope resolution
-       operator, object, function, and enumerator names are ignored.  
+       operator, object, function, and enumerator names are ignored.
 
      (Note that cp_parser_class_or_namespace_name only calls this
      function if the token after the name is the scope resolution
@@ -9260,7 +10023,7 @@ cp_parser_namespace_name (cp_parser* parser)
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
-  
+
   return namespace_decl;
 }
 
@@ -9268,7 +10031,7 @@ cp_parser_namespace_name (cp_parser* parser)
 
    namespace-definition:
      named-namespace-definition
-     unnamed-namespace-definition  
+     unnamed-namespace-definition
 
    named-namespace-definition:
      original-namespace-definition
@@ -9276,10 +10039,10 @@ cp_parser_namespace_name (cp_parser* parser)
 
    original-namespace-definition:
      namespace identifier { namespace-body }
-   
+
    extension-namespace-definition:
      namespace original-namespace-name { namespace-body }
+
    unnamed-namespace-definition:
      namespace { namespace-body } */
 
@@ -9343,7 +10106,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   /* Look for the `=' token.  */
   cp_parser_require (parser, CPP_EQ, "`='");
   /* Look for the qualified-namespace-specifier.  */
-  namespace_specifier 
+  namespace_specifier
     = cp_parser_qualified_namespace_specifier (parser);
   /* Look for the `;' token.  */
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
@@ -9364,7 +10127,7 @@ static tree
 cp_parser_qualified_namespace_specifier (cp_parser* parser)
 {
   /* Look for the optional `::'.  */
-  cp_parser_global_scope_opt (parser, 
+  cp_parser_global_scope_opt (parser,
                              /*current_scope_valid_p=*/false);
 
   /* Look for the optional nested-name-specifier.  */
@@ -9392,10 +10155,11 @@ cp_parser_using_declaration (cp_parser* parser)
   tree decl;
   tree identifier;
   tree scope;
+  tree qscope;
 
   /* Look for the `using' keyword.  */
   cp_parser_require_keyword (parser, RID_USING, "`using'");
-  
+
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* See if it's `typename'.  */
@@ -9408,29 +10172,31 @@ cp_parser_using_declaration (cp_parser* parser)
     }
 
   /* Look for the optional global scope qualification.  */
-  global_scope_p 
+  global_scope_p
     = (cp_parser_global_scope_opt (parser,
-                                  /*current_scope_valid_p=*/false) 
+                                  /*current_scope_valid_p=*/false)
        != NULL_TREE);
 
   /* If we saw `typename', or didn't see `::', then there must be a
      nested-name-specifier present.  */
   if (typename_p || !global_scope_p)
-    cp_parser_nested_name_specifier (parser, typename_p, 
-                                    /*check_dependency_p=*/true,
-                                    /*type_p=*/false,
-                                    /*is_declaration=*/true);
+    qscope = cp_parser_nested_name_specifier (parser, typename_p,
+                                             /*check_dependency_p=*/true,
+                                             /*type_p=*/false,
+                                             /*is_declaration=*/true);
   /* Otherwise, we could be in either of the two productions.  In that
      case, treat the nested-name-specifier as optional.  */
   else
-    cp_parser_nested_name_specifier_opt (parser,
-                                        /*typename_keyword_p=*/false,
-                                        /*check_dependency_p=*/true,
-                                        /*type_p=*/false,
-                                        /*is_declaration=*/true);
+    qscope = cp_parser_nested_name_specifier_opt (parser,
+                                                 /*typename_keyword_p=*/false,
+                                                 /*check_dependency_p=*/true,
+                                                 /*type_p=*/false,
+                                                 /*is_declaration=*/true);
+  if (!qscope)
+    qscope = global_namespace;
 
   /* Parse the unqualified-id.  */
-  identifier = cp_parser_unqualified_id (parser, 
+  identifier = cp_parser_unqualified_id (parser,
                                         /*template_keyword_p=*/false,
                                         /*check_dependency_p=*/true,
                                         /*declarator_p=*/true);
@@ -9463,9 +10229,9 @@ cp_parser_using_declaration (cp_parser* parser)
          if (decl == error_mark_node)
            cp_parser_name_lookup_error (parser, identifier, decl, NULL);
          else if (scope)
-           do_local_using_decl (decl);
+           do_local_using_decl (decl, qscope, identifier);
          else
-           do_toplevel_using_decl (decl);
+           do_toplevel_using_decl (decl, qscope, identifier);
        }
     }
 
@@ -9473,8 +10239,8 @@ cp_parser_using_declaration (cp_parser* parser)
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
 }
 
-/* Parse a using-directive.  
+/* Parse a using-directive.
+
    using-directive:
      using namespace :: [opt] nested-name-specifier [opt]
        namespace-name ;  */
@@ -9510,7 +10276,7 @@ cp_parser_using_directive (cp_parser* parser)
 /* Parse an asm-definition.
 
    asm-definition:
-     asm ( string-literal ) ;  
+     asm ( string-literal ) ;
 
    GNU Extension:
 
@@ -9519,8 +10285,8 @@ cp_parser_using_directive (cp_parser* parser)
      asm volatile [opt] ( string-literal : asm-operand-list [opt] ) ;
      asm volatile [opt] ( string-literal : asm-operand-list [opt]
                           : asm-operand-list [opt] ) ;
-     asm volatile [opt] ( string-literal : asm-operand-list [opt] 
-                          : asm-operand-list [opt] 
+     asm volatile [opt] ( string-literal : asm-operand-list [opt]
+                          : asm-operand-list [opt]
                           : asm-operand-list [opt] ) ;  */
 
 static void
@@ -9549,12 +10315,13 @@ cp_parser_asm_definition (cp_parser* parser)
   /* Look for the opening `('.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
   /* Look for the string.  */
+  c_lex_string_translate = 0;
   token = cp_parser_require (parser, CPP_STRING, "asm body");
   if (!token)
-    return;
+    goto finish;
   string = token->value;
   /* If we're allowing GNU extensions, check for the extended assembly
-     syntax.  Unfortunately, the `:' tokens need not be separated by 
+     syntax.  Unfortunately, the `:' tokens need not be separated by
      a space in C, and so, for compatibility, we tolerate that here
      too.  Doing that means that we have to treat the `::' operator as
      two `:' tokens.  */
@@ -9575,7 +10342,7 @@ cp_parser_asm_definition (cp_parser* parser)
          /* Consume the `:'.  */
          cp_lexer_consume_token (parser->lexer);
          /* Parse the output-operands.  */
-         if (cp_lexer_next_token_is_not (parser->lexer, 
+         if (cp_lexer_next_token_is_not (parser->lexer,
                                          CPP_COLON)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_SCOPE)
@@ -9601,7 +10368,7 @@ cp_parser_asm_definition (cp_parser* parser)
            /* Consume the `:'.  */
            cp_lexer_consume_token (parser->lexer);
          /* Parse the output-operands.  */
-         if (cp_lexer_next_token_is_not (parser->lexer, 
+         if (cp_lexer_next_token_is_not (parser->lexer,
                                          CPP_COLON)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_SCOPE)
@@ -9614,7 +10381,7 @@ cp_parser_asm_definition (cp_parser* parser)
        clobbers_p = true;
 
       /* Look for clobbers.  */
-      if (clobbers_p 
+      if (clobbers_p
          || cp_lexer_next_token_is (parser->lexer, CPP_COLON))
        {
          if (!clobbers_p)
@@ -9632,19 +10399,20 @@ cp_parser_asm_definition (cp_parser* parser)
                                           /*consume_paren=*/true);
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
 
-  /* Create the ASM_STMT.  */
+  /* Create the ASM_EXPR.  */
   if (at_function_scope_p ())
     {
-      asm_stmt = 
-       finish_asm_stmt (volatile_p 
-                        ? ridpointers[(int) RID_VOLATILE] : NULL_TREE,
-                        string, outputs, inputs, clobbers);
-      /* If the extended syntax was not used, mark the ASM_STMT.  */
+      asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
+                                 inputs, clobbers);
+      /* If the extended syntax was not used, mark the ASM_EXPR.  */
       if (!extended_p)
        ASM_INPUT_P (asm_stmt) = 1;
     }
   else
     assemble_asm (string);
+
+ finish:
+  c_lex_string_translate = 1;
 }
 
 /* Declarators [gram.dcl.decl] */
@@ -9661,13 +10429,13 @@ cp_parser_asm_definition (cp_parser* parser)
 
    function-definition:
      decl-specifier-seq [opt] declarator ctor-initializer [opt]
-       function-body 
-     decl-specifier-seq [opt] declarator function-try-block  
+       function-body
+     decl-specifier-seq [opt] declarator function-try-block
 
    GNU Extension:
 
    function-definition:
-     __extension__ function-definition 
+     __extension__ function-definition
 
    The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator.
    Returns a representation of the entity declared.  If MEMBER_P is TRUE,
@@ -9684,16 +10452,16 @@ cp_parser_asm_definition (cp_parser* parser)
    is FALSE.  */
 
 static tree
-cp_parser_init_declarator (cp_parser* parser, 
-                          tree decl_specifiers, 
-                          tree prefix_attributes,
+cp_parser_init_declarator (cp_parser* parser,
+                          cp_decl_specifier_seq *decl_specifiers,
                           bool function_definition_allowed_p,
                           bool member_p,
                           int declares_class_or_enum,
                           bool* function_definition_p)
 {
   cp_token *token;
-  tree declarator;
+  cp_declarator *declarator;
+  tree prefix_attributes;
   tree attributes;
   tree asm_specification;
   tree initializer;
@@ -9704,6 +10472,11 @@ cp_parser_init_declarator (cp_parser* parser,
   bool is_non_constant_init;
   int ctor_dtor_or_conv_p;
   bool friend_p;
+  bool pop_p = false;
+
+  /* Gather the attributes that were provided with the
+     decl-specifiers.  */
+  prefix_attributes = decl_specifiers->attributes;
 
   /* Assume that this is not the declarator for a function
      definition.  */
@@ -9711,12 +10484,12 @@ cp_parser_init_declarator (cp_parser* parser,
     *function_definition_p = false;
 
   /* Defer access checks while parsing the declarator; we cannot know
-     what names are accessible until we know what is being 
+     what names are accessible until we know what is being
      declared.  */
   resume_deferring_access_checks ();
 
   /* Parse the declarator.  */
-  declarator 
+  declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                            &ctor_dtor_or_conv_p,
                            /*parenthesized_p=*/NULL);
@@ -9725,7 +10498,7 @@ cp_parser_init_declarator (cp_parser* parser,
 
   /* If the DECLARATOR was erroneous, there's no need to go
      further.  */
-  if (declarator == error_mark_node)
+  if (declarator == cp_error_declarator)
     return error_mark_node;
 
   cp_parser_check_for_definition_in_return_type (declarator,
@@ -9783,7 +10556,7 @@ cp_parser_init_declarator (cp_parser* parser,
                                                        declarator,
                                                        prefix_attributes);
          else
-           decl 
+           decl
              = (cp_parser_function_definition_from_specifiers_and_declarator
                 (parser, decl_specifiers, prefix_attributes, declarator));
 
@@ -9794,24 +10567,24 @@ cp_parser_init_declarator (cp_parser* parser,
   /* [dcl.dcl]
 
      Only in function declarations for constructors, destructors, and
-     type conversions can the decl-specifier-seq be omitted.  
+     type conversions can the decl-specifier-seq be omitted.
 
      We explicitly postpone this check past the point where we handle
      function-definitions because we tolerate function-definitions
      that are missing their return types in some modes.  */
-  if (!decl_specifiers && ctor_dtor_or_conv_p <= 0)
+  if (!decl_specifiers->any_specifiers_p && ctor_dtor_or_conv_p <= 0)
     {
-      cp_parser_error (parser, 
+      cp_parser_error (parser,
                       "expected constructor, destructor, or type conversion");
       return error_mark_node;
     }
 
   /* An `=' or an `(' indicates an initializer.  */
-  is_initialized = (token->type == CPP_EQ 
+  is_initialized = (token->type == CPP_EQ
                     || token->type == CPP_OPEN_PAREN);
   /* If the init-declarator isn't initialized and isn't followed by a
      `,' or `;', it's not a valid init-declarator.  */
-  if (!is_initialized 
+  if (!is_initialized
       && token->type != CPP_COMMA
       && token->type != CPP_SEMICOLON)
     {
@@ -9828,11 +10601,11 @@ cp_parser_init_declarator (cp_parser* parser,
      sure this was intended to be a declarator.  Then continue
      declaring the variable(s), as int, to try to cut down on further
      errors.  */
-  if (decl_specifiers != NULL
-      && TREE_VALUE (decl_specifiers) == error_mark_node)
+  if (decl_specifiers->any_specifiers_p
+      && decl_specifiers->type == error_mark_node)
     {
       cp_parser_error (parser, "invalid type in declaration");
-      TREE_VALUE (decl_specifiers) = integer_type_node;
+      decl_specifiers->type = integer_type_node;
     }
 
   /* Check to see whether or not this declaration is a friend.  */
@@ -9849,9 +10622,7 @@ cp_parser_init_declarator (cp_parser* parser,
     {
       if (parser->in_unbraced_linkage_specification_p)
        {
-         decl_specifiers = tree_cons (error_mark_node,
-                                      get_identifier ("extern"),
-                                      decl_specifiers);
+         decl_specifiers->storage_class = sc_extern;
          have_extern_spec = false;
        }
       decl = start_decl (declarator, decl_specifiers,
@@ -9861,11 +10632,11 @@ cp_parser_init_declarator (cp_parser* parser,
   /* Enter the SCOPE.  That way unqualified names appearing in the
      initializer will be looked up in SCOPE.  */
   if (scope)
-    push_scope (scope);
+    pop_p = push_scope (scope);
 
   /* Perform deferred access control checks, now that we know in which
      SCOPE the declared entity resides.  */
-  if (!member_p && decl) 
+  if (!member_p && decl)
     {
       tree saved_current_function_decl = NULL_TREE;
 
@@ -9877,7 +10648,7 @@ cp_parser_init_declarator (cp_parser* parser,
          saved_current_function_decl = current_function_decl;
          current_function_decl = decl;
        }
-       
+
       /* Perform the access control checks for the declarator and the
         the decl-specifiers.  */
       perform_deferred_access_checks ();
@@ -9889,7 +10660,7 @@ cp_parser_init_declarator (cp_parser* parser,
 
   /* Parse the initializer.  */
   if (is_initialized)
-    initializer = cp_parser_initializer (parser, 
+    initializer = cp_parser_initializer (parser,
                                         &is_parenthesized_init,
                                         &is_non_constant_init);
   else
@@ -9909,9 +10680,9 @@ cp_parser_init_declarator (cp_parser* parser,
 
   /* Leave the SCOPE, now that we have processed the initializer.  It
      is important to do this before calling cp_finish_decl because it
-     makes decisions about whether to create DECL_STMTs or not based
+     makes decisions about whether to create DECL_EXPRs or not based
      on the current scope.  */
-  if (scope)
+  if (pop_p)
     pop_scope (scope);
 
   /* For an in-class declaration, use `grokfield' to create the
@@ -9924,12 +10695,12 @@ cp_parser_init_declarator (cp_parser* parser,
       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
        cp_parser_save_default_args (parser, decl);
     }
-  
+
   /* Finish processing the declaration.  But, skip friend
      declarations.  */
   if (!friend_p && decl)
-    cp_finish_decl (decl, 
-                   initializer, 
+    cp_finish_decl (decl,
+                   initializer,
                    asm_specification,
                    /* If the initializer is in parentheses, then this is
                       a direct-initialization, which means that an
@@ -9940,7 +10711,7 @@ cp_parser_init_declarator (cp_parser* parser,
 
   /* Remember whether or not variables were initialized by
      constant-expressions.  */
-  if (decl && TREE_CODE (decl) == VAR_DECL 
+  if (decl && TREE_CODE (decl) == VAR_DECL
       && is_initialized && !is_non_constant_init)
     DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
 
@@ -9948,10 +10719,10 @@ cp_parser_init_declarator (cp_parser* parser,
 }
 
 /* Parse a declarator.
-   
+
    declarator:
      direct-declarator
-     ptr-operator declarator  
+     ptr-operator declarator
 
    abstract-declarator:
      ptr-operator abstract-declarator [opt]
@@ -9961,59 +10732,39 @@ cp_parser_init_declarator (cp_parser* parser,
 
    declarator:
      attributes [opt] direct-declarator
-     attributes [opt] ptr-operator declarator  
+     attributes [opt] ptr-operator declarator
 
    abstract-declarator:
      attributes [opt] ptr-operator abstract-declarator [opt]
      attributes [opt] direct-abstract-declarator
-     
-   Returns a representation of the declarator.  If the declarator has
-   the form `* declarator', then an INDIRECT_REF is returned, whose
-   only operand is the sub-declarator.  Analogously, `& declarator' is
-   represented as an ADDR_EXPR.  For `X::* declarator', a SCOPE_REF is
-   used.  The first operand is the TYPE for `X'.  The second operand
-   is an INDIRECT_REF whose operand is the sub-declarator.
-
-   Otherwise, the representation is as for a direct-declarator.
-
-   (It would be better to define a structure type to represent
-   declarators, rather than abusing `tree' nodes to represent
-   declarators.  That would be much clearer and save some memory.
-   There is no reason for declarators to be garbage-collected, for
-   example; they are created during parser and no longer needed after
-   `grokdeclarator' has been called.)
-
-   For a ptr-operator that has the optional cv-qualifier-seq,
-   cv-qualifiers will be stored in the TREE_TYPE of the INDIRECT_REF
-   node.
 
    If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
    detect constructor, destructor or conversion operators. It is set
    to -1 if the declarator is a name, and +1 if it is a
    function. Otherwise it is set to zero. Usually you just want to
    test for >0, but internally the negative value is used.
-   
+
    (The reason for CTOR_DTOR_OR_CONV_P is that a declaration must have
    a decl-specifier-seq unless it declares a constructor, destructor,
    or conversion.  It might seem that we could check this condition in
    semantic analysis, rather than parsing, but that makes it difficult
    to handle something like `f()'.  We want to notice that there are
    no decl-specifiers, and therefore realize that this is an
-   expression, not a declaration.)  
+   expression, not a declaration.)
+
    If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
    the declarator is a direct-declarator of the form "(...)".  */
 
-static tree
-cp_parser_declarator (cp_parser* parser, 
-                      cp_parser_declarator_kind dcl_kind, 
+static cp_declarator *
+cp_parser_declarator (cp_parser* parser,
+                      cp_parser_declarator_kind dcl_kind,
                       int* ctor_dtor_or_conv_p,
                      bool* parenthesized_p)
 {
   cp_token *token;
-  tree declarator;
+  cp_declarator *declarator;
   enum tree_code code;
-  tree cv_qualifier_seq;
+  cp_cv_quals cv_quals;
   tree class_type;
   tree attributes = NULL_TREE;
 
@@ -10024,16 +10775,16 @@ cp_parser_declarator (cp_parser* parser,
 
   if (cp_parser_allow_gnu_extensions_p (parser))
     attributes = cp_parser_attributes_opt (parser);
-  
+
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
-  
+
   /* Check for the ptr-operator production.  */
   cp_parser_parse_tentatively (parser);
   /* Parse the ptr-operator.  */
-  code = cp_parser_ptr_operator (parser, 
-                                &class_type, 
-                                &cv_qualifier_seq);
+  code = cp_parser_ptr_operator (parser,
+                                &class_type,
+                                &cv_quals);
   /* If that worked, then we have a ptr-operator.  */
   if (cp_parser_parse_definitely (parser))
     {
@@ -10055,18 +10806,17 @@ cp_parser_declarator (cp_parser* parser,
         case where the dependent declarator is absent.  */
       if (dcl_kind != CP_PARSER_DECLARATOR_NAMED
          && !cp_parser_parse_definitely (parser))
-       declarator = NULL_TREE;
-       
+       declarator = NULL;
+
       /* Build the representation of the ptr-operator.  */
-      if (code == INDIRECT_REF)
-       declarator = make_pointer_declarator (cv_qualifier_seq, 
-                                             declarator);
-      else
-       declarator = make_reference_declarator (cv_qualifier_seq,
-                                               declarator);
-      /* Handle the pointer-to-member case.  */
       if (class_type)
-       declarator = build_nt (SCOPE_REF, class_type, declarator);
+       declarator = make_ptrmem_declarator (cv_quals,
+                                            class_type,
+                                            declarator);
+      else if (code == INDIRECT_REF)
+       declarator = make_pointer_declarator (cv_quals, declarator);
+      else
+       declarator = make_reference_declarator (cv_quals, declarator);
     }
   /* Everything else is a direct-declarator.  */
   else
@@ -10078,9 +10828,9 @@ cp_parser_declarator (cp_parser* parser,
                                                ctor_dtor_or_conv_p);
     }
 
-  if (attributes && declarator != error_mark_node)
-    declarator = tree_cons (attributes, declarator, NULL_TREE);
-  
+  if (attributes && declarator != cp_error_declarator)
+    declarator->attributes = attributes;
+
   return declarator;
 }
 
@@ -10089,14 +10839,14 @@ cp_parser_declarator (cp_parser* parser,
    direct-declarator:
      declarator-id
      direct-declarator ( parameter-declaration-clause )
-       cv-qualifier-seq [opt] 
+       cv-qualifier-seq [opt]
        exception-specification [opt]
      direct-declarator [ constant-expression [opt] ]
-     ( declarator )  
+     ( declarator )
 
    direct-abstract-declarator:
      direct-abstract-declarator [opt]
-       ( parameter-declaration-clause ) 
+       ( parameter-declaration-clause )
        cv-qualifier-seq [opt]
        exception-specification [opt]
      direct-abstract-declarator [opt] [ constant-expression [opt] ]
@@ -10109,29 +10859,21 @@ cp_parser_declarator (cp_parser* parser,
    CP_PARSER_DECLARATOR_EITHER, if we can accept either - in the case
    of ambiguity we prefer an abstract declarator, as per
    [dcl.ambig.res].  CTOR_DTOR_OR_CONV_P is as for
-   cp_parser_declarator.
-
-   For the declarator-id production, the representation is as for an
-   id-expression, except that a qualified name is represented as a
-   SCOPE_REF.  A function-declarator is represented as a CALL_EXPR;
-   see the documentation of the FUNCTION_DECLARATOR_* macros for
-   information about how to find the various declarator components.
-   An array-declarator is represented as an ARRAY_REF.  The
-   direct-declarator is the first operand; the constant-expression
-   indicating the size of the array is the second operand.  */
+   cp_parser_declarator.  */
 
-static tree
+static cp_declarator *
 cp_parser_direct_declarator (cp_parser* parser,
                              cp_parser_declarator_kind dcl_kind,
                              int* ctor_dtor_or_conv_p)
 {
   cp_token *token;
-  tree declarator = NULL_TREE;
+  cp_declarator *declarator = NULL;
   tree scope = NULL_TREE;
   bool saved_default_arg_ok_p = parser->default_arg_ok_p;
   bool saved_in_declarator_p = parser->in_declarator_p;
   bool first = true;
-  
+  bool pop_p = false;
+
   while (true)
     {
       /* Peek at the next token.  */
@@ -10148,7 +10890,7 @@ cp_parser_direct_declarator (cp_parser* parser,
             template parameter `(T)' is a
             parameter-declaration-clause, and not a parenthesized
             named declarator.
-            
+
             We first try and parse a parameter-declaration-clause,
             and then try a nested declarator (if FIRST is true).
 
@@ -10171,16 +10913,16 @@ cp_parser_direct_declarator (cp_parser* parser,
               int i (int (3));
 
             The former is a function-declaration; the latter is a
-            variable initialization.  
+            variable initialization.
 
             Thus again, we try a parameter-declaration-clause, and if
             that fails, we back out and return.  */
 
          if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
            {
-             tree params;
+             cp_parameter_declarator *params;
              unsigned saved_num_template_parameter_lists;
-             
+
              cp_parser_parse_tentatively (parser);
 
              /* Consume the `('.  */
@@ -10192,7 +10934,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                  parser->default_arg_ok_p = false;
                  parser->in_declarator_p = true;
                }
-         
+
              /* Inside the function parameter list, surrounding
                 template-parameter-lists do not apply.  */
              saved_num_template_parameter_lists
@@ -10209,7 +10951,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                 exception-specification.  */
              if (cp_parser_parse_definitely (parser))
                {
-                 tree cv_qualifiers;
+                 cp_cv_quals cv_quals;
                  tree exception_specification;
 
                  if (ctor_dtor_or_conv_p)
@@ -10219,46 +10961,51 @@ cp_parser_direct_declarator (cp_parser* parser,
                  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
                  /* Parse the cv-qualifier-seq.  */
-                 cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser);
+                 cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
                  /* And the exception-specification.  */
-                 exception_specification 
+                 exception_specification
                    = cp_parser_exception_specification_opt (parser);
 
                  /* Create the function-declarator.  */
                  declarator = make_call_declarator (declarator,
                                                     params,
-                                                    cv_qualifiers,
+                                                    cv_quals,
                                                     exception_specification);
                  /* Any subsequent parameter lists are to do with
                     return type, so are not those of the declared
                     function.  */
                  parser->default_arg_ok_p = false;
-                 
+
                  /* Repeat the main loop.  */
                  continue;
                }
            }
-         
+
          /* If this is the first, we can try a parenthesized
             declarator.  */
          if (first)
            {
+             bool saved_in_type_id_in_expr_p;
+
              parser->default_arg_ok_p = saved_default_arg_ok_p;
              parser->in_declarator_p = saved_in_declarator_p;
-             
+
              /* Consume the `('.  */
              cp_lexer_consume_token (parser->lexer);
              /* Parse the nested declarator.  */
-             declarator 
+             saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p;
+             parser->in_type_id_in_expr_p = true;
+             declarator
                = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL);
+             parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
              first = false;
              /* Expect a `)'.  */
              if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
-               declarator = error_mark_node;
-             if (declarator == error_mark_node)
+               declarator = cp_error_declarator;
+             if (declarator == cp_error_declarator)
                break;
-             
+
              goto handle_declarator;
            }
          /* Otherwise, we must be done.  */
@@ -10273,7 +11020,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 
          if (ctor_dtor_or_conv_p)
            *ctor_dtor_or_conv_p = 0;
-         
+
          first = false;
          parser->default_arg_ok_p = false;
          parser->in_declarator_p = true;
@@ -10287,60 +11034,64 @@ cp_parser_direct_declarator (cp_parser* parser,
            {
              bool non_constant_p;
 
-             bounds 
+             bounds
                = cp_parser_constant_expression (parser,
                                                 /*allow_non_constant=*/true,
                                                 &non_constant_p);
              if (!non_constant_p)
-               bounds = cp_parser_fold_non_dependent_expr (bounds);
+               bounds = fold_non_dependent_expr (bounds);
            }
          else
            bounds = NULL_TREE;
          /* Look for the closing `]'.  */
          if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
            {
-             declarator = error_mark_node;
+             declarator = cp_error_declarator;
              break;
            }
 
-         declarator = build_nt (ARRAY_REF, declarator, bounds);
+         declarator = make_array_declarator (declarator, bounds);
        }
       else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
        {
+         tree id;
+
          /* Parse a declarator-id */
          if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
            cp_parser_parse_tentatively (parser);
-         declarator = cp_parser_declarator_id (parser);
+         id = cp_parser_declarator_id (parser);
          if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
            {
              if (!cp_parser_parse_definitely (parser))
-               declarator = error_mark_node;
-             else if (TREE_CODE (declarator) != IDENTIFIER_NODE)
+               id = error_mark_node;
+             else if (TREE_CODE (id) != IDENTIFIER_NODE)
                {
                  cp_parser_error (parser, "expected unqualified-id");
-                 declarator = error_mark_node;
+                 id = error_mark_node;
                }
            }
-         
-         if (declarator == error_mark_node)
-           break;
-         
-         if (TREE_CODE (declarator) == SCOPE_REF
-             && !current_scope ())
+
+         if (id == error_mark_node)
+           {
+             declarator = cp_error_declarator;
+             break;
+           }
+
+         if (TREE_CODE (id) == SCOPE_REF && !current_scope ())
            {
-             tree scope = TREE_OPERAND (declarator, 0);
+             tree scope = TREE_OPERAND (id, 0);
 
              /* In the declaration of a member of a template class
                 outside of the class itself, the SCOPE will sometimes
                 be a TYPENAME_TYPE.  For example, given:
-                 
+
                         template <typename T>
                 int S<T>::R::i = 3;
-                 
+
                 the SCOPE will be a TYPENAME_TYPE for `S<T>::R'.  In
                 this context, we must resolve S<T>::R to an ordinary
                 type, rather than a typename type.
-                 
+
                 The reason we normally avoid resolving TYPENAME_TYPEs
                 is that a specialization of `S' might render
                 `S<T>::R' not a type.  However, if `S' is
@@ -10354,56 +11105,70 @@ cp_parser_direct_declarator (cp_parser* parser,
                  type = resolve_typename_type (scope,
                                                 /*only_current_p=*/false);
                  /* If that failed, the declarator is invalid.  */
-                 if (type != error_mark_node)
-                   scope = type;
+                 if (type == error_mark_node)
+                   error ("`%T::%D' is not a type",
+                          TYPE_CONTEXT (scope),
+                          TYPE_IDENTIFIER (scope));
                  /* Build a new DECLARATOR.  */
-                 declarator = build_nt (SCOPE_REF, 
-                                        scope,
-                                        TREE_OPERAND (declarator, 1));
+                 id = build_nt (SCOPE_REF, type, TREE_OPERAND (id, 1));
                }
            }
-      
-         /* Check to see whether the declarator-id names a constructor, 
-            destructor, or conversion.  */
-         if (declarator && ctor_dtor_or_conv_p 
-             && ((TREE_CODE (declarator) == SCOPE_REF 
-                  && CLASS_TYPE_P (TREE_OPERAND (declarator, 0)))
-                 || (TREE_CODE (declarator) != SCOPE_REF
-                     && at_class_scope_p ())))
+
+         declarator = make_id_declarator (id);
+         if (id)
            {
-             tree unqualified_name;
              tree class_type;
+             tree unqualified_name;
 
-             /* Get the unqualified part of the name.  */
-             if (TREE_CODE (declarator) == SCOPE_REF)
+             if (TREE_CODE (id) == SCOPE_REF
+                 && CLASS_TYPE_P (TREE_OPERAND (id, 0)))
                {
-                 class_type = TREE_OPERAND (declarator, 0);
-                 unqualified_name = TREE_OPERAND (declarator, 1);
+                 class_type = TREE_OPERAND (id, 0);
+                 unqualified_name = TREE_OPERAND (id, 1);
                }
              else
                {
                  class_type = current_class_type;
-                 unqualified_name = declarator;
+                 unqualified_name = id;
                }
 
-             /* See if it names ctor, dtor or conv.  */
-             if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
-                 || IDENTIFIER_TYPENAME_P (unqualified_name)
-                 || constructor_name_p (unqualified_name, class_type))
-               *ctor_dtor_or_conv_p = -1;
+             if (class_type)
+               {
+                 if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
+                   declarator->u.id.sfk = sfk_destructor;
+                 else if (IDENTIFIER_TYPENAME_P (unqualified_name))
+                   declarator->u.id.sfk = sfk_conversion;
+                 else if (constructor_name_p (unqualified_name,
+                                              class_type)
+                          || (TREE_CODE (unqualified_name) == TYPE_DECL
+                              && same_type_p (TREE_TYPE (unqualified_name),
+                                              class_type)))
+                   declarator->u.id.sfk = sfk_constructor;
+
+                 if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none)
+                   *ctor_dtor_or_conv_p = -1;
+                 if (TREE_CODE (id) == SCOPE_REF
+                     && TREE_CODE (unqualified_name) == TYPE_DECL
+                     && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
+                   {
+                     error ("invalid use of constructor as a template");
+                     inform ("use `%T::%D' instead of `%T::%T' to name the "
+                             "constructor in a qualified name", class_type,
+                             DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
+                             class_type, class_type);
+                   }
+               }
            }
 
        handle_declarator:;
          scope = get_scope_of_declarator (declarator);
          if (scope)
-           /* Any names that appear after the declarator-id for a member
-                      are looked up in the containing scope.  */
-           push_scope (scope);
+           /* Any names that appear after the declarator-id for a
+              member are looked up in the containing scope.  */
+           pop_p = push_scope (scope);
          parser->in_declarator_p = true;
          if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
-             || (declarator
-                 && (TREE_CODE (declarator) == SCOPE_REF
-                     || TREE_CODE (declarator) == IDENTIFIER_NODE)))
+             || (declarator && declarator->kind == cdk_id))
            /* Default args are only allowed on function
               declarations.  */
            parser->default_arg_ok_p = saved_default_arg_ok_p;
@@ -10423,16 +11188,16 @@ cp_parser_direct_declarator (cp_parser* parser,
     cp_parser_error (parser, "expected declarator");
 
   /* If we entered a scope, we must exit it now.  */
-  if (scope)
+  if (pop_p)
     pop_scope (scope);
 
   parser->default_arg_ok_p = saved_default_arg_ok_p;
   parser->in_declarator_p = saved_in_declarator_p;
-  
+
   return declarator;
 }
 
-/* Parse a ptr-operator.  
+/* Parse a ptr-operator.
 
    ptr-operator:
      * cv-qualifier-seq [opt]
@@ -10444,17 +11209,17 @@ cp_parser_direct_declarator (cp_parser* parser,
    ptr-operator:
      & cv-qualifier-seq [opt]
 
-   Returns INDIRECT_REF if a pointer, or pointer-to-member, was
-   used.  Returns ADDR_EXPR if a reference was used.  In the
-   case of a pointer-to-member, *TYPE is filled in with the 
-   TYPE containing the member.  *CV_QUALIFIER_SEQ is filled in
-   with the cv-qualifier-seq, or NULL_TREE, if there are no
-   cv-qualifiers.  Returns ERROR_MARK if an error occurred.  */
-   
+   Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
+   Returns ADDR_EXPR if a reference was used.  In the case of a
+   pointer-to-member, *TYPE is filled in with the TYPE containing the
+   member.  *CV_QUALS is filled in with the cv-qualifier-seq, or
+   TYPE_UNQUALIFIED, if there are no cv-qualifiers.  Returns
+   ERROR_MARK if an error occurred.  */
+
 static enum tree_code
-cp_parser_ptr_operator (cp_parser* parser, 
-                        tree* type, 
-                        tree* cv_qualifier_seq)
+cp_parser_ptr_operator (cp_parser* parser,
+                        tree* type,
+                       cp_cv_quals *cv_quals)
 {
   enum tree_code code = ERROR_MARK;
   cp_token *token;
@@ -10462,7 +11227,7 @@ cp_parser_ptr_operator (cp_parser* parser,
   /* Assume that it's not a pointer-to-member.  */
   *type = NULL_TREE;
   /* And that there are no cv-qualifiers.  */
-  *cv_qualifier_seq = NULL_TREE;
+  *cv_quals = TYPE_UNQUALIFIED;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -10479,9 +11244,9 @@ cp_parser_ptr_operator (cp_parser* parser,
         `&', if we are allowing GNU extensions.  (The only qualifier
         that can legally appear after `&' is `restrict', but that is
         enforced during semantic analysis.  */
-      if (code == INDIRECT_REF 
+      if (code == INDIRECT_REF
          || cp_parser_allow_gnu_extensions_p (parser))
-       *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser);
+       *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
     }
   else
     {
@@ -10511,7 +11276,7 @@ cp_parser_ptr_operator (cp_parser* parser,
          /* Indicate that the `*' operator was used.  */
          code = INDIRECT_REF;
          /* Look for the optional cv-qualifier-seq.  */
-         *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser);
+         *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
        }
       /* If that didn't work we don't have a ptr-operator.  */
       if (!cp_parser_parse_definitely (parser))
@@ -10524,78 +11289,74 @@ cp_parser_ptr_operator (cp_parser* parser,
 /* Parse an (optional) cv-qualifier-seq.
 
    cv-qualifier-seq:
-     cv-qualifier cv-qualifier-seq [opt]  
+     cv-qualifier cv-qualifier-seq [opt]
 
-   Returns a TREE_LIST.  The TREE_VALUE of each node is the
-   representation of a cv-qualifier.  */
+   cv-qualifier:
+     const
+     volatile
 
-static tree
-cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
-{
-  tree cv_qualifiers = NULL_TREE;
-  
-  while (true)
-    {
-      tree cv_qualifier;
+   GNU Extension:
 
-      /* Look for the next cv-qualifier.  */
-      cv_qualifier = cp_parser_cv_qualifier_opt (parser);
-      /* If we didn't find one, we're done.  */
-      if (!cv_qualifier)
-       break;
+   cv-qualifier:
+     __restrict__
 
-      /* Add this cv-qualifier to the list.  */
-      cv_qualifiers 
-       = tree_cons (NULL_TREE, cv_qualifier, cv_qualifiers);
-    }
+   Returns a bitmask representing the cv-qualifiers.  */
 
-  /* We built up the list in reverse order.  */
-  return nreverse (cv_qualifiers);
-}
+static cp_cv_quals
+cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
+{
+  cp_cv_quals cv_quals = TYPE_UNQUALIFIED;
 
-/* Parse an (optional) cv-qualifier.
+  while (true)
+    {
+      cp_token *token;
+      cp_cv_quals cv_qualifier;
 
-   cv-qualifier:
-     const
-     volatile  
+      /* Peek at the next token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      /* See if it's a cv-qualifier.  */
+      switch (token->keyword)
+       {
+       case RID_CONST:
+         cv_qualifier = TYPE_QUAL_CONST;
+         break;
 
-   GNU Extension:
+       case RID_VOLATILE:
+         cv_qualifier = TYPE_QUAL_VOLATILE;
+         break;
 
-   cv-qualifier:
-     __restrict__ */
+       case RID_RESTRICT:
+         cv_qualifier = TYPE_QUAL_RESTRICT;
+         break;
 
-static tree
-cp_parser_cv_qualifier_opt (cp_parser* parser)
-{
-  cp_token *token;
-  tree cv_qualifier = NULL_TREE;
+       default:
+         cv_qualifier = TYPE_UNQUALIFIED;
+         break;
+       }
 
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  /* See if it's a cv-qualifier.  */
-  switch (token->keyword)
-    {
-    case RID_CONST:
-    case RID_VOLATILE:
-    case RID_RESTRICT:
-      /* Save the value of the token.  */
-      cv_qualifier = token->value;
-      /* Consume the token.  */
-      cp_lexer_consume_token (parser->lexer);
-      break;
+      if (!cv_qualifier)
+       break;
 
-    default:
-      break;
+      if (cv_quals & cv_qualifier)
+       {
+         error ("duplicate cv-qualifier");
+         cp_lexer_purge_token (parser->lexer);
+       }
+      else
+       {
+         cp_lexer_consume_token (parser->lexer);
+         cv_quals |= cv_qualifier;
+       }
     }
 
-  return cv_qualifier;
+  return cv_quals;
 }
 
 /* Parse a declarator-id.
 
    declarator-id:
      id-expression
-     :: [opt] nested-name-specifier [opt] type-name  
+     :: [opt] nested-name-specifier [opt] type-name
 
    In the `id-expression' case, the value returned is as for
    cp_parser_id_expression if the id-expression was an unqualified-id.
@@ -10628,7 +11389,7 @@ cp_parser_declarator_id (cp_parser* parser)
                                           /*check_dependency_p=*/false,
                                           /*template_p=*/NULL,
                                           /*declarator_p=*/true);
-  /* If the name was qualified, create a SCOPE_REF to represent 
+  /* If the name was qualified, create a SCOPE_REF to represent
      that.  */
   if (parser->scope)
     {
@@ -10649,27 +11410,25 @@ cp_parser_declarator_id (cp_parser* parser)
 static tree
 cp_parser_type_id (cp_parser* parser)
 {
-  tree type_specifier_seq;
-  tree abstract_declarator;
+  cp_decl_specifier_seq type_specifier_seq;
+  cp_declarator *abstract_declarator;
 
   /* Parse the type-specifier-seq.  */
-  type_specifier_seq 
-    = cp_parser_type_specifier_seq (parser);
-  if (type_specifier_seq == error_mark_node)
+  cp_parser_type_specifier_seq (parser, &type_specifier_seq);
+  if (type_specifier_seq.type == error_mark_node)
     return error_mark_node;
 
   /* There might or might not be an abstract declarator.  */
   cp_parser_parse_tentatively (parser);
   /* Look for the declarator.  */
-  abstract_declarator 
+  abstract_declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
                            /*parenthesized_p=*/NULL);
   /* Check to see if there really was a declarator.  */
   if (!cp_parser_parse_definitely (parser))
-    abstract_declarator = NULL_TREE;
+    abstract_declarator = NULL;
 
-  return groktypename (build_tree_list (type_specifier_seq,
-                                       abstract_declarator));
+  return groktypename (&type_specifier_seq, abstract_declarator);
 }
 
 /* Parse a type-specifier-seq.
@@ -10682,14 +11441,16 @@ cp_parser_type_id (cp_parser* parser)
    type-specifier-seq:
      attributes type-specifier-seq [opt]
 
-   Returns a TREE_LIST.  Either the TREE_VALUE of each node is a
-   type-specifier, or the TREE_PURPOSE is a list of attributes.  */
+   Sets *TYPE_SPECIFIER_SEQ to represent the sequence.  */
 
-static tree
-cp_parser_type_specifier_seq (cp_parser* parser)
+static void
+cp_parser_type_specifier_seq (cp_parser* parser,
+                             cp_decl_specifier_seq *type_specifier_seq)
 {
   bool seen_type_specifier = false;
-  tree type_specifier_seq = NULL_TREE;
+
+  /* Clear the TYPE_SPECIFIER_SEQ.  */
+  clear_decl_specs (type_specifier_seq);
 
   /* Parse the type-specifiers and attributes.  */
   while (true)
@@ -10699,39 +11460,36 @@ cp_parser_type_specifier_seq (cp_parser* parser)
       /* Check for attributes first.  */
       if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
        {
-         type_specifier_seq = tree_cons (cp_parser_attributes_opt (parser),
-                                         NULL_TREE,
-                                         type_specifier_seq);
+         type_specifier_seq->attributes =
+           chainon (type_specifier_seq->attributes,
+                    cp_parser_attributes_opt (parser));
          continue;
        }
 
-      /* After the first type-specifier, others are optional.  */
-      if (seen_type_specifier)
-       cp_parser_parse_tentatively (parser);
       /* Look for the type-specifier.  */
-      type_specifier = cp_parser_type_specifier (parser, 
-                                                CP_PARSER_FLAGS_NONE,
-                                                /*is_friend=*/false,
+      type_specifier = cp_parser_type_specifier (parser,
+                                                CP_PARSER_FLAGS_OPTIONAL,
+                                                type_specifier_seq,
                                                 /*is_declaration=*/false,
                                                 NULL,
                                                 NULL);
       /* If the first type-specifier could not be found, this is not a
         type-specifier-seq at all.  */
-      if (!seen_type_specifier && type_specifier == error_mark_node)
-       return error_mark_node;
+      if (!seen_type_specifier && !type_specifier)
+       {
+         cp_parser_error (parser, "expected type-specifier");
+         type_specifier_seq->type = error_mark_node;
+         return;
+       }
       /* If subsequent type-specifiers could not be found, the
         type-specifier-seq is complete.  */
-      else if (seen_type_specifier && !cp_parser_parse_definitely (parser))
+      else if (seen_type_specifier && !type_specifier)
        break;
 
-      /* Add the new type-specifier to the list.  */
-      type_specifier_seq 
-       = tree_cons (NULL_TREE, type_specifier, type_specifier_seq);
       seen_type_specifier = true;
     }
 
-  /* We built up the list in reverse order.  */
-  return nreverse (type_specifier_seq);
+  return;
 }
 
 /* Parse a parameter-declaration-clause.
@@ -10740,19 +11498,17 @@ cp_parser_type_specifier_seq (cp_parser* parser)
      parameter-declaration-list [opt] ... [opt]
      parameter-declaration-list , ...
 
-   Returns a representation for the parameter declarations.  Each node
-   is a TREE_LIST.  (See cp_parser_parameter_declaration for the exact
-   representation.)  If the parameter-declaration-clause ends with an
-   ellipsis, PARMLIST_ELLIPSIS_P will hold of the first node in the
-   list.  A return value of NULL_TREE indicates a
-   parameter-declaration-clause consisting only of an ellipsis.  */
+   Returns a representation for the parameter declarations.  A return
+   value of NULL indicates a parameter-declaration-clause consisting
+   only of an ellipsis.  */
 
-static tree
+static cp_parameter_declarator *
 cp_parser_parameter_declaration_clause (cp_parser* parser)
 {
-  tree parameters;
+  cp_parameter_declarator *parameters;
   cp_token *token;
   bool ellipsis_p;
+  bool is_error;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -10761,7 +11517,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     {
       /* Consume the `...' token.  */
       cp_lexer_consume_token (parser->lexer);
-      return NULL_TREE;
+      return NULL;
     }
   else if (token->type == CPP_CLOSE_PAREN)
     /* There are no parameters.  */
@@ -10769,29 +11525,29 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
 #ifndef NO_IMPLICIT_EXTERN_C
       if (in_system_header && current_class_type == NULL
          && current_lang_name == lang_name_c)
-       return NULL_TREE;
+       return NULL;
       else
 #endif
-       return void_list_node;
+       return no_parameters;
     }
   /* Check for `(void)', too, which is a special case.  */
   else if (token->keyword == RID_VOID
-          && (cp_lexer_peek_nth_token (parser->lexer, 2)->type 
+          && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
               == CPP_CLOSE_PAREN))
     {
       /* Consume the `void' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* There are no parameters.  */
-      return void_list_node;
+      return no_parameters;
     }
-  
+
   /* Parse the parameter-declaration-list.  */
-  parameters = cp_parser_parameter_declaration_list (parser);
+  parameters = cp_parser_parameter_declaration_list (parser, &is_error);
   /* If a parse error occurred while parsing the
      parameter-declaration-list, then the entire
      parameter-declaration-clause is erroneous.  */
-  if (parameters == error_mark_node)
-    return error_mark_node;
+  if (is_error)
+    return NULL;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -10801,10 +11557,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       /* Consume the `,'.  */
       cp_lexer_consume_token (parser->lexer);
       /* Expect an ellipsis.  */
-      ellipsis_p 
+      ellipsis_p
        = (cp_parser_require (parser, CPP_ELLIPSIS, "`...'") != NULL);
     }
-  /* It might also be `...' if the optional trailing `,' was 
+  /* It might also be `...' if the optional trailing `,' was
      omitted.  */
   else if (token->type == CPP_ELLIPSIS)
     {
@@ -10817,7 +11573,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     ellipsis_p = false;
 
   /* Finish the parameter list.  */
-  return finish_parmlist (parameters, ellipsis_p);
+  if (parameters && ellipsis_p)
+    parameters->ellipsis_p = true;
+
+  return parameters;
 }
 
 /* Parse a parameter-declaration-list.
@@ -10828,34 +11587,40 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
 
    Returns a representation of the parameter-declaration-list, as for
    cp_parser_parameter_declaration_clause.  However, the
-   `void_list_node' is never appended to the list.  */
+   `void_list_node' is never appended to the list.  Upon return,
+   *IS_ERROR will be true iff an error occurred.  */
 
-static tree
-cp_parser_parameter_declaration_list (cp_parser* parser)
+static cp_parameter_declarator *
+cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
-  tree parameters = NULL_TREE;
+  cp_parameter_declarator *parameters = NULL;
+  cp_parameter_declarator **tail = &parameters;
+
+  /* Assume all will go well.  */
+  *is_error = false;
 
   /* Look for more parameters.  */
   while (true)
     {
-      tree parameter;
+      cp_parameter_declarator *parameter;
       bool parenthesized_p;
       /* Parse the parameter.  */
-      parameter 
-       = cp_parser_parameter_declaration (parser, 
+      parameter
+       = cp_parser_parameter_declaration (parser,
                                           /*template_parm_p=*/false,
                                           &parenthesized_p);
 
       /* If a parse error occurred parsing the parameter declaration,
         then the entire parameter-declaration-list is erroneous.  */
-      if (parameter == error_mark_node)
+      if (!parameter)
        {
-         parameters = error_mark_node;
+         *is_error = true;
+         parameters = NULL;
          break;
        }
       /* Add the new parameter to the list.  */
-      TREE_CHAIN (parameter) = parameters;
-      parameters = parameter;
+      *tail = parameter;
+      tail = &parameter->next;
 
       /* Peek at the next token.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
@@ -10877,16 +11642,17 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
          /* When parsing something like:
 
                int i(float f, double d)
-               
+
              we can tell after seeing the declaration for "f" that we
             are not looking at an initialization of a variable "i",
-            but rather at the declaration of a function "i".  
+            but rather at the declaration of a function "i".
 
             Due to the fact that the parsing of template arguments
             (as specified to a template-id) requires backtracking we
             cannot use this technique when inside a template argument
             list.  */
          if (!parser->in_template_argument_list_p
+             && !parser->in_type_id_in_expr_p
              && cp_parser_parsing_tentatively (parser)
              && !cp_parser_committed_to_tentative_parse (parser)
              /* However, a parameter-declaration of the form
@@ -10901,7 +11667,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
          cp_parser_error (parser, "expected `,' or `...'");
          if (!cp_parser_parsing_tentatively (parser)
              || cp_parser_committed_to_tentative_parse (parser))
-           cp_parser_skip_to_closing_parenthesis (parser, 
+           cp_parser_skip_to_closing_parenthesis (parser,
                                                   /*recovering=*/true,
                                                   /*or_comma=*/false,
                                                   /*consume_paren=*/false);
@@ -10909,8 +11675,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
        }
     }
 
-  /* We built up the list in reverse order; straighten it out now.  */
-  return nreverse (parameters);
+  return parameters;
 }
 
 /* Parse a parameter declaration.
@@ -10926,27 +11691,20 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
    token encountered during the parsing of the assignment-expression
    is not interpreted as a greater-than operator.)
 
-   Returns a TREE_LIST representing the parameter-declaration.  The
-   TREE_PURPOSE is the default argument expression, or NULL_TREE if
-   there is no default argument.  The TREE_VALUE is a representation
-   of the decl-specifier-seq and declarator.  In particular, the
-   TREE_VALUE will be a TREE_LIST whose TREE_PURPOSE represents the
-   decl-specifier-seq and whose TREE_VALUE represents the declarator.
-   If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
-   the declarator is of the form "(p)".  */
+   Returns a representation of the parameter, or NULL if an error
+   occurs.  If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to
+   true iff the declarator is of the form "(p)".  */
 
-static tree
-cp_parser_parameter_declaration (cp_parser *parser, 
+static cp_parameter_declarator *
+cp_parser_parameter_declaration (cp_parser *parser,
                                 bool template_parm_p,
                                 bool *parenthesized_p)
 {
   int declares_class_or_enum;
   bool greater_than_is_operator_p;
-  tree decl_specifiers;
-  tree attributes;
-  tree declarator;
+  cp_decl_specifier_seq decl_specifiers;
+  cp_declarator *declarator;
   tree default_argument;
-  tree parameter;
   cp_token *token;
   const char *saved_message;
 
@@ -10962,34 +11720,33 @@ cp_parser_parameter_declaration (cp_parser *parser,
 
   /* Type definitions may not appear in parameter types.  */
   saved_message = parser->type_definition_forbidden_message;
-  parser->type_definition_forbidden_message 
+  parser->type_definition_forbidden_message
     = "types may not be defined in parameter types";
 
   /* Parse the declaration-specifiers.  */
-  decl_specifiers 
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_NONE,
-                                   &attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_NONE,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
   /* If an error occurred, there's no reason to attempt to parse the
      rest of the declaration.  */
   if (cp_parser_error_occurred (parser))
     {
       parser->type_definition_forbidden_message = saved_message;
-      return error_mark_node;
+      return NULL;
     }
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* If the next token is a `)', `,', `=', `>', or `...', then there
      is no declarator.  */
-  if (token->type == CPP_CLOSE_PAREN 
+  if (token->type == CPP_CLOSE_PAREN
       || token->type == CPP_COMMA
       || token->type == CPP_EQ
       || token->type == CPP_ELLIPSIS
       || token->type == CPP_GREATER)
     {
-      declarator = NULL_TREE;
+      declarator = NULL;
       if (parenthesized_p)
        *parenthesized_p = false;
     }
@@ -10998,7 +11755,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
     {
       bool saved_default_arg_ok_p = parser->default_arg_ok_p;
       parser->default_arg_ok_p = false;
-  
+
       /* After seeing a decl-specifier-seq, if the next token is not a
         "(", there is no possibility that the code is a valid
         expression.  Therefore, if parsing tentatively, we commit at
@@ -11006,11 +11763,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
       if (!parser->in_template_argument_list_p
          /* In an expression context, having seen:
 
-              (int((char *)...
+              (int((char ...
 
             we cannot be sure whether we are looking at a
-            function-type (taking a "char*" as a parameter) or a cast
-            of some object of type "char*" to "int".  */
+            function-type (taking a "char" as a parameter) or a cast
+            of some object of type "char" to "int".  */
          && !parser->in_type_id_in_expr_p
          && cp_parser_parsing_tentatively (parser)
          && !cp_parser_committed_to_tentative_parse (parser)
@@ -11023,7 +11780,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
                                         parenthesized_p);
       parser->default_arg_ok_p = saved_default_arg_ok_p;
       /* After the declarator, allow more attributes.  */
-      attributes = chainon (attributes, cp_parser_attributes_opt (parser));
+      decl_specifiers.attributes
+       = chainon (decl_specifiers.attributes,
+                  cp_parser_attributes_opt (parser));
     }
 
   /* The restriction on defining new types applies only to the type
@@ -11039,7 +11798,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 
       /* If we are defining a class, then the tokens that make up the
         default argument must be saved and processed later.  */
-      if (!template_parm_p && at_class_scope_p () 
+      if (!template_parm_p && at_class_scope_p ()
          && TYPE_BEING_DEFINED (current_class_type))
        {
          unsigned depth = 0;
@@ -11104,7 +11863,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
                case CPP_NAME:
                case CPP_SCOPE:
                  /* In these cases, we should look for template-ids.
-                    For example, if the default argument is 
+                    For example, if the default argument is
                     `X<int, double>()', we need to do name lookup to
                     figure out whether or not `X' is a template; if
                     so, the `,' does not end the default argument.
@@ -11119,7 +11878,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
              /* If we've reached the end, stop.  */
              if (done)
                break;
-             
+
              /* Add the token to the token block.  */
              token = cp_lexer_consume_token (parser->lexer);
              cp_token_cache_push_token (DEFARG_TOKENS (default_argument),
@@ -11134,21 +11893,21 @@ cp_parser_parameter_declaration (cp_parser *parser,
 
          /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
             set correctly.  */
-         saved_greater_than_is_operator_p 
+         saved_greater_than_is_operator_p
            = parser->greater_than_is_operator_p;
          parser->greater_than_is_operator_p = greater_than_is_operator_p;
          /* Local variable names (and the `this' keyword) may not
             appear in a default argument.  */
-         saved_local_variables_forbidden_p 
+         saved_local_variables_forbidden_p
            = parser->local_variables_forbidden_p;
          parser->local_variables_forbidden_p = true;
          /* Parse the assignment-expression.  */
          default_argument = cp_parser_assignment_expression (parser);
          /* Restore saved state.  */
-         parser->greater_than_is_operator_p 
+         parser->greater_than_is_operator_p
            = saved_greater_than_is_operator_p;
-         parser->local_variables_forbidden_p 
-           = saved_local_variables_forbidden_p; 
+         parser->local_variables_forbidden_p
+           = saved_local_variables_forbidden_p;
        }
       if (!parser->default_arg_ok_p)
        {
@@ -11163,15 +11922,10 @@ cp_parser_parameter_declaration (cp_parser *parser,
     }
   else
     default_argument = NULL_TREE;
-  
-  /* Create the representation of the parameter.  */
-  if (attributes)
-    decl_specifiers = tree_cons (attributes, NULL_TREE, decl_specifiers);
-  parameter = build_tree_list (default_argument, 
-                              build_tree_list (decl_specifiers,
-                                               declarator));
 
-  return parameter;
+  return make_parameter_declarator (&decl_specifiers,
+                                   declarator,
+                                   default_argument);
 }
 
 /* Parse a function-body.
@@ -11182,7 +11936,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 static void
 cp_parser_function_body (cp_parser *parser)
 {
-  cp_parser_compound_statement (parser, false);
+  cp_parser_compound_statement (parser, NULL, false);
 }
 
 /* Parse a ctor-initializer-opt followed by a function-body.  Return
@@ -11210,10 +11964,10 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser)
 
    initializer:
      = initializer-clause
-     ( expression-list )  
+     ( expression-list )
 
    Returns a expression representing the initializer.  If no
-   initializer is present, NULL_TREE is returned.  
+   initializer is present, NULL_TREE is returned.
 
    *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )'
    production is used, and zero otherwise.  *IS_PARENTHESIZED_INIT is
@@ -11257,17 +12011,17 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
   return init;
 }
 
-/* Parse an initializer-clause.  
+/* Parse an initializer-clause.
 
    initializer-clause:
      assignment-expression
      { initializer-list , [opt] }
      { }
 
-   Returns an expression representing the initializer.  
+   Returns an expression representing the initializer.
 
    If the `assignment-expression' production is used the value
-   returned is simply a representation for the expression.  
+   returned is simply a representation for the expression.
 
    Otherwise, a CONSTRUCTOR is returned.  The CONSTRUCTOR_ELTS will be
    the elements of the initializer-list (or NULL_TREE, if the last
@@ -11284,20 +12038,20 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
   /* If it is not a `{', then we are looking at an
      assignment-expression.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
-    initializer 
-      = cp_parser_constant_expression (parser,
-                                      /*allow_non_constant_p=*/true,
-                                      non_constant_p);
+    {
+      initializer
+       = cp_parser_constant_expression (parser,
+                                       /*allow_non_constant_p=*/true,
+                                       non_constant_p);
+      if (!*non_constant_p)
+       initializer = fold_non_dependent_expr (initializer);
+    }
   else
     {
       /* Consume the `{' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Create a CONSTRUCTOR to represent the braced-initializer.  */
       initializer = make_node (CONSTRUCTOR);
-      /* Mark it with TREE_HAS_CONSTRUCTOR.  This should not be
-        necessary, but check_initializer depends upon it, for 
-        now.  */
-      TREE_HAS_CONSTRUCTOR (initializer) = 1;
       /* If it's not a `}', then there is a non-trivial initializer.  */
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
        {
@@ -11322,7 +12076,7 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
      initializer-list , initializer-clause
 
    GNU Extension:
-   
+
    initializer-list:
      identifier : initializer-clause
      initializer-list, identifier : initializer-clause
@@ -11364,7 +12118,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
        identifier = NULL_TREE;
 
       /* Parse the initializer.  */
-      initializer = cp_parser_initializer_clause (parser, 
+      initializer = cp_parser_initializer_clause (parser,
                                                  &clause_non_constant_p);
       /* If any clause is non-constant, so is the entire initializer.  */
       if (clause_non_constant_p)
@@ -11415,9 +12169,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
    Returns the TYPE_DECL representing the class.  */
 
 static tree
-cp_parser_class_name (cp_parser *parser, 
-                     bool typename_keyword_p, 
-                     bool template_keyword_p, 
+cp_parser_class_name (cp_parser *parser,
+                     bool typename_keyword_p,
+                     bool template_keyword_p,
                      bool type_p,
                      bool check_dependency_p,
                      bool class_head_p,
@@ -11435,21 +12189,21 @@ cp_parser_class_name (cp_parser *parser,
       cp_parser_error (parser, "expected class-name");
       return error_mark_node;
     }
-    
+
   /* PARSER->SCOPE can be cleared when parsing the template-arguments
      to a template-id, so we save it here.  */
   scope = parser->scope;
   if (scope == error_mark_node)
     return error_mark_node;
-  
+
   /* Any name names a type if we're following the `typename' keyword
      in a qualified name where the enclosing scope is type-dependent.  */
   typename_p = (typename_keyword_p && scope && TYPE_P (scope)
                && dependent_type_p (scope));
   /* Handle the common case (an identifier, but not a template-id)
      efficiently.  */
-  if (token->type == CPP_NAME 
-      && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_LESS)
+  if (token->type == CPP_NAME
+      && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
     {
       tree identifier;
 
@@ -11476,7 +12230,7 @@ cp_parser_class_name (cp_parser *parser,
          if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
            type_p = true;
          /* Look up the name.  */
-         decl = cp_parser_lookup_name (parser, identifier, 
+         decl = cp_parser_lookup_name (parser, identifier,
                                        type_p,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
@@ -11497,17 +12251,20 @@ cp_parser_class_name (cp_parser *parser,
 
   /* If this is a typename, create a TYPENAME_TYPE.  */
   if (typename_p && decl != error_mark_node)
-    decl = TYPE_NAME (make_typename_type (scope, decl,
-                                         /*complain=*/1));
+    {
+      decl = make_typename_type (scope, decl, /*complain=*/1);
+      if (decl != error_mark_node)
+       decl = TYPE_NAME (decl);
+    }
 
   /* Check to see that it is really the name of a class.  */
-  if (TREE_CODE (decl) == TEMPLATE_ID_EXPR 
+  if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
       && TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
       && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
     /* Situations like this:
 
         template <typename T> struct A {
-          typename T::template X<int>::I i; 
+          typename T::template X<int>::I i;
         };
 
        are problematic.  Is `T::template X<int>' a class-name?  The
@@ -11542,12 +12299,14 @@ cp_parser_class_specifier (cp_parser* parser)
   int has_trailing_semicolon;
   bool nested_name_specifier_p;
   unsigned saved_num_template_parameter_lists;
+  bool pop_p = false;
 
   push_deferring_access_checks (dk_no_deferred);
 
   /* Parse the class-head.  */
   type = cp_parser_class_head (parser,
-                              &nested_name_specifier_p);
+                              &nested_name_specifier_p,
+                              &attributes);
   /* If the class-head was a semantic disaster, skip the entire body
      of the class.  */
   if (!type)
@@ -11570,38 +12329,37 @@ cp_parser_class_specifier (cp_parser* parser)
   ++parser->num_classes_being_defined;
   /* Inside the class, surrounding template-parameter-lists do not
      apply.  */
-  saved_num_template_parameter_lists 
-    = parser->num_template_parameter_lists; 
+  saved_num_template_parameter_lists
+    = parser->num_template_parameter_lists;
   parser->num_template_parameter_lists = 0;
 
   /* Start the class.  */
   if (nested_name_specifier_p)
-    push_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
+    pop_p = push_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
   type = begin_class_definition (type);
+
   if (type == error_mark_node)
     /* If the type is erroneous, skip the entire body of the class.  */
     cp_parser_skip_to_closing_brace (parser);
   else
     /* Parse the member-specification.  */
     cp_parser_member_specification_opt (parser);
+
   /* Look for the trailing `}'.  */
   cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
   /* We get better error messages by noticing a common problem: a
      missing trailing `;'.  */
   token = cp_lexer_peek_token (parser->lexer);
   has_trailing_semicolon = (token->type == CPP_SEMICOLON);
-  /* Look for attributes to apply to this class.  */
+  /* Look for trailing attributes to apply to this class.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
-    attributes = cp_parser_attributes_opt (parser);
-  /* If we got any attributes in class_head, xref_tag will stick them in
-     TREE_TYPE of the type.  Grab them now.  */
-  if (type != error_mark_node)
     {
-      attributes = chainon (TYPE_ATTRIBUTES (type), attributes);
-      TYPE_ATTRIBUTES (type) = NULL_TREE;
-      type = finish_struct (type, attributes);
+      tree sub_attr = cp_parser_attributes_opt (parser);
+      attributes = chainon (attributes, sub_attr);
     }
-  if (nested_name_specifier_p)
+  if (type != error_mark_node)
+    type = finish_struct (type, attributes);
+  if (pop_p)
     pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
   /* If this class is not itself within the scope of another class,
      then we need to parse the bodies of all of the queued function
@@ -11623,21 +12381,25 @@ cp_parser_class_specifier (cp_parser* parser)
        struct A::B { void f() { } };
 
      there is no need to delay the parsing of `A::B::f'.  */
-  if (--parser->num_classes_being_defined == 0) 
+  if (--parser->num_classes_being_defined == 0)
     {
       tree queue_entry;
       tree fn;
+      tree class_type;
+      bool pop_p;
 
       /* In a first pass, parse default arguments to the functions.
         Then, in a second pass, parse the bodies of the functions.
         This two-phased approach handles cases like:
-        
-           struct S { 
-              void f() { g(); } 
+
+           struct S {
+              void f() { g(); }
               void g(int i = 3);
             };
 
          */
+      class_type = NULL_TREE;
+      pop_p = false;
       for (TREE_PURPOSE (parser->unparsed_functions_queues)
             = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));
           (queue_entry = TREE_PURPOSE (parser->unparsed_functions_queues));
@@ -11645,14 +12407,24 @@ cp_parser_class_specifier (cp_parser* parser)
             = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues)))
        {
          fn = TREE_VALUE (queue_entry);
-         /* Make sure that any template parameters are in scope.  */
-         maybe_begin_member_template_processing (fn);
          /* If there are default arguments that have not yet been processed,
             take care of them now.  */
+         if (class_type != TREE_PURPOSE (queue_entry))
+           {
+             if (pop_p)
+               pop_scope (class_type);
+             class_type = TREE_PURPOSE (queue_entry);
+             pop_p = push_scope (class_type);
+           }
+         /* Make sure that any template parameters are in scope.  */
+         maybe_begin_member_template_processing (fn);
+         /* Parse the default argument expressions.  */
          cp_parser_late_parsing_default_args (parser, fn);
          /* Remove any template parameters from the symbol table.  */
          maybe_end_member_template_processing ();
        }
+      if (pop_p)
+       pop_scope (class_type);
       /* Now parse the body of the functions.  */
       for (TREE_VALUE (parser->unparsed_functions_queues)
             = nreverse (TREE_VALUE (parser->unparsed_functions_queues));
@@ -11663,10 +12435,13 @@ cp_parser_class_specifier (cp_parser* parser)
          /* Figure out which function we need to process.  */
          fn = TREE_VALUE (queue_entry);
 
+         /* A hack to prevent garbage collection.  */
+         function_depth++;
+
          /* Parse the function.  */
          cp_parser_late_parsing_for_member (parser, fn);
+         function_depth--;
        }
-
     }
 
   /* Put back any saved access checks.  */
@@ -11684,14 +12459,14 @@ cp_parser_class_specifier (cp_parser* parser)
    class-head:
      class-key identifier [opt] base-clause [opt]
      class-key nested-name-specifier identifier base-clause [opt]
-     class-key nested-name-specifier [opt] template-id 
-       base-clause [opt]  
+     class-key nested-name-specifier [opt] template-id
+       base-clause [opt]
 
    GNU Extensions:
      class-key attributes identifier [opt] base-clause [opt]
      class-key attributes nested-name-specifier identifier base-clause [opt]
-     class-key attributes nested-name-specifier [opt] template-id 
-       base-clause [opt]  
+     class-key attributes nested-name-specifier [opt] template-id
+       base-clause [opt]
 
    Returns the TYPE of the indicated class.  Sets
    *NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions
@@ -11702,10 +12477,10 @@ cp_parser_class_specifier (cp_parser* parser)
    body of the class.  */
 
 static tree
-cp_parser_class_head (cp_parser* parser, 
-                     bool* nested_name_specifier_p)
+cp_parser_class_head (cp_parser* parser,
+                     bool* nested_name_specifier_p,
+                     tree *attributes_p)
 {
-  cp_token *token;
   tree nested_name_specifier;
   enum tag_types class_key;
   tree id = NULL_TREE;
@@ -11715,7 +12490,9 @@ cp_parser_class_head (cp_parser* parser,
   bool qualified_p = false;
   bool invalid_nested_name_p = false;
   bool invalid_explicit_specialization_p = false;
+  bool pop_p = false;
   unsigned num_templates;
+  tree bases;
 
   /* Assume no nested-name-specifier will be present.  */
   *nested_name_specifier_p = false;
@@ -11734,7 +12511,7 @@ cp_parser_class_head (cp_parser* parser,
   /* If the next token is `::', that is invalid -- but sometimes
      people do try to write:
 
-       struct ::S {};  
+       struct ::S {};
 
      Handle this gracefully by accepting the extra qualifier, and then
      issuing an error about it later if this really is a
@@ -11747,7 +12524,7 @@ cp_parser_class_head (cp_parser* parser,
 
   /* Determine the name of the class.  Begin by looking for an
      optional nested-name-specifier.  */
-  nested_name_specifier 
+  nested_name_specifier
     = cp_parser_nested_name_specifier_opt (parser,
                                           /*typename_keyword_p=*/false,
                                           /*check_dependency_p=*/false,
@@ -11760,16 +12537,16 @@ cp_parser_class_head (cp_parser* parser,
       /* Although the grammar says `identifier', it really means
         `class-name' or `template-name'.  You are only allowed to
         define a class that has already been declared with this
-        syntax.  
+        syntax.
 
         The proposed resolution for Core Issue 180 says that whever
         you see `class T::X' you should treat `X' as a type-name.
-        
+
         It is OK to define an inaccessible class; for example:
-        
+
            class A { class B; };
            class A::B {};
-        
+
          We do not know if we will see a class-name, or a
         template-name.  We look for a class-name first, in case the
         class-name is a template-id; if we looked for the
@@ -11796,16 +12573,16 @@ cp_parser_class_head (cp_parser* parser,
        nested_name_specifier = NULL_TREE;
       /* Otherwise, count the number of templates used in TYPE and its
         containing scopes.  */
-      else 
+      else
        {
          tree scope;
 
-         for (scope = TREE_TYPE (type); 
+         for (scope = TREE_TYPE (type);
               scope && TREE_CODE (scope) != NAMESPACE_DECL;
-              scope = (TYPE_P (scope) 
+              scope = (TYPE_P (scope)
                        ? TYPE_CONTEXT (scope)
-                       : DECL_CONTEXT (scope))) 
-           if (TYPE_P (scope) 
+                       : DECL_CONTEXT (scope)))
+           if (TYPE_P (scope)
                && CLASS_TYPE_P (scope)
                && CLASSTYPE_TEMPLATE_INFO (scope)
                && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope))
@@ -11820,7 +12597,7 @@ cp_parser_class_head (cp_parser* parser,
         an identifier, or nothing at all.  */
       cp_parser_parse_tentatively (parser);
       /* Check for a template-id.  */
-      id = cp_parser_template_id (parser, 
+      id = cp_parser_template_id (parser,
                                  /*template_keyword_p=*/false,
                                  /*check_dependency_p=*/true,
                                  /*is_declaration=*/true);
@@ -11841,7 +12618,8 @@ cp_parser_class_head (cp_parser* parser,
 
   pop_deferring_access_checks ();
 
-  cp_parser_check_for_invalid_template_id (parser, id);
+  if (id)
+    cp_parser_check_for_invalid_template_id (parser, id);
 
   /* If it's not a `:' or a `{' then we can't really be looking at a
      class-head, since a class-head only appears as part of a
@@ -11894,7 +12672,7 @@ cp_parser_class_head (cp_parser* parser,
     }
   /* An explicit-specialization must be preceded by "template <>".  If
      it is not, try to recover gracefully.  */
-  if (at_namespace_scope_p () 
+  if (at_namespace_scope_p ()
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
@@ -11929,12 +12707,13 @@ cp_parser_class_head (cp_parser* parser,
       /* If the class was unnamed, create a dummy name.  */
       if (!id)
        id = make_anon_name ();
-      type = xref_tag (class_key, id, attributes, /*globalize=*/false,
+      type = xref_tag (class_key, id, /*globalize=*/false,
                       parser->num_template_parameter_lists);
     }
   else
     {
       tree class_type;
+      bool pop_p = false;
 
       /* Given:
 
@@ -11961,7 +12740,7 @@ cp_parser_class_head (cp_parser* parser,
       class_type = current_class_type;
       /* Enter the scope indicated by the nested-name-specifier.  */
       if (nested_name_specifier)
-       push_scope (nested_name_specifier);
+       pop_p = push_scope (nested_name_specifier);
       /* Get the canonical version of this type.  */
       type = TYPE_MAIN_DECL (TREE_TYPE (type));
       if (PROCESSING_REAL_TEMPLATE_DECL_P ()
@@ -11971,7 +12750,8 @@ cp_parser_class_head (cp_parser* parser,
       if (nested_name_specifier)
        {
          *nested_name_specifier_p = true;
-         pop_scope (nested_name_specifier);
+         if (pop_p)
+           pop_scope (nested_name_specifier);
        }
     }
   /* Indicate whether this class was declared as a `class' or as a
@@ -11988,21 +12768,20 @@ cp_parser_class_head (cp_parser* parser,
 
      is valid.  */
   if (nested_name_specifier)
-    push_scope (nested_name_specifier);
-  /* Now, look for the base-clause.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  if (token->type == CPP_COLON)
-    {
-      tree bases;
+    pop_p = push_scope (nested_name_specifier);
+
+  bases = NULL_TREE;
+
+  /* Get the list of base-classes, if there is one.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+    bases = cp_parser_base_clause (parser);
+
+  /* Process the base classes.  */
+  xref_basetypes (type, bases);
 
-      /* Get the list of base-classes.  */
-      bases = cp_parser_base_clause (parser);
-      /* Process them.  */
-      xref_basetypes (type, bases);
-    }
   /* Leave the scope given by the nested-name-specifier.  We will
      enter the class scope itself while processing the members.  */
-  if (nested_name_specifier)
+  if (pop_p)
     pop_scope (nested_name_specifier);
 
  done:
@@ -12011,6 +12790,7 @@ cp_parser_class_head (cp_parser* parser,
       end_specialization ();
       --parser->num_template_parameter_lists;
     }
+  *attributes_p = attributes;
   return type;
 }
 
@@ -12085,23 +12865,23 @@ cp_parser_member_specification_opt (cp_parser* parser)
     }
 }
 
-/* Parse a member-declaration.  
+/* Parse a member-declaration.
 
    member-declaration:
      decl-specifier-seq [opt] member-declarator-list [opt] ;
      function-definition ; [opt]
      :: [opt] nested-name-specifier template [opt] unqualified-id ;
      using-declaration
-     template-declaration 
+     template-declaration
 
    member-declarator-list:
      member-declarator
      member-declarator-list , member-declarator
 
    member-declarator:
-     declarator pure-specifier [opt] 
+     declarator pure-specifier [opt]
      declarator constant-initializer [opt]
-     identifier [opt] : constant-expression 
+     identifier [opt] : constant-expression
 
    GNU Extensions:
 
@@ -12116,7 +12896,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
 static void
 cp_parser_member_declaration (cp_parser* parser)
 {
-  tree decl_specifiers;
+  cp_decl_specifier_seq decl_specifiers;
   tree prefix_attributes;
   tree decl;
   int declares_class_or_enum;
@@ -12152,15 +12932,16 @@ cp_parser_member_declaration (cp_parser* parser)
 
       return;
     }
-  
+
   /* Parse the decl-specifier-seq.  */
-  decl_specifiers 
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_OPTIONAL,
-                                   &prefix_attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_OPTIONAL,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
+  prefix_attributes = decl_specifiers.attributes;
+  decl_specifiers.attributes = NULL_TREE;
   /* Check for an invalid type-name.  */
-  if (cp_parser_diagnose_invalid_type_name (parser))
+  if (cp_parser_parse_and_diagnose_invalid_type_name (parser))
     return;
   /* If there is no declarator, then the decl-specifier-seq should
      specify a type.  */
@@ -12175,20 +12956,20 @@ cp_parser_member_declaration (cp_parser* parser)
 
         Each member-declaration shall declare at least one member
         name of the class.  */
-      if (!decl_specifiers)
+      if (!decl_specifiers.any_specifiers_p)
        {
          if (pedantic)
            pedwarn ("extra semicolon");
        }
-      else 
+      else
        {
          tree type;
-         
+
          /* See if this declaration is a friend.  */
-         friend_p = cp_parser_friend_p (decl_specifiers);
+         friend_p = cp_parser_friend_p (&decl_specifiers);
          /* If there were decl-specifiers, check to see if there was
             a class-declaration.  */
-         type = check_tag_decl (decl_specifiers);
+         type = check_tag_decl (&decl_specifiers);
          /* Nested classes have already been added to the class, but
             a `friend' needs to be explicitly registered.  */
          if (friend_p)
@@ -12199,34 +12980,17 @@ cp_parser_member_declaration (cp_parser* parser)
                 error ("a class-key must be used when declaring a friend");
               /* In this case:
 
-                   template <typename T> struct A { 
-                      friend struct A<T>::B; 
+                   template <typename T> struct A {
+                      friend struct A<T>::B;
                     };
+
                  A<T>::B will be represented by a TYPENAME_TYPE, and
                  therefore not recognized by check_tag_decl.  */
-              if (!type)
-                {
-                  tree specifier;
-
-                  for (specifier = decl_specifiers; 
-                       specifier;
-                       specifier = TREE_CHAIN (specifier))
-                    {
-                      tree s = TREE_VALUE (specifier);
-
-                      if (TREE_CODE (s) == IDENTIFIER_NODE)
-                         get_global_value_if_present (s, &type);
-                      if (TREE_CODE (s) == TYPE_DECL)
-                        s = TREE_TYPE (s);
-                      if (TYPE_P (s))
-                        {
-                          type = s;
-                          break;
-                        }
-                    }
-                }
-              if (!type)
+              if (!type
+                  && decl_specifiers.type
+                  && TYPE_P (decl_specifiers.type))
+                type = decl_specifiers.type;
+              if (!type || !TYPE_P (type))
                 error ("friend declaration does not name a class or "
                        "function");
               else
@@ -12235,7 +12999,7 @@ cp_parser_member_declaration (cp_parser* parser)
            }
          /* If there is no TYPE, an error message will already have
             been issued.  */
-         else if (!type)
+         else if (!type || type == error_mark_node)
            ;
          /* An anonymous aggregate has to be handled specially; such
             a declaration really declares a data member (with a
@@ -12257,9 +13021,9 @@ cp_parser_member_declaration (cp_parser* parser)
   else
     {
       /* See if these declarations will be friends.  */
-      friend_p = cp_parser_friend_p (decl_specifiers);
+      friend_p = cp_parser_friend_p (&decl_specifiers);
 
-      /* Keep going until we hit the `;' at the end of the 
+      /* Keep going until we hit the `;' at the end of the
         declaration.  */
       while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
        {
@@ -12272,7 +13036,7 @@ cp_parser_member_declaration (cp_parser* parser)
          /* Check for a bitfield declaration.  */
          if (token->type == CPP_COLON
              || (token->type == CPP_NAME
-                 && cp_lexer_peek_nth_token (parser->lexer, 2)->type 
+                 && cp_lexer_peek_nth_token (parser->lexer, 2)->type
                  == CPP_COLON))
            {
              tree identifier;
@@ -12289,7 +13053,7 @@ cp_parser_member_declaration (cp_parser* parser)
              /* Consume the `:' token.  */
              cp_lexer_consume_token (parser->lexer);
              /* Get the width of the bitfield.  */
-             width 
+             width
                = cp_parser_constant_expression (parser,
                                                 /*allow_non_constant=*/false,
                                                 NULL);
@@ -12303,28 +13067,30 @@ cp_parser_member_declaration (cp_parser* parser)
              attributes = chainon (prefix_attributes, attributes);
 
              /* Create the bitfield declaration.  */
-             decl = grokbitfield (identifier, 
-                                  decl_specifiers,
+             decl = grokbitfield (identifier
+                                  ? make_id_declarator (identifier)
+                                  : NULL,
+                                  &decl_specifiers,
                                   width);
              /* Apply the attributes.  */
              cplus_decl_attributes (&decl, attributes, /*flags=*/0);
            }
          else
            {
-             tree declarator;
+             cp_declarator *declarator;
              tree initializer;
              tree asm_specification;
              int ctor_dtor_or_conv_p;
 
              /* Parse the declarator.  */
-             declarator 
+             declarator
                = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                                        &ctor_dtor_or_conv_p,
                                        /*parenthesized_p=*/NULL);
 
              /* If something went wrong parsing the declarator, make sure
                 that we at least consume some tokens.  */
-             if (declarator == error_mark_node)
+             if (declarator == cp_error_declarator)
                {
                  /* Skip to the end of the statement.  */
                  cp_parser_skip_to_end_of_statement (parser);
@@ -12339,7 +13105,7 @@ cp_parser_member_declaration (cp_parser* parser)
                  return;
                }
 
-             cp_parser_check_for_definition_in_return_type 
+             cp_parser_check_for_definition_in_return_type
                (declarator, declares_class_or_enum);
 
              /* Look for an asm-specification.  */
@@ -12364,17 +13130,17 @@ cp_parser_member_declaration (cp_parser* parser)
                  /* In [class.mem]:
 
                     A pure-specifier shall be used only in the declaration of
-                    a virtual function.  
+                    a virtual function.
 
                     A member-declarator can contain a constant-initializer
                     only if it declares a static member of integral or
-                    enumeration type.  
+                    enumeration type.
 
                     Therefore, if the DECLARATOR is for a function, we look
                     for a pure-specifier; otherwise, we look for a
                     constant-initializer.  When we call `grokfield', it will
                     perform more stringent semantics checks.  */
-                 if (TREE_CODE (declarator) == CALL_EXPR)
+                 if (declarator->kind == cdk_function)
                    initializer = cp_parser_pure_specifier (parser);
                  else
                    /* Parse the initializer.  */
@@ -12389,7 +13155,7 @@ cp_parser_member_declaration (cp_parser* parser)
                 member-declarator.  Calling `grokfield' has
                 side-effects, so we must not do it unless we are sure
                 that we are looking at a member-declarator.  */
-             if (cp_parser_token_starts_function_definition_p 
+             if (cp_parser_token_starts_function_definition_p
                  (cp_lexer_peek_token (parser->lexer)))
                {
                  /* The grammar does not allow a pure-specifier to be
@@ -12400,7 +13166,7 @@ cp_parser_member_declaration (cp_parser* parser)
                  if (initializer)
                    error ("pure-specifier on function-definition");
                  decl = cp_parser_save_member_function_body (parser,
-                                                             decl_specifiers,
+                                                             &decl_specifiers,
                                                              declarator,
                                                              attributes);
                  /* If the member was not a friend, declare it here.  */
@@ -12416,7 +13182,7 @@ cp_parser_member_declaration (cp_parser* parser)
              else
                {
                  /* Create the declaration.  */
-                 decl = grokfield (declarator, decl_specifiers, 
+                 decl = grokfield (declarator, &decl_specifiers,
                                    initializer, asm_specification,
                                    attributes);
                  /* Any initialization must have been from a
@@ -12522,11 +13288,11 @@ cp_parser_constant_initializer (cp_parser* parser)
       cp_parser_skip_to_closing_brace (parser);
       /* Look for the trailing `}'.  */
       cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
-      
+
       return error_mark_node;
     }
 
-  return cp_parser_constant_expression (parser, 
+  return cp_parser_constant_expression (parser,
                                        /*allow_non_constant=*/false,
                                        NULL);
 }
@@ -12536,7 +13302,7 @@ cp_parser_constant_initializer (cp_parser* parser)
 /* Parse a base-clause.
 
    base-clause:
-     : base-specifier-list  
+     : base-specifier-list
 
    base-specifier-list:
      base-specifier
@@ -12544,7 +13310,7 @@ cp_parser_constant_initializer (cp_parser* parser)
 
    Returns a TREE_LIST representing the base-classes, in the order in
    which they were declared.  The representation of each node is as
-   described by cp_parser_base_specifier.  
+   described by cp_parser_base_specifier.
 
    In the case that no bases are specified, this function will return
    NULL_TREE, not ERROR_MARK_NODE.  */
@@ -12603,7 +13369,7 @@ cp_parser_base_clause (cp_parser* parser)
    ACCESS_{DEFAULT,PUBLIC,PROTECTED,PRIVATE}_[VIRTUAL]_NODE to
    indicate the specifiers provided.  The TREE_VALUE will be a TYPE
    (or the ERROR_MARK_NODE) indicating the type that was specified.  */
-       
+
 static tree
 cp_parser_base_specifier (cp_parser* parser)
 {
@@ -12665,6 +13431,18 @@ cp_parser_base_specifier (cp_parser* parser)
          break;
        }
     }
+  /* It is not uncommon to see programs mechanically, erroneously, use
+     the 'typename' keyword to denote (dependent) qualified types
+     as base classes.  */
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
+    {
+      if (!processing_template_decl)
+       error ("keyword `typename' not allowed outside of templates");
+      else
+       error ("keyword `typename' not allowed in this context "
+              "(the base class is implicitly a type)");
+      cp_lexer_consume_token (parser->lexer);
+    }
 
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
@@ -12679,7 +13457,7 @@ cp_parser_base_specifier (cp_parser* parser)
        type name.
 
      is to pretend that we have seen the `typename' keyword at this
-     point.  */ 
+     point.  */
   cp_parser_nested_name_specifier_opt (parser,
                                       /*typename_keyword_p=*/true,
                                       /*check_dependency_p=*/true,
@@ -12689,9 +13467,9 @@ cp_parser_base_specifier (cp_parser* parser)
      we see are type names or templates, as appropriate.  */
   class_scope_p = (parser->scope && TYPE_P (parser->scope));
   template_p = class_scope_p && cp_parser_optional_template_keyword (parser);
-  
+
   /* Finally, look for the class-name.  */
-  type = cp_parser_class_name (parser, 
+  type = cp_parser_class_name (parser,
                               class_scope_p,
                               template_p,
                               /*type_p=*/true,
@@ -12805,7 +13583,7 @@ cp_parser_try_block (cp_parser* parser)
 
   cp_parser_require_keyword (parser, RID_TRY, "`try'");
   try_block = begin_try_block ();
-  cp_parser_compound_statement (parser, false);
+  cp_parser_compound_statement (parser, NULL, true);
   finish_try_block (try_block);
   cp_parser_handler_seq (parser);
   finish_handler_sequence (try_block);
@@ -12830,7 +13608,7 @@ cp_parser_function_try_block (cp_parser* parser)
   /* Let the rest of the front-end know where we are.  */
   try_block = begin_function_try_block ();
   /* Parse the function-body.  */
-  ctor_initializer_p 
+  ctor_initializer_p
     = cp_parser_ctor_initializer_opt_and_function_body (parser);
   /* We're done with the `try' part.  */
   finish_function_try_block (try_block);
@@ -12881,7 +13659,7 @@ cp_parser_handler (cp_parser* parser)
   declaration = cp_parser_exception_declaration (parser);
   finish_handler_parms (declaration, handler);
   cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-  cp_parser_compound_statement (parser, false);
+  cp_parser_compound_statement (parser, NULL, false);
   finish_handler (handler);
 }
 
@@ -12891,7 +13669,7 @@ cp_parser_handler (cp_parser* parser)
      type-specifier-seq declarator
      type-specifier-seq abstract-declarator
      type-specifier-seq
-     ...  
+     ...
 
    Returns a VAR_DECL for the declaration, or NULL_TREE if the
    ellipsis variant is used.  */
@@ -12899,8 +13677,9 @@ cp_parser_handler (cp_parser* parser)
 static tree
 cp_parser_exception_declaration (cp_parser* parser)
 {
-  tree type_specifiers;
-  tree declarator;
+  tree decl;
+  cp_decl_specifier_seq type_specifiers;
+  cp_declarator *declarator;
   const char *saved_message;
 
   /* If it's an ellipsis, it's easy to handle.  */
@@ -12917,10 +13696,10 @@ cp_parser_exception_declaration (cp_parser* parser)
     = "types may not be defined in exception-declarations";
 
   /* Parse the type-specifier-seq.  */
-  type_specifiers = cp_parser_type_specifier_seq (parser);
+  cp_parser_type_specifier_seq (parser, &type_specifiers);
   /* If it's a `)', then there is no declarator.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
-    declarator = NULL_TREE;
+    declarator = NULL;
   else
     declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
                                       /*ctor_dtor_or_conv_p=*/NULL,
@@ -12929,10 +13708,19 @@ cp_parser_exception_declaration (cp_parser* parser)
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
 
-  return start_handler_parms (type_specifiers, declarator);
+  if (type_specifiers.any_specifiers_p)
+    {
+      decl = grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
+      if (decl == NULL_TREE)
+       error ("invalid catch parameter");
+    }
+  else
+    decl = NULL_TREE;
+
+  return decl;
 }
 
-/* Parse a throw-expression. 
+/* Parse a throw-expression.
 
    throw-expression:
      throw assignment-expression [opt]
@@ -12981,7 +13769,7 @@ cp_parser_asm_specification_opt (cp_parser* parser)
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
-  /* If the next token isn't the `asm' keyword, then there's no 
+  /* If the next token isn't the `asm' keyword, then there's no
      asm-specification.  */
   if (!cp_parser_is_keyword (token, RID_ASM))
     return NULL_TREE;
@@ -13004,14 +13792,14 @@ cp_parser_asm_specification_opt (cp_parser* parser)
   return asm_specification;
 }
 
-/* Parse an asm-operand-list.  
+/* Parse an asm-operand-list.
 
    asm-operand-list:
      asm-operand
      asm-operand-list , asm-operand
-     
+
    asm-operand:
-     string-literal ( expression )  
+     string-literal ( expression )
      [ string-literal ] string-literal ( expression )
 
    Returns a TREE_LIST representing the operands.  The TREE_VALUE of
@@ -13031,14 +13819,14 @@ cp_parser_asm_operand_list (cp_parser* parser)
       tree expression;
       tree name;
       cp_token *token;
-      
-      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE)) 
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
        {
          /* Consume the `[' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Read the operand name.  */
          name = cp_parser_identifier (parser);
-         if (name != error_mark_node) 
+         if (name != error_mark_node)
            name = build_string (IDENTIFIER_LENGTH (name),
                                 IDENTIFIER_POINTER (name));
          /* Look for the closing `]'.  */
@@ -13049,17 +13837,19 @@ cp_parser_asm_operand_list (cp_parser* parser)
       /* Look for the string-literal.  */
       token = cp_parser_require (parser, CPP_STRING, "string-literal");
       string_literal = token ? token->value : error_mark_node;
+      c_lex_string_translate = 1;
       /* Look for the `('.  */
       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
       /* Parse the expression.  */
       expression = cp_parser_expression (parser);
       /* Look for the `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      c_lex_string_translate = 0;
       /* Add this operand to the list.  */
       asm_operands = tree_cons (build_tree_list (name, string_literal),
-                               expression, 
+                               expression,
                                asm_operands);
-      /* If the next token is not a `,', there are no more 
+      /* If the next token is not a `,', there are no more
         operands.  */
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
        break;
@@ -13070,11 +13860,11 @@ cp_parser_asm_operand_list (cp_parser* parser)
   return nreverse (asm_operands);
 }
 
-/* Parse an asm-clobber-list.  
+/* Parse an asm-clobber-list.
 
    asm-clobber-list:
      string-literal
-     asm-clobber-list , string-literal  
+     asm-clobber-list , string-literal
 
    Returns a TREE_LIST, indicating the clobbers in the order that they
    appeared.  The TREE_VALUE of each node is a STRING_CST.  */
@@ -13094,7 +13884,7 @@ cp_parser_asm_clobber_list (cp_parser* parser)
       string_literal = token ? token->value : error_mark_node;
       /* Add it to the list.  */
       clobbers = tree_cons (NULL_TREE, string_literal, clobbers);
-      /* If the next token is not a `,', then the list is 
+      /* If the next token is not a `,', then the list is
         complete.  */
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
        break;
@@ -13111,10 +13901,10 @@ cp_parser_asm_clobber_list (cp_parser* parser)
      attributes attribute
 
    attribute:
-     __attribute__ (( attribute-list [opt] ))  
+     __attribute__ (( attribute-list [opt] ))
 
    The return value is as for cp_parser_attribute_list.  */
-     
+
 static tree
 cp_parser_attributes_opt (cp_parser* parser)
 {
@@ -13158,17 +13948,17 @@ cp_parser_attributes_opt (cp_parser* parser)
   return attributes;
 }
 
-/* Parse an attribute-list.  
+/* Parse an attribute-list.
 
-   attribute-list:  
-     attribute 
+   attribute-list:
+     attribute
      attribute-list , attribute
 
    attribute:
-     identifier     
+     identifier
      identifier ( identifier )
      identifier ( identifier , expression-list )
-     identifier ( expression-list ) 
+     identifier ( expression-list )
 
    Returns a TREE_LIST.  Each node corresponds to an attribute.  THe
    TREE_PURPOSE of each node is the identifier indicating which
@@ -13180,6 +13970,7 @@ cp_parser_attribute_list (cp_parser* parser)
 {
   tree attribute_list = NULL_TREE;
 
+  c_lex_string_translate = 0;
   while (true)
     {
       cp_token *token;
@@ -13189,12 +13980,12 @@ cp_parser_attribute_list (cp_parser* parser)
       /* Look for the identifier.  We also allow keywords here; for
         example `__attribute__ ((const))' is legal.  */
       token = cp_lexer_peek_token (parser->lexer);
-      if (token->type != CPP_NAME 
+      if (token->type != CPP_NAME
          && token->type != CPP_KEYWORD)
        return error_mark_node;
       /* Consume the token.  */
       token = cp_lexer_consume_token (parser->lexer);
-      
+
       /* Save away the identifier that indicates which attribute this is.  */
       identifier = token->value;
       attribute = build_tree_list (identifier, NULL_TREE);
@@ -13206,7 +13997,7 @@ cp_parser_attribute_list (cp_parser* parser)
        {
          tree arguments;
 
-         arguments = (cp_parser_parenthesized_expression_list 
+         arguments = (cp_parser_parenthesized_expression_list
                       (parser, true, /*non_constant_p=*/NULL));
          /* Save the identifier and arguments away.  */
          TREE_VALUE (attribute) = arguments;
@@ -13225,6 +14016,7 @@ cp_parser_attribute_list (cp_parser* parser)
       /* Consume the comma and keep going.  */
       cp_lexer_consume_token (parser->lexer);
     }
+  c_lex_string_translate = 1;
 
   /* We built up the list in reverse order.  */
   return nreverse (attribute_list);
@@ -13323,7 +14115,7 @@ cp_parser_label_declaration (cp_parser* parser)
    types.  */
 
 static tree
-cp_parser_lookup_name (cp_parser *parser, tree name, 
+cp_parser_lookup_name (cp_parser *parser, tree name,
                       bool is_type, bool is_template, bool is_namespace,
                       bool check_dependency)
 {
@@ -13367,6 +14159,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
       /* If that's not a class type, there is no destructor.  */
       if (!type || !CLASS_TYPE_P (type))
        return error_mark_node;
+      if (!CLASSTYPE_DESTRUCTORS (type))
+         return error_mark_node;
       /* If it was a class type, return the destructor.  */
       return CLASSTYPE_DESTRUCTORS (type);
     }
@@ -13376,10 +14170,10 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
      stored in PARSER->SCOPE at this point.  */
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE,
                      20000619);
-  
+
   /* Perform the lookup.  */
   if (parser->scope)
-    { 
+    {
       bool dependent_p;
 
       if (parser->scope == error_mark_node)
@@ -13413,20 +14207,22 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
        }
       else
        {
+         bool pop_p = false;
+
          /* If PARSER->SCOPE is a dependent type, then it must be a
             class type, and we must not be checking dependencies;
             otherwise, we would have processed this lookup above.  So
             that PARSER->SCOPE is not considered a dependent base by
             lookup_member, we must enter the scope here.  */
          if (dependent_p)
-           push_scope (parser->scope);
+           pop_p = push_scope (parser->scope);
          /* If the PARSER->SCOPE is a a template specialization, it
             may be instantiated during name lookup.  In that case,
             errors may be issued.  Even if we rollback the current
             tentative parse, those errors are valid.  */
          decl = lookup_qualified_name (parser->scope, name, is_type,
                                        /*complain=*/true);
-         if (dependent_p)
+         if (pop_p)
            pop_scope (parser->scope);
        }
       parser->qualifying_scope = parser->scope;
@@ -13446,8 +14242,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                                     name,
                                     /*protect=*/0, is_type);
       /* Look it up in the enclosing context, too.  */
-      decl = lookup_name_real (name, is_type, /*nonclass=*/0, 
-                              is_namespace,
+      decl = lookup_name_real (name, is_type, /*nonclass=*/0,
+                              /*block_p=*/true, is_namespace,
                               /*flags=*/0);
       parser->object_scope = object_type;
       parser->qualifying_scope = NULL_TREE;
@@ -13456,17 +14252,17 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
     }
   else
     {
-      decl = lookup_name_real (name, is_type, /*nonclass=*/0, 
-                              is_namespace,
+      decl = lookup_name_real (name, is_type, /*nonclass=*/0,
+                              /*block_p=*/true, is_namespace,
                               /*flags=*/0);
       parser->qualifying_scope = NULL_TREE;
       parser->object_scope = NULL_TREE;
     }
 
   /* If the lookup failed, let our caller know.  */
-  if (!decl 
+  if (!decl
       || decl == error_mark_node
-      || (TREE_CODE (decl) == FUNCTION_DECL 
+      || (TREE_CODE (decl) == FUNCTION_DECL
          && DECL_ANTICIPATED (decl)))
     return error_mark_node;
 
@@ -13483,7 +14279,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
       return error_mark_node;
     }
 
-  my_friendly_assert (DECL_P (decl) 
+  my_friendly_assert (DECL_P (decl)
                      || TREE_CODE (decl) == OVERLOAD
                      || TREE_CODE (decl) == SCOPE_REF
                      || TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE
@@ -13493,7 +14289,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   /* If we have resolved the name of a member declaration, check to
      see if the declaration is accessible.  When the name resolves to
      set of overloaded functions, accessibility is checked when
-     overload resolution is done.  
+     overload resolution is done.
 
      During an explicit instantiation, access is not checked at all,
      as per [temp.explicit].  */
@@ -13510,7 +14306,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 static tree
 cp_parser_lookup_name_simple (cp_parser* parser, tree name)
 {
-  return cp_parser_lookup_name (parser, name, 
+  return cp_parser_lookup_name (parser, name,
                                /*is_type=*/false,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
@@ -13530,12 +14326,12 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
   /* If the TEMPLATE_DECL is being declared as part of a class-head,
      the translation from TEMPLATE_DECL to TYPE_DECL occurs:
 
-       struct A { 
+       struct A {
          template <typename T> struct B;
        };
 
-       template <typename T> struct A::B {}; 
-   
+       template <typename T> struct A::B {};
+
      Similarly, in a elaborated-type-specifier:
 
        namespace N { struct X{}; }
@@ -13566,74 +14362,69 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
    and FALSE otherwise.  */
 
 static bool
-cp_parser_check_declarator_template_parameters (cp_parser* parser, 
-                                                tree declarator)
+cp_parser_check_declarator_template_parameters (cp_parser* parser,
+                                               cp_declarator *declarator)
 {
   unsigned num_templates;
 
   /* We haven't seen any classes that involve template parameters yet.  */
   num_templates = 0;
 
-  switch (TREE_CODE (declarator))
+  switch (declarator->kind)
     {
-    case CALL_EXPR:
-    case ARRAY_REF:
-    case INDIRECT_REF:
-    case ADDR_EXPR:
-      {
-       tree main_declarator = TREE_OPERAND (declarator, 0);
-       return
-         cp_parser_check_declarator_template_parameters (parser, 
-                                                         main_declarator);
-      }
-
-    case SCOPE_REF:
-      {
-       tree scope;
-       tree member;
-
-       scope = TREE_OPERAND (declarator, 0);
-       member = TREE_OPERAND (declarator, 1);
-
-       /* If this is a pointer-to-member, then we are not interested
-          in the SCOPE, because it does not qualify the thing that is
-          being declared.  */
-       if (TREE_CODE (member) == INDIRECT_REF)
-         return (cp_parser_check_declarator_template_parameters
-                 (parser, member));
-
-       while (scope && CLASS_TYPE_P (scope))
-         {
-           /* You're supposed to have one `template <...>'
-              for every template class, but you don't need one
-              for a full specialization.  For example:
-              
-              template <class T> struct S{};
-              template <> struct S<int> { void f(); };
-              void S<int>::f () {}
-              
-              is correct; there shouldn't be a `template <>' for
-              the definition of `S<int>::f'.  */
-           if (CLASSTYPE_TEMPLATE_INFO (scope)
-               && (CLASSTYPE_TEMPLATE_INSTANTIATION (scope)
-                   || uses_template_parms (CLASSTYPE_TI_ARGS (scope)))
-               && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
-             ++num_templates;
+    case cdk_id:
+      if (TREE_CODE (declarator->u.id.name) == SCOPE_REF)
+       {
+         tree scope;
+         tree member;
 
-           scope = TYPE_CONTEXT (scope);
-         }
-      }
+         scope = TREE_OPERAND (declarator->u.id.name, 0);
+         member = TREE_OPERAND (declarator->u.id.name, 1);
 
-      /* Fall through.  */
+         while (scope && CLASS_TYPE_P (scope))
+           {
+             /* You're supposed to have one `template <...>'
+                for every template class, but you don't need one
+                for a full specialization.  For example:
+
+                template <class T> struct S{};
+                template <> struct S<int> { void f(); };
+                void S<int>::f () {}
+
+                is correct; there shouldn't be a `template <>' for
+                the definition of `S<int>::f'.  */
+             if (CLASSTYPE_TEMPLATE_INFO (scope)
+                 && (CLASSTYPE_TEMPLATE_INSTANTIATION (scope)
+                     || uses_template_parms (CLASSTYPE_TI_ARGS (scope)))
+                 && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
+               ++num_templates;
+
+             scope = TYPE_CONTEXT (scope);
+           }
+       }
 
-    default:
       /* If the DECLARATOR has the form `X<y>' then it uses one
         additional level of template parameters.  */
-      if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
+      if (TREE_CODE (declarator->u.id.name) == TEMPLATE_ID_EXPR)
        ++num_templates;
 
-      return cp_parser_check_template_parameters (parser, 
+      return cp_parser_check_template_parameters (parser,
                                                  num_templates);
+
+    case cdk_function:
+    case cdk_array:
+    case cdk_pointer:
+    case cdk_reference:
+    case cdk_ptrmem:
+      return (cp_parser_check_declarator_template_parameters
+             (parser, declarator->declarator));
+
+    case cdk_error:
+      return true;
+
+    default:
+      abort ();
+      return false;
     }
 }
 
@@ -13647,7 +14438,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
 {
   /* If there are more template classes than parameter lists, we have
      something like:
-     
+
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
@@ -13683,8 +14474,8 @@ cp_parser_check_template_parameters (cp_parser* parser,
    the two sub-expressions.  */
 
 static tree
-cp_parser_binary_expression (cp_parser* parser, 
-                             const cp_parser_token_tree_map token_tree_map, 
+cp_parser_binary_expression (cp_parser* parser,
+                             const cp_parser_token_tree_map token_tree_map,
                              cp_parser_expression_fn fn)
 {
   tree lhs;
@@ -13707,17 +14498,31 @@ cp_parser_binary_expression (cp_parser* parser,
        break;
       /* If we find one of the tokens we want, build the corresponding
         tree representation.  */
-      for (map_node = token_tree_map; 
+      for (map_node = token_tree_map;
           map_node->token_type != CPP_EOF;
           ++map_node)
        if (map_node->token_type == token->type)
          {
+           /* Assume that an overloaded operator will not be used.  */
+           bool overloaded_p = false;
+
            /* Consume the operator token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Parse the right-hand side of the expression.  */
            rhs = (*fn) (parser);
            /* Build the binary tree node.  */
-           lhs = build_x_binary_op (map_node->tree_type, lhs, rhs);
+           lhs = build_x_binary_op (map_node->tree_type, lhs, rhs,
+                                    &overloaded_p);
+           /* If the binary operator required the use of an
+              overloaded operator, then this expression cannot be an
+              integral constant-expression.  An overloaded operator
+              can be used even if both operands are otherwise
+              permissible in an integral constant-expression if at
+              least one of the operands is of enumeration type.  */
+           if (overloaded_p
+               && (cp_parser_non_integral_constant_expression
+                   (parser, "calls to overloaded operators")))
+             lhs = error_mark_node;
            break;
          }
 
@@ -13801,7 +14606,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
   cp_parser_global_scope_opt (parser,
                              /*current_scope_valid_p=*/false);
   /* Look for the nested-name-specifier.  */
-  nested_name_p 
+  nested_name_p
     = (cp_parser_nested_name_specifier_opt (parser,
                                            /*typename_keyword_p=*/false,
                                            /*check_dependency_p=*/false,
@@ -13810,7 +14615,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
        != NULL_TREE);
   /* Outside of a class-specifier, there must be a
      nested-name-specifier.  */
-  if (!nested_name_p && 
+  if (!nested_name_p &&
       (!at_class_scope_p () || !TYPE_BEING_DEFINED (current_class_type)
        || friend_p))
     constructor_p = false;
@@ -13850,14 +14655,19 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
      is a constructor.  (It is actually a function named `f' that
      takes one parameter (of type `int') and returns a value of type
      `S::S'.  */
-  if (constructor_p 
+  if (constructor_p
       && cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
     {
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
+         /* A parameter declaration begins with a decl-specifier,
+            which is either the "attribute" keyword, a storage class
+            specifier, or (usually) a type-specifier.  */
+         && !cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)
          && !cp_parser_storage_class_specifier_opt (parser))
        {
          tree type;
+         bool pop_p = false;
          unsigned saved_num_template_parameter_lists;
 
          /* Names appearing in the type-specifier should be looked up
@@ -13869,7 +14679,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
              type = TREE_TYPE (type_decl);
              if (TREE_CODE (type) == TYPENAME_TYPE)
                {
-                 type = resolve_typename_type (type, 
+                 type = resolve_typename_type (type,
                                                /*only_current_p=*/false);
                  if (type == error_mark_node)
                    {
@@ -13877,7 +14687,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
                      return false;
                    }
                }
-             push_scope (type);
+             pop_p = push_scope (type);
            }
 
          /* Inside the constructor parameter list, surrounding
@@ -13889,7 +14699,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
          /* Look for the type-specifier.  */
          cp_parser_type_specifier (parser,
                                    CP_PARSER_FLAGS_NONE,
-                                   /*is_friend=*/false,
+                                   /*decl_specs=*/NULL,
                                    /*is_declarator=*/true,
                                    /*declares_class_or_enum=*/NULL,
                                    /*is_cv_qualifier=*/NULL);
@@ -13898,7 +14708,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
            = saved_num_template_parameter_lists;
 
          /* Leave the scope of the class.  */
-         if (type)
+         if (pop_p)
            pop_scope (type);
 
          constructor_p = !cp_parser_error_occurred (parser);
@@ -13921,17 +14731,19 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
 static tree
 cp_parser_function_definition_from_specifiers_and_declarator
   (cp_parser* parser,
-   tree decl_specifiers,
+   cp_decl_specifier_seq *decl_specifiers,
    tree attributes,
-   tree declarator)
+   const cp_declarator *declarator)
 {
   tree fn;
   bool success_p;
 
   /* Begin the function-definition.  */
-  success_p = begin_function_definition (decl_specifiers, 
-                                        attributes, 
-                                        declarator);
+  success_p = start_function (decl_specifiers, declarator, attributes);
+
+  /* The things we're about to see are not directly qualified by any
+     template headers we've seen thus far.  */
+  reset_specialization ();
 
   /* If there were names looked up in the decl-specifier-seq that we
      did not check, check them now.  We must wait until we are in the
@@ -13941,8 +14753,7 @@ cp_parser_function_definition_from_specifiers_and_declarator
 
   if (!success_p)
     {
-      /* If begin_function_definition didn't like the definition, skip
-        the entire function.  */
+      /* Skip the entire function.  */
       error ("invalid function declaration");
       cp_parser_skip_to_end_of_block_or_statement (parser);
       fn = error_mark_node;
@@ -13960,8 +14771,8 @@ cp_parser_function_definition_from_specifiers_and_declarator
 
    Returns the function defined.  */
 
-static tree 
-cp_parser_function_definition_after_declarator (cp_parser* parser, 
+static tree
+cp_parser_function_definition_after_declarator (cp_parser* parser,
                                                bool inline_p)
 {
   tree fn;
@@ -13988,13 +14799,13 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
     }
   /* The `extern' in `extern "C" void f () { ... }' does not apply to
      anything declared inside `f'.  */
-  saved_in_unbraced_linkage_specification_p 
+  saved_in_unbraced_linkage_specification_p
     = parser->in_unbraced_linkage_specification_p;
   parser->in_unbraced_linkage_specification_p = false;
   /* Inside the function, surrounding template-parameter-lists do not
      apply.  */
-  saved_num_template_parameter_lists 
-    = parser->num_template_parameter_lists; 
+  saved_num_template_parameter_lists
+    = parser->num_template_parameter_lists;
   parser->num_template_parameter_lists = 0;
   /* If the next token is `try', then we are looking at a
      function-try-block.  */
@@ -14003,18 +14814,18 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   /* A function-try-block includes the function-body, so we only do
      this next part if we're not processing a function-try-block.  */
   else
-    ctor_initializer_p 
+    ctor_initializer_p
       = cp_parser_ctor_initializer_opt_and_function_body (parser);
 
   /* Finish the function.  */
-  fn = finish_function ((ctor_initializer_p ? 1 : 0) | 
+  fn = finish_function ((ctor_initializer_p ? 1 : 0) |
                        (inline_p ? 2 : 0));
   /* Generate code for it, if necessary.  */
   expand_or_defer_fn (fn);
   /* Restore the saved values.  */
-  parser->in_unbraced_linkage_specification_p 
+  parser->in_unbraced_linkage_specification_p
     = saved_in_unbraced_linkage_specification_p;
-  parser->num_template_parameter_lists 
+  parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
 
   return fn;
@@ -14034,11 +14845,11 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   /* Look for the `template' keyword.  */
   if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"))
     return;
-      
+
   /* And the `<'.  */
   if (!cp_parser_require (parser, CPP_LESS, "`<'"))
     return;
-      
+
   /* If the next token is `>', then we have an invalid
      specialization.  Rather than complain about an invalid template
      parameter, issue an error message here.  */
@@ -14062,15 +14873,21 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   ++parser->num_template_parameter_lists;
   /* If the next token is `template', there are more template
      parameters.  */
-  if (cp_lexer_next_token_is_keyword (parser->lexer, 
+  if (cp_lexer_next_token_is_keyword (parser->lexer,
                                      RID_TEMPLATE))
     cp_parser_template_declaration_after_export (parser, member_p);
   else
     {
+      /* There are no access checks when parsing a template, as we do not
+         know if a specialization will be a friend.  */
+      push_deferring_access_checks (dk_no_check);
+
       decl = cp_parser_single_declaration (parser,
                                           member_p,
                                           &friend_p);
 
+      pop_deferring_access_checks ();
+
       /* If this is a member template declaration, let the front
         end know.  */
       if (member_p && !friend_p && decl)
@@ -14097,11 +14914,11 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   /* If DECL is a function template, we must return to parse it later.
      (Even though there is no definition, there might be default
      arguments that need handling.)  */
-  if (member_p && decl 
+  if (member_p && decl
       && (TREE_CODE (decl) == FUNCTION_DECL
          || DECL_FUNCTION_TEMPLATE_P (decl)))
     TREE_VALUE (parser->unparsed_functions_queues)
-      = tree_cons (NULL_TREE, decl, 
+      = tree_cons (NULL_TREE, decl,
                   TREE_VALUE (parser->unparsed_functions_queues));
 }
 
@@ -14113,14 +14930,13 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
    *FRIEND_P is set to TRUE iff the declaration is a friend.  */
 
 static tree
-cp_parser_single_declaration (cp_parser* parser, 
+cp_parser_single_declaration (cp_parser* parser,
                              bool member_p,
                              bool* friend_p)
 {
   int declares_class_or_enum;
   tree decl = NULL_TREE;
-  tree decl_specifiers;
-  tree attributes;
+  cp_decl_specifier_seq decl_specifiers;
   bool function_definition_p = false;
 
   /* Defer access checks until we know what is being declared.  */
@@ -14128,13 +14944,12 @@ cp_parser_single_declaration (cp_parser* parser,
 
   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
      alternative.  */
-  decl_specifiers 
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_OPTIONAL,
-                                   &attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_OPTIONAL,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
   if (friend_p)
-    *friend_p = cp_parser_friend_p (decl_specifiers);
+    *friend_p = cp_parser_friend_p (&decl_specifiers);
   /* Gather up the access checks that occurred the
      decl-specifier-seq.  */
   stop_deferring_access_checks ();
@@ -14144,8 +14959,8 @@ cp_parser_single_declaration (cp_parser* parser,
     {
       if (cp_parser_declares_only_class_p (parser))
        {
-         decl = shadow_tag (decl_specifiers);
-         if (decl)
+         decl = shadow_tag (&decl_specifiers);
+         if (decl && decl != error_mark_node)
            decl = TYPE_NAME (decl);
          else
            decl = error_mark_node;
@@ -14160,10 +14975,9 @@ cp_parser_single_declaration (cp_parser* parser,
      In that case, there's no need to warn about a missing declarator.  */
   if (!decl
       && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
-         || !value_member (error_mark_node, decl_specifiers)))
-    decl = cp_parser_init_declarator (parser, 
-                                     decl_specifiers,
-                                     attributes,
+         || decl_specifiers.type != error_mark_node))
+    decl = cp_parser_init_declarator (parser,
+                                     &decl_specifiers,
                                      /*function_definition_allowed_p=*/true,
                                      member_p,
                                      declares_class_or_enum,
@@ -14199,12 +15013,23 @@ static tree
 cp_parser_functional_cast (cp_parser* parser, tree type)
 {
   tree expression_list;
+  tree cast;
 
-  expression_list 
+  expression_list
     = cp_parser_parenthesized_expression_list (parser, false,
                                               /*non_constant_p=*/NULL);
 
-  return build_functional_cast (type, expression_list);
+  cast = build_functional_cast (type, expression_list);
+  /* [expr.const]/1: In an integral constant expression "only type
+     conversions to integral or enumeration type can be used".  */
+  if (cast != error_mark_node && !type_dependent_expression_p (type)
+      && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (type)))
+    {
+      if (cp_parser_non_integral_constant_expression
+         (parser, "a call to a constructor"))
+       return error_mark_node;
+    }
+  return cast;
 }
 
 /* Save the tokens that make up the body of a member function defined
@@ -14215,8 +15040,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
 
 static tree
 cp_parser_save_member_function_body (cp_parser* parser,
-                                    tree decl_specifiers,
-                                    tree declarator,
+                                    cp_decl_specifier_seq *decl_specifiers,
+                                    cp_declarator *declarator,
                                     tree attributes)
 {
   cp_token_cache *cache;
@@ -14228,7 +15053,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
   if (fn == error_mark_node)
     {
       /* If there's a function-body, skip it.  */
-      if (cp_parser_token_starts_function_definition_p 
+      if (cp_parser_token_starts_function_definition_p
          (cp_lexer_peek_token (parser->lexer)))
        cp_parser_skip_to_end_of_block_or_statement (parser);
       return error_mark_node;
@@ -14239,7 +15064,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
 
   /* Create a token cache.  */
   cache = cp_token_cache_new ();
-  /* Save away the tokens that make up the body of the 
+  /* Save away the tokens that make up the body of the
      function.  */
   cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, /*depth=*/0);
   /* Handle function try blocks.  */
@@ -14260,7 +15085,7 @@ cp_parser_save_member_function_body (cp_parser* parser,
 
   /* Add FN to the queue of functions to be parsed later.  */
   TREE_VALUE (parser->unparsed_functions_queues)
-    = tree_cons (NULL_TREE, fn, 
+    = tree_cons (NULL_TREE, fn,
                 TREE_VALUE (parser->unparsed_functions_queues));
 
   return fn;
@@ -14284,7 +15109,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
      When parsing a template-id, the first non-nested `>' is taken as
      the end of the template-argument-list rather than a greater-than
      operator.  */
-  saved_greater_than_is_operator_p 
+  saved_greater_than_is_operator_p
     = parser->greater_than_is_operator_p;
   parser->greater_than_is_operator_p = false;
   /* Parsing the argument list may modify SCOPE, so we save it
@@ -14320,10 +15145,10 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
          cp_lexer_consume_token (parser->lexer);
        }
     }
-  else
-    cp_parser_require (parser, CPP_GREATER, "`>'");
+  else if (!cp_parser_require (parser, CPP_GREATER, "`>'"))
+    error ("missing `>' to terminate the template argument list");
   /* The `>' token might be a greater-than operator again now.  */
-  parser->greater_than_is_operator_p 
+  parser->greater_than_is_operator_p
     = saved_greater_than_is_operator_p;
   /* Restore the SAVED_SCOPE.  */
   parser->scope = saved_scope;
@@ -14377,26 +15202,26 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
       function_scope = decl_function_context (member_function);
       if (function_scope)
        push_function_context_to (function_scope);
-      
+
       /* Save away the current lexer.  */
       saved_lexer = parser->lexer;
       /* Make a new lexer to feed us the tokens saved for this function.  */
       parser->lexer = cp_lexer_new_from_tokens (tokens);
       parser->lexer->next = saved_lexer;
-      
+
       /* Set the current source position to be the location of the first
         token in the saved inline body.  */
       cp_lexer_peek_token (parser->lexer);
-      
+
       /* Let the front end know that we going to be defining this
         function.  */
-      start_function (NULL_TREE, member_function, NULL_TREE,
-                     SF_PRE_PARSED | SF_INCLASS_INLINE);
-      
+      start_preparsed_function (member_function, NULL_TREE,
+                               SF_PRE_PARSED | SF_INCLASS_INLINE);
+
       /* Now, parse the body of the function.  */
       cp_parser_function_definition_after_declarator (parser,
                                                      /*inline_p=*/true);
-      
+
       /* Leave the scope of the containing function.  */
       if (function_scope)
        pop_function_context_from (function_scope);
@@ -14408,7 +15233,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
   maybe_end_member_template_processing ();
 
   /* Restore the queue.  */
-  parser->unparsed_functions_queues 
+  parser->unparsed_functions_queues
     = TREE_CHAIN (parser->unparsed_functions_queues);
 }
 
@@ -14426,7 +15251,7 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
     if (TREE_PURPOSE (probe))
       {
        TREE_PURPOSE (parser->unparsed_functions_queues)
-         = tree_cons (NULL_TREE, decl, 
+         = tree_cons (current_class_type, decl,
                       TREE_PURPOSE (parser->unparsed_functions_queues));
        break;
       }
@@ -14434,7 +15259,9 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
 }
 
 /* FN is a FUNCTION_DECL which may contains a parameter with an
-   unparsed DEFAULT_ARG.  Parse the default args now.  */
+   unparsed DEFAULT_ARG.  Parse the default args now.  This function
+   assumes that the current scope is the scope in which the default
+   argument should be processed.  */
 
 static void
 cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
@@ -14458,7 +15285,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       if (!TREE_PURPOSE (parameters)
          || TREE_CODE (TREE_PURPOSE (parameters)) != DEFAULT_ARG)
        continue;
-  
+
        /* Save away the current lexer.  */
       saved_lexer = parser->lexer;
        /* Create a new one, using the tokens we have saved.  */
@@ -14474,11 +15301,13 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
       parser->local_variables_forbidden_p = true;
        /* Parse the assignment-expression.  */
-      if (DECL_CLASS_SCOPE_P (fn))
-       push_nested_class (DECL_CONTEXT (fn));
       TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
-      if (DECL_CLASS_SCOPE_P (fn))
-       pop_nested_class ();
+
+      /* If the token stream has not been completely used up, then
+        there was extra junk after the end of the default
+        argument.  */
+      if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+       cp_parser_error (parser, "expected `,'");
 
        /* Restore saved state.  */
       parser->lexer = saved_lexer;
@@ -14486,7 +15315,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
     }
 
   /* Restore the queue.  */
-  parser->unparsed_functions_queues 
+  parser->unparsed_functions_queues
     = TREE_CHAIN (parser->unparsed_functions_queues);
 }
 
@@ -14511,8 +15340,8 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
      old message.  */
   saved_message = parser->type_definition_forbidden_message;
   /* And create the new one.  */
-  parser->type_definition_forbidden_message 
-    = xmalloc (strlen (format) 
+  parser->type_definition_forbidden_message
+    = xmalloc (strlen (format)
               + strlen (IDENTIFIER_POINTER (ridpointers[keyword]))
               + 1 /* `\0' */);
   sprintf ((char *) parser->type_definition_forbidden_message,
@@ -14547,14 +15376,15 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
       /* If all went well, then we're done.  */
       if (cp_parser_parse_definitely (parser))
        {
-         /* Build a list of decl-specifiers; right now, we have only
-            a single type-specifier.  */
-         type = build_tree_list (NULL_TREE,
-                                 type);
+         cp_decl_specifier_seq decl_specs;
+
+         /* Build a trivial decl-specifier-seq.  */
+         clear_decl_specs (&decl_specs);
+         decl_specs.type = type;
 
          /* Call grokdeclarator to figure out what type this is.  */
-         expr = grokdeclarator (NULL_TREE,
-                                type,
+         expr = grokdeclarator (NULL,
+                                &decl_specs,
                                 TYPENAME,
                                 /*initialized=*/0,
                                 /*attrlist=*/NULL);
@@ -14582,66 +15412,76 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 static bool
 cp_parser_declares_only_class_p (cp_parser *parser)
 {
-  /* If the next token is a `;' or a `,' then there is no 
+  /* If the next token is a `;' or a `,' then there is no
      declarator.  */
   return (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
          || cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
 }
 
-/* Simplify EXPR if it is a non-dependent expression.  Returns the
-   (possibly simplified) expression.  */
+/* Update the DECL_SPECS to reflect the STORAGE_CLASS.  */
 
-static tree
-cp_parser_fold_non_dependent_expr (tree expr)
-{
-  /* If we're in a template, but EXPR isn't value dependent, simplify
-     it.  We're supposed to treat:
-     
-       template <typename T> void f(T[1 + 1]);
-       template <typename T> void f(T[2]);
-                  
-     as two declarations of the same function, for example.  */
-  if (processing_template_decl
-      && !type_dependent_expression_p (expr)
-      && !value_dependent_expression_p (expr))
-    {
-      HOST_WIDE_INT saved_processing_template_decl;
+static void
+cp_parser_set_storage_class (cp_decl_specifier_seq *decl_specs,
+                            cp_storage_class storage_class)
+{
+  if (decl_specs->storage_class != sc_none)
+    decl_specs->multiple_storage_classes_p = true;
+  else
+    decl_specs->storage_class = storage_class;
+}
+
+/* Update the DECL_SPECS to reflect the TYPE_SPEC.  If USER_DEFINED_P
+   is true, the type is a user-defined type; otherwise it is a
+   built-in type specified by a keyword.  */
 
-      saved_processing_template_decl = processing_template_decl;
-      processing_template_decl = 0;
-      expr = tsubst_copy_and_build (expr,
-                                   /*args=*/NULL_TREE,
-                                   tf_error,
-                                   /*in_decl=*/NULL_TREE,
-                                   /*function_p=*/false);
-      processing_template_decl = saved_processing_template_decl;
+static void
+cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
+                             tree type_spec,
+                             bool user_defined_p)
+{
+  decl_specs->any_specifiers_p = true;
+
+  /* If the user tries to redeclare a built-in type (with, for example,
+     in "typedef int wchar_t;") we remember that this is what
+     happened.  In system headers, we ignore these declarations so
+     that G++ can work with system headers that are not C++-safe.  */
+  if (decl_specs->specs[(int) ds_typedef]
+      && !user_defined_p
+      && (decl_specs->type
+         || decl_specs->specs[(int) ds_long]
+         || decl_specs->specs[(int) ds_short]
+         || decl_specs->specs[(int) ds_unsigned]
+         || decl_specs->specs[(int) ds_signed]))
+    {
+      decl_specs->redefined_builtin_type = type_spec;
+      if (!decl_specs->type)
+       {
+         decl_specs->type = type_spec;
+         decl_specs->user_defined_type_p = false;
+       }
+    }
+  else if (decl_specs->type)
+    decl_specs->multiple_types_p = true;
+  else
+    {
+      decl_specs->type = type_spec;
+      decl_specs->user_defined_type_p = user_defined_p;
+      decl_specs->redefined_builtin_type = NULL_TREE;
     }
-  return expr;
 }
 
 /* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
    Returns TRUE iff `friend' appears among the DECL_SPECIFIERS.  */
 
 static bool
-cp_parser_friend_p (tree decl_specifiers)
+cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers)
 {
-  while (decl_specifiers)
-    {
-      /* See if this decl-specifier is `friend'.  */
-      if (TREE_CODE (TREE_VALUE (decl_specifiers)) == IDENTIFIER_NODE
-         && C_RID_CODE (TREE_VALUE (decl_specifiers)) == RID_FRIEND)
-       return true;
-
-      /* Go on to the next decl-specifier.  */
-      decl_specifiers = TREE_CHAIN (decl_specifiers);
-    }
-
-  return false;
+  return decl_specifiers->specs[(int) ds_friend] != 0;
 }
 
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
    issue an error message indicating that TOKEN_DESC was expected.
-   
+
    Returns the token consumed, if the token had the appropriate type.
    Otherwise, returns NULL.  */
 
@@ -14670,8 +15510,8 @@ cp_parser_require (cp_parser* parser,
    the next token is not as expected.  */
 
 static void
-cp_parser_skip_until_found (cp_parser* parser, 
-                            enum cpp_ttype type, 
+cp_parser_skip_until_found (cp_parser* parser,
+                            enum cpp_ttype type,
                             const char* token_desc)
 {
   cp_token *token;
@@ -14685,7 +15525,7 @@ cp_parser_skip_until_found (cp_parser* parser,
     {
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
-      /* If we've reached the token we want, consume it and 
+      /* If we've reached the token we want, consume it and
         stop.  */
       if (token->type == type && !nesting_depth)
        {
@@ -14695,11 +15535,11 @@ cp_parser_skip_until_found (cp_parser* parser,
       /* If we've run out of tokens, stop.  */
       if (token->type == CPP_EOF)
        return;
-      if (token->type == CPP_OPEN_BRACE 
+      if (token->type == CPP_OPEN_BRACE
          || token->type == CPP_OPEN_PAREN
          || token->type == CPP_OPEN_SQUARE)
        ++nesting_depth;
-      else if (token->type == CPP_CLOSE_BRACE 
+      else if (token->type == CPP_CLOSE_BRACE
               || token->type == CPP_CLOSE_PAREN
               || token->type == CPP_CLOSE_SQUARE)
        {
@@ -14713,7 +15553,7 @@ cp_parser_skip_until_found (cp_parser* parser,
 
 /* If the next token is the indicated keyword, consume it.  Otherwise,
    issue an error message indicating that TOKEN_DESC was expected.
-   
+
    Returns the token consumed, if the token had the appropriate type.
    Otherwise, returns NULL.  */
 
@@ -14743,7 +15583,7 @@ cp_parser_require_keyword (cp_parser* parser,
 /* Returns TRUE iff TOKEN is a token that can begin the body of a
    function-definition.  */
 
-static bool 
+static bool
 cp_parser_token_starts_function_definition_p (cp_token* token)
 {
   return (/* An ordinary function-body begins with an `{'.  */
@@ -14779,10 +15619,35 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
   cp_token *token;
 
   token = cp_lexer_peek_token (parser->lexer);
-  return (token->type == CPP_COMMA || token->type == CPP_GREATER 
+  return (token->type == CPP_COMMA || token->type == CPP_GREATER
          || token->type == CPP_RSHIFT);
 }
+
+/* Returns TRUE iff the n-th token is a ">", or the n-th is a "[" and the
+   (n+1)-th is a ":" (which is a possible digraph typo for "< ::").  */
+
+static bool
+cp_parser_nth_token_starts_template_argument_list_p (cp_parser * parser,
+                                                    size_t n)
+{
+  cp_token *token;
+
+  token = cp_lexer_peek_nth_token (parser->lexer, n);
+  if (token->type == CPP_LESS)
+    return true;
+  /* Check for the sequence `<::' in the original code. It would be lexed as
+     `[:', where `[' is a digraph, and there is no whitespace before
+     `:'.  */
+  if (token->type == CPP_OPEN_SQUARE && token->flags & DIGRAPH)
+    {
+      cp_token *token2;
+      token2 = cp_lexer_peek_nth_token (parser->lexer, n+1);
+      if (token2->type == CPP_COLON && !(token2->flags & PREV_WHITE))
+       return true;
+    }
+  return false;
+}
+
 /* Returns the kind of tag indicated by TOKEN, if it is a class-key,
    or none_type otherwise.  */
 
@@ -14797,7 +15662,7 @@ cp_parser_token_is_class_key (cp_token* token)
       return record_type;
     case RID_UNION:
       return union_type;
-      
+
     default:
       return none_type;
     }
@@ -14811,10 +15676,10 @@ cp_parser_check_class_key (enum tag_types class_key, tree type)
   if ((TREE_CODE (type) == UNION_TYPE) != (class_key == union_type))
     pedwarn ("`%s' tag used in naming `%#T'",
            class_key == union_type ? "union"
-            : class_key == record_type ? "struct" : "class", 
+            : class_key == record_type ? "struct" : "class",
             type);
 }
-                          
+
 /* Issue an error message if DECL is redeclared with different
    access than its original declaration [class.access.spec/3].
    This applies to nested classes and nested class templates.
@@ -14833,7 +15698,7 @@ static void cp_parser_check_access_in_redeclaration (tree decl)
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
-   Return TRUE iff it is present, in which case it will be 
+   Return TRUE iff it is present, in which case it will be
    consumed.  */
 
 static bool
@@ -14885,13 +15750,13 @@ cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
   parser->object_scope = NULL_TREE;
 }
 
-/* Add tokens to CACHE until an non-nested END token appears.  */
+/* Add tokens to CACHE until a non-nested END token appears.  */
 
 static void
-cp_parser_cache_group (cp_parser *parser, 
-                      cp_token_cache *cache,
-                      enum cpp_ttype end,
-                      unsigned depth)
+cp_parser_cache_group_1 (cp_parser *parser,
+                        cp_token_cache *cache,
+                        enum cpp_ttype end,
+                        unsigned depth)
 {
   while (true)
     {
@@ -14901,27 +15766,48 @@ cp_parser_cache_group (cp_parser *parser,
       if ((end == CPP_CLOSE_PAREN || depth == 0)
          && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
        return;
-      /* Consume the next token.  */
-      token = cp_lexer_consume_token (parser->lexer);
       /* If we've reached the end of the file, stop.  */
-      if (token->type == CPP_EOF)
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
        return;
+      /* Consume the next token.  */
+      token = cp_lexer_consume_token (parser->lexer);
       /* Add this token to the tokens we are saving.  */
       cp_token_cache_push_token (cache, token);
       /* See if it starts a new group.  */
       if (token->type == CPP_OPEN_BRACE)
        {
-         cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, depth + 1);
+         cp_parser_cache_group_1 (parser, cache, CPP_CLOSE_BRACE, depth + 1);
          if (depth == 0)
            return;
        }
       else if (token->type == CPP_OPEN_PAREN)
-       cp_parser_cache_group (parser, cache, CPP_CLOSE_PAREN, depth + 1);
+       cp_parser_cache_group_1 (parser, cache, CPP_CLOSE_PAREN, depth + 1);
       else if (token->type == end)
        return;
     }
 }
 
+/* Convenient interface for cp_parser_cache_group_1 that makes sure we
+   preserve string tokens in both translated and untranslated
+   forms.  */
+
+static void
+cp_parser_cache_group (cp_parser *parser,
+                        cp_token_cache *cache,
+                        enum cpp_ttype end,
+                        unsigned depth)
+{
+  int saved_c_lex_string_translate;
+
+  saved_c_lex_string_translate = c_lex_string_translate;
+  c_lex_string_translate = -1;
+
+  cp_parser_cache_group_1 (parser, cache, end, depth);
+
+  c_lex_string_translate = saved_c_lex_string_translate;
+}
+
+
 /* Begin parsing tentatively.  We always save tokens while parsing
    tentatively so that if the tentative parsing fails we can restore the
    tokens.  */
@@ -15024,7 +15910,7 @@ cp_parser_committed_to_tentative_parse (cp_parser* parser)
 
 /* Returns nonzero iff an error has occurred during the most recent
    tentative parse.  */
-   
+
 static bool
 cp_parser_error_occurred (cp_parser* parser)
 {
@@ -15041,7 +15927,6 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser)
 }
 
 \f
-
 /* The parser.  */
 
 static GTY (()) cp_parser *the_parser;
@@ -15054,6 +15939,14 @@ void
 c_parse_file (void)
 {
   bool error_occurred;
+  static bool already_called = false;
+
+  if (already_called)
+    {
+      sorry ("inter-module optimizations not implemented for C++");
+      return;
+    }
+  already_called = true;
 
   the_parser = cp_parser_new ();
   push_deferring_access_checks (flag_access_control
@@ -15062,14 +15955,6 @@ c_parse_file (void)
   the_parser = NULL;
 }
 
-/* Clean up after parsing the entire translation unit.  */
-
-void
-free_parser_stacks (void)
-{
-  /* Nothing to do.  */
-}
-
 /* This variable must be provided by every front end.  */
 
 int yydebug;