Bug 21734 - gcc-2.96 has precompilation bugs
Summary: gcc-2.96 has precompilation bugs
Alias: None
Product: Red Hat Linux
Classification: Retired
Component: gcc (Show other bugs)
(Show other bugs)
Version: 7.0
Hardware: i686 Linux
Target Milestone: ---
Assignee: Jakub Jelinek
QA Contact: David Lawrence
Depends On:
TreeView+ depends on / blocked
Reported: 2000-12-05 09:24 UTC by Need Real Name
Modified: 2007-03-27 03:38 UTC (History)
0 users

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Last Closed: 2000-12-05 14:10:27 UTC
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---

Attachments (Terms of Use)

Description Need Real Name 2000-12-05 09:24:29 UTC
using g++ from gcc-2.96 gives precompilation errors.
When trying to precompile the following lines:
        #define F0(arg)
        #define F1(arg) arg
        #define F2(arg) arg##1 , arg##2
        #define F3(arg) F2(##arg) , arg##3
It gives the warning:
        warning: nothing can be pasted after this token
at the last line.  It looks like it cannot preprocess F2(##arg).
This ends up in not being able to preprocess the rest of the source.

Comment 1 Jakub Jelinek 2000-12-05 09:42:06 UTC
This is actually a warning, and a valid one. ## pasting operator shall
be only used to paste two tokens together into one token, but in case
of F2(##arg) there is nothing to paste in front of arg. Just remove change
that into F2(arg) , arg##3 and it will be valid source.

Comment 2 Need Real Name 2000-12-05 10:50:58 UTC
If a formal parameter in a macro definition is preceeded or followed by the
token-pasting operator, the formal parameter is immediately replaced by the
unexpanded actual argument.  Macro expansion is not performed on the argument
prior to replacement.
Check that the following lines:
     #define F0(arg)
     #define F1(arg) arg
     #define F2(arg) (arg1 + arg2##0)
     #define F3(arg1, arg2) (F2(##arg1, arg2) + 1)
     #define F4(arg1, arg2, narg1) F3(F##narg1(arg1), arg2)
     F4(1, 2, 0)
are preprocessed to:
     (( + 20) + 1)
On the other hand, if the token was expanded prior to replacement, line 4 would
be illegal:
     (F2( , 2) +1)

Note that gcc-2.95 correctly precompiles the above macros.

Comment 3 Jakub Jelinek 2000-12-05 11:09:48 UTC
What standard are you mentioning here?
ISO/IEC 9899:1999 states that
If the result is not a valid preprocessing token, the behaviour is undefined.

Comment 4 Need Real Name 2000-12-05 13:01:23 UTC
The ISO/IEC 9899:1999 [#1] states:  Argument substitution

       [#1]  After  the arguments for the invocation of a function-
       like macro have been identified, argument substitution takes
       place.  A parameter in the replacement list, unless preceded
       by a # or  ##  preprocessing  token  or  followed  by  a  ##
       preprocessing   token   (see  below),  is  replaced  by  the
       corresponding argument after all  macros  contained  therein
       have   been   expanded.    Before  being  substituted,  each
       argument's  preprocessing  tokens   are   completely   macro
       replaced  as  if  they  formed the rest of the preprocessing
       file; no other preprocessing tokens are available.

The ISO/IEC 9899:1999 [#3] states that:  The ## operator


       [#2] If, in the replacement list of a function-like macro, a
       parameter is  immediately  preceded  or  followed  by  a  ##
       preprocessing  token,  the  parameter  is  replaced  by  the
       corresponding  argument's  preprocessing   token   sequence;
       however, if an argument consists of no preprocessing tokens,
       the parameter is replaced  by  a  placemarker  preprocessing
       token instead.145)

       [#3]   ... Placemarker  preprocessing  tokens  are  handled  specially:
       concatenation  of  two  placemarkers  results  in  a  single
       placemarker  preprocessing  token,  and  concatenation  of a
       placemarker  with  a  non-placemarker  preprocessing   token
       results  in the non-placemarker preprocessing token.  If the
       result is not a valid preprocessing token, the  behavior  is
       undefined.   The  resulting  token  is available for further
       macro replacement.

I think it is pretty clear that [#1] has higher precedence than [#3].

Comment 5 Jakub Jelinek 2000-12-05 13:11:25 UTC
Well, my reading is different.  The second paragraph sais that such construct
has undefined behaviour, and undefined behaviour means the preprocessor
is allowed to do anything it wants, preprocess it somehow, don't preprocess
it at all, start nethack.  At that point the first paragraph is irrelevant
I think.
Probably it will be better if you argue with Zack Weinberg <zackw@stanford.edu>
and Neil Booth <neilb@earthling.net>, the authors of the new preprocessor.

Comment 6 Need Real Name 2000-12-05 13:37:23 UTC
The source I wrote has one error:
     #define F2(arg1, arg2) (arg1 + arg2##0)

Comment 7 Jakub Jelinek 2000-12-05 13:48:29 UTC
I don't understand why the second testcase was given then, because it
is preprocessed with RH7 cpp as you expected (only prints out a warning
that it has undefined behaviour). But current CVS gcc already will not preprocess
it as you expected:

$ cat XX.c
#define F0(arg)
#define F1(arg) arg
#define F2(arg1, arg2) (arg1 + arg2##0)
#define F3(arg1, arg2) (F2(##arg1, arg2) + 1)
#define F4(arg1, arg2, narg1) F3(F##narg1(arg1), arg2)
F4(1, 2, 0)
$ gcc -E XX.c
# 1 "XX.c"
XX.c:4:27: warning: nothing can be pasted after this token

(( + 20) + 1)
$ /usr/src/gcc-2.95.2/obj/gcc/xgcc -B /usr/src/gcc-2.95.2/obj/gcc/ -E XX.c
# 1 "XX.c"

((     +       20)  + 1)
$ ./xgcc -B ./ -E XX.c
# 1 "XX.c"

XX.c:6:1: warning: pasting "(" and "F0" does not give a valid preprocessing token
((F0(1) + 20) + 1)
$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/2.96/specs
gcc version 2.96 20000731 (Red Hat Linux 7.0)
$ /usr/src/gcc-2.95.2/obj/gcc/xgcc -B /usr/src/gcc-2.95.2/obj/gcc/ -v
Reading specs from /usr/src/gcc-2.95.2/obj/gcc/specs
gcc version 2.95.2 19991024 (release)
$ ./xgcc -B ./ -v
Reading specs from ./specs
Configured with:
gcc version 2.97 20001205 (experimental)

Comment 8 Need Real Name 2000-12-05 14:07:14 UTC
This is precisely one of my points:  2.95.2 (release) does it correctly, but
2.96 and 2.97, which are development snapshots, are wrong.
The second example was just to simplify the ideea.  The real example I have is
not compiling at all on 2.96 or 2.97, but it compiles on 2.95.2.  I could send
you this one, but it is quite complicated. The main features are present in the
second example.

Comment 9 Jakub Jelinek 2000-12-05 14:10:24 UTC
Ok, I'll say it this way, unless you convince cpp authors this is a bug
in cpp (this change was intentional, btw), this will be the behaviour of gcc 3.0
and following gcc releases.

Note You need to log in before you can comment on or make changes to this bug.