OSDN Git Service

PR c++/18389
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index e964f48..265abdb 100644 (file)
 #include "diagnostic.h"
 #include "toplev.h"
 #include "output.h"
+#include "target.h"
 
 \f
 /* The lexer.  */
 
-/* Overview
-   --------
-
-   A cp_lexer represents a stream of cp_tokens.  It allows arbitrary
-   look-ahead.
-
-   Methodology
-   -----------
-
-   We use a circular buffer to store incoming tokens.
-
-   Some artifacts of the C++ language (such as the
-   expression/declaration ambiguity) require arbitrary look-ahead.
-   The strategy we adopt for dealing with these problems is to attempt
-   to parse one construct (e.g., the declaration) and fall back to the
-   other (e.g., the expression) if that attempt does not succeed.
-   Therefore, we must sometimes store an arbitrary number of tokens.
-
-   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.  */
+/* The cp_lexer_* routines mediate between the lexer proper (in libcpp
+   and c-lex.c) and the C++ parser.  */
 
 /* A C++ token.  */
 
@@ -74,135 +53,57 @@ typedef struct cp_token GTY (())
   ENUM_BITFIELD (rid) keyword : 8;
   /* Token flags.  */
   unsigned char flags;
+  /* True if this token is from a system header.  */
+  BOOL_BITFIELD in_system_header : 1;
+  /* True if this token is from a context where it is implicitly extern "C" */
+  BOOL_BITFIELD implicit_extern_c : 1;
   /* The value associated with this token, if any.  */
   tree value;
   /* The location at which this token was found.  */
   location_t location;
 } cp_token;
 
-/* The number of tokens in a single token block.
-   Computed so that cp_token_block fits in a 512B allocation unit.  */
-
-#define CP_TOKEN_BLOCK_NUM_TOKENS ((512 - 3*sizeof (char*))/sizeof (cp_token))
-
-/* A group of tokens.  These groups are chained together to store
-   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.)
-
-   This somewhat ungainly data structure (as opposed to, say, a
-   variable-length array), is used due to constraints imposed by the
-   current garbage-collection methodology.  If it is made more
-   flexible, we could perhaps simplify the data structures involved.  */
-
-typedef struct cp_token_block GTY (())
-{
-  /* The tokens.  */
-  cp_token tokens[CP_TOKEN_BLOCK_NUM_TOKENS];
-  /* The number of tokens in this block.  */
-  size_t num_tokens;
-  /* The next token block in the chain.  */
-  struct cp_token_block *next;
-  /* The previous block in the chain.  */
-  struct cp_token_block *prev;
-} cp_token_block;
-
-typedef struct cp_token_cache GTY (())
-{
-  /* The first block in the cache.  NULL if there are no tokens in the
-     cache.  */
-  cp_token_block *first;
-  /* The last block in the cache.  NULL If there are no tokens in the
-     cache.  */
-  cp_token_block *last;
-} cp_token_cache;
-
-/* Prototypes.  */
-
-static cp_token_cache *cp_token_cache_new
-  (void);
-static void cp_token_cache_push_token
-  (cp_token_cache *, cp_token *);
-
-/* Create a new cp_token_cache.  */
+/* We use a stack of token pointer for saving token sets.  */
+typedef struct cp_token *cp_token_position;
+DEF_VEC_MALLOC_P (cp_token_position);
 
-static cp_token_cache *
-cp_token_cache_new (void)
+static const cp_token eof_token =
 {
-  return ggc_alloc_cleared (sizeof (cp_token_cache));
-}
-
-/* Add *TOKEN to *CACHE.  */
-
-static void
-cp_token_cache_push_token (cp_token_cache *cache,
-                          cp_token *token)
-{
-  cp_token_block *b = cache->last;
-
-  /* See if we need to allocate a new token block.  */
-  if (!b || b->num_tokens == CP_TOKEN_BLOCK_NUM_TOKENS)
-    {
-      b = ggc_alloc_cleared (sizeof (cp_token_block));
-      b->prev = cache->last;
-      if (cache->last)
-       {
-         cache->last->next = b;
-         cache->last = b;
-       }
-      else
-       cache->first = cache->last = b;
-    }
-  /* Add this token to the current token block.  */
-  b->tokens[b->num_tokens++] = *token;
-}
+  CPP_EOF, RID_MAX, 0, 0, 0, NULL_TREE,
+#if USE_MAPPED_LOCATION
+  0
+#else
+  {0, 0}
+#endif
+};
 
 /* The cp_lexer structure represents the C++ lexer.  It is responsible
    for managing the token stream from the preprocessor and supplying
-   it to the parser.  */
+   it to the parser.  Tokens are never added to the cp_lexer after
+   it is created.  */
 
 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;
-  /* The first valid token in the buffer, or NULL if none.  */
-  cp_token * GTY ((skip (""))) first_token;
-  /* The next available token.  If NEXT_TOKEN is NULL, then there are
+  /* The memory allocated for the buffer.  NULL if this lexer does not
+     own the token buffer.  */
+  cp_token * GTY ((length ("%h.buffer_length"))) buffer;
+  /* If the lexer owns the buffer, this is the number of tokens in the
+     buffer.  */
+  size_t buffer_length;
+  
+  /* A pointer just past the last available token.  The tokens
+     in this lexer are [buffer, last_token).  */
+  cp_token_position GTY ((skip)) last_token;
+
+  /* The next available token.  If NEXT_TOKEN is &eof_token, then there are
      no more available tokens.  */
-  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_position GTY ((skip)) next_token;
 
   /* A stack indicating positions at which cp_lexer_save_tokens was
      called.  The top entry is the most recent position at which we
-     began saving tokens.  The entries are differences in token
-     position between FIRST_TOKEN and the first saved token.
-
-     If the stack is non-empty, we are saving tokens.  When a token is
-     consumed, the NEXT_TOKEN pointer will move, but the FIRST_TOKEN
-     pointer will not.  The token stream will be preserved so that it
-     can be reexamined later.
-
-     If the stack is empty, then we are not saving tokens.  Whenever a
-     token is consumed, the FIRST_TOKEN pointer will be moved, and the
-     consumed token will be gone forever.  */
-  varray_type saved_tokens;
-
-  /* The STRING_CST tokens encountered while processing the current
-     string literal.  */
-  varray_type string_tokens;
-
-  /* True if we should obtain more tokens from the preprocessor; false
-     if we are processing a saved token cache.  */
-  bool main_lexer_p;
+     began saving tokens.  If the stack is non-empty, we are saving
+     tokens.  */
+  VEC (cp_token_position) *GTY ((skip)) saved_tokens;
 
   /* True if we should output debugging information.  */
   bool debugging_p;
@@ -211,27 +112,38 @@ typedef struct cp_lexer GTY (())
   struct cp_lexer *next;
 } cp_lexer;
 
+/* cp_token_cache is a range of tokens.  There is no need to represent
+   allocate heap memory for it, since tokens are never removed from the
+   lexer's array.  There is also no need for the GC to walk through
+   a cp_token_cache, since everything in here is referenced through
+   a lexer.  */
+
+typedef struct cp_token_cache GTY(())
+{
+  /* The beginning of the token range.  */
+  cp_token * GTY((skip)) first;
+
+  /* Points immediately after the last token in the range.  */
+  cp_token * GTY ((skip)) last;
+} cp_token_cache;
+
 /* Prototypes.  */
 
 static cp_lexer *cp_lexer_new_main
   (void);
 static cp_lexer *cp_lexer_new_from_tokens
-  (struct cp_token_cache *);
+  (cp_token_cache *tokens);
+static void cp_lexer_destroy
+  (cp_lexer *);
 static int cp_lexer_saving_tokens
   (const cp_lexer *);
-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
-  (cp_lexer *, cp_token *, cp_token *);
-static cp_token *cp_lexer_read_token
-  (cp_lexer *);
-static void cp_lexer_maybe_grow_buffer
-  (cp_lexer *);
+static cp_token_position cp_lexer_token_position
+  (cp_lexer *, bool);
+static cp_token *cp_lexer_token_at
+  (cp_lexer *, cp_token_position);
 static void cp_lexer_get_preprocessor_token
   (cp_lexer *, cp_token *);
-static cp_token *cp_lexer_peek_token
+static inline cp_token *cp_lexer_peek_token
   (cp_lexer *);
 static cp_token *cp_lexer_peek_nth_token
   (cp_lexer *, size_t);
@@ -246,15 +158,16 @@ static cp_token *cp_lexer_consume_token
 static void cp_lexer_purge_token
   (cp_lexer *);
 static void cp_lexer_purge_tokens_after
-  (cp_lexer *, cp_token *);
+  (cp_lexer *, cp_token_position);
+static void cp_lexer_handle_pragma
+  (cp_lexer *);
 static void cp_lexer_save_tokens
   (cp_lexer *);
 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
-  (cp_lexer *, const cp_token *);
+#ifdef ENABLE_CHECKING
 static void cp_lexer_print_token
   (FILE *, cp_token *);
 static inline bool cp_lexer_debugging_p
@@ -263,11 +176,22 @@ static void cp_lexer_start_debugging
   (cp_lexer *) ATTRIBUTE_UNUSED;
 static void cp_lexer_stop_debugging
   (cp_lexer *) ATTRIBUTE_UNUSED;
+#else
+/* If we define cp_lexer_debug_stream to NULL it will provoke warnings
+   about passing NULL to functions that require non-NULL arguments
+   (fputs, fprintf).  It will never be used, so all we need is a value
+   of the right type that's guaranteed not to be NULL.  */
+#define cp_lexer_debug_stream stdout
+#define cp_lexer_print_token(str, tok) (void) 0
+#define cp_lexer_debugging_p(lexer) 0
+#endif /* ENABLE_CHECKING */
 
-/* Manifest constants.  */
+static cp_token_cache *cp_token_cache_new
+  (cp_token *, cp_token *);
 
-#define CP_TOKEN_BUFFER_SIZE 5
-#define CP_SAVED_TOKENS_SIZE 5
+/* Manifest constants.  */
+#define CP_LEXER_BUFFER_SIZE 10000
+#define CP_SAVED_TOKEN_STACK 5
 
 /* A token type for keywords, as opposed to ordinary identifiers.  */
 #define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
@@ -286,13 +210,19 @@ static void cp_lexer_stop_debugging
 #define CPP_NESTED_NAME_SPECIFIER ((enum cpp_ttype) (CPP_TEMPLATE_ID + 1))
 
 /* A token type for tokens that are not tokens at all; these are used
-   to mark the end of a token block.  */
-#define CPP_NONE (CPP_NESTED_NAME_SPECIFIER + 1)
+   to represent slots in the array where there used to be a token
+   that has now been deleted.  */
+#define CPP_PURGED ((enum cpp_ttype) (CPP_NESTED_NAME_SPECIFIER + 1))
+
+/* The number of token types, including C++-specific ones.  */
+#define N_CP_TTYPES ((int) (CPP_PURGED + 1))
 
 /* Variables.  */
 
+#ifdef ENABLE_CHECKING
 /* The stream to which debugging output should be written.  */
 static FILE *cp_lexer_debug_stream;
+#endif /* ENABLE_CHECKING */
 
 /* Create a new main C++ lexer, the lexer that gets tokens from the
    preprocessor.  */
@@ -300,8 +230,18 @@ static FILE *cp_lexer_debug_stream;
 static cp_lexer *
 cp_lexer_new_main (void)
 {
-  cp_lexer *lexer;
   cp_token first_token;
+  cp_lexer *lexer;
+  cp_token *pos;
+  size_t alloc;
+  size_t space;
+  cp_token *buffer;
+
+  /* Tell cpplib we want CPP_PRAGMA tokens.  */
+  cpp_get_options (parse_in)->defer_pragmas = true;
+
+  /* Tell c_lex not to merge string constants.  */
+  c_lex_return_raw_strings = true;
 
   /* It's possible that lexing the first token will load a PCH file,
      which is a GC collection point.  So we have to grab the first
@@ -310,313 +250,142 @@ cp_lexer_new_main (void)
   c_common_no_more_pch ();
 
   /* Allocate the memory.  */
-  lexer = ggc_alloc_cleared (sizeof (cp_lexer));
+  lexer = GGC_CNEW (cp_lexer);
 
-  /* Create the circular buffer.  */
-  lexer->buffer = ggc_calloc (CP_TOKEN_BUFFER_SIZE, sizeof (cp_token));
-  lexer->buffer_end = lexer->buffer + CP_TOKEN_BUFFER_SIZE;
-
-  /* There is one token in the buffer.  */
-  lexer->last_token = lexer->buffer + 1;
-  lexer->first_token = lexer->buffer;
-  lexer->next_token = lexer->buffer;
-  memcpy (lexer->buffer, &first_token, sizeof (cp_token));
+#ifdef ENABLE_CHECKING  
+  /* Initially we are not debugging.  */
+  lexer->debugging_p = false;
+#endif /* ENABLE_CHECKING */
+  lexer->saved_tokens = VEC_alloc (cp_token_position, CP_SAVED_TOKEN_STACK);
+        
+  /* Create the buffer.  */
+  alloc = CP_LEXER_BUFFER_SIZE;
+  buffer = ggc_alloc (alloc * sizeof (cp_token));
+
+  /* Put the first token in the buffer.  */
+  space = alloc;
+  pos = buffer;
+  *pos = first_token;
+  
+  /* Get the remaining tokens from the preprocessor.  */
+  while (pos->type != CPP_EOF)
+    {
+      pos++;
+      if (!--space)
+       {
+         space = alloc;
+         alloc *= 2;
+         buffer = ggc_realloc (buffer, alloc * sizeof (cp_token));
+         pos = buffer + space;
+       }
+      cp_lexer_get_preprocessor_token (lexer, pos);
+    }
+  lexer->buffer = buffer;
+  lexer->buffer_length = alloc - space;
+  lexer->last_token = pos;
+  lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token;
 
-  /* This lexer obtains more tokens by calling c_lex.  */
-  lexer->main_lexer_p = true;
+  /* Pragma processing (via cpp_handle_deferred_pragma) may result in
+     direct calls to c_lex.  Those callers all expect c_lex to do
+     string constant concatenation.  */
+  c_lex_return_raw_strings = false;
 
-  /* Create the SAVED_TOKENS stack.  */
-  VARRAY_INT_INIT (lexer->saved_tokens, CP_SAVED_TOKENS_SIZE, "saved_tokens");
+  gcc_assert (lexer->next_token->type != CPP_PURGED);
+  return lexer;
+}
 
-  /* Create the STRINGS array.  */
-  VARRAY_TREE_INIT (lexer->string_tokens, 32, "strings");
+/* Create a new lexer whose token stream is primed with the tokens in
+   CACHE.  When these tokens are exhausted, no new tokens will be read.  */
 
-  /* Assume we are not debugging.  */
+static cp_lexer *
+cp_lexer_new_from_tokens (cp_token_cache *cache)
+{
+  cp_token *first = cache->first;
+  cp_token *last = cache->last;
+  cp_lexer *lexer = GGC_CNEW (cp_lexer);
+
+  /* We do not own the buffer.  */
+  lexer->buffer = NULL;
+  lexer->buffer_length = 0;
+  lexer->next_token = first == last ? (cp_token *)&eof_token : first;
+  lexer->last_token = last;
+  
+  lexer->saved_tokens = VEC_alloc (cp_token_position, CP_SAVED_TOKEN_STACK);
+
+#ifdef ENABLE_CHECKING
+  /* Initially we are not debugging.  */
   lexer->debugging_p = false;
+#endif
 
+  gcc_assert (lexer->next_token->type != CPP_PURGED);
   return lexer;
 }
 
-/* Create a new lexer whose token stream is primed with the TOKENS.
-   When these tokens are exhausted, no new tokens will be read.  */
+/* Frees all resources associated with LEXER.  */
 
-static cp_lexer *
-cp_lexer_new_from_tokens (cp_token_cache *tokens)
+static void
+cp_lexer_destroy (cp_lexer *lexer)
 {
-  cp_lexer *lexer;
-  cp_token *token;
-  cp_token_block *block;
-  ptrdiff_t num_tokens;
-
-  /* Allocate the memory.  */
-  lexer = ggc_alloc_cleared (sizeof (cp_lexer));
-
-  /* Create a new buffer, appropriately sized.  */
-  num_tokens = 0;
-  for (block = tokens->first; block != NULL; block = block->next)
-    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)
-    {
-      memcpy (token, block->tokens, block->num_tokens * sizeof (cp_token));
-      token += block->num_tokens;
-    }
-
-  /* The FIRST_TOKEN is the beginning of the buffer.  */
-  lexer->first_token = lexer->buffer;
-  /* The next available token is also at the beginning of the buffer.  */
-  lexer->next_token = lexer->buffer;
-  /* The buffer is full.  */
-  lexer->last_token = lexer->first_token;
-
-  /* This lexer doesn't obtain more tokens.  */
-  lexer->main_lexer_p = false;
-
-  /* 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");
-
-  /* Assume we are not debugging.  */
-  lexer->debugging_p = false;
-
-  return lexer;
+  if (lexer->buffer)
+    ggc_free (lexer->buffer);
+  VEC_free (cp_token_position, lexer->saved_tokens);
+  ggc_free (lexer);
 }
 
 /* Returns nonzero if debugging information should be output.  */
 
+#ifdef ENABLE_CHECKING
+
 static inline bool
 cp_lexer_debugging_p (cp_lexer *lexer)
 {
   return lexer->debugging_p;
 }
 
-/* Set the current source position from the information stored in
-   TOKEN.  */
-
-static inline void
-cp_lexer_set_source_position_from_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
-                                         const cp_token *token)
-{
-  /* Ideally, the source position information would not be a global
-     variable, but it is.  */
-
-  /* Update the line number.  */
-  if (token->type != CPP_EOF)
-    input_location = token->location;
-}
-
-/* TOKEN points into the circular token buffer.  Return a pointer to
-   the next token in the buffer.  */
+#endif /* ENABLE_CHECKING */
 
-static inline cp_token *
-cp_lexer_next_token (cp_lexer* lexer, cp_token* token)
+static inline cp_token_position
+cp_lexer_token_position (cp_lexer *lexer, bool previous_p)
 {
-  token++;
-  if (token == lexer->buffer_end)
-    token = lexer->buffer;
-  return token;
+  gcc_assert (!previous_p || lexer->next_token != &eof_token);
+  
+  return lexer->next_token - previous_p;
 }
 
-/* TOKEN points into the circular token buffer.  Return a pointer to
-   the previous token in the buffer.  */
-
 static inline cp_token *
-cp_lexer_prev_token (cp_lexer* lexer, cp_token* token)
+cp_lexer_token_at (cp_lexer *lexer ATTRIBUTE_UNUSED, cp_token_position pos)
 {
-  if (token == lexer->buffer)
-    token = lexer->buffer_end;
-  return token - 1;
+  return pos;
 }
 
 /* nonzero if we are presently saving tokens.  */
 
-static int
+static inline int
 cp_lexer_saving_tokens (const cp_lexer* lexer)
 {
-  return VARRAY_ACTIVE_SIZE (lexer->saved_tokens) != 0;
-}
-
-/* Return a pointer to the token that is N tokens beyond TOKEN in the
-   buffer.  */
-
-static cp_token *
-cp_lexer_advance_token (cp_lexer *lexer, cp_token *token, ptrdiff_t n)
-{
-  token += n;
-  if (token >= lexer->buffer_end)
-    token = lexer->buffer + (token - lexer->buffer_end);
-  return token;
-}
-
-/* Returns the number of times that START would have to be incremented
-   to reach FINISH.  If START and FINISH are the same, returns zero.  */
-
-static ptrdiff_t
-cp_lexer_token_difference (cp_lexer* lexer, cp_token* start, cp_token* finish)
-{
-  if (finish >= start)
-    return finish - start;
-  else
-    return ((lexer->buffer_end - lexer->buffer)
-           - (start - finish));
-}
-
-/* Obtain another token from the C preprocessor and add it to the
-   token buffer.  Returns the newly read token.  */
-
-static cp_token *
-cp_lexer_read_token (cp_lexer* lexer)
-{
-  cp_token *token;
-
-  /* Make sure there is room in the buffer.  */
-  cp_lexer_maybe_grow_buffer (lexer);
-
-  /* If there weren't any tokens, then this one will be the first.  */
-  if (!lexer->first_token)
-    lexer->first_token = lexer->last_token;
-  /* Similarly, if there were no available tokens, there is one now.  */
-  if (!lexer->next_token)
-    lexer->next_token = lexer->last_token;
-
-  /* Figure out where we're going to store the new token.  */
-  token = lexer->last_token;
-
-  /* Get a new token from the preprocessor.  */
-  cp_lexer_get_preprocessor_token (lexer, token);
-
-  /* Increment LAST_TOKEN.  */
-  lexer->last_token = cp_lexer_next_token (lexer, token);
-
-  /* Strings should have type `const char []'.  Right now, we will
-     have an ARRAY_TYPE that is constant rather than an array of
-     constant elements.
-     FIXME: Make fix_string_type get this right in the first place.  */
-  if ((token->type == CPP_STRING || token->type == CPP_WSTRING)
-      && flag_const_strings)
-    {
-      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;
-    }
-
-  return token;
-}
-
-/* If the circular buffer is full, make it bigger.  */
-
-static void
-cp_lexer_maybe_grow_buffer (cp_lexer* lexer)
-{
-  /* If the buffer is full, enlarge it.  */
-  if (lexer->last_token == lexer->first_token)
-    {
-      cp_token *new_buffer;
-      cp_token *old_buffer;
-      cp_token *new_first_token;
-      ptrdiff_t buffer_length;
-      size_t num_tokens_to_copy;
-
-      /* Remember the current buffer pointer.  It will become invalid,
-        but we will need to do pointer arithmetic involving this
-        value.  */
-      old_buffer = lexer->buffer;
-      /* Compute the current buffer size.  */
-      buffer_length = lexer->buffer_end - lexer->buffer;
-      /* Allocate a buffer twice as big.  */
-      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
-        FIRST_TOKEN to the second half of the newly allocated
-        buffer.  */
-      num_tokens_to_copy = (lexer->first_token - old_buffer);
-      memcpy (new_buffer + buffer_length,
-             new_buffer,
-             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,
-             (buffer_length - num_tokens_to_copy) * sizeof (cp_token));
-
-      /* Now recompute all of the buffer pointers.  */
-      new_first_token
-       = new_buffer + (lexer->first_token - old_buffer);
-      if (lexer->next_token != NULL)
-       {
-         ptrdiff_t next_token_delta;
-
-         if (lexer->next_token > lexer->first_token)
-           next_token_delta = lexer->next_token - lexer->first_token;
-         else
-           next_token_delta =
-             buffer_length - (lexer->first_token - lexer->next_token);
-         lexer->next_token = new_first_token + next_token_delta;
-       }
-      lexer->last_token = new_first_token + buffer_length;
-      lexer->buffer = new_buffer;
-      lexer->buffer_end = new_buffer + buffer_length * 2;
-      lexer->first_token = new_first_token;
-    }
+  return VEC_length (cp_token_position, lexer->saved_tokens) != 0;
 }
 
