This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

re: macro expansion in pragmas


    On Fri, Sep 29, 2006 at 06:40:29PM -0700, Ian Lance Taylor wrote:
    > This is an interesting idea, but it seems to me that pragma expansion
    > should itself be under the control of a pragma.  Otherwise you have
    > program which will have surprisingly different behaviour depending
    > upon the command line options used.  Is that doable?

Yes, I don't see any problem with this.  Normally you'd put the option
into the makefile, I'd expect.  

    On Sat, 30 Sep 2006 03:17:25 -0400, Jakub Jelinek wrote:
    > libcpp already supports expansion/non-expansion on a per-pragma
    > namespace basis.  When registering a pragma with a namespace,
    > you can say if it will be macro expanded or not.  So, e.g. omp
    > namespace is always macro expanded, STDC namespace is not, pack
    > namespace is expanded or not expanded depending on the habits of
    > the target for compatibility with other compilers on the target,
    > etc.  The namespace name itself is never expanded, which is IMHO
    > a good thing.

I haven't looked at the C standard in a long time but I wasn't aware
that pragma namespaces were part of the standard (are they?).  In
particular, the application that this patch was written for expects

   #define FOO BAR
   #pragma FOO

to result in passing "#pragma BAR" out of the preprocessor.  The app
was originally written for Microsoft C and that's apparently what
Microsoft C does with macros in pragmas.  In this instance, FOO would
be the namespace name, and it has to be expanded.

