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]

Re: cpplib bug fix (macro expansion)


This patch fixes your test case, but will break under other conditions.
Specifically:

1) it does not account for comments which can occur between the macro name and
the opening parenthesis:

  #define F(a) a
  F/*comment*/(1);

2) You should use is_hor_space instead of is_space

3) The marking method is used in order to preserve the original whitespace in non
macro buffers in the case where it is not a macro call. Your patch would replace
that whitepace with a single blank.

  #define foo(a) a
  foo    bar  /* 4 spaces */

should not expand to

foo bar

with only one space.

Dave

Zack Weinberg wrote:

> This patch fixes a bug in an unusual case of macro expansion with
> cpplib.
>
> #define a(x) x bar
> #define foo(y) junk
> a(foo)
>
> should become
>
> foo bar
>
> when run through cpp.  Instead, cpplib produces
>
> foobar
>
> The tokens are pasted when they shouldn't be.
>
> The bug is in cpp_get_token, in the block beginning after the comment
> /* If macro wants an arglist, verify that a '(' follows... */ This
> block threw away whitespace provided by a macro expansion while
> looking for the open parenthesis.  The fix is to push at least one
> space into the token buffer rather than backtracking.
>
> zw
>
> 1998-09-27 01:24 -0400  Zack Weinberg  <zack@rabi.phys.columbia.edu>
>
>         * cpplib.c (cpp_get_token): When checking for an invocation of
>         a macro with arguments, don't muck around with markers.  Just
>         remember if we saw whitespace, and shove a space into the
>         token buffer if so.  (Fixes bug causing unwanted token pasting.)
>
> --- gcc/cpplib.c.bug    Sat Sep 26 21:55:20 1998
> +++ gcc/cpplib.c        Sun Sep 27 00:15:56 1998
> @@ -5086,32 +5086,36 @@
>                decide this is not a macro call and leave things that way.  */
>             if (hp->type == T_MACRO && hp->value.defn->nargs >= 0)
>             {
> -             struct parse_marker macro_mark;
> -             int is_macro_call;
> -             while (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
> -               {
> -                 cpp_buffer *next_buf;
> -                 cpp_skip_hspace (pfile);
> -                 if (PEEKC () != EOF)
> -                   break;
> -                 next_buf = CPP_PREV_BUFFER (CPP_BUFFER (pfile));
> -                 (*CPP_BUFFER (pfile)->cleanup) (CPP_BUFFER (pfile), pfile);
> -                 CPP_BUFFER (pfile) = next_buf;
> -               }
> -             parse_set_mark (&macro_mark, pfile);
> -             for (;;)
> -               {
> -                 cpp_skip_hspace (pfile);
> +             int was_whitespace = 0;
> +
> +             do
> +             {
>                   c = PEEKC ();
> -                 is_macro_call = c == '(';
> -                 if (c != '\n')
> -                   break;
> -                 FORWARD (1);
> -               }
> -             if (!is_macro_call)
> -               parse_goto_mark (&macro_mark, pfile);
> -             parse_clear_mark (&macro_mark);
> -             if (!is_macro_call)
> +                 if (c == EOF)
> +                 {
> +                     if (CPP_IS_MACRO_BUFFER (CPP_BUFFER (pfile)))
> +                     {
> +                         cpp_pop_buffer (pfile);
> +                         continue;
> +                     }
> +                     else
> +                         break;
> +                 }
> +
> +                 if (is_space[c])
> +                 {
> +                     was_whitespace = 1;
> +                     if (c == '\n')
> +                         FORWARD (1);
> +                     cpp_skip_hspace (pfile);
> +                 }
> +             }
> +             while (c == EOF || is_space[c]);
> +
> +             if (was_whitespace)
> +               CPP_PUTC (pfile, ' ');
> +
> +             if (c != '(')
>                 return CPP_NAME;
>             }
>             /* This is now known to be a macro call.  */





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