-/* Store the next token from the preprocessor in *TOKEN.  */
+/* Store the next token from the preprocessor in *TOKEN.  Return true
+   if we reach EOF.  */
 
 static void
 cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
                                  cp_token *token)
 {
-  bool done;
-
-  /* If this not the main lexer, return a terminating CPP_EOF token.  */
-  if (lexer != NULL && !lexer->main_lexer_p)
-    {
-      token->type = CPP_EOF;
-      token->location.line = 0;
-      token->location.file = NULL;
-      token->value = NULL_TREE;
-      token->keyword = RID_MAX;
-
-      return;
-    }
-
-  done = false;
-  /* Keep going until we get a token we like.  */
-  while (!done)
-    {
-      /* Get a new token from the preprocessor.  */
-      token->type = c_lex_with_flags (&token->value, &token->flags);
-      /* Issue messages about tokens we cannot process.  */
-      switch (token->type)
-       {
-       case CPP_ATSIGN:
-       case CPP_HASH:
-       case CPP_PASTE:
-         error ("invalid token");
-         break;
+  static int is_extern_c = 0;
 
-       default:
-         /* This is a good token, so we exit the loop.  */
-         done = true;
-         break;
-       }
-    }
-  /* Now we've got our token.  */
+   /* Get a new token from the preprocessor.  */
+  token->type = c_lex_with_flags (&token->value, &token->flags);
   token->location = input_location;
+  token->in_system_header = in_system_header;
+
+  /* On some systems, some header files are surrounded by an 
+     implicit extern "C" block.  Set a flag in the token if it
+     comes from such a header.  */
+  is_extern_c += pending_lang_change;
+  pending_lang_change = 0;
+  token->implicit_extern_c = is_extern_c > 0;
 
   /* Check to see if this token is a keyword.  */
   if (token->type == CPP_NAME
@@ -636,47 +405,43 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
     token->keyword = RID_MAX;
 }
 
+/* Update the globals input_location and in_system_header from TOKEN.  */
+static inline void
+cp_lexer_set_source_position_from_token (cp_token *token)
+{
+  if (token->type != CPP_EOF)
+    {
+      input_location = token->location;
+      in_system_header = token->in_system_header;
+    }
+}
+
 /* Return a pointer to the next token in the token stream, but do not
    consume it.  */
 
-static cp_token *
-cp_lexer_peek_token (cp_lexerlexer)
+static inline cp_token *
+cp_lexer_peek_token (cp_lexer *lexer)
 {
-  cp_token *token;
-
-  /* If there are no tokens, read one now.  */
-  if (!lexer->next_token)
-    cp_lexer_read_token (lexer);
-
-  /* Provide debugging output.  */
   if (cp_lexer_debugging_p (lexer))
     {
-      fprintf (cp_lexer_debug_stream, "cp_lexer: peeking at token: ");
+      fputs ("cp_lexer: peeking at token: ", cp_lexer_debug_stream);
       cp_lexer_print_token (cp_lexer_debug_stream, lexer->next_token);
-      fprintf (cp_lexer_debug_stream, "\n");
+      putc ('\n', cp_lexer_debug_stream);
     }
-
-  token = lexer->next_token;
-  cp_lexer_set_source_position_from_token (lexer, token);
-  return token;
+  return lexer->next_token;
 }
 
 /* Return true if the next token has the indicated TYPE.  */
 
-static bool
+static inline bool
 cp_lexer_next_token_is (cp_lexer* lexer, enum cpp_ttype type)
 {
-  cp_token *token;
-
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (lexer);
-  /* Check to see if it has the indicated TYPE.  */
-  return token->type == type;
+  return cp_lexer_peek_token (lexer)->type == type;
 }
 
 /* Return true if the next token does not have the indicated TYPE.  */
 
-static bool
+static inline bool
 cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type)
 {
   return !cp_lexer_next_token_is (lexer, type);
@@ -684,7 +449,7 @@ cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type)
 
 /* Return true if the next token is the indicated KEYWORD.  */
 
-static bool
+static inline bool
 cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
 {
   cp_token *token;
@@ -696,7 +461,10 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
 }
 
 /* Return a pointer to the Nth token in the token stream.  If N is 1,
-   then this is precisely equivalent to cp_lexer_peek_token.  */
+   then this is precisely equivalent to cp_lexer_peek_token (except
+   that it is not inline).  One would like to disallow that case, but
+   there is one case (cp_parser_nth_token_starts_template_id) where
+   the caller passes a variable for N and it might be 1.  */
 
 static cp_token *
 cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
@@ -704,139 +472,141 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
   cp_token *token;
 
   /* N is 1-based, not zero-based.  */
-  my_friendly_assert (n > 0, 20000224);
+  gcc_assert (n > 0 && lexer->next_token != &eof_token);
 
-  /* Skip ahead from NEXT_TOKEN, reading more tokens as necessary.  */
+  if (cp_lexer_debugging_p (lexer))
+    fprintf (cp_lexer_debug_stream,
+            "cp_lexer: peeking ahead %ld at token: ", (long)n);
+
+  --n;
   token = lexer->next_token;
-  /* If there are no tokens in the buffer, get one now.  */
-  if (!token)
+  while (n != 0)
     {
-      cp_lexer_read_token (lexer);
-      token = lexer->next_token;
+      ++token;
+      if (token == lexer->last_token)
+       {
+         token = (cp_token *)&eof_token;
+         break;
+       }
+      
+      if (token->type != CPP_PURGED)
+       --n;
     }
 
-  /* Now, read tokens until we have enough.  */
-  while (--n > 0)
+  if (cp_lexer_debugging_p (lexer))
     {
-      /* Advance to the next token.  */
-      token = cp_lexer_next_token (lexer, token);
-      /* If that's all the tokens we have, read a new one.  */
-      if (token == lexer->last_token)
-       token = cp_lexer_read_token (lexer);
+      cp_lexer_print_token (cp_lexer_debug_stream, token);
+      putc ('\n', cp_lexer_debug_stream);
     }
 
   return token;
 }
 
-/* Consume the next token.  The pointer returned is valid only until
-   another token is read.  Callers should preserve copy the token
-   explicitly if they will need its value for a longer period of
-   time.  */
+/* Return the next token, and advance the lexer's next_token pointer
+   to point to the next non-purged token.  */
 
 static cp_token *
 cp_lexer_consume_token (cp_lexer* lexer)
 {
-  cp_token *token;
-
-  /* If there are no tokens, read one now.  */
-  if (!lexer->next_token)
-    cp_lexer_read_token (lexer);
-
-  /* Remember the token we'll be returning.  */
-  token = lexer->next_token;
+  cp_token *token = lexer->next_token;
 
-  /* Increment NEXT_TOKEN.  */
-  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)
-    lexer->next_token = NULL;
-
-  /* If we're not saving tokens, then move FIRST_TOKEN too.  */
-  if (!cp_lexer_saving_tokens (lexer))
+  gcc_assert (token != &eof_token);
+  
+  do
     {
-      /* If there are no tokens available, set FIRST_TOKEN to NULL.  */
-      if (!lexer->next_token)
-       lexer->first_token = NULL;
-      else
-       lexer->first_token = lexer->next_token;
+      lexer->next_token++;
+      if (lexer->next_token == lexer->last_token)
+       {
+         lexer->next_token = (cp_token *)&eof_token;
+         break;
+       }
+      
     }
-
+  while (lexer->next_token->type == CPP_PURGED);
+  
+  cp_lexer_set_source_position_from_token (token);
+  
   /* Provide debugging output.  */
   if (cp_lexer_debugging_p (lexer))
     {
-      fprintf (cp_lexer_debug_stream, "cp_lexer: consuming token: ");
+      fputs ("cp_lexer: consuming token: ", cp_lexer_debug_stream);
       cp_lexer_print_token (cp_lexer_debug_stream, token);
-      fprintf (cp_lexer_debug_stream, "\n");
+      putc ('\n', cp_lexer_debug_stream);
     }
-
+  
   return token;
 }
 
-/* Permanently remove the next token from the token stream.  There
-   must be a valid next token already; this token never reads
-   additional tokens from the preprocessor.  */
+/* Permanently remove the next token from the token stream, and
+   advance the next_token pointer to refer to the next non-purged
+   token.  */
 
 static void
 cp_lexer_purge_token (cp_lexer *lexer)
 {
-  cp_token *token;
-  cp_token *next_token;
+  cp_token *tok = lexer->next_token;
+  
+  gcc_assert (tok != &eof_token);
+  tok->type = CPP_PURGED;
+  tok->location = UNKNOWN_LOCATION;
+  tok->value = NULL_TREE;
+  tok->keyword = RID_MAX;
 
-  token = lexer->next_token;
-  while (true)
+  do
     {
-      next_token = cp_lexer_next_token (lexer, token);
-      if (next_token == lexer->last_token)
-       break;
-      *token = *next_token;
-      token = next_token;
+      tok++;
+      if (tok == lexer->last_token)
+       {
+         tok = (cp_token *)&eof_token;
+         break;
+       }
     }
-
-  lexer->last_token = token;
-  /* The token purged may have been the only token remaining; if so,
-     clear NEXT_TOKEN.  */
-  if (lexer->next_token == token)
-    lexer->next_token = NULL;
+  while (tok->type == CPP_PURGED);
+  lexer->next_token = tok;
 }
 
-/* Permanently remove all tokens after TOKEN, up to, but not
+/* Permanently remove all tokens after TOK, up to, but not
    including, the token that will be returned next by
    cp_lexer_peek_token.  */
 
 static void
-cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *token)
+cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
 {
-  cp_token *peek;
-  cp_token *t1;
-  cp_token *t2;
+  cp_token *peek = lexer->next_token;
 
-  if (lexer->next_token)
-    {
-      /* Copy the tokens that have not yet been read to the location
-        immediately following TOKEN.  */
-      t1 = cp_lexer_next_token (lexer, token);
-      t2 = peek = cp_lexer_peek_token (lexer);
-      /* Move tokens into the vacant area between TOKEN and PEEK.  */
-      while (t2 != lexer->last_token)
-       {
-         *t1 = *t2;
-         t1 = cp_lexer_next_token (lexer, t1);
-         t2 = cp_lexer_next_token (lexer, t2);
-       }
-      /* Now, the next available token is right after TOKEN.  */
-      lexer->next_token = cp_lexer_next_token (lexer, token);
-      /* And the last token is wherever we ended up.  */
-      lexer->last_token = t1;
-    }
-  else
+  if (peek == &eof_token)
+    peek = lexer->last_token;
+  
+  gcc_assert (tok < peek);
+
+  for ( tok += 1; tok != peek; tok += 1)
     {
-      /* There are no tokens in the buffer, so there is nothing to
-        copy.  The last token in the buffer is TOKEN itself.  */
-      lexer->last_token = cp_lexer_next_token (lexer, token);
+      tok->type = CPP_PURGED;
+      tok->location = UNKNOWN_LOCATION;
+      tok->value = NULL_TREE;
+      tok->keyword = RID_MAX;
     }
 }
 
+/* Consume and handle a pragma token.  */
+static void
+cp_lexer_handle_pragma (cp_lexer *lexer)
+{
+  cpp_string s;
+  cp_token *token = cp_lexer_consume_token (lexer);
+  gcc_assert (token->type == CPP_PRAGMA);
+  gcc_assert (token->value);
+
+  s.len = TREE_STRING_LENGTH (token->value);
+  s.text = (const unsigned char *) TREE_STRING_POINTER (token->value);
+
+  cpp_handle_deferred_pragma (parse_in, &s);
+
+  /* Clearing token->value here means that we will get an ICE if we
+     try to process this #pragma again (which should be impossible).  */
+  token->value = NULL;
+}
+
 /* Begin saving tokens.  All tokens consumed after this point will be
    preserved.  */
 
@@ -847,15 +617,7 @@ cp_lexer_save_tokens (cp_lexer* lexer)
   if (cp_lexer_debugging_p (lexer))
     fprintf (cp_lexer_debug_stream, "cp_lexer: saving tokens\n");
 
-  /* Make sure that LEXER->NEXT_TOKEN is non-NULL so that we can
-     restore the tokens if required.  */
-  if (!lexer->next_token)
-    cp_lexer_read_token (lexer);
-
-  VARRAY_PUSH_INT (lexer->saved_tokens,
-                  cp_lexer_token_difference (lexer,
-                                             lexer->first_token,
-                                             lexer->next_token));
+  VEC_safe_push (cp_token_position, lexer->saved_tokens, lexer->next_token);
 }
 
 /* Commit to the portion of the token stream most recently saved.  */
@@ -867,7 +629,7 @@ cp_lexer_commit_tokens (cp_lexer* lexer)
   if (cp_lexer_debugging_p (lexer))
     fprintf (cp_lexer_debug_stream, "cp_lexer: committing tokens\n");
 
-  VARRAY_POP (lexer->saved_tokens);
+  VEC_pop (cp_token_position, lexer->saved_tokens);
 }
 
 /* Return all tokens saved since the last call to cp_lexer_save_tokens
@@ -876,96 +638,63 @@ cp_lexer_commit_tokens (cp_lexer* lexer)
 static void
 cp_lexer_rollback_tokens (cp_lexer* lexer)
 {
-  size_t delta;
-
   /* Provide debugging output.  */
   if (cp_lexer_debugging_p (lexer))
     fprintf (cp_lexer_debug_stream, "cp_lexer: restoring tokens\n");
 
-  /* Find the token that was the NEXT_TOKEN when we started saving
-     tokens.  */
-  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,
-                                             delta);
-  /* It might be the case that there were no tokens when we started
-     saving tokens, but that there are some tokens now.  */
-  if (!lexer->next_token && lexer->first_token)
-    lexer->next_token = lexer->first_token;
-
-  /* Stop saving tokens.  */
-  VARRAY_POP (lexer->saved_tokens);
+  lexer->next_token = VEC_pop (cp_token_position, lexer->saved_tokens);
 }
 
 /* Print a representation of the TOKEN on the STREAM.  */
 
+#ifdef ENABLE_CHECKING
+
 static void
-cp_lexer_print_token (FILE * stream, cp_token* token)
-{
-  const char *token_type = NULL;
+cp_lexer_print_token (FILE * stream, cp_token *token)
+{
+  /* We don't use cpp_type2name here because the parser defines
+     a few tokens of its own.  */
+  static const char *const token_names[] = {
+    /* cpplib-defined token types */
+#define OP(e, s) #e,
+#define TK(e, s) #e,
+    TTYPE_TABLE
+#undef OP
+#undef TK
+    /* C++ parser token types - see "Manifest constants", above.  */
+    "KEYWORD",
+    "TEMPLATE_ID",
+    "NESTED_NAME_SPECIFIER",
+    "PURGED"
+  };
+  
+  /* If we have a name for the token, print it out.  Otherwise, we
+     simply give the numeric code.  */
+  gcc_assert (token->type < ARRAY_SIZE(token_names));
+  fputs (token_names[token->type], stream);
 
-  /* Figure out what kind of token this is.  */
+  /* For some tokens, print the associated data.  */
   switch (token->type)
     {
-    case CPP_EQ:
-      token_type = "EQ";
-      break;
-
-    case CPP_COMMA:
-      token_type = "COMMA";
-      break;
-
-    case CPP_OPEN_PAREN:
-      token_type = "OPEN_PAREN";
-      break;
-
-    case CPP_CLOSE_PAREN:
-      token_type = "CLOSE_PAREN";
-      break;
-
-    case CPP_OPEN_BRACE:
-      token_type = "OPEN_BRACE";
-      break;
-
-    case CPP_CLOSE_BRACE:
-      token_type = "CLOSE_BRACE";
-      break;
-
-    case CPP_SEMICOLON:
-      token_type = "SEMICOLON";
-      break;
-
+    case CPP_KEYWORD:
+      /* Some keywords have a value that is not an IDENTIFIER_NODE.
+        For example, `struct' is mapped to an INTEGER_CST.  */
+      if (TREE_CODE (token->value) != IDENTIFIER_NODE)
+       break;
+      /* else fall through */
     case CPP_NAME:
-      token_type = "NAME";
+      fputs (IDENTIFIER_POINTER (token->value), stream);
       break;
 
-    case CPP_EOF:
-      token_type = "EOF";
-      break;
-
-    case CPP_KEYWORD:
-      token_type = "keyword";
+    case CPP_STRING:
+    case CPP_WSTRING:
+    case CPP_PRAGMA:
+      fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->value));
       break;
 
-      /* This is not a token that we know how to handle yet.  */
     default:
       break;
     }
-
-  /* If we have a name for the token, print it out.  Otherwise, we
-     simply give the numeric code.  */
-  if (token_type)
-    fprintf (stream, "%s", token_type);
-  else
-    fprintf (stream, "%d", token->type);
-  /* And, for an identifier, print the identifier 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
-         && TREE_CODE (token->value) == IDENTIFIER_NODE))
-    fprintf (stream, " %s", IDENTIFIER_POINTER (token->value));
 }
 
 /* Start emitting debugging information.  */
@@ -984,7 +713,211 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
   --lexer->debugging_p;
 }
 
+#endif /* ENABLE_CHECKING */
+
+/* Create a new cp_token_cache, representing a range of tokens.  */
+
+static cp_token_cache *
+cp_token_cache_new (cp_token *first, cp_token *last)
+{
+  cp_token_cache *cache = GGC_NEW (cp_token_cache);
+  cache->first = first;
+  cache->last = last;
+  return cache;
+}
+
 \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
@@ -1034,18 +967,11 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
    Future Improvements
    -------------------
 
-   The performance of the parser could probably be improved
-   substantially.  Some possible improvements include:
-
-     - The expression parser recurses through the various levels of
-       precedence as specified in the grammar, rather than using an
-       operator-precedence technique.  Therefore, parsing a simple
-       identifier requires multiple recursive calls.
-
-     - We could often eliminate the need to parse tentatively by
-       looking ahead a little bit.  In some places, this approach
-       might not entirely eliminate the need to parse tentatively, but
-       it might still speed up the average case.  */
+   The performance of the parser could probably be improved substantially.
+   We could often eliminate the need to parse tentatively by looking ahead
+   a little bit.  In some places, this approach might not entirely eliminate
+   the need to parse tentatively, but it might still speed up the average
+   case.  */
 
 /* Flags that are passed to some parsing functions.  These values can
    be bitwise-ored together.  */
@@ -1073,20 +999,39 @@ typedef enum cp_parser_declarator_kind
   CP_PARSER_DECLARATOR_EITHER
 } cp_parser_declarator_kind;
 
-/* A mapping from a token type to a corresponding tree node type.  */
+/* The precedence values used to parse binary expressions.  The minimum value
+   of PREC must be 1, because zero is reserved to quickly discriminate
+   binary operators from other tokens.  */
 
