[gnu.gcc.bug] gcc-cpp: nested expansion / stringification problem

Raeburn@ATHENA.MIT.EDU (Ken Raeburn) (02/25/90)

(1.37, vax)

I think cpp is expanding the following code incorrectly:

    /*
     * test of cpp
     */

    #include "./assert.h" /* running in 1.37 src directory */

    #define A(X)	(assert(X))
    #define X1(X)	(A(X), X.one)
    #define X2(X)	(A(X), X.two)
    #define X3(X)	(A(X), X.three)
    #define X4(X)	(A(X), X.four)

    foo (X) {
	return X4 (X3 (X2 (X1 (X))));
    }

The output contains strings with `\' characters before double-quotes
only doubled, rather than tripled as would be necessary to get the
correct string values.

(In the original code, I wanted the pre-substitution text of the
argument in the string, obviously, but the macros I was writing were
evolving in the wrong direction.)

 [multics!raeburn]
 {/mit/gnu/dev/build/vax-gcc-1.37}
<1002  3:09am> % ./cpp -v foo.c
GNU CPP version 1.37
foo.c:14: only 2 args to macro `__assert'
foo.c:14: unterminated string or character constant
foo.c:0: unterminated macro call
foo.c:16: only 2 args to macro `__assert'
# 1 "foo.c"
 



# 1 "/mit/gnu/vaxlib/gcc-include/./assert.h" 1
 











void __eprintf ();               




void abort();


















# 5 "foo.c" 2








foo (X) {
    return ((((((((((((((((X) ? 0 : (__eprintf ("Failed assertion " "X" " at line %d of `"  "foo.c" "'.\n",  14),       abort ()) ) ) , X.one) ) ? 0 : (__eprintf ("Failed assertion " "((((X) ? 0 : (__eprintf (\"Failed assertion \" \"X\" \" at line %d of `\" \"foo.c\" \"'.\\n\", 14), abort ()))), X.one)"        " at line %d of `"  "foo.c" "'.\n",  14),       abort ()) ) ) , ((((X) ? 0 : (__eprintf ("Failed assertion " "X"        " at line %d of `"  "foo.c" "'.\n",  14),       abort ()) ) ) , X.one) .two) ) 


? 0 : (__eprintf ("Failed assertion " "((((((((X) ? 0 : (__eprintf (\"Failed assertion \" \"X\" \" at line %d of `\" \"foo.c\" \"'.\\n\", 14), abort ()))), X.one)) ? 0 : (__eprintf (\"Failed assertion \" \"((((X) ? 0 : (__eprintf (\\"Failed assertion \\" \\"X\\" \\" at line %d of `\\" \\"foo.c\\" \\"'.\\\\n\\\", 14), abort ()))), X.one)\" \" at line %d of `\" \"foo.c\" \"'.\\n\"    " at line %d of `"  14 "'.\n", ),       abort ()) , abort ())))) ? 0 : (__eprintf ("Failed as!
sertion " "((((((((((((X) ? 0 : (_

_eprintf (\"Failed assertion \" \"X\" \" at line %d of `\" \"foo.c\" \"'.\\n\", 14), abort ()))), X.one)) ? 0 : (__eprintf (\"Failed assertion \" \"((((X) ? 0 : (__eprintf (\\"Failed assertion \\" \\"X\\" \\" at line %d of `\\" \\"foo.c\\" \\"'.\\\\n\\\", 14), abort ()))), X.one)\" \" at line %d of `\" \"foo.c\" \"'.\\n\"      " at line %d of `"  14 "'.\n", ),       abort ()) , abort ()))), ((((X) ? 0 : (__eprintf (\"Failed assertion \" \"X\" \" at line %d of `\" \"foo.c\" \"'.\\n\", 14), abort ()))), X.on


e).two)) ? 0 : (__eprintf (\"Failed assertion \" \"((((((((X) ? 0 : (__eprintf (\\"Failed assertion \\" \\"X\\" \\" at line %d of `\\" \\"foo.c\\" \\"'.\\\\n\\\", 14), abort ()))), X.one)) ? 0 : (__eprintf (\\\"Failed assertion \\\" \\\"((((X) ? 0 : (__eprintf (\\\\\"Failed assertion \\\\\" \\\"X\\\\\" \\\" at line %d of `\\\\\" \\\"foo.c\\\\\" \\\"'.\\\\\\\\n\\\\\\\", 14), abort ()))), X.one)\\\" \\\" at line %d of `\\\" \\\"foo.c\\\" \\\"'.\\n\\" \" at line %d of `\" 14 \!
"'.\\n\", ), abort ()), abort ()))

)", "foo.c", 16)) ) Exit 33              ./cpp -v foo.c
 [multics!raeburn]
 {/mit/gnu/dev/build/vax-gcc-1.37}
<1003  3:09am> % exit
 [multics!raeburn]
 {/mit/gnu/dev/build/vax-gcc-1.37}
<1004  3:10am> % 
script done on Sun Feb 25 03:10:06 1990

Raeburn@ATHENA.MIT.EDU (Ken Raeburn) (02/25/90)

I didn't notice before sending in my last report, but the assert.h
that was being used was from a previous gcc release.  (The directory I
was in had only my gcc object files, not sources and header files.)
Here's the header file I was really using:

   /* Allow this file to be included multiple times
      with different settings of NDEBUG.  */
   #undef assert
   #undef __assert

   #ifdef NDEBUG
   #define assert(ignore)
   #else

   #define assert(expression)  \
     ((expression) ? 0 : __assert (#expression, __FILE__, __LINE__))

   void __eprintf ();		/* Defined in gnulib */

   #ifdef __GNUC__
   volatile void abort();
   #else
   void abort();
   #endif

   #ifdef __STDC__

   #define __assert(expression, file, line)  \
     (__eprintf ("Failed assertion " expression		\
		 " at line %d of `" file "'.\n", line),	\
      abort ())

   #else /* no __STDC__; i.e. -traditional.  */

   #define __assert(expression, file, line)  \
     (__eprintf ("Failed assertion at line %d of `%s'.\n", line, file),	\
      abort ())

   #endif /* no __STDC__; i.e. -traditional.  */

   #endif

This doesn't change the fact that the expansion seems incorrect.

Also, some line breaks appear to have been added by my local mailer;
the big ugly expression really was all one line.

-- Ken