OSDN Git Service

PR preprocessor/34692
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Jan 2008 09:01:27 +0000 (09:01 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 25 Jan 2008 09:01:27 +0000 (09:01 +0000)
* macro.c (collect_args): Add pragma_buff argument.  Push
CPP_PRAGMA ... CPP_PRAGMA_EOL tokens to *pragma_buff, rather
than into arguments.  Reset prevent_expansion and parsing_args
state at CPP_PRAGMA_EOL/CPP_EOF.
(funlike_invocation_p): Add pragma_buff argument, pass it through
to collect_args.
(enter_macro_context): Add result argument.  Adjust
funlike_invocation_p caller.  Emit all deferred pragma tokens
gathered during collect_args before the expansion, add a padding
token.  Return 2 instead of 1 if any pragma tokens were prepended.
(cpp_get_token): If enter_macro_context returns 2, don't return
a padding token, instead cycle to grab CPP_PRAGMA token.
* directives.c (_cpp_handle_directive): If was_parsing_args
in deferred pragma, leave parsing_args and prevent_expansion as is.

* gcc.dg/cpp/pr34692.c: New test.
* gcc.dg/gomp/pr34692.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131819 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/cpp/pr34692.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gomp/pr34692.c [new file with mode: 0644]
libcpp/ChangeLog
libcpp/directives.c
libcpp/macro.c

index 8705d66..a722cb3 100644 (file)
@@ -1,3 +1,9 @@
+2008-01-25  Jakub Jelinek  <jakub@redhat.com>
+
+       PR preprocessor/34692
+       * gcc.dg/cpp/pr34692.c: New test.
+       * gcc.dg/gomp/pr34692.c: New test.
+
 2008-01-25  Olga Golovanevsky  <olga@il.ibm.com>
 
         * gcc.dg/struct/wo_prof_malloc_size_var.c: UnXFAIL.
 2008-01-25  Olga Golovanevsky  <olga@il.ibm.com>
 
         * gcc.dg/struct/wo_prof_malloc_size_var.c: UnXFAIL.
diff --git a/gcc/testsuite/gcc.dg/cpp/pr34692.c b/gcc/testsuite/gcc.dg/cpp/pr34692.c
new file mode 100644 (file)
index 0000000..bcb0ca3
--- /dev/null
@@ -0,0 +1,35 @@
+/* PR preprocessor/34692 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+/* { dg-require-visibility "" } */
+/* { dg-final { scan-hidden "vara" } } */
+/* { dg-final { scan-hidden "varb" } } */
+/* { dg-final { scan-hidden "varc" } } */
+/* { dg-final { scan-hidden "vard" } } */
+/* { dg-final { scan-assembler "a b cde f g h" } } */
+
+#define FOO(y, x) y #x
+#define BAR(x) x
+#define BAZ(x) x
+FOO (const char *vara =,
+a
+#pragma GCC visibility push(hidden)
+b
+#pragma GCC visibility push(hidden)
+cde f g h);
+int varb = 6;
+#pragma GCC visibility pop
+#pragma GCC visibility pop
+FOO (
+BAR (
+#pragma GCC visibility push(hidden)
+const) char *varc =,);
+#pragma GCC visibility pop
+FOO (
+BAR (
+BAZ (
+#pragma GCC visibility push(hidden)
+#pragma GCC visibility push(hidden)
+const) char) *vard =,);
+#pragma GCC visibility pop
+#pragma GCC visibility pop
diff --git a/gcc/testsuite/gcc.dg/gomp/pr34692.c b/gcc/testsuite/gcc.dg/gomp/pr34692.c
new file mode 100644 (file)
index 0000000..0e1a1eb
--- /dev/null
@@ -0,0 +1,26 @@
+/* PR preprocessor/34692 */
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+/* { dg-final { scan-tree-dump-times "#pragma omp parallel" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "#pragma omp for private" 1 "gimple" } } */
+
+void
+foo (void)
+{
+  int i;
+#define FOO(y, x) y #x
+#define BAR(x) x
+#define BAZ(x) x
+FOO (for (i = 0; i < 10; i++) { const char *vara =,
+a
+#define P parallel
+#pragma omp P
+#undef P
+#define P for
+b
+#pragma omp P
+#undef P
+#define parallel atomic
+cde f g h);
+  }
+}
index eb2a35c..a14c38e 100644 (file)
@@ -1,12 +1,30 @@
+2008-01-25  Jakub Jelinek  <jakub@redhat.com>
+
+       PR preprocessor/34692
+       * macro.c (collect_args): Add pragma_buff argument.  Push
+       CPP_PRAGMA ... CPP_PRAGMA_EOL tokens to *pragma_buff, rather
+       than into arguments.  Reset prevent_expansion and parsing_args
+       state at CPP_PRAGMA_EOL/CPP_EOF.
+       (funlike_invocation_p): Add pragma_buff argument, pass it through
+       to collect_args.
+       (enter_macro_context): Add result argument.  Adjust
+       funlike_invocation_p caller.  Emit all deferred pragma tokens
+       gathered during collect_args before the expansion, add a padding
+       token.  Return 2 instead of 1 if any pragma tokens were prepended.
+       (cpp_get_token): If enter_macro_context returns 2, don't return
+       a padding token, instead cycle to grab CPP_PRAGMA token.
+       * directives.c (_cpp_handle_directive): If was_parsing_args
+       in deferred pragma, leave parsing_args and prevent_expansion as is.
+
 2008-01-22  Tom Tromey  <tromey@redhat.com>
 
 2008-01-22  Tom Tromey  <tromey@redhat.com>
 
-       PR c++/34859:
+       PR c++/34859
        * macro.c (_cpp_create_definition): Handle __STDC_LIMIT_MACROS and
        __STDC_CONSTANT_MACROS.
 
 2008-01-07  Fred Fish  <fnf@specifix.com>
 
        * macro.c (_cpp_create_definition): Handle __STDC_LIMIT_MACROS and
        __STDC_CONSTANT_MACROS.
 
 2008-01-07  Fred Fish  <fnf@specifix.com>
 
-       PR preprocessor/30363:
+       PR preprocessor/30363
        * traditional.c (replace_args_and_push): Add local variable
        cxtquote, calculate the replacement text size assuming a 
        worst case of every input character quoted with backslash,
        * traditional.c (replace_args_and_push): Add local variable
        cxtquote, calculate the replacement text size assuming a 
        worst case of every input character quoted with backslash,
@@ -15,7 +33,7 @@
 
 2008-01-03  Tom Tromey  <tromey@redhat.com>
 
 
 2008-01-03  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/34602.
+       PR preprocessor/34602
        * directives.c (do_line): Don't try to spell EOF token.
        (do_linemarker): Add comment.
 
        * directives.c (do_line): Don't try to spell EOF token.
        (do_linemarker): Add comment.
 
@@ -26,7 +44,7 @@
 
 2007-12-06  Tom Tromey  <tromey@redhat.com>
 
 
 2007-12-06  Tom Tromey  <tromey@redhat.com>
 
-       PR c/29172:
+       PR c/29172
        * internal.h (struct cpp_reader) <file_hash_entries>: Changed
        type.
        <file_hash_entries_allocated, file_hash_entries_used>: Removed.
        * internal.h (struct cpp_reader) <file_hash_entries>: Changed
        type.
        <file_hash_entries_allocated, file_hash_entries_used>: Removed.
 
 2007-12-03  Tom Tromey  <tromey@redhat.com>
 
 
 2007-12-03  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/34288:
+       PR preprocessor/34288
        * configure.ac, config.in: Rebuilt.
        * configure.ac: Check for ssize_t.
 
 2007-11-30  Tom Tromey  <tromey@redhat.com>
 
        * configure.ac, config.in: Rebuilt.
        * configure.ac: Check for ssize_t.
 
 2007-11-30  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/32868:
+       PR preprocessor/32868
        * macro.c (_cpp_create_definition): Special case
        __STDC_FORMAT_MACROS.
 
        * macro.c (_cpp_create_definition): Special case
        __STDC_FORMAT_MACROS.
 
@@ -59,7 +77,7 @@
 
 2007-11-11  Tom Tromey  <tromey@redhat.com>
 
 
 2007-11-11  Tom Tromey  <tromey@redhat.com>
 
-       PR c++/17557:
+       PR c++/17557
        * include/cpplib.h (cpp_included_before): Declare.
        * files.c (struct file_hash_entry) <location>: New field.
        (_cpp_find_file): Initialize new field.
        * include/cpplib.h (cpp_included_before): Declare.
        * files.c (struct file_hash_entry) <location>: New field.
        (_cpp_find_file): Initialize new field.
 
 2007-11-01  Tom Tromey  <tromey@redhat.com>
 
 
 2007-11-01  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/30805:
+       PR preprocessor/30805
        * macro.c (paste_tokens): Handle padding token.
        (paste_tokens): Don't abort unless padding has PASTE_LEFT flag.
 
 2007-10-31  Tom Tromey  <tromey@redhat.com>
 
        * macro.c (paste_tokens): Handle padding token.
        (paste_tokens): Don't abort unless padding has PASTE_LEFT flag.
 
 2007-10-31  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/30786:
+       PR preprocessor/30786
        * macro.c (builtin_macro): Return result of _cpp_do__Pragma.
        * directives.c (_cpp_do__Pragma): Return error status.
        * internal.h (_cpp_do__Pragma): Update.
        * macro.c (builtin_macro): Return result of _cpp_do__Pragma.
        * directives.c (_cpp_do__Pragma): Return error status.
        * internal.h (_cpp_do__Pragma): Update.
 
 2007-08-18  Tom Tromey  <tromey@redhat.com>
 
 
 2007-08-18  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/32974:
+       PR preprocessor/32974
        * directives.c (parse_include): Don't check for EOL when
        processing #pragma dependency.
 
        * directives.c (parse_include): Don't check for EOL when
        processing #pragma dependency.
 
 
 2007-05-02  Tom Tromey  <tromey@redhat.com>
 
 
 2007-05-02  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/28709:
+       PR preprocessor/28709
        * macro.c (paste_tokens): Remove PASTE_LEFT from the old lhs.
 
 2007-03-30  Michael Meissner  <michael.meissner@amd.com>
        * macro.c (paste_tokens): Remove PASTE_LEFT from the old lhs.
 
 2007-03-30  Michael Meissner  <michael.meissner@amd.com>
 
 2007-01-30  Tom Tromey  <tromey@redhat.com>
 
 
 2007-01-30  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/30468:
+       PR preprocessor/30468
        * mkdeps.c (apply_vpath): Strip successive '/'s if we stripped
        './'.
 
 2007-01-30  Tom Tromey  <tromey@redhat.com>
 
        * mkdeps.c (apply_vpath): Strip successive '/'s if we stripped
        './'.
 
 2007-01-30  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/29966:
+       PR preprocessor/29966
        * macro.c (lex_expansion_token): Save and restore cpp_reader's
        cur_token.
        (_cpp_create_definition): Don't restore cur_token here.
        * macro.c (lex_expansion_token): Save and restore cpp_reader's
        cur_token.
        (_cpp_create_definition): Don't restore cur_token here.
 
 2007-01-12  Tom Tromey  <tromey@redhat.com>
 
 
 2007-01-12  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/28227:
+       PR preprocessor/28227
        * directives.c (lex_macro_node): Added 'is_def_or_undef'
        argument.
        (do_define): Update.
        * directives.c (lex_macro_node): Added 'is_def_or_undef'
        argument.
        (do_define): Update.
 
 2007-01-04  Tom Tromey  <tromey@redhat.com>
 
 
 2007-01-04  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/28165:
+       PR preprocessor/28165
        * internal.h (cpp_in_primary_file): New function.
        * directives.c (do_include_next): Use cpp_in_primary_file.
        (do_pragma_once): Likewise.
        * internal.h (cpp_in_primary_file): New function.
        * directives.c (do_include_next): Use cpp_in_primary_file.
        (do_pragma_once): Likewise.
 
 2006-12-28  Tom Tromey  <tromey@redhat.com>
 
 
 2006-12-28  Tom Tromey  <tromey@redhat.com>
 
-       PR preprocessor/30001:
+       PR preprocessor/30001
        * charset.c (_cpp_convert_input): Check that to.len is greater
        than zero.
 
        * charset.c (_cpp_convert_input): Check that to.len is greater
        than zero.
 
index 6e2e55c..c77e84b 100644 (file)
@@ -475,7 +475,7 @@ _cpp_handle_directive (cpp_reader *pfile, int indented)
     _cpp_backup_tokens (pfile, 1);
 
   end_directive (pfile, skip);
     _cpp_backup_tokens (pfile, 1);
 
   end_directive (pfile, skip);
-  if (was_parsing_args)
+  if (was_parsing_args && !pfile->state.in_deferred_pragma)
     {
       /* Restore state when within macro args.  */
       pfile->state.parsing_args = 2;
     {
       /* Restore state when within macro args.  */
       pfile->state.parsing_args = 2;
index 3a3bf41..fd624b1 100644 (file)
@@ -41,11 +41,13 @@ struct macro_arg
 
 /* Macro expansion.  */
 
 
 /* Macro expansion.  */
 
-static int enter_macro_context (cpp_reader *, cpp_hashnode *);
+static int enter_macro_context (cpp_reader *, cpp_hashnode *,
+                               const cpp_token *);
 static int builtin_macro (cpp_reader *, cpp_hashnode *);
 static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
                                 const cpp_token **, unsigned int);
 static int builtin_macro (cpp_reader *, cpp_hashnode *);
 static void push_ptoken_context (cpp_reader *, cpp_hashnode *, _cpp_buff *,
                                 const cpp_token **, unsigned int);
-static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *);
+static _cpp_buff *collect_args (cpp_reader *, const cpp_hashnode *,
+                               _cpp_buff **);
 static cpp_context *next_context (cpp_reader *);
 static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
 static void expand_arg (cpp_reader *, macro_arg *);
 static cpp_context *next_context (cpp_reader *);
 static const cpp_token *padding_token (cpp_reader *, const cpp_token *);
 static void expand_arg (cpp_reader *, macro_arg *);
@@ -55,7 +57,8 @@ static void paste_all_tokens (cpp_reader *, const cpp_token *);
 static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *);
 static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *,
                          macro_arg *);
 static bool paste_tokens (cpp_reader *, const cpp_token **, const cpp_token *);
 static void replace_args (cpp_reader *, cpp_hashnode *, cpp_macro *,
                          macro_arg *);