-typedef struct cp_parser_token_tree_map_node
+enum cp_parser_prec
 {
-  /* The token type.  */
-  ENUM_BITFIELD (cpp_ttype) token_type : 8;
-  /* The corresponding tree code.  */
-  ENUM_BITFIELD (tree_code) tree_type : 8;
-} cp_parser_token_tree_map_node;
+  PREC_NOT_OPERATOR,
+  PREC_LOGICAL_OR_EXPRESSION,
+  PREC_LOGICAL_AND_EXPRESSION,
+  PREC_INCLUSIVE_OR_EXPRESSION,
+  PREC_EXCLUSIVE_OR_EXPRESSION,
+  PREC_AND_EXPRESSION,
+  PREC_EQUALITY_EXPRESSION,
+  PREC_RELATIONAL_EXPRESSION,
+  PREC_SHIFT_EXPRESSION,
+  PREC_ADDITIVE_EXPRESSION,
+  PREC_MULTIPLICATIVE_EXPRESSION,
+  PREC_PM_EXPRESSION,
+  NUM_PREC_VALUES = PREC_PM_EXPRESSION
+};
 
-/* A complete map consists of several ordinary entries, followed by a
-   terminator.  The terminating entry has a token_type of CPP_EOF.  */
+/* A mapping from a token type to a corresponding tree node type, with a
+   precedence value.  */
 
-typedef cp_parser_token_tree_map_node cp_parser_token_tree_map[];
+typedef struct cp_parser_binary_operations_map_node
+{
+  /* The token type.  */
+  enum cpp_ttype token_type;
+  /* The corresponding tree code.  */
+  enum tree_code tree_type;
+  /* The precedence of this operator.  */
+  enum cp_parser_prec prec;
+} cp_parser_binary_operations_map_node;
 
 /* The status of a tentative parse.  */
 
@@ -1101,8 +1046,20 @@ typedef enum cp_parser_status_kind
   CP_PARSER_STATUS_KIND_COMMITTED
 } cp_parser_status_kind;
 
-/* Context that is saved and restored when parsing tentatively.  */
+typedef struct cp_parser_expression_stack_entry
+{
+  tree lhs;
+  enum tree_code tree_type;
+  int prec;
+} cp_parser_expression_stack_entry;
+
+/* The stack for storing partial expressions.  We only need NUM_PREC_VALUES
+   entries because precedence levels on the stack are monotonically
+   increasing.  */
+typedef struct cp_parser_expression_stack_entry
+  cp_parser_expression_stack[NUM_PREC_VALUES];
 
+/* Context that is saved and restored when parsing tentatively.  */
 typedef struct cp_parser_context GTY (())
 {
   /* If this is a tentative parsing context, the status of the
@@ -1113,6 +1070,7 @@ typedef struct cp_parser_context GTY (())
      scope given by OBJECT_TYPE (the type of `x' or `*x') and also in
      the context of the containing expression.  */
   tree object_type;
+
   /* The next parsing context in the stack.  */
   struct cp_parser_context *next;
 } cp_parser_context;
@@ -1126,7 +1084,51 @@ 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;
+
+/* The operator-precedence table used by cp_parser_binary_expression.
+   Transformed into an associative array (binops_by_token) by
+   cp_parser_new.  */
+
+static const cp_parser_binary_operations_map_node binops[] = {
+  { CPP_DEREF_STAR, MEMBER_REF, PREC_PM_EXPRESSION },
+  { CPP_DOT_STAR, DOTSTAR_EXPR, PREC_PM_EXPRESSION },
+
+  { CPP_MULT, MULT_EXPR, PREC_MULTIPLICATIVE_EXPRESSION },
+  { CPP_DIV, TRUNC_DIV_EXPR, PREC_MULTIPLICATIVE_EXPRESSION },
+  { CPP_MOD, TRUNC_MOD_EXPR, PREC_MULTIPLICATIVE_EXPRESSION },
+
+  { CPP_PLUS, PLUS_EXPR, PREC_ADDITIVE_EXPRESSION },
+  { CPP_MINUS, MINUS_EXPR, PREC_ADDITIVE_EXPRESSION },
+
+  { CPP_LSHIFT, LSHIFT_EXPR, PREC_SHIFT_EXPRESSION },
+  { CPP_RSHIFT, RSHIFT_EXPR, PREC_SHIFT_EXPRESSION },
+
+  { CPP_LESS, LT_EXPR, PREC_RELATIONAL_EXPRESSION },
+  { CPP_GREATER, GT_EXPR, PREC_RELATIONAL_EXPRESSION },
+  { CPP_LESS_EQ, LE_EXPR, PREC_RELATIONAL_EXPRESSION },
+  { CPP_GREATER_EQ, GE_EXPR, PREC_RELATIONAL_EXPRESSION },
+  { CPP_MIN, MIN_EXPR, PREC_RELATIONAL_EXPRESSION },
+  { CPP_MAX, MAX_EXPR, PREC_RELATIONAL_EXPRESSION },
+
+  { CPP_EQ_EQ, EQ_EXPR, PREC_EQUALITY_EXPRESSION },
+  { CPP_NOT_EQ, NE_EXPR, PREC_EQUALITY_EXPRESSION },
+
+  { CPP_AND, BIT_AND_EXPR, PREC_AND_EXPRESSION },
+
+  { CPP_XOR, BIT_XOR_EXPR, PREC_EXCLUSIVE_OR_EXPRESSION },
+
+  { CPP_OR, BIT_IOR_EXPR, PREC_INCLUSIVE_OR_EXPRESSION },
+
+  { CPP_AND_AND, TRUTH_ANDIF_EXPR, PREC_LOGICAL_AND_EXPRESSION },
+
+  { CPP_OR_OR, TRUTH_ORIF_EXPR, PREC_LOGICAL_OR_EXPRESSION }
+};
+
+/* The same as binops, but initialized by cp_parser_new so that
+   binops_by_token[N].token_type == N.  Used in cp_parser_binary_expression
+   for speed.  */
+static cp_parser_binary_operations_map_node binops_by_token[N_CP_TTYPES];
 
 /* Constructors and destructors.  */
 
@@ -1147,7 +1149,8 @@ cp_parser_context_new (cp_parser_context* next)
       memset (context, 0, sizeof (*context));
     }
   else
-    context = ggc_alloc_cleared (sizeof (cp_parser_context));
+    context = GGC_CNEW (cp_parser_context);
+
   /* No errors have occurred yet in this context.  */
   context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
   /* If this is not the bottomost context, copy information that we
@@ -1232,9 +1235,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;
@@ -1264,6 +1264,14 @@ typedef struct cp_parser GTY(())
      alternatives.  */
   bool in_type_id_in_expr_p;
 
+  /* TRUE if we are currently in a header file where declarations are
+     implicitly extern "C".  */
+  bool implicit_extern_c;
+
+  /* TRUE if strings in expressions should be translated to the execution
+     character set.  */
+  bool translate_strings_p;
+
   /* If non-NULL, then we are parsing a construct where new type
      definitions are not permitted.  The string stored here will be
      issued as an error message if a type is defined.  */
@@ -1320,6 +1328,8 @@ static cp_parser *cp_parser_new
 
 static tree cp_parser_identifier
   (cp_parser *);
+static tree cp_parser_string_literal
+  (cp_parser *, bool, bool);
 
 /* Basic concepts [gram.basic]  */
 
@@ -1342,6 +1352,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
@@ -1355,10 +1369,10 @@ 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 *);
@@ -1366,27 +1380,7 @@ static tree cp_parser_delete_expression
   (cp_parser *);
 static tree cp_parser_cast_expression
   (cp_parser *, bool);
-static tree cp_parser_pm_expression
-  (cp_parser *);
-static tree cp_parser_multiplicative_expression
-  (cp_parser *);
-static tree cp_parser_additive_expression
-  (cp_parser *);
-static tree cp_parser_shift_expression
-  (cp_parser *);
-static tree cp_parser_relational_expression
-  (cp_parser *);
-static tree cp_parser_equality_expression
-  (cp_parser *);
-static tree cp_parser_and_expression
-  (cp_parser *);
-static tree cp_parser_exclusive_or_expression
-  (cp_parser *);
-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_binary_expression
   (cp_parser *);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
@@ -1398,19 +1392,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
@@ -1439,16 +1435,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
@@ -1481,28 +1478,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_parser_declarator_kind, int *, bool *);
-static tree cp_parser_direct_declarator
-  (cp_parser *, cp_parser_declarator_kind, int *);
+  (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *);
+static cp_declarator *cp_parser_declarator
+  (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
+static cp_declarator *cp_parser_direct_declarator
+  (cp_parser *, cp_parser_declarator_kind, int *, bool);
 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 *);
@@ -1548,7 +1543,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 *);
@@ -1573,7 +1568,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
@@ -1628,25 +1623,23 @@ static void cp_parser_label_declaration
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
-  (cp_parser *, tree, bool, bool, bool, bool);
+  (cp_parser *, tree, bool, bool, bool, bool, bool *);
 static tree cp_parser_lookup_name_simple
   (cp_parser *, tree);
 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
   (cp_parser *);
-static tree cp_parser_binary_expression
-  (cp_parser *, const cp_parser_token_tree_map, cp_parser_expression_fn);
 static tree cp_parser_global_scope_opt
   (cp_parser *, bool);
 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
@@ -1656,7 +1649,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
@@ -1669,8 +1662,12 @@ static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
+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
@@ -1694,7 +1691,7 @@ static bool cp_parser_optional_template_keyword
 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);
+  (cp_parser *, enum cpp_ttype, unsigned);
 static void cp_parser_parse_tentatively
   (cp_parser *);
 static void cp_parser_commit_to_tentative_parse
@@ -1716,7 +1713,7 @@ 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 bool cp_parser_non_integral_constant_expression
@@ -1772,16 +1769,21 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword)
   return token->keyword == keyword;
 }
 
-/* Issue the indicated error MESSAGE.  */
+/* If not parsing tentatively, issue a diagnostic of the form
+      FILE:LINE: MESSAGE before TOKEN
+   where TOKEN is the next token in the input stream.  MESSAGE
+   (specified by the caller) is usually of the form "expected
+   OTHER-TOKEN".  */
 
 static void
 cp_parser_error (cp_parser* parser, const char* message)
 {
-  /* Output the MESSAGE -- unless we're parsing tentatively.  */
   if (!cp_parser_simulate_error (parser))
     {
-      cp_token *token;
-      token = cp_lexer_peek_token (parser->lexer);
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      /* This diagnostic makes more sense if it is tagged to the line
+        of the token we just peeked at.  */
+      cp_lexer_set_source_position_from_token (token);
       c_parse_error (message,
                     /* Because c_parser_error does not understand
                        CPP_KEYWORD, keywords are treated like
@@ -1807,19 +1809,26 @@ 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);
+       error ("%<::%D%> has not been declared", name);
+      else if (parser->object_scope 
+              && !CLASS_TYPE_P (parser->object_scope))
+       error ("request for member %qD in non-class type %qT",
+              name, parser->object_scope);
+      else if (parser->object_scope)
+       error ("%<%T::%D%> has not been declared", 
+              parser->object_scope, name);
       else
-       error ("`%D' has not been declared", name);
+       error ("%qD has not been declared", name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("`%D::%D' %s", parser->scope, name, desired);
+    error ("%<%D::%D%> %s", parser->scope, name, desired);
   else if (parser->scope == global_namespace)
-    error ("`::%D' %s", name, desired);
+    error ("%<::%D%> %s", name, desired);
   else
-    error ("`%D' %s", name, desired);
+    error ("%qD %s", name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -1858,18 +1867,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");
 }
@@ -1883,42 +1893,28 @@ static void
 cp_parser_check_for_invalid_template_id (cp_parser* parser,
                                         tree type)
 {
-  ptrdiff_t start;
-  cp_token *token;
+  cp_token_position start = 0;
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
     {
       if (TYPE_P (type))
-       error ("`%T' is not a template", type);
+       error ("%qT is not a template", type);
       else if (TREE_CODE (type) == IDENTIFIER_NODE)
-       error ("`%s' is not a template", IDENTIFIER_POINTER (type));
+       error ("%qE is not a template", type);
       else
        error ("invalid template-id");
       /* Remember the location of the invalid "<".  */
       if (cp_parser_parsing_tentatively (parser)
          && !cp_parser_committed_to_tentative_parse (parser))
-       {
-         token = cp_lexer_peek_token (parser->lexer);
-         token = cp_lexer_prev_token (parser->lexer, token);
-         start = cp_lexer_token_difference (parser->lexer,
-                                            parser->lexer->first_token,
-                                            token);
-       }
-      else
-       start = -1;
+       start = cp_lexer_token_position (parser->lexer, true);
       /* Consume the "<".  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the template arguments.  */
       cp_parser_enclosed_template_argument_list (parser);
       /* Permanently remove the invalid template arguments so that
         this error message is not issued again.  */
-      if (start >= 0)
-       {
-         token = cp_lexer_advance_token (parser->lexer,
-                                         parser->lexer->first_token,
-                                         start);
-         cp_lexer_purge_tokens_after (parser->lexer, token);
-       }
+      if (start)
+       cp_lexer_purge_tokens_after (parser->lexer, start);
     }
 }
 
@@ -1958,12 +1954,12 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
   /* 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",
+    error ("invalid use of template-name %qE without an argument list",
       decl);
   else if (!parser->scope)
     {
       /* Issue an error message.  */
-      error ("`%E' does not name a type", id);
+      error ("%qE 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:
 
@@ -1994,7 +1990,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
                    if (TREE_CODE (field) == TYPE_DECL
                        && DECL_NAME (field) == id)
                      {
-                       inform ("(perhaps `typename %T::%E' was intended)",
+                       inform ("(perhaps %<typename %T::%E%> was intended)",
                                BINFO_TYPE (b), id);
                        break;
                      }
@@ -2009,13 +2005,12 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
   else
     {
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-       error ("`%E' in namespace `%E' does not name a type",
+       error ("%qE in namespace %qE 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);
+       error ("%qE in class %qT does not name a type", id, parser->scope);
       else
-       abort();
+       gcc_unreachable ();
     }
 }
 
@@ -2051,13 +2046,10 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
       cp_parser_abort_tentative_parse (parser);
       return false;
     }
-  if (!cp_parser_parse_definitely (parser))
+  if (!cp_parser_parse_definitely (parser)
+      || TREE_CODE (id) != IDENTIFIER_NODE)
     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
@@ -2079,6 +2071,7 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
 {
   unsigned paren_depth = 0;
   unsigned brace_depth = 0;
+  int result;
 
   if (recovering && !or_comma && cp_parser_parsing_tentatively (parser)
       && !cp_parser_committed_to_tentative_parse (parser))
@@ -2090,23 +2083,35 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
 
       /* 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)
        {
@@ -2118,13 +2123,18 @@ 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);
     }
+
+  return result;
 }
 
 /* Consume tokens until we reach the end of the current statement.
@@ -2301,12 +2311,18 @@ cp_parser_new (void)
 {
   cp_parser *parser;
   cp_lexer *lexer;
+  unsigned i;
 
   /* cp_lexer_new_main is called before calling ggc_alloc because
      cp_lexer_new_main might load a PCH file.  */
   lexer = cp_lexer_new_main ();
 
-  parser = ggc_alloc_cleared (sizeof (cp_parser));
+  /* Initialize the binops_by_token so that we can get the tree
+     directly from the token.  */
+  for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
+    binops_by_token[binops[i].token_type] = binops[i];
+
+  parser = GGC_CNEW (cp_parser);
   parser->lexer = lexer;
   parser->context = cp_parser_context_new (NULL);
 
@@ -2324,9 +2340,6 @@ cp_parser_new (void)
   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;
 
@@ -2348,6 +2361,12 @@ cp_parser_new (void)
   /* We are not parsing a type-id inside an expression.  */
   parser->in_type_id_in_expr_p = false;
 
+  /* Declarations aren't implicitly extern "C".  */
+  parser->implicit_extern_c = false;
+
+  /* String literals should be translated to the execution character set.  */
+  parser->translate_strings_p = true;
+
   /* The unparsed function queue is empty.  */
   parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
 
@@ -2360,6 +2379,36 @@ cp_parser_new (void)
   return parser;
 }
 
+/* Create a cp_lexer structure which will emit the tokens in CACHE
+   and push it onto the parser's lexer stack.  This is used for delayed
+   parsing of in-class method bodies and default arguments, and should
+   not be confused with tentative parsing.  */
+static void
+cp_parser_push_lexer_for_tokens (cp_parser *parser, cp_token_cache *cache)
+{
+  cp_lexer *lexer = cp_lexer_new_from_tokens (cache);
+  lexer->next = parser->lexer;
+  parser->lexer = lexer;
+
+  /* Move the current source position to that of the first token in the
+     new lexer.  */
+  cp_lexer_set_source_position_from_token (lexer->next_token);
+}
+
+/* Pop the top lexer off the parser stack.  This is never used for the
+   "main" lexer, only for those pushed by cp_parser_push_lexer_for_tokens.  */
+static void
+cp_parser_pop_lexer (cp_parser *parser)
+{
+  cp_lexer *lexer = parser->lexer;
+  parser->lexer = lexer->next;
+  cp_lexer_destroy (lexer);
+
+  /* Put the current source position back where it was before this
+     lexer was pushed.  */
+  cp_lexer_set_source_position_from_token (parser->lexer->next_token);
+}
+
 /* Lexical conventions [gram.lex]  */
 
 /* Parse an identifier.  Returns an IDENTIFIER_NODE representing the
@@ -2376,6 +2425,101 @@ cp_parser_identifier (cp_parser* parser)
   return token ? token->value : error_mark_node;
 }
 
+/* Parse a sequence of adjacent string constants.  Returns a
+   TREE_STRING representing the combined, nul-terminated string
+   constant.  If TRANSLATE is true, translate the string to the
+   execution character set.  If WIDE_OK is true, a wide string is
+   invalid here.
+
+   C++98 [lex.string] says that if a narrow string literal token is
+   adjacent to a wide string literal token, the behavior is undefined.
+   However, C99 6.4.5p4 says that this results in a wide string literal.
+   We follow C99 here, for consistency with the C front end.
+
+   This code is largely lifted from lex_string() in c-lex.c.
+
+   FUTURE: ObjC++ will need to handle @-strings here.  */
+static tree
+cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
+{
+  tree value;
+  bool wide = false;
+  size_t count;
+  struct obstack str_ob;
+  cpp_string str, istr, *strs;
+  cp_token *tok;
+
+  tok = cp_lexer_peek_token (parser->lexer);
+  if (!cp_parser_is_string_literal (tok))
+    {
+      cp_parser_error (parser, "expected string-literal");
+      return error_mark_node;
+    }
+
+  /* Try to avoid the overhead of creating and destroying an obstack
+     for the common case of just one string.  */
+  if (!cp_parser_is_string_literal
+      (cp_lexer_peek_nth_token (parser->lexer, 2)))
+    {
+      cp_lexer_consume_token (parser->lexer);
+
+      str.text = (const unsigned char *)TREE_STRING_POINTER (tok->value);
+      str.len = TREE_STRING_LENGTH (tok->value);
+      count = 1;
+      if (tok->type == CPP_WSTRING)
+       wide = true;
+
+      strs = &str;
+    }
+  else
+    {
+      gcc_obstack_init (&str_ob);
+      count = 0;
+
+      do
+       {
+         cp_lexer_consume_token (parser->lexer);
+         count++;
+         str.text = (unsigned char *)TREE_STRING_POINTER (tok->value);
+         str.len = TREE_STRING_LENGTH (tok->value);
+         if (tok->type == CPP_WSTRING)
+           wide = true;
+
+         obstack_grow (&str_ob, &str, sizeof (cpp_string));
+
+         tok = cp_lexer_peek_token (parser->lexer);
+       }
+      while (cp_parser_is_string_literal (tok));
+
+      strs = (cpp_string *) obstack_finish (&str_ob);
+    }
+
+  if (wide && !wide_ok)
+    {
+      cp_parser_error (parser, "a wide string is invalid in this context");
+      wide = false;
+    }
+
+  if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
+      (parse_in, strs, count, &istr, wide))
+    {
+      value = build_string (istr.len, (char *)istr.text);
+      free ((void *)istr.text);
+
+      TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
+      value = fix_string_type (value);
+    }
+  else
+    /* cpp_interpret_string has issued an error.  */
+    value = error_mark_node;
+
+  if (count > 1)
+    obstack_free (&str_ob, 0);
+
+  return value;
+}
+
+
 /* Basic concepts [gram.basic]  */
 
 /* Parse a translation-unit.
@@ -2388,27 +2532,63 @@ cp_parser_identifier (cp_parser* parser)
 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;
+       {
+         /* Get rid of the token array; we don't need it any more.  */
+         cp_lexer_destroy (parser->lexer);
+         parser->lexer = NULL;
 
-      /* Otherwise, issue an error message.  */
-      cp_parser_error (parser, "expected declaration");
-      return false;
-    }
+         /* This file might have been a context that's implicitly extern
+            "C".  If so, pop the lang context.  (Only relevant for PCH.) */
+         if (parser->implicit_extern_c)
+           {
+             pop_lang_context ();
+             parser->implicit_extern_c = false;
+           }
 
-  /* Consume the EOF token.  */
-  cp_parser_require (parser, CPP_EOF, "end-of-file");
+         /* Finish up.  */
+         finish_translation_unit ();
 
-  /* Finish up.  */
-  finish_translation_unit ();
+         success = true;
+         break;
+       }
+      else
+       {
+         cp_parser_error (parser, "expected declaration");
+         success = false;
+         break;
+       }
+    }
+
+  /* Make sure the declarator obstack was fully cleaned up.  */
+  gcc_assert (obstack_next_free (&declarator_obstack)
+             == declarator_obstack_base);
 
   /* All went well.  */
