This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: _Pragma() from macros - bug
- From: Neil Booth <neil at daikokuya dot co dot uk>
- To: Zack Weinberg <zack at codesourcery dot com>, gcc-patches at gcc dot gnu dot org
- Cc: Andrew Suffield <asuffield at debian dot org>, 157416 at bugs dot debian dot org
- Date: Tue, 3 Sep 2002 22:52:17 +0100
- Subject: Re: _Pragma() from macros - bug
- References: <20020830010026.GA31786@codesourcery.com>
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" } }
+*/