-static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *);
+static _cpp_buff *funlike_invocation_p (cpp_reader *, cpp_hashnode *,
+                                       _cpp_buff **);
 static bool create_iso_definition (cpp_reader *, cpp_macro *);
 
 /* #define directive parsing and handling.  */
 static bool create_iso_definition (cpp_reader *, cpp_macro *);
 
 /* #define directive parsing and handling.  */
@@ -575,9 +578,12 @@ _cpp_arguments_ok (cpp_reader *pfile, cpp_macro *macro, const cpp_hashnode *node
    invocation.  Assumes the opening parenthesis has been processed.
    If there is an error, emits an appropriate diagnostic and returns
    NULL.  Each argument is terminated by a CPP_EOF token, for the
    invocation.  Assumes the opening parenthesis has been processed.
    If there is an error, emits an appropriate diagnostic and returns
    NULL.  Each argument is terminated by a CPP_EOF token, for the
-   future benefit of expand_arg().  */
+   future benefit of expand_arg().  If there are any deferred
+   #pragma directives among macro arguments, store pointers to the
+   CPP_PRAGMA ... CPP_PRAGMA_EOL tokens into *PRAGMA_BUFF buffer.  */
 static _cpp_buff *
 static _cpp_buff *
-collect_args (cpp_reader *pfile, const cpp_hashnode *node)
+collect_args (cpp_reader *pfile, const cpp_hashnode *node,
+             _cpp_buff **pragma_buff)
 {
   _cpp_buff *buff, *base_buff;
   cpp_macro *macro;
 {
   _cpp_buff *buff, *base_buff;
   cpp_macro *macro;
@@ -645,6 +651,51 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node)
          else if (token->type == CPP_EOF
                   || (token->type == CPP_HASH && token->flags & BOL))
            break;
          else if (token->type == CPP_EOF
                   || (token->type == CPP_HASH && token->flags & BOL))
            break;
+         else if (token->type == CPP_PRAGMA)
+           {
+             cpp_token *newtok = _cpp_temp_token (pfile);
+
+             /* CPP_PRAGMA token lives in directive_result, which will
+                be overwritten on the next directive.  */
+             *newtok = *token;
+             token = newtok;
+             do
+               {
+                 if (*pragma_buff == NULL
+                     || BUFF_ROOM (*pragma_buff) < sizeof (cpp_token *))
+                   {
+                     _cpp_buff *next;
+                     if (*pragma_buff == NULL)
+                       *pragma_buff
+                         = _cpp_get_buff (pfile, 32 * sizeof (cpp_token *));
+                     else
+                       {
+                         next = *pragma_buff;
+                         *pragma_buff
+                           = _cpp_get_buff (pfile,
+                                            (BUFF_FRONT (*pragma_buff)
+                                             - (*pragma_buff)->base) * 2);
+                         (*pragma_buff)->next = next;
+                       }
+                   }
+                 *(const cpp_token **) BUFF_FRONT (*pragma_buff) = token;
+                 BUFF_FRONT (*pragma_buff) += sizeof (cpp_token *);
+                 if (token->type == CPP_PRAGMA_EOL)
+                   break;
+                 token = cpp_get_token (pfile);
+               }
+             while (token->type != CPP_EOF);
+
+             /* In deferred pragmas parsing_args and prevent_expansion
+                had been changed, reset it.  */
+             pfile->state.parsing_args = 2;
+             pfile->state.prevent_expansion = 1;
+
+             if (token->type == CPP_EOF)
+               break;
+             else
+               continue;
+           }
 
          arg->first[ntokens++] = token;
        }
 
          arg->first[ntokens++] = token;
        }