-  return true;
+  return success;
 }
 
 /* Expressions [gram.expr] */
@@ -2463,12 +2643,19 @@ 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:
+      /* ??? Should wide strings be allowed when parser->translate_strings_p
+         is false (i.e. in attributes)?  If not, we can kill the third
+        argument to cp_parser_string_literal.  */
+      return cp_parser_string_literal (parser,
+                                      parser->translate_strings_p,
+                                      true);
+
     case CPP_OPEN_PAREN:
       {
        tree expr;
@@ -2501,7 +2688,7 @@ cp_parser_primary_expression (cp_parser *parser,
            /* 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);
          }
@@ -2548,7 +2735,7 @@ cp_parser_primary_expression (cp_parser *parser,
          cp_lexer_consume_token (parser->lexer);
          if (parser->local_variables_forbidden_p)
            {
-             error ("`this' may not be used in this context");
+             error ("%<this%> may not be used in this context");
              return error_mark_node;
            }
          /* Pointers cannot appear in constant-expressions.  */
@@ -2603,27 +2790,7 @@ cp_parser_primary_expression (cp_parser *parser,
          }
 
        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");
@@ -2661,7 +2828,18 @@ cp_parser_primary_expression (cp_parser *parser,
        /* Look up the name.  */
        else
          {
-           decl = cp_parser_lookup_name_simple (parser, id_expression);
+           bool ambiguous_p;
+
+           decl = cp_parser_lookup_name (parser, id_expression,
+                                         /*is_type=*/false,
+                                         /*is_template=*/false,
+                                         /*is_namespace=*/false,
+                                         /*check_dependency=*/true,
+                                         &ambiguous_p);
+           /* If the lookup was ambiguous, an error will already have
+              been issued.  */
+           if (ambiguous_p)
+             return error_mark_node;
            /* If name lookup gives us a SCOPE_REF, then the
               qualifying scope was dependent.  Just propagate the
               name.  */
@@ -2692,7 +2870,7 @@ cp_parser_primary_expression (cp_parser *parser,
                decl = check_for_out_of_scope_variable (decl);
                if (local_variable_p (decl))
                  {
-                   error ("local variable `%D' may not appear in this context",
+                   error ("local variable %qD may not appear in this context",
                           decl);
                    return error_mark_node;
                  }
@@ -2775,7 +2953,7 @@ cp_parser_id_expression (cp_parser *parser,
                                            /*typename_keyword_p=*/false,
                                            check_dependency_p,
                                            /*type_p=*/false,
-                                           /*is_declarator=*/false)
+                                           declarator_p)
        != NULL_TREE);
   /* If there is a nested-name-specifier, then we are looking at
      the first qualified-id production.  */
@@ -3057,7 +3235,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        if (declarator_p
            && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
            && !DECL_SELF_REFERENCE_P (type_decl))
-         error ("typedef-name `%D' used as destructor declarator",
+         error ("typedef-name %qD used as destructor declarator",
                 type_decl);
 
        return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
@@ -3124,8 +3302,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
 {
   bool success = false;
   tree access_check = NULL_TREE;
-  ptrdiff_t start;
-  cp_tokentoken;
+  cp_token_position start = 0;
+  cp_token *token;
 
   /* If the next token corresponds to a nested name specifier, there
      is no need to reparse it.  However, if CHECK_DEPENDENCY_P is
@@ -3144,14 +3322,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
   /* Remember where the nested-name-specifier starts.  */
   if (cp_parser_parsing_tentatively (parser)
       && !cp_parser_committed_to_tentative_parse (parser))
-    {
-      token = cp_lexer_peek_token (parser->lexer);
-      start = cp_lexer_token_difference (parser->lexer,
-                                        parser->lexer->first_token,
-                                        token);
-    }
-  else
-    start = -1;
+    start = cp_lexer_token_position (parser->lexer, false);
 
   push_deferring_access_checks (dk_deferred);
 
@@ -3215,6 +3386,16 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
         might destroy it.  */
       old_scope = parser->scope;
       saved_qualifying_scope = parser->qualifying_scope;
+      /* In a declarator-id like "X<T>::I::Y<T>" we must be able to
+        look up names in "X<T>::I" in order to determine that "Y" is
+        a template.  So, if we have a typename at this point, we make
+        an effort to look through it.  */
+      if (is_declaration 
+         && !typename_keyword_p
+         && parser->scope 
+         && TREE_CODE (parser->scope) == TYPENAME_TYPE)
+       parser->scope = resolve_typename_type (parser->scope, 
+                                              /*only_current_p=*/false);
       /* Parse the qualifying entity.  */
       new_scope
        = cp_parser_class_or_namespace_name (parser,
@@ -3253,8 +3434,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
 
                  decl = cp_parser_lookup_name_simple (parser, token->value);
                  if (TREE_CODE (decl) == TEMPLATE_DECL)
-                   error ("`%D' used without template parameters",
-                          decl);
+                   error ("%qD used without template parameters", decl);
                  else
                    cp_parser_name_lookup_error
                      (parser, token->value, decl,
@@ -3303,21 +3483,18 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
      token.  That way, should we re-parse the token stream, we will
      not have to repeat the effort required to do the parse, nor will
      we issue duplicate error messages.  */
-  if (success && start >= 0)
+  if (success && start)
     {
-      /* Find the token that corresponds to the start of the
-        template-id.  */
-      token = cp_lexer_advance_token (parser->lexer,
-                                     parser->lexer->first_token,
-                                     start);
-
+      cp_token *token = cp_lexer_token_at (parser->lexer, start);
+      
       /* Reset the contents of the START token.  */
       token->type = CPP_NESTED_NAME_SPECIFIER;
       token->value = build_tree_list (access_check, parser->scope);
       TREE_TYPE (token->value) = parser->qualifying_scope;
       token->keyword = RID_MAX;
+      
       /* Purge all subsequent tokens.  */
-      cp_lexer_purge_tokens_after (parser->lexer, token);
+      cp_lexer_purge_tokens_after (parser->lexer, start);
     }
 
   pop_deferring_access_checks ();
@@ -3520,10 +3697,7 @@ 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))
-           && (cp_parser_non_integral_constant_expression 
+           && (cp_parser_non_integral_constant_expression
                (parser,
                 "a cast to a type other than an integral or "
                 "enumeration type")))
@@ -3548,7 +3722,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
              = build_const_cast (type, expression);
            break;
          default:
-           abort ();
+           gcc_unreachable ();
          }
       }
       break;
@@ -3594,7 +3768,10 @@ 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;
       }
@@ -3637,7 +3814,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
        /* Create a TYPENAME_TYPE to represent the type to which the
           functional cast is being performed.  */
        else
-         type = make_typename_type (parser->scope, id, 
+         type = make_typename_type (parser->scope, id,
                                     /*complain=*/1);
 
        postfix_expression = cp_parser_functional_cast (parser, type);
@@ -3655,8 +3832,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
        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);
+                                               /*decl_specs=*/NULL,
+                                               CP_PARSER_FLAGS_NONE);
        /* Parse the cast itself.  */
        if (!cp_parser_error_occurred (parser))
          postfix_expression
@@ -3762,27 +3939,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
       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 (cp_parser_non_integral_constant_expression 
-               (parser, "an array reference"))
-             postfix_expression = error_mark_node;
-         }
+         postfix_expression
+           = cp_parser_postfix_open_square_expression (parser,
+                                                       postfix_expression,
+                                                       false);
+         idk = CP_ID_KIND_NONE;
          break;
 
        case CPP_OPEN_PAREN:
@@ -3810,20 +3971,38 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            koenig_p = false;
            if (idk == CP_ID_KIND_UNQUALIFIED)
              {
+               if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
+                 {
+                   if (args)
+                     {
+                       koenig_p = true;
+                       postfix_expression
+                         = perform_koenig_lookup (postfix_expression, args);
+                     }
+                   else
+                     postfix_expression
+                       = unqualified_fn_lookup_error (postfix_expression);
+                 }
                /* 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)
-                       || TREE_CODE (postfix_expression) == IDENTIFIER_NODE))
+               else if (args && is_overloaded_fn (postfix_expression))
                  {
-                   koenig_p = true;
-                   postfix_expression
-                     = perform_koenig_lookup (postfix_expression, args);
+                   tree fn = get_first_fn (postfix_expression);
+
+                   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+                     fn = OVL_CURRENT (TREE_OPERAND (fn, 0));
+
+                   /* Only do argument dependent lookup if regular
+                      lookup does not find a set of member functions.
+                      [basic.lookup.koenig]/2a  */
+                   if (!DECL_FUNCTION_MEMBER_P (fn))
+                     {
+                       koenig_p = true;
+                       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)
@@ -3839,7 +4018,8 @@ 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;
                  }
 
@@ -3885,172 +4065,242 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
             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;
-               /* 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;
-             }
 
-           /* 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;
-                 }
-               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;
+         /* Consume the `.' or `->' operator.  */
+         cp_lexer_consume_token (parser->lexer);
 
-               /* 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));
-             }
+         postfix_expression
+           = cp_parser_postfix_dot_deref_expression (parser, token->type,
+                                                     postfix_expression,
+                                                     false, &idk);
+         break;
+
+       case CPP_PLUS_PLUS:
+         /* postfix-expression ++  */
+         /* Consume the `++' token.  */
+         cp_lexer_consume_token (parser->lexer);
+         /* Generate a representation for the complete expression.  */
+         postfix_expression
+           = finish_increment_expr (postfix_expression,
+                                    POSTINCREMENT_EXPR);
+         /* Increments may not appear in constant-expressions.  */
+         if (cp_parser_non_integral_constant_expression (parser,
+                                                         "an increment"))
+           postfix_expression = error_mark_node;
+         idk = CP_ID_KIND_NONE;
+         break;
+
+       case CPP_MINUS_MINUS:
+         /* postfix-expression -- */
+         /* Consume the `--' token.  */
+         cp_lexer_consume_token (parser->lexer);
+         /* Generate a representation for the complete expression.  */
+         postfix_expression
+           = finish_increment_expr (postfix_expression,
+                                    POSTDECREMENT_EXPR);
+         /* Decrements may not appear in constant-expressions.  */
+         if (cp_parser_non_integral_constant_expression (parser,
+                                                         "a decrement"))
+           postfix_expression = error_mark_node;
+         idk = CP_ID_KIND_NONE;
+         break;
+
+       default:
+         return postfix_expression;
+       }
+    }
+
+  /* We should never get here.  */
+  gcc_unreachable ();
+  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 expressions 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;
+  bool pseudo_destructor_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;
+    }
+
+  /* Assume this expression is not a pseudo-destructor access.  */
+  pseudo_destructor_p = false;
+
+  /* If the SCOPE is a scalar type, then, if this is a valid program,
+     we must be looking at a pseudo-destructor-name.  */
+  if (scope && SCALAR_TYPE_P (scope))
+    {
+      tree s;
+      tree type;
+
+      cp_parser_parse_tentatively (parser);
+      /* Parse the pseudo-destructor-name.  */
+      s = NULL_TREE;
+      cp_parser_pseudo_destructor_name (parser, &s, &type);
+      if (cp_parser_parse_definitely (parser))
+       {
+         pseudo_destructor_p = true;
+         postfix_expression
+           = finish_pseudo_destructor_expr (postfix_expression,
+                                            s, TREE_TYPE (type));
+       }
+    }
+
+  if (!pseudo_destructor_p)
+    {
+      /* If the SCOPE is not a scalar type, we are looking at an
+        ordinary class member access expression, rather than a
+        pseudo-destructor-name.  */
+      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;
 
-           /* 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 (/* The "->" operator is allowed in the implementation
-                  of "offsetof".  The "." operator may appear in the
-                  name of the member.  */
-               !parser->in_offsetof_p
-               && (cp_parser_non_integral_constant_expression 
-                   (parser,
-                    token_type == CPP_DEREF ? "'->'" : "`.'")))
-             postfix_expression = error_mark_node;
-         }
-         break;
+             struct X { void f(); };
+             template <typename T> void f(T* t) { t->X::f(); }
 
-       case CPP_PLUS_PLUS:
-         /* postfix-expression ++  */
-         /* Consume the `++' token.  */
-         cp_lexer_consume_token (parser->lexer);
-         /* Generate a representation for the complete expression.  */
-         postfix_expression
-           = finish_increment_expr (postfix_expression,
-                                    POSTINCREMENT_EXPR);
-         /* Increments may not appear in constant-expressions.  */
-         if (cp_parser_non_integral_constant_expression (parser,
-                                                         "an increment"))
-           postfix_expression = error_mark_node;
-         idk = CP_ID_KIND_NONE;
-         break;
+        Even though "t" is dependent, "X::f" is not and has been resolved
+        to a BASELINK; there is no need to include scope information.  */
 
-       case CPP_MINUS_MINUS:
-         /* postfix-expression -- */
-         /* Consume the `--' token.  */
-         cp_lexer_consume_token (parser->lexer);
-         /* Generate a representation for the complete expression.  */
-         postfix_expression
-           = finish_increment_expr (postfix_expression,
-                                    POSTDECREMENT_EXPR);
-         /* Decrements may not appear in constant-expressions.  */
-         if (cp_parser_non_integral_constant_expression (parser,
-                                                         "a decrement"))
-           postfix_expression = error_mark_node;
-         idk = CP_ID_KIND_NONE;
-         break;
+      /* But we do need to remember that there was an explicit scope for
+        virtual function calls.  */
+      if (parser->scope)
+       *idk = CP_ID_KIND_QUALIFIED;
 
-       default:
-         return postfix_expression;
+      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);
     }
 
-  /* We should never get here.  */
-  abort ();
-  return error_mark_node;
+  /* 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.
@@ -4080,6 +4330,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                                         bool *non_constant_p)
 {
   tree expression_list = NULL_TREE;
+  bool fold_expr_p = is_attribute_list;
   tree identifier = NULL_TREE;
 
   /* Assume all the expressions will be constant.  */
@@ -4122,6 +4373,9 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
            else
              expr = cp_parser_assignment_expression (parser);
 
+           if (fold_expr_p)
+             expr = fold_non_dependent_expr (expr);
+
             /* Add it to the list.  We add error_mark_node
                expressions to the list, so that we can still tell if
                the correct form for a parenthesized expression-list
@@ -4189,6 +4443,9 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
 {
   bool nested_name_specifier_p;
 
+  /* Assume that things will not work out.  */
+  *type = error_mark_node;
+
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true);
   /* Look for the optional nested-name-specifier.  */
@@ -4221,17 +4478,18 @@ 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)
+      if (*scope == error_mark_node)
+       return;
+
+      /* If 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 (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;
        }
 
@@ -4414,10 +4672,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);
@@ -4435,10 +4690,10 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
 
-      if (non_constant_p 
+      if (non_constant_p
          && cp_parser_non_integral_constant_expression (parser,
                                                         non_constant_p))
        expression = error_mark_node;
@@ -4495,6 +4750,7 @@ cp_parser_new_expression (cp_parser* parser)
   tree placement;
   tree type;
   tree initializer;
+  tree nelts;
 
   /* Look for the optional `::' operator.  */
   global_scope_p
@@ -4522,7 +4778,7 @@ 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, 
+      /* 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))
@@ -4531,10 +4787,11 @@ cp_parser_new_expression (cp_parser* parser)
          inform ("try removing the parentheses around the type-id");
          cp_parser_direct_new_declarator (parser);
        }
+      nelts = NULL_TREE;
     }
   /* 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))
@@ -4548,7 +4805,7 @@ cp_parser_new_expression (cp_parser* parser)
     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.
@@ -4575,15 +4832,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
@@ -4593,13 +4854,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);
+
+  /* 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;
+    }
 
-  return build_tree_list (type_specifier_seq, 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.
@@ -4608,39 +4916,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;
     }
@@ -4649,7 +4952,7 @@ 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.
@@ -4658,13 +4961,12 @@ cp_parser_new_declarator_opt (cp_parser* parser)
      [ 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)
     {
@@ -4690,7 +4992,8 @@ cp_parser_direct_new_declarator (cp_parser* parser)
                                              /*complain=*/true);
              if (!expression)
                {
-                 error ("expression in new-declarator must have integral or enumeration type");
+                 error ("expression in new-declarator must have integral "
+                         "or enumeration type");
                  expression = error_mark_node;
                }
            }
@@ -4705,7 +5008,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       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.  */
@@ -4878,7 +5181,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
          if (parser->integral_constant_expression_p
              && !dependent_type_p (type)
              && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
-             && (cp_parser_non_integral_constant_expression 
+             && (cp_parser_non_integral_constant_expression
                  (parser,
                   "a cast to a type other than an integral or "
                   "enumeration type")))
@@ -4895,101 +5198,29 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
   return cp_parser_unary_expression (parser, address_p);
 }
 
-/* Parse a pm-expression.
+/* Parse a binary expression of the general form:
 
    pm-expression:
      cast-expression
      pm-expression .* cast-expression
      pm-expression ->* cast-expression
 
-     Returns a representation of the expression.  */
-
-static tree
-cp_parser_pm_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_DEREF_STAR, MEMBER_REF },
-    { CPP_DOT_STAR, DOTSTAR_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
-
-  return cp_parser_binary_expression (parser, map,
-                                     cp_parser_simple_cast_expression);
-}
-
-/* Parse a multiplicative-expression.
-
    multiplicative-expression:
      pm-expression
      multiplicative-expression * pm-expression
      multiplicative-expression / pm-expression
      multiplicative-expression % pm-expression
 
-   Returns a representation of the expression.  */
-
-static tree
-cp_parser_multiplicative_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_MULT, MULT_EXPR },
-    { CPP_DIV, TRUNC_DIV_EXPR },
-    { CPP_MOD, TRUNC_MOD_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
-
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_pm_expression);
-}
-
-/* Parse an additive-expression.
-
    additive-expression:
      multiplicative-expression
      additive-expression + multiplicative-expression
      additive-expression - multiplicative-expression
 
-   Returns a representation of the expression.  */
-
-static tree
-cp_parser_additive_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_PLUS, PLUS_EXPR },
-    { CPP_MINUS, MINUS_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
-
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_multiplicative_expression);
-}
-
-/* Parse a shift-expression.
-
    shift-expression:
      additive-expression
      shift-expression << additive-expression
      shift-expression >> additive-expression
 
-   Returns a representation of the expression.  */
-
-static tree
-cp_parser_shift_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_LSHIFT, LSHIFT_EXPR },
-    { CPP_RSHIFT, RSHIFT_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
-
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_additive_expression);
-}
-
-/* Parse a relational-expression.
-
    relational-expression:
      shift-expression
      relational-expression < shift-expression
@@ -4997,161 +5228,150 @@ cp_parser_shift_expression (cp_parser* parser)
      relational-expression <= shift-expression
      relational-expression >= shift-expression
 
-   GNU Extension:
-
+  GNU Extension:
+  
    relational-expression:
      relational-expression <? shift-expression
      relational-expression >? shift-expression
 
-   Returns a representation of the expression.  */
-
-static tree
-cp_parser_relational_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_LESS, LT_EXPR },
-    { CPP_GREATER, GT_EXPR },
-    { CPP_LESS_EQ, LE_EXPR },
-    { CPP_GREATER_EQ, GE_EXPR },
-    { CPP_MIN, MIN_EXPR },
-    { CPP_MAX, MAX_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
-
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_shift_expression);
-}
-
-/* Parse an equality-expression.
-
    equality-expression:
      relational-expression
      equality-expression == relational-expression
      equality-expression != relational-expression
 
-   Returns a representation of the expression.  */
-
-static tree
-cp_parser_equality_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_EQ_EQ, EQ_EXPR },
-    { CPP_NOT_EQ, NE_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
-
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_relational_expression);
-}
-
-/* Parse an and-expression.
-
    and-expression:
      equality-expression
      and-expression & equality-expression
 
-   Returns a representation of the expression.  */
-
-static tree
-cp_parser_and_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_AND, BIT_AND_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
-
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_equality_expression);
-}
-
-/* Parse an exclusive-or-expression.
-
    exclusive-or-expression:
      and-expression
      exclusive-or-expression ^ and-expression
 
-   Returns a representation of the expression.  */
+   inclusive-or-expression:
+     exclusive-or-expression
+     inclusive-or-expression | exclusive-or-expression
 
-static tree
-cp_parser_exclusive_or_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_XOR, BIT_XOR_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
+   logical-and-expression:
+     inclusive-or-expression
+     logical-and-expression && inclusive-or-expression
 
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_and_expression);
-}
+   logical-or-expression:
+     logical-and-expression
+     logical-or-expression || logical-and-expression
 
