public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* `Cpp: 'ICOM_FN(##xfn)' generates a warning :-(
@ 2001-01-02 16:03 Francois Gouget
  2001-01-03  4:36 ` Alexandre Oliva
  2001-01-03  6:16 ` Neil Booth
  0 siblings, 2 replies; 7+ messages in thread
From: Francois Gouget @ 2001-01-02 16:03 UTC (permalink / raw)
  To: gcc; +Cc: jakub

   Hi,


  I'm having problems with the following piece of code (extracted from
Wine's source):

#define GetObject You_cannot_use_GetObject_in_this_context

#define ICOM_FN(xfn)    fn ## xfn
#define DECLARE1(xfn)    void ICOM_FN(xfn) (void);
#define DECLARE2(xfn)    void ICOM_FN(##xfn) (void);


ICOM_FN(GetObject)
DECLARE1(GetObject)
DECLARE2(GetObject)


   I expect to get (blank and not relevant lines removed):

fnGetObject  
void fnYou_cannot_use_GetObject_in_this_context     (void); 
void fnGetObject    (void); 

   But I've had problems with recent versions of gcc. One version
(20001002) produced:
test.c:6:38: warning: nothing can be pasted after this token
fnGetObject
void fnYou_cannot_use_GetObject_in_this_context (void);
void fnYou_cannot_use_GetObject_in_this_context (void);

   But more recent versions work again so this seems to be fixed. But I
still get the following warning:
test.c:11:1: warning: pasting "(" and "GetObject" does not give a valid
preprocessing token


   Is this use of '##' still going to be supported in the future?
   Is it possible to not issue a warning in this situation (I know about
the macro vararg problem).


   Reading the Cpp documentation I see:

-- http://gcc.gnu.org/onlinedocs/cpp_1.html#SEC46
Attempting to paste two tokens which together do not form a valid  
preprocessing token The preprocessor currently warns about this and  
outputs the two tokens adjacently, which is probably the behavior the   
programmer intends. It may not work in future, though. Most of the time,
when you get this warning, you will find that `##' is being used  
superstitiously, to guard against whitespace appearing between two
tokens. It is almost always safe to delete the `##'.
--

   But this does not cover what I do which is to use the concatenation
operator to avoid the argument prescan described in 'Separate Expansion
of Macro Arguments'

-- http://gcc.gnu.org/onlinedocs/cpp_toc.html#SEC29
We have explained that the expansion of a macro, including the
substituted arguments, is re-scanned for macro calls to be expanded.

What really happens is more subtle: first each argument is scanned
separately for macro calls. Then the resulting tokens are substituted
into the macro body to produce the macro expansion, and the macro
expansion is scanned again for macros to expand.
--

-- http://gcc.gnu.org/onlinedocs/cpp_toc.html#SEC29 
The prescan is not done when an argument is stringified or concatenated.
--

   Since this is unrelated to the macro vararg issue it would be nice if
there was a way to avoid the warning in this context (otherwise we'll
have to change the code and duplicate 30+ macros :-( ).


PS:
  I apologize if this is the wrong mailing list. Would gcc-bugs be more
appropriate (seems like it is more gnats oriented)?  
  jakub, Bernhard Rosenkraenzer told me you would be interested in being
cc-ed.

--
Francois Gouget         fgouget@free.fr        http://fgouget.free.fr/
               RFC 2549: ftp://ftp.isi.edu/in-notes/rfc2549.txt
                IP over Avian Carriers with Quality of Service




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: `Cpp: 'ICOM_FN(##xfn)' generates a warning :-(
  2001-01-02 16:03 `Cpp: 'ICOM_FN(##xfn)' generates a warning :-( Francois Gouget
@ 2001-01-03  4:36 ` Alexandre Oliva
  2001-01-03 10:01   ` Francois Gouget
  2001-01-03  6:16 ` Neil Booth
  1 sibling, 1 reply; 7+ messages in thread
From: Alexandre Oliva @ 2001-01-03  4:36 UTC (permalink / raw)
  To: Francois Gouget; +Cc: gcc, jakub

On Jan  2, 2001, Francois Gouget <fgouget@free.fr> wrote:

> #define DECLARE2(xfn)    void ICOM_FN(##xfn) (void);

This doesn't produce a valid token after token pasting.  CVS GCC is
correct in warning about it.

I think an ISO C-compliant solution would be to define DECLARE2 so
that it takes an additional empty argument, and use token pasting to
paste this empty argument to the symbol name.

#define DECLARE2(xfn,empty) void ICOM_FN(empty ## xfn) (void);

DECLARE2(GetObject,)


The alternative I see to preserve the interface of DECLARE2 is to not
use ICOM_FN, but instead concatenate fn with xfn explicitly.

I don't know if any of these are viable alternatives for Wine.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: `Cpp: 'ICOM_FN(##xfn)' generates a warning :-(
  2001-01-02 16:03 `Cpp: 'ICOM_FN(##xfn)' generates a warning :-( Francois Gouget
  2001-01-03  4:36 ` Alexandre Oliva
@ 2001-01-03  6:16 ` Neil Booth
  1 sibling, 0 replies; 7+ messages in thread
From: Neil Booth @ 2001-01-03  6:16 UTC (permalink / raw)
  To: Francois Gouget; +Cc: gcc, jakub

Francois Gouget wrote:-

> #define DECLARE2(xfn)    void ICOM_FN(##xfn) (void);
> 
>    I expect to get (blank and not relevant lines removed):
> 
> void fnGetObject    (void); 
> 
>    But more recent versions work again so this seems to be fixed. But I
> still get the following warning:
> test.c:11:1: warning: pasting "(" and "GetObject" does not give a valid
> preprocessing token
> 
>    Is this use of '##' still going to be supported in the future?

No.  GCC in future versions may even upgrade this warning to a hard
error.

>    Is it possible to not issue a warning in this situation (I know about
> the macro vararg problem).

No.  There may be other ways to achieve what you want; e.g. having an
extra empty argument and pasting that, or making it a varargs argument
if you don't want to have to enter the comma in invocations.

Neil.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: `Cpp: 'ICOM_FN(##xfn)' generates a warning :-(
  2001-01-03  4:36 ` Alexandre Oliva
@ 2001-01-03 10:01   ` Francois Gouget
  2001-01-03 10:33     ` Francois Gouget
  0 siblings, 1 reply; 7+ messages in thread
From: Francois Gouget @ 2001-01-03 10:01 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc, jakub

On 3 Jan 2001, Alexandre Oliva wrote:

> On Jan  2, 2001, Francois Gouget <fgouget@free.fr> wrote:
> 
> > #define DECLARE2(xfn)    void ICOM_FN(##xfn) (void);
> 
> This doesn't produce a valid token after token pasting.  CVS GCC is
> correct in warning about it.
> 
> I think an ISO C-compliant solution would be to define DECLARE2 so
> that it takes an additional empty argument, and use token pasting to
> paste this empty argument to the symbol name.
> 
> #define DECLARE2(xfn,empty) void ICOM_FN(empty ## xfn) (void);
> 
> DECLARE2(GetObject,)

   Brilliant!
   I didn't think about that, I like it.


> The alternative I see to preserve the interface of DECLARE2 is to not
> use ICOM_FN, but instead concatenate fn with xfn explicitly.

   The problem with this solution is that, I should have said so, we
change the definition of ICOM_FN depending on another macro. So ICOM_FN
does not always prepend fn. So we would have to duplicate all the macros
that use ICOM_FN. Feasible but ugly.


   But I like your first suggestion. I'll implement it, that way we'll
avoid all problems.

   Thanks.


--
Francois Gouget         fgouget@free.fr        http://fgouget.free.fr/
  Good judgment comes from experience, and experience comes from bad judgment
                               -- Barry LePatner

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: `Cpp: 'ICOM_FN(##xfn)' generates a warning :-(
  2001-01-03 10:01   ` Francois Gouget
@ 2001-01-03 10:33     ` Francois Gouget
  2001-01-03 11:15       ` Alexandre Oliva
  0 siblings, 1 reply; 7+ messages in thread
From: Francois Gouget @ 2001-01-03 10:33 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc, jakub

On Wed, 3 Jan 2001, Francois Gouget wrote:

> On 3 Jan 2001, Alexandre Oliva wrote:
> 
> > On Jan  2, 2001, Francois Gouget <fgouget@free.fr> wrote:
> > 
> > > #define DECLARE2(xfn)    void ICOM_FN(##xfn) (void);
> > 
> > This doesn't produce a valid token after token pasting.  CVS GCC is
> > correct in warning about it.
> > 
> > I think an ISO C-compliant solution would be to define DECLARE2 so
> > that it takes an additional empty argument, and use token pasting to
> > paste this empty argument to the symbol name.
> > 
> > #define DECLARE2(xfn,empty) void ICOM_FN(empty ## xfn) (void);
> > 
> > DECLARE2(GetObject,)
> 
>    Brilliant!
>    I didn't think about that, I like it.

   Oups. I talked too fast. It's still brilliant and I didn't think of
it. But I got confused and thought I could just modify ICOM_FN when in
fact it's DECLARE I have to modify, i.e. in Wine ICOM_METHOD. These
macros are used to declare each COM method (about 1500 of them so far).
Of course, I'd rather not add commas all other the place.

   Is there any other way I could avoid the prescan?


> > The alternative I see to preserve the interface of DECLARE2 is to not
> > use ICOM_FN, but instead concatenate fn with xfn explicitly.
> 
>    The problem with this solution is that, I should have said so, we
> change the definition of ICOM_FN depending on another macro. So ICOM_FN
> does not always prepend fn. So we would have to duplicate all the macros
> that use ICOM_FN. Feasible but ugly.

   Well, less of a problem than modifying the 1500 uses of the
ICOM_METHOD macros. It means instead I'l duplicate the definition of
(only) 33 macros :-(


   Currently it looks like so:


#ifndef ICOM_CINTERFACE

#define ICOM_METHOD(ret,xfn) \
     public: virtual ret CALLBACK (xfn)(void) = 0;
#define ICOM_METHOD1(ret,xfn,ta,na) \
     public: virtual ret CALLBACK (xfn)(ta a) = 0;
...

#define ICOM_FN(xfn)             xfn

#else /* ICOM_CINTERFACE */

#ifdef __WINE__
#define ICOM_FN(xfn)             fn##xfn
#else
#define ICOM_FN(xfn)             xfn
#endif

#define ICOM_METHOD(ret,xfn) \
    ret CALLBACK (*ICOM_FN(##xfn))(ICOM_INTERFACE* me);
#define ICOM_METHOD1(ret,xfn,ta,na) \
    ret CALLBACK (*ICOM_FN(##xfn))(ICOM_INTERFACE* me,ta a);
...

#endif /* ICOM_CINTERFACE `*/

#define ICOM_CALL(xfn, p)        ICOM_VTBL(p)->ICOM_FN(##xfn)(p)
...


--
Francois Gouget         fgouget@free.fr        http://fgouget.free.fr/
 "Only wimps use tape backup: _real_ men just upload their important stuff on
       ftp, and let the rest of the world mirror it ;)" -- Linus Torvalds


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: `Cpp: 'ICOM_FN(##xfn)' generates a warning :-(
  2001-01-03 10:33     ` Francois Gouget
@ 2001-01-03 11:15       ` Alexandre Oliva
  2001-01-03 15:52         ` Francois Gouget
  0 siblings, 1 reply; 7+ messages in thread
From: Alexandre Oliva @ 2001-01-03 11:15 UTC (permalink / raw)
  To: Francois Gouget; +Cc: gcc, jakub

On Jan  3, 2001, Francois Gouget <fgouget@free.fr> wrote:

>    Is there any other way I could avoid the prescan?

Neil suggested using a varargs macro argument, introduced in C99 and
supported by CVS GCC.

#define DECLARE2(xfn,...) void ICOM_FN(xfn ## __VA_ARGS__) (void)

One solution that appears to work with old and new version of GCC is:

#define DECLARE2(xfn,rest...) void ICOM_FN(xfn ## rest) (void)

But the use of the ISO C99-compliant solution is encouraged.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: `Cpp: 'ICOM_FN(##xfn)' generates a warning :-(
  2001-01-03 11:15       ` Alexandre Oliva
@ 2001-01-03 15:52         ` Francois Gouget
  0 siblings, 0 replies; 7+ messages in thread
From: Francois Gouget @ 2001-01-03 15:52 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc

On 3 Jan 2001, Alexandre Oliva wrote:

> On Jan  3, 2001, Francois Gouget <fgouget@free.fr> wrote:
> 
> >    Is there any other way I could avoid the prescan?
> 
> Neil suggested using a varargs macro argument, introduced in C99 and
> supported by CVS GCC.
> 
> #define DECLARE2(xfn,...) void ICOM_FN(xfn ## __VA_ARGS__) (void)
> 
> One solution that appears to work with old and new version of GCC is:
> 
> #define DECLARE2(xfn,rest...) void ICOM_FN(xfn ## rest) (void)
> 
> But the use of the ISO C99-compliant solution is encouraged.


   Ah! I did not think about it that way. That works.
   I'm not overly enthusisatic about using vararg macros though. The
problem is it's hard to make them work across compilers (not that Wine's
code is extremely protable to start with but we try still).

   Oh well, we'll duplicate the definitions. It's not that bad.

   Thanks a lot for your help!


--
Francois Gouget         fgouget@free.fr        http://fgouget.free.fr/
                     Avoid the Gates of Hell - use Linux.



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2001-01-03 15:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-01-02 16:03 `Cpp: 'ICOM_FN(##xfn)' generates a warning :-( Francois Gouget
2001-01-03  4:36 ` Alexandre Oliva
2001-01-03 10:01   ` Francois Gouget
2001-01-03 10:33     ` Francois Gouget
2001-01-03 11:15       ` Alexandre Oliva
2001-01-03 15:52         ` Francois Gouget
2001-01-03  6:16 ` Neil Booth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).