@@ -709,9 +760,11 @@ collect_args (cpp_reader *pfile, const cpp_hashnode *node)
 /* Search for an opening parenthesis to the macro of NODE, in such a
    way that, if none is found, we don't lose the information in any
    intervening padding tokens.  If we find the parenthesis, collect
 /* Search for an opening parenthesis to the macro of NODE, in such a
    way that, if none is found, we don't lose the information in any
    intervening padding tokens.  If we find the parenthesis, collect
-   the arguments and return the buffer containing them.  */
+   the arguments and return the buffer containing them.  PRAGMA_BUFF
+   argument is the same as in collect_args.  */
 static _cpp_buff *
 static _cpp_buff *
-funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
+funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node,
+                     _cpp_buff **pragma_buff)
 {
   const cpp_token *token, *padding = NULL;
 
 {
   const cpp_token *token, *padding = NULL;
 
@@ -728,7 +781,7 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
   if (token->type == CPP_OPEN_PAREN)
     {
       pfile->state.parsing_args = 2;
   if (token->type == CPP_OPEN_PAREN)
     {
       pfile->state.parsing_args = 2;
-      return collect_args (pfile, node);
+      return collect_args (pfile, node, pragma_buff);
     }
 
   /* CPP_EOF can be the end of macro arguments, or the end of the
     }
 
   /* CPP_EOF can be the end of macro arguments, or the end of the
@@ -749,9 +802,13 @@ funlike_invocation_p (cpp_reader *pfile, cpp_hashnode *node)
 /* Push the context of a macro with hash entry NODE onto the context
    stack.  If we can successfully expand the macro, we push a context
    containing its yet-to-be-rescanned replacement list and return one.
 /* Push the context of a macro with hash entry NODE onto the context
    stack.  If we can successfully expand the macro, we push a context
    containing its yet-to-be-rescanned replacement list and return one.
-   Otherwise, we don't push a context and return zero.  */
+   If there were additionally any unexpanded deferred #pragma directives
+   among macro arguments, push another context containing the
+   pragma tokens before the yet-to-be-rescanned replacement list
+   and return two.  Otherwise, we don't push a context and return zero.  */
 static int
 static int
-enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
+enter_macro_context (cpp_reader *pfile, cpp_hashnode *node,
+                    const cpp_token *result)
 {
   /* The presence of a macro invalidates a file's controlling macro.  */
   pfile->mi_valid = false;
 {
   /* The presence of a macro invalidates a file's controlling macro.  */
   pfile->mi_valid = false;
@@ -762,6 +819,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
   if (! (node->flags & NODE_BUILTIN))
     {
       cpp_macro *macro = node->value.macro;
   if (! (node->flags & NODE_BUILTIN))
     {
       cpp_macro *macro = node->value.macro;
+      _cpp_buff *pragma_buff = NULL;
 
       if (macro->fun_like)
        {
 
       if (macro->fun_like)
        {
@@ -770,7 +828,7 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
          pfile->state.prevent_expansion++;
          pfile->keep_tokens++;
          pfile->state.parsing_args = 1;
          pfile->state.prevent_expansion++;
          pfile->keep_tokens++;
          pfile->state.parsing_args = 1;
-         buff = funlike_invocation_p (pfile, node);
+         buff = funlike_invocation_p (pfile, node, &pragma_buff);
          pfile->state.parsing_args = 0;
          pfile->keep_tokens--;
          pfile->state.prevent_expansion--;
          pfile->state.parsing_args = 0;
          pfile->keep_tokens--;
          pfile->state.prevent_expansion--;
@@ -782,6 +840,9 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
  "function-like macro \"%s\" must be used with arguments in traditional C",
                           NODE_NAME (node));
 
  "function-like macro \"%s\" must be used with arguments in traditional C",
                           NODE_NAME (node));
 
+             if (pragma_buff)
+               _cpp_release_buff (pfile, pragma_buff);
+
              return 0;
            }
 
              return 0;
            }
 
@@ -798,6 +859,25 @@ enter_macro_context (cpp_reader *pfile, cpp_hashnode *node)
       if (macro->paramc == 0)
        _cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count);
 
       if (macro->paramc == 0)
        _cpp_push_token_context (pfile, node, macro->exp.tokens, macro->count);
 
+      if (pragma_buff)
+       {
+         if (!pfile->state.in_directive)
+           _cpp_push_token_context (pfile, NULL,
+                                    padding_token (pfile, result), 1);
+         do
+           {
+             _cpp_buff *tail = pragma_buff->next;
+             pragma_buff->next = NULL;
+             push_ptoken_context (pfile, NULL, pragma_buff,
+                                  (const cpp_token **) pragma_buff->base,
+                                  ((const cpp_token **) BUFF_FRONT (pragma_buff)
+                                   - (const cpp_token **) pragma_buff->base));
+             pragma_buff = tail;
+           }
+         while (pragma_buff != NULL);
+         return 2;
+       }
+
       return 1;
     }
 
       return 1;
     }
 
@@ -1144,14 +1224,17 @@ cpp_get_token (cpp_reader *pfile)
 
       if (!(node->flags & NODE_DISABLED))
        {
 
       if (!(node->flags & NODE_DISABLED))
        {
+         int ret;
          /* If not in a macro context, and we're going to start an
             expansion, record the location.  */
          if (can_set && !context->macro)
            pfile->invocation_location = result->src_loc;
          /* If not in a macro context, and we're going to start an
             expansion, record the location.  */
          if (can_set && !context->macro)
            pfile->invocation_location = result->src_loc;
-         if (!pfile->state.prevent_expansion
-             && enter_macro_context (pfile, node))
+         if (pfile->state.prevent_expansion)
+           break;
+         ret = enter_macro_context (pfile, node, result);
+         if (ret)
            {
            {
-             if (pfile->state.in_directive)
+             if (pfile->state.in_directive || ret == 2)
                continue;
              return padding_token (pfile, result);
            }
                continue;
              return padding_token (pfile, result);
            }