+   All these are implemented with a single function like:
 
-/* Parse an inclusive-or-expression.
+   binary-expression:
+     simple-cast-expression
+     binary-expression <token> binary-expression
 
-   inclusive-or-expression:
-     exclusive-or-expression
-     inclusive-or-expression | exclusive-or-expression
+   The binops_by_token map is used to get the tree codes for each <token> type.
+   binary-expressions are associated according to a precedence table.  */
 
-   Returns a representation of the expression.  */
+#define TOKEN_PRECEDENCE(token) \
+  ((token->type == CPP_GREATER && !parser->greater_than_is_operator_p) \
+   ? PREC_NOT_OPERATOR \
+   : binops_by_token[token->type].prec)
 
 static tree
-cp_parser_inclusive_or_expression (cp_parser* parser)
+cp_parser_binary_expression (cp_parser* parser)
 {
-  static const cp_parser_token_tree_map map = {
-    { CPP_OR, BIT_IOR_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
-
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_exclusive_or_expression);
-}
+  cp_parser_expression_stack stack;
+  cp_parser_expression_stack_entry *sp = &stack[0];
+  tree lhs, rhs;
+  cp_token *token;
+  enum tree_code tree_type;
+  enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
+  bool overloaded_p;
 
-/* Parse a logical-and-expression.
+  /* Parse the first expression.  */
+  lhs = cp_parser_simple_cast_expression (parser);
 
-   logical-and-expression:
-     inclusive-or-expression
-     logical-and-expression && inclusive-or-expression
+  for (;;)
+    {
+      /* Get an operator token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      new_prec = TOKEN_PRECEDENCE (token);
+
+      /* Popping an entry off the stack means we completed a subexpression:
+         - either we found a token which is not an operator (`>' where it is not
+           an operator, or prec == PREC_NOT_OPERATOR), in which case popping
+           will happen repeatedly;
+         - or, we found an operator which has lower priority.  This is the case 
+           where the recursive descent *ascends*, as in `3 * 4 + 5' after
+           parsing `3 * 4'.  */
+      if (new_prec <= prec)
+        {
+          if (sp == stack)
+           break;
+          else
+           goto pop;
+        }
 
-   Returns a representation of the expression.  */
+     get_rhs:
+      tree_type = binops_by_token[token->type].tree_type;
 
-static tree
-cp_parser_logical_and_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_AND_AND, TRUTH_ANDIF_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
+      /* We used the operator token.  */
+      cp_lexer_consume_token (parser->lexer);
 
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_inclusive_or_expression);
-}
+      /* Extract another operand.  It may be the RHS of this expression
+         or the LHS of a new, higher priority expression.  */
+      rhs = cp_parser_simple_cast_expression (parser);
 
-/* Parse a logical-or-expression.
+      /* Get another operator token.  Look up its precedence to avoid
+         building a useless (immediately popped) stack entry for common
+         cases such as 3 + 4 + 5 or 3 * 4 + 5.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      lookahead_prec = TOKEN_PRECEDENCE (token);
+      if (lookahead_prec > new_prec)
+        {
+          /* ... and prepare to parse the RHS of the new, higher priority
+             expression.  Since precedence levels on the stack are
+            monotonically increasing, we do not have to care about
+            stack overflows.  */
+          sp->prec = prec;
+          sp->tree_type = tree_type;
+          sp->lhs = lhs;
+          sp++;
+          lhs = rhs;
+          prec = new_prec;
+          new_prec = lookahead_prec;
+          goto get_rhs;
+
+         pop:
+          /* If the stack is not empty, we have parsed into LHS the right side
+            (`4' in the example above) of an expression we had suspended.
+            We can use the information on the stack to recover the LHS (`3') 
+            from the stack together with the tree code (`MULT_EXPR'), and
+            the precedence of the higher level subexpression
+            (`PREC_ADDITIVE_EXPRESSION').  TOKEN is the CPP_PLUS token,
+            which will be used to actually build the additive expression.  */
+          --sp;
+         prec = sp->prec;
+          tree_type = sp->tree_type;
+          rhs = lhs;
+          lhs = sp->lhs;
+        }
 
-   logical-or-expression:
-     logical-and-expression
-     logical-or-expression || logical-and-expression
+      overloaded_p = false;
+      lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p);
 
-   Returns a representation of the expression.  */
+      /* 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.  */
 
-static tree
-cp_parser_logical_or_expression (cp_parser* parser)
-{
-  static const cp_parser_token_tree_map map = {
-    { CPP_OR_OR, TRUTH_ORIF_EXPR },
-    { CPP_EOF, ERROR_MARK }
-  };
+      if (overloaded_p
+          && (cp_parser_non_integral_constant_expression 
+              (parser, "calls to overloaded operators")))
+        return error_mark_node;
+    }
 
-  return cp_parser_binary_expression (parser,
-                                     map,
-                                     cp_parser_logical_and_expression);
+  return lhs;
 }
 
+
 /* Parse the `? expression : assignment-expression' part of a
    conditional-expression.  The LOGICAL_OR_EXPR is the
    logical-or-expression that started the conditional-expression.
@@ -5214,8 +5434,8 @@ cp_parser_assignment_expression (cp_parser* parser)
      logical-or-expression.  */
   else
     {
-      /* Parse the logical-or-expression.  */
-      expr = cp_parser_logical_or_expression (parser);
+      /* Parse the binary expressions (logical-or-expression).  */
+      expr = cp_parser_binary_expression (parser);
       /* If the next token is a `?' then we're actually looking at a
         conditional-expression.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
@@ -5451,6 +5671,92 @@ 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:
+  /* If we're processing a template, we can't finish the semantics yet.
+     Otherwise we can fold the entire expression now.  */
+  if (processing_template_decl)
+    expr = build1 (OFFSETOF_EXPR, size_type_node, expr);
+  else
+    expr = fold_offsetof (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.
@@ -5466,18 +5772,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)
@@ -5489,7 +5795,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:
@@ -5526,11 +5832,18 @@ 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);
+  /* CPP_PRAGMA is a #pragma inside a function body, which constitutes
+     a statement all its own.  */
+  else if (token->type == CPP_PRAGMA)
+    {
+      cp_lexer_handle_pragma (parser->lexer);
+      return;
+    }
 
   /* Everything else must be a declaration-statement or an
      expression-statement.  Try for the declaration-statement
@@ -5548,12 +5861,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.
@@ -5568,11 +5881,11 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
    labeled-statement:
      case constant-expression ... constant-expression : statement
 
-   Returns the new CASE_LABEL, for a `case' or `default' label.  For
-   an ordinary label, returns a LABEL_STMT.  */
+   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;
@@ -5616,7 +5929,7 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
          expr_hi = NULL_TREE;
 
        if (!parser->in_switch_statement_p)
-         error ("case label `%E' not within a switch statement", expr);
+         error ("case label %qE not within a switch statement", expr);
        else
          statement = finish_case_label (expr, expr_hi);
       }
@@ -5640,7 +5953,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;
@@ -5657,7 +5970,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;
 
@@ -5669,12 +5982,12 @@ cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p)
   /* 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);
@@ -5689,10 +6002,11 @@ 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;
 
@@ -5700,9 +6014,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 `}'.  */
@@ -5718,7 +6032,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)
@@ -5729,7 +6043,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);
     }
 }
 
@@ -5783,35 +6097,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.  */
@@ -5820,7 +6129,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.  */
@@ -5854,7 +6163,7 @@ cp_parser_selection_statement (cp_parser* parser)
 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.  */
@@ -5865,7 +6174,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.  */
@@ -5874,13 +6183,14 @@ 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,
-                                        /*parenthesized_p=*/NULL);
+                                        /*parenthesized_p=*/NULL,
+                                        /*member_p=*/false);
       /* Parse the attributes.  */
       attributes = cp_parser_attributes_opt (parser);
       /* Parse the asm-specification.  */
@@ -5897,10 +6207,13 @@ cp_parser_condition (cp_parser* parser)
         for sure.  */
       if (cp_parser_parse_definitely (parser))
        {
+         bool pop_p;   
+
          /* Create the declaration.  */
-         decl = start_decl (declarator, type_specifiers,
+         decl = start_decl (declarator, &type_specifiers,
                             /*initialized_p=*/true,
-                            attributes, /*prefix_attributes=*/NULL_TREE);
+                            attributes, /*prefix_attributes=*/NULL_TREE,
+                            &pop_p);
          /* Parse the assignment-expression.  */
          initializer = cp_parser_assignment_expression (parser);
 
@@ -5910,6 +6223,9 @@ cp_parser_condition (cp_parser* parser)
                          asm_specification,
                          LOOKUP_ONLYCONVERTING);
 
+         if (pop_p)
+           pop_scope (DECL_CONTEXT (decl));
+
          return convert_from_reference (decl);
        }
     }
@@ -6027,7 +6343,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;
@@ -6093,8 +6409,7 @@ cp_parser_for_init_statement (cp_parser* parser)
    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)
@@ -6121,7 +6436,7 @@ cp_parser_jump_statement (cp_parser* parser)
        }
       else
        statement = finish_break_stmt ();
-      cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       break;
 
     case RID_CONTINUE:
@@ -6132,7 +6447,7 @@ cp_parser_jump_statement (cp_parser* parser)
        }
       else
        statement = finish_continue_stmt ();
-      cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       break;
 
     case RID_RETURN:
@@ -6148,7 +6463,7 @@ cp_parser_jump_statement (cp_parser* parser)
        /* Build the return-statement.  */
        statement = finish_return_stmt (expr);
        /* Look for the final `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       }
       break;
 
@@ -6167,7 +6482,7 @@ cp_parser_jump_statement (cp_parser* parser)
       else
        finish_goto_stmt (cp_parser_identifier (parser));
       /* Look for the final `;'.  */
-      cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       break;
 
     default:
@@ -6186,9 +6501,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 ();
 }
@@ -6213,7 +6536,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.  */
@@ -6221,7 +6544,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;
@@ -6235,21 +6558,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] */
@@ -6277,23 +6596,33 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
        {
          /* A declaration consisting of a single semicolon is
             invalid.  Allow it unless we're being pedantic.  */
-         if (pedantic && !in_system_header)
-           pedwarn ("extra `;'");
          cp_lexer_consume_token (parser->lexer);
+         if (pedantic && !in_system_header)
+           pedwarn ("extra %<;%>");
          continue;
        }
 
-      /* The C lexer modifies PENDING_LANG_CHANGE when it wants the
-        parser to enter or exit implicit `extern "C"' blocks.  */
-      while (pending_lang_change > 0)
+      /* If we're entering or exiting a region that's implicitly
+        extern "C", modify the lang context appropriately.  */
+      if (!parser->implicit_extern_c && token->implicit_extern_c)
        {
          push_lang_context (lang_name_c);
-         --pending_lang_change;
+         parser->implicit_extern_c = true;
        }
-      while (pending_lang_change < 0)
+      else if (parser->implicit_extern_c && !token->implicit_extern_c)
+       {
+         pop_lang_context ();
+         parser->implicit_extern_c = false;
+       }
+
+      if (token->type == CPP_PRAGMA)
        {
-         pop_lang_context ();
-         ++pending_lang_change;
+         /* A top-level declaration can consist solely of a #pragma.
+            A nested declaration cannot, so this is done here and not
+            in cp_parser_declaration.  (A #pragma at block scope is
+            handled in cp_parser_statement.)  */
+         cp_lexer_handle_pragma (parser->lexer);
+         continue;
        }
 
       /* Parse the declaration itself.  */
@@ -6323,10 +6652,7 @@ cp_parser_declaration (cp_parser* parser)
   cp_token token1;
   cp_token token2;
   int saved_pedantic;
-
-  /* Set this here since we can be called after
-     pushing the linkage specification.  */
-  c_lex_string_translate = true;
+  void *p;
 
   /* Check for the `__extension__' keyword.  */
   if (cp_parser_extension_opt (parser, &saved_pedantic))
@@ -6342,13 +6668,12 @@ 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 = false;
-
   if (token1.type != CPP_EOF)
     token2 = *cp_lexer_peek_nth_token (parser->lexer, 2);
 
+  /* 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
@@ -6399,7 +6724,8 @@ cp_parser_declaration (cp_parser* parser)
     /* Try to parse a block-declaration, or a function-definition.  */
     cp_parser_block_declaration (parser, /*statement_p=*/false);
 
-  c_lex_string_translate = true;
+  /* Free any declarators allocated.  */
+  obstack_free (&declarator_obstack, p);
 }
 
 /* Parse a block-declaration.
@@ -6498,8 +6824,7 @@ static void
 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;
 
@@ -6519,18 +6844,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;
@@ -6542,7 +6867,8 @@ cp_parser_simple_declaration (cp_parser* parser,
        T t;
 
      where "T" should name a type -- but does not.  */