I hadn't really thought about controlling expansion with a pragma,
since it would mean having to insert the pragma (possibly through an
#include) into every source file that needs expansion, a pretty ugly
thing IMO.  Does anyone really favor that approach?

Per Andrew Pinski's suggestion I replaced -expand-pragmas with
-fexpand-pragmas, which eliminates the need to modify gcc.c (thanks!).
I also added a crude test of an omp pragma with the expansion option
enabled, but I should figure out some more thorough tests of this.

A revised patch (still against 117181) follows.  I've removed the
ChangeLog diffs from the patch and have broken them out, also per
Andrew.

--Paul

================================================================

gcc/testsuite/ChangeLog	entry:

2006-09-24  Paul Rubin <phr-gcc@nightsong.com>
 
 	* gcc.dg/cpp/pragma-exp0.c, gcc.dg/cpp/pragma-exp0.c:
 	new tests.

gcc/ChangeLog entry:

2006-09-24  Paul Rubin  <phr-gcc@nightsong.com>

	* c-ppoutput.c (cb_def_pragma): use scan_translation_unit
	instead of cpp_output_line to copy pragmas, allowing re-use
	of scan_translation_unit's complex paste avoidance logic.
        (preprocess_file): pass new arg to scan_translation_unit.
	(scan_translation_unit): add 'ipad' arg for use with pragma expansion.

	*  c.opt (expand-pragmas): new flag.

	* c-opts.c (c_common_handle_option) add OPT_expand_pragmas

	* gcc.c (option_map): add -expand-pragmas
	(cpp_options): add (--expand-pragmas)



bash-3.00$ svn diff
Index: gcc/doc/cpp.texi
===================================================================
--- gcc/doc/cpp.texi	(revision 117181)
+++ gcc/doc/cpp.texi	(working copy)
@@ -3859,9 +3859,19 @@
 @item Treatment of a @samp{#pragma} directive that after macro-expansion
 results in a standard pragma.
 
-No macro expansion occurs on any @samp{#pragma} directive line, so the
-question does not arise.
+Macro expansion in #pragma directives is controlled by the 
+@option{-expand-pragmas} command line option.  If this option is not
+enabled, then no macro expansion occurs on any @samp{#pragma}
+directive line, so the question does not arise.
 
+If the option is enabled, then macros are expanded in #pragma
+directives, @emph{except} for the STDC pragmas.  C99 requires that
+STDC pragmas @emph{not} be expanded.
+
+The @option{-expand-pragmas} option is intended to tell GCC how to
+treat pragma expansion more similarly to how Microsoft C treats it.
+This makes porting code from Microsoft C easier in some circumstances.
+
 Note that GCC does not yet implement any of the standard
 pragmas.
 
Index: gcc/doc/cppopts.texi
===================================================================
--- gcc/doc/cppopts.texi	(revision 117181)
+++ gcc/doc/cppopts.texi	(working copy)
@@ -344,6 +344,20 @@
 location.  The filename may be absolute or it may be relative to GCC's
 current directory.
 
+@item -expand-pragmas
+@opindex expand-pragmas
+This option instructs the preprocessor to expand preprocessor macros
+inside @code{pragma} directives, similarly (but maybe not identically)
+to how Microsoft C does it.  GCC's default is to never expand macros
+in @code{#pragma} directives.
+
+With @option{-expand-pragmas} set, GCC expands macros in pragmas,
+except for pragmas in the @code{STDC} namespace.  The C99 standard
+prohibits expansion of some specific pragmas, all of which are in
+@code{STDC}.  The standard leaves expansion of the other pragmas up to
+implementations.
+
+
 @end ifclear
 @item -x c
 @itemx -x c++
Index: gcc/gcc.c
===================================================================
--- gcc/gcc.c	(revision 117181)
+++ gcc/gcc.c	(working copy)
@@ -789,6 +789,7 @@
 static const char *cpp_options =
 "%(cpp_unique_options) %1 %{m*} %{std*&ansi&trigraphs} %{W*&pedantic*} %{w}\
  %{f*} %{g*:%{!g0:%{!fno-working-directory:-fworking-directory}}} %{O*}\
+ %{expand-pragmas}\
  %{undef} %{save-temps:-fpch-preprocess}";
 
 /* This contains cpp options which are not passed when the preprocessor
@@ -1078,6 +1079,7 @@
    {"--dumpbase", "-dumpbase", "a"},
    {"--encoding", "-fencoding=", "aj"},
    {"--entry", "-e", 0},
+   {"--expand-pragmas", "-expand-pragmas", 0},
    {"--extra-warnings", "-W", 0},
    {"--extdirs", "-fextdirs=", "aj"},
    {"--for-assembler", "-Wa", "a"},
Index: gcc/testsuite/gcc.dg/cpp/pragma-exp0.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/pragma-exp0.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/pragma-exp0.c	(revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do preprocess } */
+
+/* Test that without -expand-pragmas, preprocessor symbols in pragmas
+   don't get expanded.
+ */
+
+
+#pragma frobozz
+int x = 3;
+
+#define frobozz muffin
+#pragma frobozz
+
+/* make sure there's not unwanted token pasting */
+#define FOO abc
+#define BAR def
+#pragma FOO BAR ghi
+
+/* { dg-final { scan-file pragma-exp0.i "#pragma frobozz" } } */
+/* { dg-final { scan-file-not pragma-exp0.i "#pragma muffin" } } */
+/* { dg-final { scan-file pragma-exp0.i "#pragma FOO BAR ghi" } } */
Index: gcc/testsuite/gcc.dg/cpp/pragma-exp1.c
===================================================================
--- gcc/testsuite/gcc.dg/cpp/pragma-exp1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cpp/pragma-exp1.c	(revision 0)
@@ -0,0 +1,44 @@
+/* { dg-do preprocess } */
+/* { dg-options -expand-pragmas } */
+
+/* test that expand-pragmas causes pragma <preprocessor symbol>
+   to get expanded */
+
+#pragma frobozz
+int x = 3;
+
+#define frobozz muffin
+#pragma frobozz
+
+/* make sure there's not unwanted token pasting */
+#define FOO abc
+#define BAR def
+#pragma FOO BAR ghi
+
+/* check that STDC pragmas aren't expanded, per C99 */
+#pragma STDC abc FOO xyz
+
+/* even if STDC is redefined */
+#define STDC blah
+#pragma STDC abc2 FOO xyz
+
+/* expand a macro with arguments */
+#define ADD(x,y,z) x+y+z
+
+/* check that macro with args gets expanded correctly at beginning of
+   pragma */
+#pragma ADD(a,b,c) xyz
+
+/* and also when not at the beginning */
+#pragma xyz ADD(a,b,c)
+
+
+/* { dg-final { scan-file pragma-exp1.i "#pragma frobozz" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma muffin" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma abc def ghi" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma STDC abc FOO xyz" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma STDC abc2 FOO xyz" } } */
+/* { dg-final { scan-file-not pragma-exp1.i "#pragma STDC abc abc xyz" } } */
+/* { dg-final { scan-file-not pragma-exp1.i "#pragma blah" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma a\\+b\\+c xyz" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma xyz a\\+b\\+c" } } */
Index: gcc/c.opt
===================================================================
--- gcc/c.opt	(revision 117181)
+++ gcc/c.opt	(working copy)
@@ -435,6 +435,10 @@
 C ObjC C++ ObjC++ Joined
 ; Documented in common.opt.  FIXME - what about -dI, -dD, -dN and -dD?
 
+expand-pragmas
+C ObjC C++ ObjC++
+Expand preprocessor macros in #pragma statements
+
 faccess-control
 C++ ObjC++
 Enforce class member access control semantics
Index: gcc/c-opts.c
===================================================================
--- gcc/c-opts.c	(revision 117181)
+++ gcc/c-opts.c	(working copy)
@@ -555,6 +555,10 @@
       handle_OPT_d (arg);
       break;
 
+    case OPT_expand_pragmas:
+      cpp_opts->expand_pragmas = true;
+      break;
+
     case OPT_fcond_mismatch:
       if (!c_dialect_cxx ())
 	{
Index: gcc/c-ppoutput.c
===================================================================
--- gcc/c-ppoutput.c	(revision 117181)
+++ gcc/c-ppoutput.c	(working copy)
@@ -40,7 +40,7 @@
 } print;
 
 /* General output routines.  */
-static void scan_translation_unit (cpp_reader *);
+static void scan_translation_unit (cpp_reader *, bool);
 static void scan_translation_unit_trad (cpp_reader *);
 static void account_for_newlines (const unsigned char *, size_t);
 static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
@@ -76,7 +76,7 @@
   else if (cpp_get_options (pfile)->traditional)
     scan_translation_unit_trad (pfile);
   else
-    scan_translation_unit (pfile);
+    scan_translation_unit (pfile, false);
 
   /* -dM command line option.  Should this be elsewhere?  */
   if (flag_dump_macros == 'M')
@@ -131,9 +131,12 @@
 }
 
 /* Writes out the preprocessed file, handling spacing and paste
-   avoidance issues.  */
+   avoidance issues.  IPAD means make sure not to paste to previous
+   token (which might not be flagged with PREV_WHITE depending on
+   where it came from). */
+
 static void
-scan_translation_unit (cpp_reader *pfile)
+scan_translation_unit (cpp_reader *pfile, bool ipad)
 {
   bool avoid_paste = false;
 
@@ -142,6 +145,9 @@
     {
       const cpp_token *token = cpp_get_token (pfile);
 
+      if (ipad)
+	avoid_paste = true;
+
       if (token->type == CPP_PADDING)
 	{
 	  avoid_paste = true;
@@ -160,11 +166,15 @@
 	{
 	  if (print.source == NULL)
 	    print.source = token;
-	  if (print.source->flags & PREV_WHITE
+	  if (ipad
+	      || print.source->flags & PREV_WHITE
 	      || (print.prev
 		  && cpp_avoid_paste (pfile, print.prev, token))
 	      || (print.prev == NULL && token->type == CPP_HASH))
-	    putc (' ', print.outf);
+	    {
+	      putc (' ', print.outf);
+	      ipad = false;
+	    }
 	}
       else if (token->flags & PREV_WHITE)
 	putc (' ', print.outf);
@@ -422,8 +432,9 @@
 cb_def_pragma (cpp_reader *pfile, source_location line)
 {
   maybe_print_line (line);
-  fputs ("#pragma ", print.outf);
-  cpp_output_line (pfile, print.outf);
+  fputs ("#pragma", print.outf);
+  scan_translation_unit (pfile, true);
+  putc ('\n', print.outf);
   print.src_line++;
 }
 
Index: libcpp/directives.c
===================================================================
--- libcpp/directives.c	(revision 117181)
+++ libcpp/directives.c	(working copy)
@@ -1259,7 +1259,9 @@
    expansion happens for other pragmas is implementation defined.
    This implementation allows for a mix of both, since GCC did not
    traditionally macro expand its (few) pragmas, whereas OpenMP
-   specifies that macro expansion should happen.  */
+   specifies that macro expansion should happen.  It also supports
+   a command-line option (-expand-pragmas) that causes all pragmas
+   to be expanded by default. */
 static void
 do_pragma (cpp_reader *pfile)
 {
@@ -1268,10 +1270,43 @@
   cpp_token ns_token;
   unsigned int count = 1;
 
+  char save_directive_wants_padding;
+  bool reenable_expansion;
+
+  /* Decide whether to expand macros as follows:
+     1. Turn off macro expansion
+     2. Read token to find out what namespace
+     3. If it's STDC, don't re-enable expansion
+     4. Otherwise, enable expansion if expand_pragmas is turned on,
+        and push back the token. */
+
   pfile->state.prevent_expansion++;
+  reenable_expansion = true;
 
   token = cpp_get_token (pfile);
   ns_token = *token;
+
+  /* for testing effect of the pragma expansion feature on code that
+     doesn't expect it, set this to 1 and it will always expand regardless
+     of the -expand-pragmas option. */
+#define ALWAYS_EXPAND 0
+
+#if !ALWAYS_EXPAND
+  if (CPP_OPTION(pfile, expand_pragmas) &&
+      token->type == CPP_NAME &&
+      (NODE_LEN(token->val.node) != 4 ||
+       ustrncmp(NODE_NAME(token->val.node), (unsigned char *) "STDC", 4)))
+#endif
+    {
+      _cpp_backup_tokens(pfile, 1);
+      pfile->state.prevent_expansion--;      
+      reenable_expansion = false;
+      token = cpp_get_token (pfile);
+    }
+
+  save_directive_wants_padding = pfile->state.directive_wants_padding;
+  pfile->state.directive_wants_padding = 1;
+
   if (token->type == CPP_NAME)
     {
       p = lookup_pragma_entry (pfile->pragmas, token->val.node);
@@ -1339,7 +1374,10 @@
       pfile->cb.def_pragma (pfile, pfile->directive_line);
     }
 
-  pfile->state.prevent_expansion--;
+  if (reenable_expansion)
+    pfile->state.prevent_expansion--;
+
+  pfile->state.directive_wants_padding = save_directive_wants_padding;
 }
 
 /* Handle #pragma once.  */
Index: libcpp/macro.c
===================================================================
--- libcpp/macro.c	(revision 117181)
+++ libcpp/macro.c	(working copy)
@@ -1077,6 +1077,9 @@
 {
   const cpp_token *result;
 
+#define NOPAD (pfile->state.in_directive && \
+   !pfile->state.directive_wants_padding)
+
   for (;;)
     {
       cpp_hashnode *node;
@@ -1095,7 +1098,7 @@
 	  if (result->flags & PASTE_LEFT)
 	    {
 	      paste_all_tokens (pfile, result);
-	      if (pfile->state.in_directive)
+	      if (NOPAD)
 		continue;
 	      return padding_token (pfile, result);
 	    }
@@ -1103,7 +1106,7 @@
       else
 	{
 	  _cpp_pop_context (pfile);
-	  if (pfile->state.in_directive)
+	  if (NOPAD)
 	    continue;
 	  return &pfile->avoid_paste;
 	}
@@ -1124,7 +1127,7 @@
 	  if (!pfile->state.prevent_expansion
 	      && enter_macro_context (pfile, node))
 	    {
-	      if (pfile->state.in_directive)
+	      if (NOPAD)
 		continue;
 	      return padding_token (pfile, result);
 	    }
@@ -1142,6 +1145,7 @@
 
       break;
     }
+#undef NOPAD
 
   return result;
 }
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 117181)
+++ libcpp/include/cpplib.h	(working copy)
@@ -405,6 +405,9 @@
   /* True if dependencies should be restored from a precompiled header.  */
   bool restore_pch_deps;
 
+  /* True if #pragma statements should be macro-expanded. */
+  bool expand_pragmas;
+
   /* Dependency generation.  */
   struct
   {
Index: doc/cpp.texi
===================================================================
--- doc/cpp.texi	(revision 117267)
+++ doc/cpp.texi	(working copy)
@@ -3859,9 +3859,16 @@
 @item Treatment of a @samp{#pragma} directive that after macro-expansion
 results in a standard pragma.
 
-No macro expansion occurs on any @samp{#pragma} directive line, so the
-question does not arise.
+Macro expansion in #pragma directives is controlled by the
+@option{-expand-pragmas} command line option.  If this option is not
+enabled, then no macro expansion occurs on any @samp{#pragma}
+directive line other than certain special GOMP-related pragmas which
+can't expand to standard pragmas, so the question does not arise.
 
+If the option is enabled, then macros are expanded in #pragma
+directives, @emph{except} for the STDC pragmas.  C99 requires that
+STDC pragmas @emph{not} be expanded.
+
 Note that GCC does not yet implement any of the standard
 pragmas.
 
Index: doc/cppopts.texi
===================================================================
--- doc/cppopts.texi	(revision 117267)
+++ doc/cppopts.texi	(working copy)
@@ -344,6 +344,20 @@
 location.  The filename may be absolute or it may be relative to GCC's
 current directory.
 
+@item -expand-pragmas
+@opindex expand-pragmas
+This option instructs the preprocessor to expand preprocessor macros
+inside @code{pragma} directives.  GCC's default is to never expand
+macros in @code{#pragma} directives, except for certain GOMP-related
+pragmas for which expansion is required.
+
+With @option{-expand-pragmas} set, GCC expands macros in pragmas,
+except for pragmas in the @code{STDC} namespace.  The C99 standard
+prohibits expansion of some specific pragmas, all of which are in
+@code{STDC}.  The standard leaves expansion of the other pragmas up to
+implementations.
+
+
 @end ifclear
 @item -x c
 @itemx -x c++
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 117267)
+++ ChangeLog	(working copy)
@@ -1,3 +1,15 @@
+2006-09-27  Paul Rubin  <phr-gcc@nightsong.com>
+
+	* c-ppoutput.c (cb_def_pragma): use scan_translation_unit
+	instead of cpp_output_line to copy pragmas, allowing re-use
+	of scan_translation_unit's complex paste avoidance logic.
+        (preprocess_file): pass new arg to scan_translation_unit.
+	(scan_translation_unit): add 'ipad' arg for use with pragma expansion.
+
+	* c.opt (fexpand-pragmas): new flag.
+
+	* c-opts.c (c_common_handle_option) add OPT_fexpand_pragmas
+
 2006-09-27  Steven G. Kargl  <kargl@gcc.gnu.org>
 
 	* doc/install.texi: Document required versions of GMP and MPFR.
Index: testsuite/gcc.dg/cpp/pragma-exp0.c
===================================================================
--- testsuite/gcc.dg/cpp/pragma-exp0.c	(revision 0)
+++ testsuite/gcc.dg/cpp/pragma-exp0.c	(revision 0)
@@ -0,0 +1,21 @@
+/* { dg-do preprocess } */
+
+/* Test that without -expand-pragmas, preprocessor symbols in pragmas
+   don't get expanded.
+ */
+
+
+#pragma frobozz
+int x = 3;
+
+#define frobozz muffin
+#pragma frobozz
+
+/* make sure there's not unwanted token pasting */
+#define FOO abc
+#define BAR def
+#pragma FOO BAR ghi
+
+/* { dg-final { scan-file pragma-exp0.i "#pragma frobozz" } } */
+/* { dg-final { scan-file-not pragma-exp0.i "#pragma muffin" } } */
+/* { dg-final { scan-file pragma-exp0.i "#pragma FOO BAR ghi" } } */
Index: testsuite/gcc.dg/cpp/pragma-exp1.c
===================================================================
--- testsuite/gcc.dg/cpp/pragma-exp1.c	(revision 0)
+++ testsuite/gcc.dg/cpp/pragma-exp1.c	(revision 0)
@@ -0,0 +1,48 @@
+/* { dg-do preprocess } */
+/* { dg-options -expand-pragmas } */
+
+/* test that expand-pragmas causes pragma <preprocessor symbol>
+   to get expanded */
+
+#pragma frobozz
+int x = 3;
+
+#define frobozz muffin
+#pragma frobozz
+
+/* make sure there's not unwanted token pasting */
+#define FOO abc
+#define BAR def
+#pragma FOO BAR ghi
+
+/* check that STDC pragmas aren't expanded, per C99 */
+#pragma STDC abc FOO xyz
+
+/* even if STDC is redefined */
+#define STDC blah
+#pragma STDC abc2 FOO xyz
+
+/* expand a macro with arguments */
+#define ADD(x,y,z) x+y+z
+
+/* check that macro with args gets expanded correctly at beginning of
+   pragma */
+#pragma ADD(a,b,c) xyz
+
+/* and also when not at the beginning */
+#pragma xyz ADD(a,b,c)
+
+/* check that omp macro still properly expands */
+#pragma omp frobozz
+
+
+/* { dg-final { scan-file pragma-exp1.i "#pragma frobozz" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma muffin" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma abc def ghi" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma STDC abc FOO xyz" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma STDC abc2 FOO xyz" } } */
+/* { dg-final { scan-file-not pragma-exp1.i "#pragma STDC abc abc xyz" } } */
+/* { dg-final { scan-file-not pragma-exp1.i "#pragma blah" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma a\\+b\\+c xyz" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma xyz a\\+b\\+c" } } */
+/* { dg-final { scan-file pragma-exp1.i "#pragma omp muffin" } } */
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog	(revision 117274)
+++ testsuite/ChangeLog	(working copy)
@@ -1,3 +1,8 @@
+2006-09-27  Paul Rubin <phr-gcc@nightsong.com>
+ 
+ 	* gcc.dg/cpp/pragma-exp0.c, gcc.dg/cpp/pragma-exp1.c:
+ 	new tests.
+
 2006-09-27  Steven G. Kargl  <kargls@gcc.gnu.org>
 
 	PR fortran/28276
Index: c.opt
===================================================================
--- c.opt	(revision 117267)
+++ c.opt	(working copy)
@@ -495,6 +495,10 @@
 C ObjC C++ ObjC++ Joined RejectNegative
 -fexec-charset=<cset>	Convert all strings and character constants to character set <cset>
 
+fexpand-pragmas
+C ObjC C++ ObjC++
+Expand preprocessor macros in #pragma statements
+
 fextended-identifiers
 C ObjC C++ ObjC++
 Permit universal character names (\\u and \\U) in identifiers
Index: c-opts.c
===================================================================
--- c-opts.c	(revision 117267)
+++ c-opts.c	(working copy)
@@ -555,6 +555,10 @@
       handle_OPT_d (arg);
       break;
 
+    case OPT_fexpand_pragmas:
+      cpp_opts->expand_pragmas = true;
+      break;
+
     case OPT_fcond_mismatch:
       if (!c_dialect_cxx ())
 	{
Index: c-ppoutput.c
===================================================================
--- c-ppoutput.c	(revision 117267)
+++ c-ppoutput.c	(working copy)
@@ -40,7 +40,7 @@
 } print;
 
 /* General output routines.  */
-static void scan_translation_unit (cpp_reader *);
+static void scan_translation_unit (cpp_reader *, bool);
 static void scan_translation_unit_trad (cpp_reader *);
 static void account_for_newlines (const unsigned char *, size_t);
 static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
@@ -76,7 +76,7 @@
   else if (cpp_get_options (pfile)->traditional)
     scan_translation_unit_trad (pfile);
   else
-    scan_translation_unit (pfile);
+    scan_translation_unit (pfile, false);
 
   /* -dM command line option.  Should this be elsewhere?  */
   if (flag_dump_macros == 'M')
@@ -131,9 +131,12 @@
 }
 
 /* Writes out the preprocessed file, handling spacing and paste
-   avoidance issues.  */
+   avoidance issues.  IPAD means make sure not to paste to previous
+   token (which might not be flagged with PREV_WHITE depending on
+   where it came from). */
+
 static void
-scan_translation_unit (cpp_reader *pfile)
+scan_translation_unit (cpp_reader *pfile, bool ipad)
 {
   bool avoid_paste = false;
 
@@ -142,6 +145,9 @@
     {
       const cpp_token *token = cpp_get_token (pfile);
 
+      if (ipad)
+	avoid_paste = true;
+
       if (token->type == CPP_PADDING)
 	{
 	  avoid_paste = true;
@@ -160,11 +166,15 @@
 	{
 	  if (print.source == NULL)
 	    print.source = token;
-	  if (print.source->flags & PREV_WHITE
+	  if (ipad
+	      || print.source->flags & PREV_WHITE
 	      || (print.prev
 		  && cpp_avoid_paste (pfile, print.prev, token))
 	      || (print.prev == NULL && token->type == CPP_HASH))
-	    putc (' ', print.outf);
+	    {
+	      putc (' ', print.outf);
+	      ipad = false;
+	    }
 	}
       else if (token->flags & PREV_WHITE)
 	putc (' ', print.outf);
@@ -422,8 +432,9 @@
 cb_def_pragma (cpp_reader *pfile, source_location line)
 {
   maybe_print_line (line);
-  fputs ("#pragma ", print.outf);
-  cpp_output_line (pfile, print.outf);
+  fputs ("#pragma", print.outf);
+  scan_translation_unit (pfile, true);
+  putc ('\n', print.outf);
   print.src_line++;
 }
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]