+2004-09-21  Zack Weinberg  <zack@codesourcery.com>
+
+       * parser.c (cp_lexer_peek_token, cp_lexer_consume_token):
+       Don't handle CPP_PRAGMA tokens specially.
+       (cp_lexer_handle_pragma): Use cp_lexer_consume_token.  Don't
+       purge the token; do clear token->value after processing.  Add
+       assertion at beginning that token->value is nonzero.
+       (cp_parser_statement, cp_parser_declaration_seq_opt): Handle
+       CPP_PRAGMA as a full statement or declaration in its own right.
+
 2004-09-21  Matt Austern  <austern@apple.com>
 
        PR c++/15049
        * decl.c (grokvardecl): Accept declarations of global variables
        using anonymous types.
-       
+
 2004-09-21  Roger Sayle  <roger@eyesopen.com>
 
        PR c++/7503
 
   if (lexer->next_token->type == CPP_PURGED)
     cp_lexer_skip_purged_tokens (lexer);
 
-  if (lexer->next_token->type == CPP_PRAGMA)
-    cp_lexer_handle_pragma (lexer);
-
   token = lexer->next_token;
 
   /* Provide debugging output.  */
   if (lexer->next_token->type == CPP_PURGED)
     cp_lexer_skip_purged_tokens (lexer);
 
-  if (lexer->next_token->type == CPP_PRAGMA)
-    cp_lexer_handle_pragma (lexer);
-
   token = lexer->next_token++;
 
   /* Provide debugging output.  */
     }
 }
 
-/* Handle a pragma token and skip over it. We need the loop because
-   the next token might also be a pragma token. */
+/* Consume and handle a pragma token.   */
 static void
 cp_lexer_handle_pragma (cp_lexer *lexer)
 {
-  gcc_assert (lexer->next_token->type == CPP_PRAGMA);
+  cpp_string s;
+  cp_token *token = cp_lexer_consume_token (lexer);
+  gcc_assert (token->type == CPP_PRAGMA);
+  gcc_assert (token->value);
 
-  while (lexer->next_token->type == CPP_PRAGMA)
-    {
-      tree t = lexer->next_token->value;
-      cpp_string s;
-      s.len = TREE_STRING_LENGTH (t);
-      s.text = (const unsigned char *) TREE_STRING_POINTER (t);
+  s.len = TREE_STRING_LENGTH (token->value);
+  s.text = (const unsigned char *) TREE_STRING_POINTER (token->value);
 
-      cp_lexer_set_source_position_from_token (lexer, lexer->next_token);
-      cpp_handle_deferred_pragma (parse_in, &s);
+  cp_lexer_set_source_position_from_token (lexer, token);
+  cpp_handle_deferred_pragma (parse_in, &s);
 
-      /* Make sure we don't run this pragma twice. */
-      cp_lexer_purge_token (lexer);
-      cp_lexer_skip_purged_tokens (lexer);
-    }
+  /* 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
   /* Anything that starts with a `{' must be a compound-statement.  */
   else if (token->type == CPP_OPEN_BRACE)
     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
          continue;
        }
 
+      if (token->type == CPP_PRAGMA)
+       {
+         /* 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;
+       }
+
       /* 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)