-  if (cp_parser_parse_and_diagnose_invalid_type_name (parser))
+  if (!decl_specifiers.type
+      && cp_parser_parse_and_diagnose_invalid_type_name (parser))
     {
       /* If parsing tentatively, we should commit; we really are
         looking at a declaration.  */
@@ -6550,6 +6876,13 @@ cp_parser_simple_declaration (cp_parser* parser,
       /* Give up.  */
       goto done;
     }
+  
+  /* If we have seen at least one decl-specifier, and the next token
+     is not a parenthesis, then we must be looking at a declaration.
+     (After "int (" we might be looking at a functional cast.)  */
+  if (decl_specifiers.any_specifiers_p 
+      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
+    cp_parser_commit_to_tentative_parse (parser);
 
   /* Keep going until we hit the `;' at the end of the simple
      declaration.  */
@@ -6563,7 +6896,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,
@@ -6603,7 +6936,12 @@ cp_parser_simple_declaration (cp_parser* parser,
       /* Anything else is an error.  */
       else
        {
-         cp_parser_error (parser, "expected `,' or `;'");
+         /* If we have already issued an error message we don't need
+            to issue another one.  */
+         if (decl != error_mark_node
+             || (cp_parser_parsing_tentatively (parser)
+                 && !cp_parser_committed_to_tentative_parse (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.  */
@@ -6626,7 +6964,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 ();
     }
@@ -6652,23 +6990,12 @@ cp_parser_simple_declaration (cp_parser* parser,
 
    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.
+   The parser flags FLAGS is used to control type-specifier parsing.
 
    *DECLARES_CLASS_OR_ENUM is set to the bitwise or of the following
    flags:
@@ -6680,27 +7007,25 @@ cp_parser_simple_declaration (cp_parser* parser,
 
    */
 
-static tree
+static void
 cp_parser_decl_specifier_seq (cp_parser* parser,
-                              cp_parser_flags flags,
-                              tree* attributes,
+                             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.  */
@@ -6709,25 +7034,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)
-           error ("duplicate `friend'");
-         else
-           friend_p = true;
-         /* The representation of the specifier is simply the
-            appropriate TREE_IDENTIFIER node.  */
-         decl_spec = token->value;
+       case RID_FRIEND:
+         if (decl_specs->specs[(int) ds_friend]++)
+           error ("duplicate %<friend%>");
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
          break;
@@ -6739,15 +7061,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.  */
@@ -6767,35 +7087,71 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
              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);
@@ -6838,44 +7194,31 @@ 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.
@@ -6920,22 +7263,36 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
      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.
@@ -6947,37 +7304,26 @@ cp_parser_function_specifier_opt (cp_parser* parser)
 static void
 cp_parser_linkage_specification (cp_parser* parser)
 {
-  cp_token *token;
   tree linkage;
 
   /* Look for the `extern' keyword.  */
   cp_parser_require_keyword (parser, RID_EXTERN, "`extern'");
 
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  /* If it's not a string-literal, then there's a problem.  */
-  if (!cp_parser_is_string_literal (token))
-    {
-      cp_parser_error (parser, "expected language-name");
-      return;
-    }
-  /* Consume the token.  */
-  cp_lexer_consume_token (parser->lexer);
+  /* Look for the string-literal.  */
+  linkage = cp_parser_string_literal (parser, false, false);
 
   /* Transform the literal into an identifier.  If the literal is a
      wide-character string, or contains embedded NULs, then we can't
      handle it as the user wants.  */
-  if (token->type == CPP_WSTRING
-      || (strlen (TREE_STRING_POINTER (token->value))
-         != (size_t) (TREE_STRING_LENGTH (token->value) - 1)))
+  if (strlen (TREE_STRING_POINTER (linkage))
+      != (size_t) (TREE_STRING_LENGTH (linkage) - 1))
     {
       cp_parser_error (parser, "invalid linkage-specification");
       /* Assume C++ linkage.  */
-      linkage = get_identifier ("c++");
+      linkage = lang_name_cplusplus;
     }
-  /* If it's a simple string constant, things are easier.  */
   else
-    linkage = get_identifier (TREE_STRING_POINTER (token->value));
+    linkage = get_identifier (TREE_STRING_POINTER (linkage));
 
   /* We're now using the new linkage.  */
   push_lang_context (linkage);
@@ -7080,21 +7426,25 @@ 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;
+  tree type_specified;
 
   /* 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,
-                        /*initialized=*/0, &attributes);
+  type_specified =  grokdeclarator (declarator, &type_specifiers, TYPENAME,
+                                   /*initialized=*/0, &attributes);
+  if (attributes)
+    cplus_decl_attributes (&type_specified, attributes, /*flags=*/0);
+  return type_specified;
 }
 
 /* Parse an (optional) conversion-declarator.
@@ -7102,45 +7452,40 @@ cp_parser_conversion_type_id (cp_parser* parser)
    conversion-declarator:
      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.
@@ -7272,8 +7617,16 @@ cp_parser_mem_initializer_id (cp_parser* parser)
 {
   bool global_scope_p;
   bool nested_name_specifier_p;
+  bool template_p = false;
   tree id;
 
+  /* `typename' is not allowed in this context ([temp.res]).  */
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
+    {
+      error ("keyword %<typename%> not allowed in this context (a qualified "
+            "member initializer is implicitly a type)");
+      cp_lexer_consume_token (parser->lexer);
+    }
   /* Look for the optional `::' operator.  */
   global_scope_p
     = (cp_parser_global_scope_opt (parser,
@@ -7298,12 +7651,14 @@ cp_parser_mem_initializer_id (cp_parser* parser)
                                            /*type_p=*/true,
                                            /*is_declaration=*/true)
        != NULL_TREE);
+  if (nested_name_specifier_p)
+    template_p = cp_parser_optional_template_keyword (parser);
   /* If there is a `::' operator or a nested-name-specifier, then we
      are definitely looking for a class-name.  */
   if (global_scope_p || nested_name_specifier_p)
     return cp_parser_class_name (parser,
                                 /*typename_keyword_p=*/true,
-                                /*template_keyword_p=*/false,
+                                /*template_keyword_p=*/template_p,
                                 /*type_p=*/false,
                                 /*check_dependency_p=*/true,
                                 /*class_head_p=*/false,
@@ -7630,7 +7985,7 @@ cp_parser_template_declaration (cp_parser* parser, bool member_p)
       /* Consume the `export' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Warn that we do not support `export'.  */
-      warning ("keyword `export' not implemented, and will be ignored");
+      warning ("keyword %<export%> not implemented, and will be ignored");
     }
 
   cp_parser_template_declaration_after_export (parser, member_p);
@@ -7654,13 +8009,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.  */
@@ -7680,13 +8036,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.  */
@@ -7728,9 +8088,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.
@@ -7819,9 +8186,15 @@ cp_parser_type_parameter (cp_parser* parser)
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
            && cp_lexer_next_token_is_not (parser->lexer, CPP_GREATER)
            && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
-         identifier = cp_parser_identifier (parser);
+         {
+           identifier = cp_parser_identifier (parser);
+           /* Treat invalid names as if the parameter were nameless.  */
+           if (identifier == error_mark_node)
+             identifier = NULL_TREE;
+         }
        else
          identifier = NULL_TREE;
+
        /* Create the template parameter.  */
        parameter = finish_template_template_parm (class_type_node,
                                                   identifier);
@@ -7853,7 +8226,8 @@ cp_parser_type_parameter (cp_parser* parser)
                                        /*is_type=*/false,
                                        /*is_template=*/is_template,
                                        /*is_namespace=*/false,
-                                       /*check_dependency=*/true);
+                                       /*check_dependency=*/true,
+                                       /*ambiguous_p=*/NULL);
            /* See if the default argument is valid.  */
            default_argument
              = check_template_template_default_arg (default_argument);
@@ -7863,15 +8237,13 @@ cp_parser_type_parameter (cp_parser* parser)
 
        /* Create the combined representation of the parameter and the
           default argument.  */
-       parameter =  build_tree_list (default_argument, parameter);
+       parameter = build_tree_list (default_argument, parameter);
       }
       break;
 
     default:
-      /* Anything else is an error.  */
-      cp_parser_error (parser,
-                      "expected `class', `typename', or `template'");
-      parameter = error_mark_node;
+      gcc_unreachable ();
+      break;
     }
 
   return parameter;
@@ -7900,7 +8272,7 @@ cp_parser_template_id (cp_parser *parser,
   tree template;
   tree arguments;
   tree template_id;
-  ptrdiff_t start_of_id;
+  cp_token_position start_of_id = 0;
   tree access_check = NULL_TREE;
   cp_token *next_token, *next_token_2;
   bool is_identifier;
@@ -7937,14 +8309,7 @@ cp_parser_template_id (cp_parser *parser,
   /* Remember where the template-id starts.  */
   if (cp_parser_parsing_tentatively (parser)
       && !cp_parser_committed_to_tentative_parse (parser))
-    {
-      next_token = cp_lexer_peek_token (parser->lexer);
-      start_of_id = cp_lexer_token_difference (parser->lexer,
-                                              parser->lexer->first_token,
-                                              next_token);
-    }
-  else
-    start_of_id = -1;
+    start_of_id = cp_lexer_token_position (parser->lexer, false);
 
   push_deferring_access_checks (dk_deferred);
 
@@ -7963,7 +8328,7 @@ cp_parser_template_id (cp_parser *parser,
   /* 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 = cp_lexer_peek_token (parser->lexer);
   next_token_2 = cp_lexer_peek_nth_token (parser->lexer, 2);
   if (next_token->type == CPP_OPEN_SQUARE
       && next_token->flags & DIGRAPH
@@ -7984,21 +8349,21 @@ cp_parser_template_id (cp_parser *parser,
             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 `<'");
+         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 `::'");
+      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)");
+             inform ("(if you use -fpermissive G++ will accept your code)");
              hint = true;
            }
        }
@@ -8028,10 +8393,9 @@ cp_parser_template_id (cp_parser *parser,
     {
       /* If it's not a class-template or a template-template, it should be
         a function-template.  */
-      my_friendly_assert ((DECL_FUNCTION_TEMPLATE_P (template)
-                          || TREE_CODE (template) == OVERLOAD
-                          || BASELINK_P (template)),
-                         20010716);
+      gcc_assert ((DECL_FUNCTION_TEMPLATE_P (template)
+                  || TREE_CODE (template) == OVERLOAD
+                  || BASELINK_P (template)));
 
       template_id = lookup_template_function (template, arguments);
     }
@@ -8046,22 +8410,17 @@ cp_parser_template_id (cp_parser *parser,
      the effort required to do the parse, nor will we issue duplicate
      error messages about problems during instantiation of the
      template.  */
-  if (start_of_id >= 0)
+  if (start_of_id)
     {
-      cp_token *token;
-
-      /* Find the token that corresponds to the start of the
-        template-id.  */
-      token = cp_lexer_advance_token (parser->lexer,
-                                     parser->lexer->first_token,
-                                     start_of_id);
-
+      cp_token *token = cp_lexer_token_at (parser->lexer, start_of_id);
+      
       /* Reset the contents of the START_OF_ID token.  */
       token->type = CPP_TEMPLATE_ID;
       token->value = build_tree_list (access_check, template_id);
       token->keyword = RID_MAX;
+      
       /* Purge all subsequent tokens.  */
-      cp_lexer_purge_tokens_after (parser->lexer, token);
+      cp_lexer_purge_tokens_after (parser->lexer, start_of_id);
     }
 
   pop_deferring_access_checks ();
@@ -8165,28 +8524,26 @@ cp_parser_template_name (cp_parser* parser,
       if (is_declaration
          && !template_keyword_p
          && parser->scope && TYPE_P (parser->scope)
-         && dependent_type_p (parser->scope))
+         && check_dependency_p
+         && 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;
+         cp_token_position start = 0;
+         
          /* 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);
+         error ("non-template %qD used as template", 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)
              && !cp_parser_committed_to_tentative_parse (parser))
            {
              cp_parser_simulate_error (parser);
-             token = cp_lexer_peek_token (parser->lexer);
-             token = cp_lexer_prev_token (parser->lexer, token);
-             start = cp_lexer_token_difference (parser->lexer,
-                                                parser->lexer->first_token,
-                                                token);
+             start = cp_lexer_token_position (parser->lexer, true);
            }
-         else
-           start = -1;
          /* Parse the template arguments so that we can issue error
             messages about them.  */
          cp_lexer_consume_token (parser->lexer);
@@ -8201,13 +8558,8 @@ cp_parser_template_name (cp_parser* parser,
             template argument list.  That will prevent duplicate
             error messages from being issued about the missing
             "template" keyword.  */
-         if (start >= 0)
-           {
-             token = cp_lexer_advance_token (parser->lexer,
-                                             parser->lexer->first_token,
-                                             start);
-             cp_lexer_purge_tokens_after (parser->lexer, token);
-           }
+         if (start)
+           cp_lexer_purge_tokens_after (parser->lexer, start);
          if (is_identifier)
            *is_identifier = true;
          return identifier;
@@ -8219,7 +8571,7 @@ cp_parser_template_name (cp_parser* parser,
         (and must) do name-lookup normally.  */
       if (template_keyword_p
          && (!parser->scope
-             || (TYPE_P (parser->scope) 
+             || (TYPE_P (parser->scope)
                  && dependent_type_p (parser->scope))))
        return identifier;
     }
@@ -8229,7 +8581,8 @@ cp_parser_template_name (cp_parser* parser,
                                /*is_type=*/false,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
-                               check_dependency_p);
+                               check_dependency_p,
+                               /*ambiguous_p=*/NULL);
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
@@ -8410,12 +8763,17 @@ 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,
+                                         /*ambiguous_p=*/NULL);
       if (TREE_CODE (argument) != TEMPLATE_DECL
          && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
        cp_parser_error (parser, "expected template-name");
@@ -8560,8 +8918,7 @@ 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
@@ -8571,7 +8928,9 @@ cp_parser_explicit_instantiation (cp_parser* parser)
       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.  */
@@ -8583,11 +8942,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.  */
@@ -8595,7 +8953,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 ();
@@ -8604,19 +8962,20 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     }
   else
     {
-      tree declarator;
+      cp_declarator *declarator;
       tree decl;
 
       /* Parse the declarator.  */
       declarator
        = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                                /*ctor_dtor_or_conv_p=*/NULL,
-                               /*parenthesized_p=*/NULL);
+                               /*parenthesized_p=*/NULL,
+                               /*member_p=*/false);
       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.  */
@@ -8701,15 +9060,14 @@ 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.
+
+   The parser flags FLAGS is used to control type-specifier parsing.
 
-   If IS_FRIEND is TRUE then this type-specifier is being declared a
-   `friend'.  If IS_DECLARATION is TRUE, then this type-specifier is
-   appearing in a decl-specifier-seq.
+   If IS_DECLARATION is TRUE, then this type-specifier is appearing
+   in a decl-specifier-seq.
 
    If DECLARES_CLASS_OR_ENUM is non-NULL, and the type-specifier is a
    class-specifier, enum-specifier, or elaborated-type-specifier, then
@@ -8724,7 +9082,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
 static tree
 cp_parser_type_specifier (cp_parser* parser,
                          cp_parser_flags flags,
-                         bool is_friend,
+                         cp_decl_specifier_seq *decl_specs,
                          bool is_declaration,
                          int* declares_class_or_enum,
                          bool* is_cv_qualifier)
@@ -8732,6 +9090,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)
@@ -8747,67 +9106,111 @@ cp_parser_type_specifier (cp_parser* parser,
   keyword = token->keyword;
   switch (keyword)
     {
+    case RID_ENUM:
+      /* 'enum' [identifier] '{' introduces an enum-specifier;
+        'enum' <anything else> introduces an elaborated-type-specifier.  */
+      if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE
+         || (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME
+             && cp_lexer_peek_nth_token (parser->lexer, 3)->type
+                == CPP_OPEN_BRACE))
+       {
+         type_spec = cp_parser_enum_specifier (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;
+       }
+      else
+       goto elaborated_type_specifier;
+
       /* Any of these indicate either a class-specifier, or an
         elaborated-type-specifier.  */
     case RID_CLASS:
     case RID_STRUCT:
     case RID_UNION:
-    case RID_ENUM:
       /* Parse tentatively so that we can back up if we don't find a
-        class-specifier or enum-specifier.  */
+        class-specifier.  */
       cp_parser_parse_tentatively (parser);
-      /* Look for the class-specifier or enum-specifier.  */
-      if (keyword == RID_ENUM)
-       type_spec = cp_parser_enum_specifier (parser);
-      else
-       type_spec = cp_parser_class_specifier (parser);
-
+      /* Look for the class-specifier.  */
+      type_spec = cp_parser_class_specifier (parser);
       /* If that worked, we're done.  */
       if (cp_parser_parse_definitely (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;
        }
 
       /* Fall through.  */
+    elaborated_type_specifier:
+      /* We're declaring (not defining) a class or enum.  */
+      if (declares_class_or_enum)
+       *declares_class_or_enum = 1;
 
+      /* Fall through.  */
     case RID_TYPENAME:
       /* Look for an elaborated-type-specifier.  */
-      type_spec = cp_parser_elaborated_type_specifier (parser,
-                                                      is_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;
+      type_spec
+       = (cp_parser_elaborated_type_specifier
+          (parser,
+           decl_specs && decl_specs->specs[(int) ds_friend],
+           is_declaration));
+      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.  */
@@ -8843,14 +9246,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;
@@ -8862,6 +9264,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:
@@ -8871,18 +9275,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:
@@ -8896,19 +9310,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;
@@ -8919,6 +9333,18 @@ 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;
 
@@ -8927,26 +9353,33 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
         that the type was a template.  */
       cp_parser_check_for_invalid_template_id (parser, type);
 
-      return identifier_p ? id : TYPE_NAME (type);
+      return TYPE_NAME (type);
     }
 
   /* The type-specifier must be a user-defined type.  */
   if (!(flags & CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES))
     {
+      bool qualified_p;
+      bool global_p;
+
       /* Don't gobble tokens or issue error messages if this is an
         optional type-specifier.  */
       if (flags & CP_PARSER_FLAGS_OPTIONAL)
        cp_parser_parse_tentatively (parser);
 
       /* Look for the optional `::' operator.  */
-      cp_parser_global_scope_opt (parser,
-                                 /*current_scope_valid_p=*/false);
+      global_p
+       = (cp_parser_global_scope_opt (parser,
+                                      /*current_scope_valid_p=*/false)
+          != NULL_TREE);
       /* 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
@@ -8968,10 +9401,20 @@ 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
+         && !global_p
+         && !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)
          && !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.  */
@@ -9108,7 +9551,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       tag_type = typename_type;
       /* The `typename' keyword is only allowed in templates.  */
       if (!processing_template_decl)
-       pedwarn ("using `typename' outside of template");
+       pedwarn ("using %<typename%> outside of template");
     }
   /* Otherwise it must be a class-key.  */
   else
@@ -9201,7 +9644,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
                                        /*is_type=*/true,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
-                                       /*check_dependency=*/true);
+                                       /*check_dependency=*/true,
+                                       /*ambiguous_p=*/NULL);
 
          /* If we are parsing friend declaration, DECL may be a
             TEMPLATE_DECL tree node here.  However, we need to check
@@ -9314,47 +9758,56 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
    enum-specifier:
      enum identifier [opt] { enumerator-list [opt] }
 
+   GNU Extensions:
+     enum identifier [opt] { enumerator-list [opt] } attributes
+
    Returns an ENUM_TYPE representing the enumeration.  */
 
 static tree
 cp_parser_enum_specifier (cp_parser* parser)
 {
-  cp_token *token;
-  tree identifier = NULL_TREE;
+  tree identifier;
   tree type;
 
-  /* Look for the `enum' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_ENUM, "`enum'"))
-    return error_mark_node;
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
+  /* Caller guarantees that the current token is 'enum', an identifier
+     possibly follows, and the token after that is an opening brace.
+     If we don't have an identifier, fabricate an anonymous name for
+     the enumeration being defined.  */
+  cp_lexer_consume_token (parser->lexer);
 
-  /* See if it is an identifier.  */
-  if (token->type == CPP_NAME)
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     identifier = cp_parser_identifier (parser);
-
-  /* Look for the `{'.  */
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
-    return error_mark_node;
-
-  /* At this point, we're going ahead with the enum-specifier, even
-     if some other problem occurs.  */
-  cp_parser_commit_to_tentative_parse (parser);
+  else
+    identifier = make_anon_name ();
 
   /* Issue an error message if type-definitions are forbidden here.  */
   cp_parser_check_type_definition (parser);
 
-  /* Create the new type.  */
-  type = start_enum (identifier ? identifier : make_anon_name ());
+  /* Create the new type.  We do this before consuming the opening brace
+     so the enum will be recorded as being on the line of its tag (or the
+     'enum' keyword, if there is no tag).  */
+  type = start_enum (identifier);
 
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  /* If it's not a `}', then there are some enumerators.  */
-  if (token->type != CPP_CLOSE_BRACE)
+  /* Consume the opening brace.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  /* If the next token is not '}', then there are some enumerators.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
     cp_parser_enumerator_list (parser, type);
-  /* Look for the `}'.  */
+
+  /* Consume the final '}'.  */
   cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
 
+  /* Look for trailing attributes to apply to this enumeration, and
+     apply them if appropriate.  */
+  if (cp_parser_allow_gnu_extensions_p (parser))
+    {
+      tree trailing_attr = cp_parser_attributes_opt (parser);
+      cplus_decl_attributes (&type,
+                            trailing_attr,
+                            (int) ATTR_FLAG_TYPE_IN_PLACE);
+    }
+
   /* Finish up the enumeration.  */
   finish_enum (type);
 
@@ -9373,15 +9826,12 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
 {
   while (true)
     {
-      cp_token *token;
-
       /* Parse an enumerator-definition.  */
       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
-        list.  */
-      if (token->type != CPP_COMMA)
+
+      /* If the next token is not a ',', we've reached the end of
+        the list.  */
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
        break;
       /* Otherwise, consume the `,' and keep going.  */
       cp_lexer_consume_token (parser->lexer);
@@ -9408,7 +9858,6 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
 static void
 cp_parser_enumerator_definition (cp_parser* parser, tree type)
 {
-  cp_token *token;
   tree identifier;
   tree value;
 
@@ -9417,10 +9866,8 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
   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.  */
-  if (token->type == CPP_EQ)
+  /* If the next token is an '=', then there is an explicit value.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
     {
       /* Consume the `=' token.  */
       cp_lexer_consume_token (parser->lexer);
@@ -9477,7 +9924,8 @@ cp_parser_namespace_name (cp_parser* parser)
                                          /*is_type=*/false,
                                          /*is_template=*/false,
                                          /*is_namespace=*/true,
-                                         /*check_dependency=*/true);
+                                         /*check_dependency=*/true,
+                                         /*ambiguous_p=*/NULL);
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
@@ -9616,7 +10064,6 @@ cp_parser_using_declaration (cp_parser* parser)
   bool global_scope_p;
   tree decl;
   tree identifier;
-  tree scope;
   tree qscope;
 
   /* Look for the `using' keyword.  */
@@ -9675,8 +10122,7 @@ cp_parser_using_declaration (cp_parser* parser)
     error ("a template-id may not appear in a using-declaration");
   else
     {
-      scope = current_scope ();
-      if (scope && TYPE_P (scope))
+      if (at_class_scope_p ())
        {
          /* Create the USING_DECL.  */
          decl = do_class_using_decl (build_nt (SCOPE_REF,
@@ -9690,7 +10136,7 @@ cp_parser_using_declaration (cp_parser* parser)
          decl = cp_parser_lookup_name_simple (parser, identifier);
          if (decl == error_mark_node)
            cp_parser_name_lookup_error (parser, identifier, decl, NULL);
-         else if (scope)
+         else if (!at_namespace_scope_p ())
            do_local_using_decl (decl, qscope, identifier);
          else
            do_toplevel_using_decl (decl, qscope, identifier);
@@ -9754,7 +10200,6 @@ cp_parser_using_directive (cp_parser* parser)
 static void
 cp_parser_asm_definition (cp_parser* parser)
 {
-  cp_token *token;
   tree string;
   tree outputs = NULL_TREE;
   tree inputs = NULL_TREE;
@@ -9775,13 +10220,17 @@ cp_parser_asm_definition (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the opening `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return;
   /* Look for the string.  */
-  c_lex_string_translate = false;
-  token = cp_parser_require (parser, CPP_STRING, "asm body");
-  if (!token)
-    goto finish;
-  string = token->value;
+  string = cp_parser_string_literal (parser, false, false);
+  if (string == error_mark_node)
+    {
+      cp_parser_skip_to_closing_parenthesis (parser, true, false,
+                                            /*consume_paren=*/true);
+      return;
+    }
+
   /* If we're allowing GNU extensions, check for the extended assembly
      syntax.  Unfortunately, the `:' tokens need not be separated by
      a space in C, and so, for compatibility, we tolerate that here
@@ -9815,26 +10264,19 @@ cp_parser_asm_definition (cp_parser* parser)
       /* If the next token is `::', there are no outputs, and the
         next token is the beginning of the inputs.  */
       else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
-       {
-         /* Consume the `::' token.  */
-         cp_lexer_consume_token (parser->lexer);
-         /* The inputs are coming next.  */
-         inputs_p = true;
-       }
+       /* The inputs are coming next.  */
+       inputs_p = true;
 
       /* Look for inputs.  */
       if (inputs_p
          || cp_lexer_next_token_is (parser->lexer, CPP_COLON))
        {
-         if (!inputs_p)
-           /* Consume the `:'.  */
-           cp_lexer_consume_token (parser->lexer);
+         /* Consume the `:' or `::'.  */
+         cp_lexer_consume_token (parser->lexer);
          /* Parse the output-operands.  */
          if (cp_lexer_next_token_is_not (parser->lexer,
                                          CPP_COLON)
              && cp_lexer_next_token_is_not (parser->lexer,
-                                            CPP_SCOPE)
-             && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            inputs = cp_parser_asm_operand_list (parser);
        }
@@ -9846,9 +10288,8 @@ cp_parser_asm_definition (cp_parser* parser)
       if (clobbers_p
          || cp_lexer_next_token_is (parser->lexer, CPP_COLON))
        {
-         if (!clobbers_p)
-           /* Consume the `:'.  */
-           cp_lexer_consume_token (parser->lexer);
+         /* Consume the `:' or `::'.  */
+         cp_lexer_consume_token (parser->lexer);
          /* Parse the clobbers.  */
          if (cp_lexer_next_token_is_not (parser->lexer,
                                          CPP_CLOSE_PAREN))
@@ -9861,22 +10302,23 @@ 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;
+       {
+         tree temp = asm_stmt;
+         if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
+           temp = TREE_OPERAND (temp, 0);
+         
+         ASM_INPUT_P (temp) = 1;
+       }
     }
   else
     assemble_asm (string);
-
- finish:
-  c_lex_string_translate = true;
 }
 
 /* Declarators [gram.dcl.decl] */
@@ -9917,15 +10359,15 @@ cp_parser_asm_definition (cp_parser* parser)
 
 static tree
 cp_parser_init_declarator (cp_parser* parser,
-                          tree decl_specifiers,
-                          tree prefix_attributes,
+                          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;
@@ -9938,6 +10380,10 @@ cp_parser_init_declarator (cp_parser* parser,
   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.  */
   if (function_definition_p)
@@ -9952,13 +10398,14 @@ cp_parser_init_declarator (cp_parser* parser,
   declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                            &ctor_dtor_or_conv_p,
-                           /*parenthesized_p=*/NULL);
+                           /*parenthesized_p=*/NULL,
+                           /*member_p=*/false);
   /* Gather up the deferred checks.  */
   stop_deferring_access_checks ();
 
   /* 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,
@@ -10032,7 +10479,7 @@ cp_parser_init_declarator (cp_parser* parser,
      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,
                       "expected constructor, destructor, or type conversion");
@@ -10048,7 +10495,7 @@ cp_parser_init_declarator (cp_parser* parser,
       && token->type != CPP_COMMA
       && token->type != CPP_SEMICOLON)
     {
-      cp_parser_error (parser, "expected init-declarator");
+      cp_parser_error (parser, "expected initializer");
       return error_mark_node;
     }
 
@@ -10061,11 +10508,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.  */
@@ -10082,18 +10529,16 @@ 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,
-                        is_initialized, attributes, prefix_attributes);
+                        is_initialized, attributes, prefix_attributes,
+                        &pop_p);
     }
-
-  /* Enter the SCOPE.  That way unqualified names appearing in the
-     initializer will be looked up in SCOPE.  */
-  if (scope)
+  else if (scope)
+    /* Enter the SCOPE.  That way unqualified names appearing in the
+       initializer will be looked up in SCOPE.  */
     pop_p = push_scope (scope);
 
   /* Perform deferred access control checks, now that we know in which
@@ -10140,17 +10585,12 @@ cp_parser_init_declarator (cp_parser* parser,
     if (cp_parser_attributes_opt (parser))
       warning ("attributes after parenthesized initializer ignored");
 
-  /* 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
-     on the current scope.  */
-  if (pop_p)
-    pop_scope (scope);
-
   /* For an in-class declaration, use `grokfield' to create the
      declaration.  */
   if (member_p)
     {
+      if (pop_p)
+       pop_scope (scope);
       decl = grokfield (declarator, decl_specifiers,
                        initializer, /*asmspec=*/NULL_TREE,
                        /*attributes=*/NULL_TREE);
@@ -10160,16 +10600,20 @@ cp_parser_init_declarator (cp_parser* parser,
 
   /* Finish processing the declaration.  But, skip friend
      declarations.  */
-  if (!friend_p && decl)
-    cp_finish_decl (decl,
-                   initializer,
-                   asm_specification,
-                   /* If the initializer is in parentheses, then this is
-                      a direct-initialization, which means that an
-                      `explicit' constructor is OK.  Otherwise, an
-                      `explicit' constructor cannot be used.  */
-                   ((is_parenthesized_init || !is_initialized)
+  if (!friend_p && decl && decl != error_mark_node)
+    {
+      cp_finish_decl (decl,
+                     initializer,
+                     asm_specification,
+                     /* If the initializer is in parentheses, then this is
+                        a direct-initialization, which means that an
+                        `explicit' constructor is OK.  Otherwise, an
+                        `explicit' constructor cannot be used.  */
+                     ((is_parenthesized_init || !is_initialized)
                     ? 0 : LOOKUP_ONLYCONVERTING));
+      if (pop_p)
+       pop_scope (DECL_CONTEXT (decl));
+    }
 
   /* Remember whether or not variables were initialized by
      constant-expressions.  */
@@ -10200,26 +10644,6 @@ cp_parser_init_declarator (cp_parser* parser,
      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
@@ -10235,18 +10659,21 @@ cp_parser_init_declarator (cp_parser* parser,
    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 "(...)".  */
+   the declarator is a direct-declarator of the form "(...)".  
 
-static tree
+   MEMBER_P is true iff this declarator is a member-declarator.  */
+
+static cp_declarator *
 cp_parser_declarator (cp_parser* parser,
                       cp_parser_declarator_kind dcl_kind,
                       int* ctor_dtor_or_conv_p,
-                     bool* parenthesized_p)
+                     bool* parenthesized_p,
+                     bool member_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;
 
@@ -10266,7 +10693,7 @@ cp_parser_declarator (cp_parser* parser,
   /* Parse the ptr-operator.  */
   code = cp_parser_ptr_operator (parser,
                                 &class_type,
-                                &cv_qualifier_seq);
+                                &cv_quals);
   /* If that worked, then we have a ptr-operator.  */
   if (cp_parser_parse_definitely (parser))
     {
@@ -10282,24 +10709,24 @@ cp_parser_declarator (cp_parser* parser,
       /* Parse the dependent declarator.  */
       declarator = cp_parser_declarator (parser, dcl_kind,
                                         /*ctor_dtor_or_conv_p=*/NULL,
-                                        /*parenthesized_p=*/NULL);
+                                        /*parenthesized_p=*/NULL,
+                                        /*member_p=*/false);
 
       /* If we are parsing an abstract-declarator, we must handle the
         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
@@ -10308,11 +10735,12 @@ cp_parser_declarator (cp_parser* parser,
        *parenthesized_p = cp_lexer_next_token_is (parser->lexer,
                                                   CPP_OPEN_PAREN);
       declarator = cp_parser_direct_declarator (parser, dcl_kind,
-                                               ctor_dtor_or_conv_p);
+                                               ctor_dtor_or_conv_p,
+                                               member_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;
 }
@@ -10341,25 +10769,17 @@ cp_parser_declarator (cp_parser* parser,
    we are parsing a direct-declarator.  It is
    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.  */
+   [dcl.ambig.res].  CTOR_DTOR_OR_CONV_P and MEMBER_P are as for
+   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)
+                             int* ctor_dtor_or_conv_p,
+                            bool member_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;
@@ -10412,10 +10832,17 @@ cp_parser_direct_declarator (cp_parser* parser,
 
          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);
+             /* In a member-declarator, the only valid interpretation
+                of a parenthesis is the start of a
+                parameter-declaration-clause.  (It is invalid to
+                initialize a static data member with a parenthesized
+                initializer; only the "=" form of initialization is
+                permitted.)  */
+             if (!member_p)
+               cp_parser_parse_tentatively (parser);
 
              /* Consume the `('.  */
              cp_lexer_consume_token (parser->lexer);
@@ -10441,9 +10868,9 @@ cp_parser_direct_declarator (cp_parser* parser,
 
              /* If all went well, parse the cv-qualifier-seq and the
                 exception-specification.  */
-             if (cp_parser_parse_definitely (parser))
+             if (member_p || cp_parser_parse_definitely (parser))
                {
-                 tree cv_qualifiers;
+                 cp_cv_quals cv_quals;
                  tree exception_specification;
 
                  if (ctor_dtor_or_conv_p)
@@ -10453,7 +10880,7 @@ 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
                    = cp_parser_exception_specification_opt (parser);
@@ -10461,7 +10888,7 @@ cp_parser_direct_declarator (cp_parser* 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
@@ -10489,13 +10916,14 @@ cp_parser_direct_declarator (cp_parser* parser,
              parser->in_type_id_in_expr_p = true;
              declarator
                = cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
-                                       /*parenthesized_p=*/NULL);
+                                       /*parenthesized_p=*/NULL,
+                                       member_p);
              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;
@@ -10532,42 +10960,51 @@ cp_parser_direct_declarator (cp_parser* parser,
                                                 &non_constant_p);
              if (!non_constant_p)
                bounds = fold_non_dependent_expr (bounds);
+             else if (!at_function_scope_p ())
+               {
+                 error ("array bound is not an integer constant");
+                 bounds = error_mark_node;
+               }
            }
          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 (id == error_mark_node)
+           {
+             declarator = cp_error_declarator;
+             break;
+           }
 
-         if (TREE_CODE (declarator) == SCOPE_REF
-             && !current_scope ())
+         if (TREE_CODE (id) == SCOPE_REF && at_namespace_scope_p ())
            {
-             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
@@ -10593,46 +11030,60 @@ 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;
+               }
+
+             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);
+                   }
                }
-
-             /* 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)
-                 || (TREE_CODE (unqualified_name) == TYPE_DECL
-                     && same_type_p (TREE_TYPE (unqualified_name),
-                                     class_type)))
-               *ctor_dtor_or_conv_p = -1;
            }
 
        handle_declarator:;
@@ -10643,9 +11094,7 @@ cp_parser_direct_declarator (cp_parser* parser,
            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;
@@ -10686,17 +11135,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_cv_quals *cv_quals)
 {
   enum tree_code code = ERROR_MARK;
   cp_token *token;
@@ -10704,7 +11153,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);
@@ -10723,7 +11172,7 @@ cp_parser_ptr_operator (cp_parser* parser,
         enforced during semantic analysis.  */
       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
     {
@@ -10753,7 +11202,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))
@@ -10768,35 +11217,6 @@ cp_parser_ptr_operator (cp_parser* parser,
    cv-qualifier-seq:
      cv-qualifier cv-qualifier-seq [opt]
 
-   Returns a TREE_LIST.  The TREE_VALUE of each node is the
-   representation of a cv-qualifier.  */
-
-static tree
-cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
-{
-  tree cv_qualifiers = NULL_TREE;
-
-  while (true)
-    {
-      tree cv_qualifier;
-
-      /* 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;
-
-      /* Add this cv-qualifier to the list.  */
-      cv_qualifiers
-       = tree_cons (NULL_TREE, cv_qualifier, cv_qualifiers);
-    }
-
-  /* We built up the list in reverse order.  */
-  return nreverse (cv_qualifiers);
-}
-
-/* Parse an (optional) cv-qualifier.
-
    cv-qualifier:
      const
      volatile
@@ -10804,33 +11224,58 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
    GNU Extension:
 
    cv-qualifier:
-     __restrict__ */
+     __restrict__
 
-static tree
-cp_parser_cv_qualifier_opt (cp_parser* parser)
+   Returns a bitmask representing the cv-qualifiers.  */
+
+static cp_cv_quals
+cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 {
-  cp_token *token;
-  tree cv_qualifier = NULL_TREE;
+  cp_cv_quals cv_quals = TYPE_UNQUALIFIED;
 
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  /* See if it's a cv-qualifier.  */
-  switch (token->keyword)
+  while (true)
     {
-    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;
+      cp_token *token;
+      cp_cv_quals cv_qualifier;
 
-    default:
-      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:
+         cv_qualifier = TYPE_QUAL_CONST;
+         break;
+
+       case RID_VOLATILE:
+         cv_qualifier = TYPE_QUAL_VOLATILE;
+         break;
+
+       case RID_RESTRICT:
+         cv_qualifier = TYPE_QUAL_RESTRICT;
+         break;
+
+       default:
+         cv_qualifier = TYPE_UNQUALIFIED;
+         break;
+       }
+
+      if (!cv_qualifier)
+       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.
@@ -10891,13 +11336,12 @@ 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.  */
@@ -10905,13 +11349,13 @@ cp_parser_type_id (cp_parser* parser)
   /* Look for the declarator.  */
   abstract_declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
-                           /*parenthesized_p=*/NULL);
+                           /*parenthesized_p=*/NULL,
+                           /*member_p=*/false);
   /* 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.
@@ -10924,14 +11368,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)
@@ -10941,39 +11387,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,
+                                                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.
@@ -10982,19 +11425,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);
@@ -11003,7 +11444,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.  */
@@ -11011,10 +11452,10 @@ 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
@@ -11024,16 +11465,16 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       /* 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);
@@ -11059,7 +11500,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.
@@ -11070,17 +11514,22 @@ 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
@@ -11090,14 +11539,15 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
 
       /* 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)
@@ -11141,7 +11591,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser)
        }
       else
        {
-         cp_parser_error (parser, "expected `,' or `...'");
+         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,
@@ -11152,8 +11602,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.
@@ -11169,27 +11618,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
+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;
 
@@ -11209,17 +11651,16 @@ cp_parser_parameter_declaration (cp_parser *parser,
     = "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.  */
@@ -11232,7 +11673,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
       || token->type == CPP_ELLIPSIS
       || token->type == CPP_GREATER)
     {
-      declarator = NULL_TREE;
+      declarator = NULL;
       if (parenthesized_p)
        *parenthesized_p = false;
     }
@@ -11263,10 +11704,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
       declarator = cp_parser_declarator (parser,
                                         CP_PARSER_DECLARATOR_EITHER,
                                         /*ctor_dtor_or_conv_p=*/NULL,
-                                        parenthesized_p);
+                                        parenthesized_p,
+                                        /*member_p=*/false);
       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
@@ -11286,18 +11730,15 @@ cp_parser_parameter_declaration (cp_parser *parser,
          && TYPE_BEING_DEFINED (current_class_type))
        {
          unsigned depth = 0;
-
-         /* Create a DEFAULT_ARG to represented the unparsed default
-             argument.  */
-         default_argument = make_node (DEFAULT_ARG);
-         DEFARG_TOKENS (default_argument) = cp_token_cache_new ();
+         cp_token *first_token;
+         cp_token *token;
 
          /* Add tokens until we have processed the entire default
-            argument.  */
+            argument.  We add the range [first_token, token).  */
+         first_token = cp_lexer_peek_token (parser->lexer);
          while (true)
            {
              bool done = false;
-             cp_token *token;
 
              /* Peek at the next token.  */
              token = cp_lexer_peek_token (parser->lexer);
@@ -11365,9 +11806,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
 
              /* Add the token to the token block.  */
              token = cp_lexer_consume_token (parser->lexer);
-             cp_token_cache_push_token (DEFARG_TOKENS (default_argument),
-                                        token);
            }
+
+         /* Create a DEFAULT_ARG to represented the unparsed default
+             argument.  */
+         default_argument = make_node (DEFAULT_ARG);
+         DEFARG_TOKENS (default_argument)
+           = cp_token_cache_new (first_token, token);  
        }
       /* Outside of a class definition, we can just parse the
          assignment-expression.  */
@@ -11407,14 +11852,9 @@ 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.
@@ -11425,7 +11865,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
@@ -11528,7 +11968,7 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
      assignment-expression.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
     {
-      initializer 
+      initializer
        = cp_parser_constant_expression (parser,
                                        /*allow_non_constant_p=*/true,
                                        non_constant_p);
@@ -11541,10 +11981,6 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
       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))
        {
@@ -11727,7 +12163,8 @@ cp_parser_class_name (cp_parser *parser,
                                        type_p,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
-                                       check_dependency_p);
+                                       check_dependency_p,
+                                       /*ambiguous_p=*/NULL);
        }
     }
   else
@@ -11788,11 +12225,12 @@ cp_parser_class_specifier (cp_parser* parser)
 {
   cp_token *token;
   tree type;
-  tree attributes;
+  tree attributes = NULL_TREE;
   int has_trailing_semicolon;
   bool nested_name_specifier_p;
   unsigned saved_num_template_parameter_lists;
   bool pop_p = false;
+  tree scope = NULL_TREE;
 
   push_deferring_access_checks (dk_no_deferred);
 
@@ -11828,14 +12266,19 @@ cp_parser_class_specifier (cp_parser* parser)
 
   /* Start the class.  */
   if (nested_name_specifier_p)
-    pop_p = push_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
+    {
+      scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));
+      pop_p = push_scope (scope);
+    }
   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
@@ -11851,7 +12294,7 @@ cp_parser_class_specifier (cp_parser* parser)
   if (type != error_mark_node)
     type = finish_struct (type, attributes);
   if (pop_p)
-    pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
+    pop_scope (scope);
   /* 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
      definitions.  Note that the queued functions defined in a class
@@ -11876,6 +12319,8 @@ cp_parser_class_specifier (cp_parser* parser)
     {
       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.
@@ -11887,6 +12332,8 @@ cp_parser_class_specifier (cp_parser* parser)
             };
 
          */
+      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));
@@ -11894,14 +12341,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));
@@ -11919,7 +12376,6 @@ cp_parser_class_specifier (cp_parser* parser)
          cp_parser_late_parsing_for_member (parser, fn);
          function_depth--;
        }
