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: _Pragma() from macros - bug


Zack Weinberg wrote:-

> This was reported to the Debian bug-tracking system:
> 
> $ cat foo.c
> _Pragma("foo"); int y;
> #define FOO _Pragma("foo"); int x;
> FOO
> aps100@cyclone:~$ cpp-3.2 foo.c
> # 1 "foo.c"
> # 1 "<built-in>"
> # 1 "<command line>"
> # 1 "foo.c"
> 
> # 1 "foo.c"
> #pragma foo 
> # 1 "foo.c"
>              ; int y;
> 
> 
> # 3 "foo.c"
> #pragma ; int x;foo 
> 
> > The first line is expanded correctly; the third is not (rendering
> > _Pragma almost completely useless).
> 
> Do you have time to look into this, Neil?

Fixed with a nasty kludge thus.

We really should be leaving _Pragma as-is in preprocessed output IMO;
(but processing it for pragmas handled by CPP itself) then this whole
issue goes away, and so does the hoops I jump through to retain
correct token line numbering.  That's for 3.4.

Bootstrapped and regtested; I'm going to put this in.

Neil.

	* cpphash.h (FIRST, LAST, CUR, RLIMIT): Fix definitions.
	* cpplib.c (destringize_and_run): Kludge around getting
	tokens from in-progress macros.
	(_cpp_do__Pragma): Simplify.
testsuite:
	* gcc.dg/cpp/_Pragma4.c: New test.

Index: cpphash.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpphash.h,v
retrieving revision 1.170
diff -u -p -r1.170 cpphash.h
--- cpphash.h	12 Aug 2002 22:44:29 -0000	1.170
+++ cpphash.h	3 Sep 2002 21:51:47 -0000
@@ -166,10 +166,10 @@ struct tokenrun
 };
 
 /* Accessor macros for struct cpp_context.  */
-#define FIRST(c) (c->u.iso.first)
-#define LAST(c) (c->u.iso.last)
-#define CUR(c) (c->u.trad.cur)
-#define RLIMIT(c) (c->u.trad.rlimit)
+#define FIRST(c) ((c)->u.iso.first)
+#define LAST(c) ((c)->u.iso.last)
+#define CUR(c) ((c)->u.trad.cur)
+#define RLIMIT(c) ((c)->u.trad.rlimit)
 
 typedef struct cpp_context cpp_context;
 struct cpp_context
Index: cpplib.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.c,v
retrieving revision 1.321
diff -u -p -r1.321 cpplib.c
--- cpplib.c	14 Aug 2002 20:17:54 -0000	1.321
+++ cpplib.c	3 Sep 2002 21:51:47 -0000
@@ -1277,6 +1277,9 @@ destringize_and_run (pfile, in)
 {
   const unsigned char *src, *limit;
   char *dest, *result;
+  cpp_context saved_context;
+  cpp_context *saved_cur_context;
+  unsigned int saved_line;
 
   dest = result = alloca (in->len + 1);
   for (src = in->text, limit = src + in->len; src < limit;)
@@ -1288,7 +1291,40 @@ destringize_and_run (pfile, in)
     }
   *dest = '\0';
 
+  /* FIXME.  All this saving is a horrible kludge to handle the case
+     when we're in a macro expansion.
+
+     A better strategy it to not convert _Pragma to #pragma if doing
+     preprocessed output, but to just pass it through as-is, unless it
+     is a CPP pragma in which case is should be processed normally.
+     When compiling the preprocessed output the _Pragma should be
+     handled.  This will be become necessary when we move to
+     line-at-a-time lexing since we will be macro-expanding the line
+     before outputting / compiling it.  */
+  saved_line = pfile->line;
+  saved_context = pfile->base_context;
+  saved_cur_context = pfile->context;
+  pfile->context = &pfile->base_context;
   run_directive (pfile, T_PRAGMA, result, dest - result);
+  pfile->context = saved_cur_context;
+  pfile->base_context = saved_context;
+  pfile->line = saved_line;
+
+  /* See above comment.  For the moment, we'd like
+
+     token1 _Pragma ("foo") token2
+
+     to be output as
+
+		token1
+		# 7 "file.c"
+		#pragma foo
+		# 7 "file.c"
+			       token2
+
+      Getting the line markers is a little tricky.  */
+  if (pfile->cb.line_change)
+    (*pfile->cb.line_change) (pfile, pfile->cur_token, false);
 }
 
 /* Handle the _Pragma operator.  */
@@ -1298,26 +1334,11 @@ _cpp_do__Pragma (pfile)
 {
   const cpp_token *string = get__Pragma_string (pfile);
 
-  if (!string)
+  if (string)
+    destringize_and_run (pfile, &string->val.str);
+  else
     cpp_error (pfile, DL_ERROR,
 	       "_Pragma takes a parenthesized string literal");
-  else
-    {
-      /* Ideally, we'd like
-			token1 _Pragma ("foo") token2
-	 to be output as
-			token1
-			# 7 "file.c"
-			#pragma foo
-			# 7 "file.c"
-					       token2
-	 Getting these correct line markers is a little tricky.  */
-
-      unsigned int orig_line = pfile->line;
-      destringize_and_run (pfile, &string->val.str);
-      pfile->line = orig_line;
-      pfile->buffer->saved_flags = BOL;
-    }
 }
 
 /* Just ignore #sccs on all systems.  */
Index: testsuite/gcc.dg/cpp/_Pragma4.c
===================================================================
RCS file: testsuite/gcc.dg/cpp/_Pragma4.c
diff -N testsuite/gcc.dg/cpp/_Pragma4.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ testsuite/gcc.dg/cpp/_Pragma4.c	3 Sep 2002 21:51:47 -0000
@@ -0,0 +1,12 @@
+/* { dg-do preprocess } */
+
+/* Based on Debian GNATS PR 157416.  3 Sep 2002.  */
+
+#define b foo _Pragma ("bar") baz
+a b c 
+
+/*
+   { dg-final { if ![file exists _Pragma4.i] { return }                   } }
+   { dg-final { if { [grep _Pragma4.i "#pragma bat "] != "" } { return }  } }
+   { dg-final { fail "_Pragma4.c: #pragma appearing on its own line"      } }
+*/


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