-
     }
 
   /* Put back any saved access checks.  */
@@ -11959,7 +12415,6 @@ 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;
@@ -11971,6 +12426,7 @@ cp_parser_class_head (cp_parser* parser,
   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;
@@ -12096,7 +12552,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
@@ -12104,7 +12561,7 @@ cp_parser_class_head (cp_parser* parser,
      xref_tag, since that has irreversible side-effects.  */
   if (!cp_parser_next_token_starts_class_definition_p (parser))
     {
-      cp_parser_error (parser, "expected `{' or `:'");
+      cp_parser_error (parser, "expected %<{%> or %<:%>");
       return error_mark_node;
     }
 
@@ -12123,14 +12580,12 @@ cp_parser_class_head (cp_parser* parser,
       tree scope;
       /* Figure out in what scope the declaration is being placed.  */
       scope = current_scope ();
-      if (!scope)
-       scope = current_namespace;
       /* If that scope does not contain the scope in which the
         class was originally declared, the program is invalid.  */
       if (scope && !is_ancestor (scope, nested_name_specifier))
        {
-         error ("declaration of `%D' in `%D' which does not "
-                "enclose `%D'", type, scope, nested_name_specifier);
+         error ("declaration of %qD in %qD which does not enclose %qD",
+                 type, scope, nested_name_specifier);
          type = NULL_TREE;
          goto done;
        }
@@ -12153,7 +12608,7 @@ cp_parser_class_head (cp_parser* parser,
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
-      error ("an explicit specialization must be preceded by 'template <>'");
+      error ("an explicit specialization must be preceded by %<template <>%>");
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
         cp_parser_explicit_specialization.  */
@@ -12246,17 +12701,16 @@ cp_parser_class_head (cp_parser* parser,
      is valid.  */
   if (nested_name_specifier)
     pop_p = 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;
 
-      /* Get the list of base-classes.  */
-      bases = cp_parser_base_clause (parser);
-      /* Process them.  */
-      xref_basetypes (type, bases);
-    }
+  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);
+
   /* Leave the scope given by the nested-name-specifier.  We will
      enter the class scope itself while processing the members.  */
   if (pop_p)
@@ -12336,6 +12790,13 @@ cp_parser_member_specification_opt (cp_parser* parser)
          break;
 
        default:
+         /* Accept #pragmas at class scope.  */
+         if (token->type == CPP_PRAGMA)
+           {
+             cp_lexer_handle_pragma (parser->lexer);
+             break;
+           }
+
          /* Otherwise, the next construction must be a
             member-declaration.  */
          cp_parser_member_declaration (parser);
@@ -12374,7 +12835,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;
@@ -12412,13 +12873,15 @@ cp_parser_member_declaration (cp_parser* parser)
     }
 
   /* 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_parse_and_diagnose_invalid_type_name (parser))
+  if (!decl_specifiers.type
+      && cp_parser_parse_and_diagnose_invalid_type_name (parser))
     return;
   /* If there is no declarator, then the decl-specifier-seq should
      specify a type.  */
@@ -12433,20 +12896,21 @@ 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");
+         cp_token *token = cp_lexer_peek_token (parser->lexer);
+         if (pedantic && !token->in_system_header)
+           pedwarn ("%Hextra %<;%>", &token->location);
        }
       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)
@@ -12463,27 +12927,10 @@ cp_parser_member_declaration (cp_parser* parser)
 
                  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
+                  && 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");
@@ -12493,7 +12940,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
@@ -12515,7 +12962,7 @@ 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
         declaration.  */
@@ -12561,15 +13008,17 @@ 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;
@@ -12578,11 +13027,12 @@ cp_parser_member_declaration (cp_parser* parser)
              declarator
                = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                                        &ctor_dtor_or_conv_p,
-                                       /*parenthesized_p=*/NULL);
+                                       /*parenthesized_p=*/NULL,
+                                       /*member_p=*/true);
 
              /* 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);
@@ -12632,7 +13082,7 @@ cp_parser_member_declaration (cp_parser* parser)
                     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.  */
@@ -12658,7 +13108,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.  */
@@ -12674,7 +13124,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
@@ -12702,7 +13152,7 @@ cp_parser_member_declaration (cp_parser* parser)
          else if (cp_lexer_next_token_is_not (parser->lexer,
                                               CPP_SEMICOLON))
            {
-             cp_parser_error (parser, "expected `;'");
+             cp_parser_error (parser, "expected %<;%>");
              /* Skip tokens until we find a `;'.  */
              cp_parser_skip_to_end_of_statement (parser);
 
@@ -12887,7 +13337,7 @@ cp_parser_base_specifier (cp_parser* parser)
          if (virtual_p && !duplicate_virtual_error_issued_p)
            {
              cp_parser_error (parser,
-                              "`virtual' specified more than once in base-specified");
+                              "%<virtual%> specified more than once in base-specified");
              duplicate_virtual_error_issued_p = true;
            }
 
@@ -12929,9 +13379,9 @@ cp_parser_base_specifier (cp_parser* parser)
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
       if (!processing_template_decl)
-       error ("keyword `typename' not allowed outside of templates");
+       error ("keyword %<typename%> not allowed outside of templates");
       else
-       error ("keyword `typename' not allowed in this context "
+       error ("keyword %<typename%> not allowed in this context "
               "(the base class is implicitly a type)");
       cp_lexer_consume_token (parser->lexer);
     }
@@ -13075,7 +13525,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);
@@ -13151,7 +13601,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);
 }
 
@@ -13169,8 +13619,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.  */
@@ -13187,19 +13638,29 @@ 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,
-                                      /*parenthesized_p=*/NULL);
+                                      /*parenthesized_p=*/NULL,
+                                      /*member_p=*/false);
 
   /* 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.
@@ -13262,11 +13723,7 @@ cp_parser_asm_specification_opt (cp_parser* parser)
   cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
 
   /* Look for the string-literal.  */
-  token = cp_parser_require (parser, CPP_STRING, "string-literal");
-  if (token)
-    asm_specification = token->value;
-  else
-    asm_specification = NULL_TREE;
+  asm_specification = cp_parser_string_literal (parser, false, false);
 
   /* Look for the `)'.  */
   cp_parser_require (parser, CPP_CLOSE_PAREN, "`('");
@@ -13300,9 +13757,6 @@ cp_parser_asm_operand_list (cp_parser* parser)
       tree string_literal;
       tree expression;
       tree name;
-      cp_token *token;
-
-      c_lex_string_translate = false;
 
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
        {
@@ -13319,16 +13773,15 @@ cp_parser_asm_operand_list (cp_parser* parser)
       else
        name = NULL_TREE;
       /* 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 = true;
+      string_literal = cp_parser_string_literal (parser, false, false);
+
       /* 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 = false;
+
       /* Add this operand to the list.  */
       asm_operands = tree_cons (build_tree_list (name, string_literal),
                                expression,
@@ -13360,12 +13813,10 @@ cp_parser_asm_clobber_list (cp_parser* parser)
 
   while (true)
     {
-      cp_token *token;
       tree string_literal;
 
       /* Look for the string literal.  */
-      token = cp_parser_require (parser, CPP_STRING, "string-literal");
-      string_literal = token ? token->value : error_mark_node;
+      string_literal = cp_parser_string_literal (parser, false, false);
       /* Add it to the list.  */
       clobbers = tree_cons (NULL_TREE, string_literal, clobbers);
       /* If the next token is not a `,', then the list is
@@ -13453,8 +13904,9 @@ static tree
 cp_parser_attribute_list (cp_parser* parser)
 {
   tree attribute_list = NULL_TREE;
+  bool save_translate_strings_p = parser->translate_strings_p;
 
-  c_lex_string_translate = false;
+  parser->translate_strings_p = false;
   while (true)
     {
       cp_token *token;
@@ -13500,7 +13952,7 @@ cp_parser_attribute_list (cp_parser* parser)
       /* Consume the comma and keep going.  */
       cp_lexer_consume_token (parser->lexer);
     }
-  c_lex_string_translate = true;
+  parser->translate_strings_p = save_translate_strings_p;
 
   /* We built up the list in reverse order.  */
   return nreverse (attribute_list);
@@ -13596,16 +14048,24 @@ cp_parser_label_declaration (cp_parser* parser)
    are ignored.
 
    If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
-   types.  */
+   types.  
+
+   If AMBIGUOUS_P is non-NULL, it is set to true if name-lookup
+   results in an ambiguity, and false otherwise.  */
 
 static tree
 cp_parser_lookup_name (cp_parser *parser, tree name,
                       bool is_type, bool is_template, bool is_namespace,
-                      bool check_dependency)
+                      bool check_dependency,
+                      bool *ambiguous_p)
 {
   tree decl;
   tree object_type = parser->context->object_type;
 
+  /* Assume that the lookup will be unambiguous.  */
+  if (ambiguous_p)
+    *ambiguous_p = false;
+
   /* Now that we have looked up the name, the OBJECT_TYPE (if any) is
      no longer valid.  Note that if we are parsing tentatively, and
      the parse fails, OBJECT_TYPE will be automatically restored.  */
@@ -13620,9 +14080,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
     return name;
   if (BASELINK_P (name))
     {
-      my_friendly_assert ((TREE_CODE (BASELINK_FUNCTIONS (name))
-                          == TEMPLATE_ID_EXPR),
-                         20020909);
+      gcc_assert (TREE_CODE (BASELINK_FUNCTIONS (name))
+                 == TEMPLATE_ID_EXPR);
       return name;
     }
 
@@ -13652,8 +14111,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   /* By this point, the NAME should be an ordinary identifier.  If
      the id-expression was a qualified name, the qualifying scope is
      stored in PARSER->SCOPE at this point.  */
-  my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE,
-                     20000619);
+  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
   /* Perform the lookup.  */
   if (parser->scope)
@@ -13684,7 +14142,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                                                  /*complain=*/1));
          else if (is_template)
            decl = make_unbound_class_template (parser->scope,
-                                               name,
+                                               name, NULL_TREE,
                                                /*complain=*/1);
          else
            decl = build_nt (SCOPE_REF, parser->scope, name);
@@ -13727,7 +14185,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                                     /*protect=*/0, is_type);
       /* Look it up in the enclosing context, too.  */
       decl = lookup_name_real (name, is_type, /*nonclass=*/0,
-                              is_namespace,
+                              /*block_p=*/true, is_namespace,
                               /*flags=*/0);
       parser->object_scope = object_type;
       parser->qualifying_scope = NULL_TREE;
@@ -13737,7 +14195,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   else
     {
       decl = lookup_name_real (name, is_type, /*nonclass=*/0,
-                              is_namespace,
+                              /*block_p=*/true, is_namespace,
                               /*flags=*/0);
       parser->qualifying_scope = NULL_TREE;
       parser->object_scope = NULL_TREE;
@@ -13753,22 +14211,23 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   /* If it's a TREE_LIST, the result of the lookup was ambiguous.  */
   if (TREE_CODE (decl) == TREE_LIST)
     {
+      if (ambiguous_p)
+       *ambiguous_p = true;
       /* The error message we have to print is too complicated for
         cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
        {
-         error ("reference to `%D' is ambiguous", name);
+         error ("reference to %qD is ambiguous", name);
          print_candidates (decl);
        }
       return error_mark_node;
     }
 
-  my_friendly_assert (DECL_P (decl)
-                     || TREE_CODE (decl) == OVERLOAD
-                     || TREE_CODE (decl) == SCOPE_REF
-                     || TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE
-                     || BASELINK_P (decl),
-                     20000619);
+  gcc_assert (DECL_P (decl)
+             || TREE_CODE (decl) == OVERLOAD
+             || TREE_CODE (decl) == SCOPE_REF
+             || TREE_CODE (decl) == UNBOUND_CLASS_TEMPLATE
+             || BASELINK_P (decl));
 
   /* If we have resolved the name of a member declaration, check to
      see if the declaration is accessible.  When the name resolves to
@@ -13794,7 +14253,8 @@ cp_parser_lookup_name_simple (cp_parser* parser, tree name)
                                /*is_type=*/false,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
-                               /*check_dependency=*/true);
+                               /*check_dependency=*/true,
+                               /*ambiguous_p=*/NULL);
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
@@ -13847,74 +14307,69 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
 
 static bool
 cp_parser_check_declarator_template_parameters (cp_parser* parser,
-                                                tree declarator)
+                                               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,
                                                  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:
+      gcc_unreachable ();
     }
+  return false;
 }
 
 /* NUM_TEMPLATES were used in the current declaration.  If that is
@@ -13950,79 +14405,6 @@ cp_parser_check_template_parameters (cp_parser* parser,
   return false;
 }
 
-/* Parse a binary-expression of the general form:
-
-   binary-expression:
-     <expr>
-     binary-expression <token> <expr>
-
-   The TOKEN_TREE_MAP maps <token> types to <expr> codes.  FN is used
-   to parser the <expr>s.  If the first production is used, then the
-   value returned by FN is returned directly.  Otherwise, a node with
-   the indicated EXPR_TYPE is returned, with operands corresponding to
-   the two sub-expressions.  */
-
-static tree
-cp_parser_binary_expression (cp_parser* parser,
-                             const cp_parser_token_tree_map token_tree_map,
-                             cp_parser_expression_fn fn)
-{
-  tree lhs;
-
-  /* Parse the first expression.  */
-  lhs = (*fn) (parser);
-  /* Now, look for more expressions.  */
-  while (true)
-    {
-      cp_token *token;
-      const cp_parser_token_tree_map_node *map_node;
-      tree rhs;
-
-      /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If the token is `>', and that's not an operator at the
-        moment, then we're done.  */
-      if (token->type == CPP_GREATER
-         && !parser->greater_than_is_operator_p)
-       break;
-      /* If we find one of the tokens we want, build the corresponding
-        tree representation.  */
-      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, 
-                                    &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;
-         }
-
-      /* If the token wasn't one of the ones we want, we're done.  */
-      if (map_node->token_type == CPP_EOF)
-       break;
-    }
-
-  return lhs;
-}
-
 /* Parse an optional `::' token indicating that the following name is
    from the global namespace.  If so, PARSER->SCOPE is set to the
    GLOBAL_NAMESPACE. Otherwise, PARSER->SCOPE is set to NULL_TREE,
@@ -14149,6 +14531,10 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
     {
       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;
@@ -14184,7 +14570,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);
@@ -14216,17 +14602,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
@@ -14236,8 +14624,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;
@@ -14362,10 +14749,16 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
     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)
@@ -14414,22 +14807,33 @@ cp_parser_single_declaration (cp_parser* parser,
 {
   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;
 
+  /* This function is only used when processing a template
+     declaration.  */
+  gcc_assert (innermost_scope_kind () == sk_template_parms
+             || innermost_scope_kind () == sk_template_spec);
+
   /* Defer access checks until we know what is being declared.  */
   push_deferring_access_checks (dk_deferred);
 
   /* 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);
+
+  /* There are no template typedefs.  */
+  if (decl_specifiers.specs[(int) ds_typedef])
+    {
+      error ("template declaration of %qs", "typedef");
+      decl = error_mark_node;
+    }
+
   /* Gather up the access checks that occurred the
      decl-specifier-seq.  */
   stop_deferring_access_checks ();
@@ -14439,15 +14843,28 @@ 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);
+
+         /* In this case:
+
+              struct C {
+                friend template <typename T> struct A<T>::B;
+              };
+
+            A<T>::B will be represented by a TYPENAME_TYPE, and
+            therefore not recognized by shadow_tag.  */
+         if (friend_p && *friend_p
+             && !decl
+             && decl_specifiers.type
+             && TYPE_P (decl_specifiers.type))
+           decl = decl_specifiers.type;
+
+         if (decl && decl != error_mark_node)
            decl = TYPE_NAME (decl);
          else
            decl = error_mark_node;
        }
     }
-  else
-    decl = NULL_TREE;
   /* If it's not a template class, try for a template function.  If
      the next token is a `;', then this declaration does not declare
      anything.  But, if there were errors in the decl-specifiers, then
@@ -14455,10 +14872,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_specifiers.type != error_mark_node))
     decl = cp_parser_init_declarator (parser,
-                                     decl_specifiers,
-                                     attributes,
+                                     &decl_specifiers,
                                      /*function_definition_allowed_p=*/true,
                                      member_p,
                                      declares_class_or_enum,
@@ -14473,7 +14889,8 @@ cp_parser_single_declaration (cp_parser* parser,
   parser->object_scope = NULL_TREE;
   /* Look for a trailing `;' after the declaration.  */
   if (!function_definition_p
-      && !cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
+      && (decl == error_mark_node
+         || !cp_parser_require (parser, CPP_SEMICOLON, "`;'")))
     cp_parser_skip_to_end_of_block_or_statement (parser);
 
   return decl;
@@ -14503,10 +14920,10 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
   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) 
+  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 
+      if (cp_parser_non_integral_constant_expression
          (parser, "a call to a constructor"))
        return error_mark_node;
     }
@@ -14521,11 +14938,12 @@ 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;
+  cp_token *first;
+  cp_token *last;
   tree fn;
 
   /* Create the function-declaration.  */
@@ -14543,18 +14961,18 @@ cp_parser_save_member_function_body (cp_parser* parser,
   /* Remember it, if there default args to post process.  */
   cp_parser_save_default_args (parser, fn);
 
-  /* Create a token cache.  */
-  cache = cp_token_cache_new ();
   /* Save away the tokens that make up the body of the
      function.  */
-  cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, /*depth=*/0);
+  first = parser->lexer->next_token;
+  cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0);
   /* Handle function try blocks.  */
   while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH))
-    cp_parser_cache_group (parser, cache, CPP_CLOSE_BRACE, /*depth=*/0);
+    cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0);
+  last = parser->lexer->next_token;
 
   /* Save away the inline definition; we will process it when the
      class is complete.  */
-  DECL_PENDING_INLINE_INFO (fn) = cache;
+  DECL_PENDING_INLINE_INFO (fn) = cp_token_cache_new (first, last);
   DECL_PENDING_INLINE_P (fn) = 1;
 
   /* We need to know that this was defined in the class, so that
@@ -14609,25 +15027,37 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
     {
       if (!saved_greater_than_is_operator_p)
        {
-         /* If we're in a nested template argument list, the '>>' has to be
-           a typo for '> >'. We emit the error message, but we continue
-           parsing and we push a '>' as next token, so that the argument
-           list will be parsed correctly..  */
-         cp_token* token;
-         error ("`>>' should be `> >' within a nested template argument list");
-         token = cp_lexer_peek_token (parser->lexer);
+         /* If we're in a nested template argument list, the '>>' has
+           to be a typo for '> >'. We emit the error message, but we
+           continue parsing and we push a '>' as next token, so that
+           the argument list will be parsed correctly.  Note that the
+           global source location is still on the token before the
+           '>>', so we need to say explicitly where we want it.  */
+         cp_token *token = cp_lexer_peek_token (parser->lexer);
+         error ("%H%<>>%> should be %<> >%> "
+                "within a nested template argument list",
+                &token->location);
+
+         /* ??? Proper recovery should terminate two levels of
+            template argument list here.  */
          token->type = CPP_GREATER;
        }
       else
        {
-         /* If this is not a nested template argument list, the '>>' is
-           a typo for '>'. Emit an error message and continue.  */
-         error ("spurious `>>', use `>' to terminate a template argument list");
+         /* If this is not a nested template argument list, the '>>'
+           is a typo for '>'. Emit an error message and continue.
+           Same deal about the token location, but here we can get it
+           right by consuming the '>>' before issuing the diagnostic.  */
          cp_lexer_consume_token (parser->lexer);
+         error ("spurious %<>>%>, use %<>%> to terminate "
+                "a template argument list");
        }
     }
-  else if (!cp_parser_require (parser, CPP_GREATER, "`>'"))
-    error ("missing `>' to terminate the template argument list");
+  else if (!cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
+    error ("missing %<>%> to terminate the template argument list");
+  else
+    /* It's what we want, a '>'; consume it.  */
+    cp_lexer_consume_token (parser->lexer);
   /* The `>' token might be a greater-than operator again now.  */
   parser->greater_than_is_operator_p
     = saved_greater_than_is_operator_p;
@@ -14646,8 +15076,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
 static void
 cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
 {
-  cp_lexer *saved_lexer;
-
   /* If this member is a template, get the underlying
      FUNCTION_DECL.  */
   if (DECL_FUNCTION_TEMPLATE_P (member_function))
@@ -14656,7 +15084,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
   /* There should not be any class definitions in progress at this
      point; the bodies of members are only parsed outside of all class
      definitions.  */
-  my_friendly_assert (parser->num_classes_being_defined == 0, 20010816);
+  gcc_assert (parser->num_classes_being_defined == 0);
   /* While we're parsing the member functions we might encounter more
      classes.  We want to handle them right away, but we don't want
      them getting mixed up with functions that are currently in the
@@ -14684,20 +15112,13 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree 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);
+      /* Push the body of the function onto the lexer stack.  */
+      cp_parser_push_lexer_for_tokens (parser, tokens);
 
       /* 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,
@@ -14706,8 +15127,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
       /* Leave the scope of the containing function.  */
       if (function_scope)
        pop_function_context_from (function_scope);
-      /* Restore the lexer.  */
-      parser->lexer = saved_lexer;
+      cp_parser_pop_lexer (parser);
     }
 
   /* Remove any template parameters from the symbol table.  */
@@ -14732,7 +15152,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;
       }
@@ -14740,15 +15160,15 @@ 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)
 {
-  cp_lexer *saved_lexer;
-  cp_token_cache *tokens;
   bool saved_local_variables_forbidden_p;
-  tree parameters;
+  tree parm;
 
   /* While we're parsing the default args, we might (due to the
      statement expression extension) encounter more classes.  We want
@@ -14757,46 +15177,42 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
   parser->unparsed_functions_queues
     = tree_cons (NULL_TREE, NULL_TREE, parser->unparsed_functions_queues);
 
-  for (parameters = TYPE_ARG_TYPES (TREE_TYPE (fn));
-       parameters;
-       parameters = TREE_CHAIN (parameters))
+  /* Local variable names (and the `this' keyword) may not appear
+     in a default argument.  */
+  saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
+  parser->local_variables_forbidden_p = true;
+
+  for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
+       parm;
+       parm = TREE_CHAIN (parm))
     {
-      if (!TREE_PURPOSE (parameters)
-         || TREE_CODE (TREE_PURPOSE (parameters)) != DEFAULT_ARG)
+      cp_token_cache *tokens;
+
+      if (!TREE_PURPOSE (parm)
+         || TREE_CODE (TREE_PURPOSE (parm)) != DEFAULT_ARG)
        continue;
 
-       /* Save away the current lexer.  */
-      saved_lexer = parser->lexer;
-       /* Create a new one, using the tokens we have saved.  */
-      tokens =  DEFARG_TOKENS (TREE_PURPOSE (parameters));
-      parser->lexer = cp_lexer_new_from_tokens (tokens);
-
-       /* Set the current source position to be the location of the
-         first token in the default argument.  */
-      cp_lexer_peek_token (parser->lexer);
-
-       /* Local variable names (and the `this' keyword) may not appear
-         in a default argument.  */
-      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 ();
+       /* Push the saved tokens for the default argument onto the parser's
+         lexer stack.  */
+      tokens = DEFARG_TOKENS (TREE_PURPOSE (parm));
+      cp_parser_push_lexer_for_tokens (parser, tokens);
+
+      /* Parse the assignment-expression.  */
+      TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser);
 
       /* 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 `,'");
+       cp_parser_error (parser, "expected %<,%>");
 
-       /* Restore saved state.  */
-      parser->lexer = saved_lexer;
-      parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
+      /* Revert to the main lexer.  */
+      cp_parser_pop_lexer (parser);
     }
 
+  /* Restore the state of local_variables_forbidden_p.  */
+  parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
+
   /* Restore the queue.  */
   parser->unparsed_functions_queues
     = TREE_CHAIN (parser->unparsed_functions_queues);
@@ -14817,7 +15233,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 
   /* Initialize FORMAT the first time we get here.  */
   if (!format)
-    format = "types may not be defined in `%s' expressions";
+    format = "types may not be defined in '%s' expressions";
 
   /* Types cannot be defined in a `sizeof' expression.  Save away the
      old message.  */
@@ -14855,18 +15271,19 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
       type = cp_parser_type_id (parser);
       parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
       /* Now, look for the trailing `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
       /* 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);
@@ -14900,24 +15317,65 @@ cp_parser_declares_only_class_p (cp_parser *parser)
          || cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
 }
 
-/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
-   Returns TRUE iff `friend' appears among the DECL_SPECIFIERS.  */
+/* Update the DECL_SPECS to reflect the STORAGE_CLASS.  */
 
-static bool
-cp_parser_friend_p (tree decl_specifiers)
+static void
+cp_parser_set_storage_class (cp_decl_specifier_seq *decl_specs,
+                            cp_storage_class storage_class)
 {
-  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;
+  if (decl_specs->storage_class != sc_none)
+    decl_specs->multiple_storage_classes_p = true;
+  else
+    decl_specs->storage_class = storage_class;
+}
 
-      /* Go on to the next decl-specifier.  */
-      decl_specifiers = TREE_CHAIN (decl_specifiers);
+/* 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.  */
+
+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 false;
+/* 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 (const cp_decl_specifier_seq *decl_specifiers)
+{
+  return decl_specifiers->specs[(int) ds_friend] != 0;
 }
 
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
@@ -15050,9 +15508,7 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser)
 }
 
 /* Returns TRUE iff the next token is the "," or ">" ending a
-   template-argument. ">>" is also accepted (after the full
-   argument was parsed) because it's probably a typo for "> >",
-   and there is a specific diagnostic for this.  */
+   template-argument.  */
 
 static bool
 cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
@@ -15060,8 +15516,7 @@ 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
-         || token->type == CPP_RSHIFT);
+  return (token->type == CPP_COMMA || token->type == CPP_GREATER);
 }
 
 /* Returns TRUE iff the n-th token is a ">", or the n-th is a "[" and the
@@ -15115,7 +15570,7 @@ static void
 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'",
+    pedwarn ("%qs tag used in naming %q#T",
            class_key == union_type ? "union"
             : class_key == record_type ? "struct" : "class",
             type);
@@ -15126,7 +15581,8 @@ cp_parser_check_class_key (enum tag_types class_key, tree type)
    This applies to nested classes and nested class templates.
    [class.mem/1].  */
 
-static void cp_parser_check_access_in_redeclaration (tree decl)
+static void
+cp_parser_check_access_in_redeclaration (tree decl)
 {
   if (!CLASS_TYPE_P (TREE_TYPE (decl)))
     return;
@@ -15135,7 +15591,7 @@ static void cp_parser_check_access_in_redeclaration (tree decl)
        != (current_access_specifier == access_private_node))
       || (TREE_PROTECTED (decl)
          != (current_access_specifier == access_protected_node)))
-    error ("%D redeclared with different access", decl);
+    error ("%qD redeclared with different access", decl);
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
@@ -15152,7 +15608,7 @@ cp_parser_optional_template_keyword (cp_parser *parser)
         template and what is not.  */
       if (!processing_template_decl)
        {
-         error ("`template' (as a disambiguator) is only allowed "
+         error ("%<template%> (as a disambiguator) is only allowed "
                 "within templates");
          /* If this part of the token stream is rescanned, the same
             error message would be generated.  So, we purge the token
@@ -15191,11 +15647,10 @@ cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
   parser->object_scope = NULL_TREE;
 }
 
-/* Add tokens to CACHE until a non-nested END token appears.  */
+/* Consume tokens up through a non-nested END token.  */
 
 static void
 cp_parser_cache_group (cp_parser *parser,
-                      cp_token_cache *cache,
                       enum cpp_ttype end,
                       unsigned depth)
 {
@@ -15212,17 +15667,15 @@ cp_parser_cache_group (cp_parser *parser,
        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 (parser, 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 (parser, CPP_CLOSE_PAREN, depth + 1);
       else if (token->type == end)
        return;
     }
@@ -15347,7 +15800,6 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser)
 }
 
 \f
-
 /* The parser.  */
 
 static GTY (()) cp_parser *the_parser;
@@ -15360,6 +15812,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