Problem with GCC 3.3 and pasting in macros

Discussion in 'C Programming' started by Boris Boehlen, Jun 25, 2003.

  1. Hello,

    One of our C files declares the following macro

    #define LRCALL_USELOCAL(op,s1,s2) RG__##op##s2;

    which used as follows:

    LRCALL_USELOCAL(DeleteGraphPool, (PDir, Pool, get_pool_mark( PDir, Pool), Status), (PDir, Pool, Status) );

    When I compile this code with GCC 3.3 I get the following error message:

    rgras.c:290:111: pasting "LG__DeleteGraphPool" and "(" does not give a valid preprocessing token

    Looking around in the web I found no applicable solution for this problem.
    For example, it has been suggested to remove the ## which is not possible
    in my case. As far as I can see the problem seems to be that we are
    passing a couple of parameters, enclosed in (...) to the macro. The code
    compiles with GCC 2.95.

    Any ideas? Please respond by mail because I'm reading this news group on
    an irregular basis.

    Regards,

    Boris Boehlen
     
    Boris Boehlen, Jun 25, 2003
    #1
    1. Advertisements

  2. This is because there is no such token as "LG__DeleteGraphPool(". The
    "(" is a token all by itself.
    For example, if you have the statement:

    LG__DeleteGraphPool(PDir, Pool, Status);

    then it should be tokenised as:

    LG__DeleteGraphPool
    (
    PDir
    ,
    Pool
    ,
    Status
    )
    ;

    As you can see, everything that can possibly have a meaning all by
    itself in the C syntax is its own token.
    Your macro isn't doing this. It's trying to tokenise this as:

    LG__DeleteGraphPool(
    PDir
    ,
    Pool
    ,
    Status
    )
    ;

    or something similar (it might even be trying to tokenise the last
    parameter as "Status)"). This breaks the C syntax rules, which are
    defined in terms of tokens, not in terms of characters.
    The only way to make it tokenise the statement correctly is to remove
    the second ## (but keep the first ##). Like it or not, it's really the
    only way to make C see the "LG__DeleteGraph(" as a function name and the
    start of a parameter list.
    If the code compiles cleanly with both ## in place in GCC 2.95, then
    GCC 2.95 is broken, although I think now Dan Pop will chime in and
    accuse me of not engaging my brain.
    I don't think you even *can* pass variable arguments to a macro in
    standard C. If you can in GCC, then it's a GCC feature, not a C feature.
    Why is your time worth more than ours? It's not like you paid for our
    services or anything. No, buddy, post here, read here.

    PS. Please try to keep your line lengths below 76 characters.

    --
    /-- Joona Palaste () ---------------------------\
    | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
    | http://www.helsinki.fi/~palaste W++ B OP+ |
    \----------------------------------------- Finland rules! ------------/
    "Bad things only happen to scoundrels."
    - Moominmamma
     
    Joona I Palaste, Jun 25, 2003
    #2
    1. Advertisements

  3. gcc3.3 is right.
    Too bad. That's the only correct solution for this macro call.
    ANSI 3.8.3.3 (The ## operator) says: 'If the result [from the ##
    operator] is not a valid preprocessing token, the behavior is
    undefined.'

    Another way might be to have two macros, one with and one without the
    second ##, and take care to use the appropriate one.
    gcc 2 is sloppier about error checking than gcc 3.
     
    Hallvard B Furuseth, Jun 25, 2003
    #3
  4. Boris Boehlen

    Dan Pop Guest

    The gcc error message is crystal clear: the result of the ## operator must
    be a preprocessing token, which is not the case in your example.
    You're invoking undefined behaviour, so a compiler is allowed to do
    anything it wants with your code:

    If the result is not a valid preprocessing token, the behavior is
    undefined.
    #define LRCALL_USELOCAL(op,s1,s2) RG__##op s2;

    BTW, are you *really* sure you want the semicolon at the end? Your
    sample invocation of the macro certainly makes it redundant and it
    could be downright harmful in other contexts.
    You post here, you read here. This way, if my advice is complete
    bullshit, someone else will have a chance to correct it.

    Dan
     
    Dan Pop, Jun 25, 2003
    #4
  5. Hello,
    Based on the response of Joona Palaste I changed this line to

    #define LRCALL_USELOCAL(op,s1,s2) RG__##op s2;

    and nothing changed.
    What are the reasons that it tries to tokenize it in that way?
    As said above, I did exactly this and nothing changed. Why?

    Kind Regards,

    Boris Boehlen
     
    Boris Boehlen, Jun 25, 2003
    #5
  6. I tried it with gcc3.3 and it worked fine. I think you must be
    #including the wrong version of the .h file which defines that macro
    or something.
    ## takes two tokens and combines them into one token.
    So the result is expected _be_ a valid token.
     
    Hallvard B Furuseth, Jun 25, 2003
    #6
  7. Perhaps the fault lies elsewhere. I tested your problem with the
    following minimalistic resemblance of your code:

    #define LRCALL_USELOCAL(op,s1,s2) LG__##op s2

    void LG__DeleteGraphPool(int PDir, int Pool, int Status) {
    return;
    }

    int get_pool_mark(int PDir, int Pool) {
    return 0;
    }

    int main(void) {
    int PDir=0, Pool=0, Status=0;
    LRCALL_USELOCAL(DeleteGraphPool, (PDir, Pool, get_pool_mark( PDir,
    Pool), Status), (PDir, Pool, Status));
    return 0;
    }

    and got no warnings other than for unused parameters. When I put the
    second ## back in, I got the original warning "LG__DeleteGraph( is not
    a valid preprocessing token" which I expected, and which I must say,
    makes perfect sense.
    BTW I have only tested with GCC 2.96. I don't have GCC 3.3 available
    for testing.

    --
    /-- Joona Palaste () ---------------------------\
    | Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
    | http://www.helsinki.fi/~palaste W++ B OP+ |
    \----------------------------------------- Finland rules! ------------/
    "Insanity is to be shared."
    - Tailgunner
     
    Joona I Palaste, Jun 25, 2003
    #7
  8. BTW,

    since you put ';' after the LRCALL_USELOCAL call, you should probably
    not have ';' in the macro.
     
    Hallvard B Furuseth, Jun 25, 2003
    #8
  9. Boris Boehlen

    Micah Cowan Guest

    It certainly wouldn't compile cleanly with warnings on (unsure and too
    lazy to verify without warnings), and certainly in strict
    conformance mode.
    There are no varargs in the code above. There are precisely three,
    protected by parens.

    -Micah
     
    Micah Cowan, Jun 26, 2003
    #9
  10. Hello,

    First I'd like to thank all of you for your help.
    I compiled your example with the gcc 3.3 from Debain and it compiles
    without any problem. Thus, the problem seems to be somewhere else.

    I'll try to find out where the problem is and try to produce a minial
    example which reproduces the error if I can't track it down.

    Again, thanks for your help.

    Boris
     
    Boris Boehlen, Jun 26, 2003
    #10
  11. Boris Boehlen

    Dan Pop Guest

    Your guess is right! Undefined behaviour requires no diagnostic and we
    have a case of undefined behaviour here. Both versions of gcc are doing
    the right thing.
    Please engage your brain *now* and explain us where are the variable
    arguments in OP's examples. AFAICT, the macro was defined with three
    parameters and invoked with three arguments, a perfect match.

    BTW, C99 supports macros with a variable argument list.

    Dan
     
    Dan Pop, Jun 26, 2003
    #11
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.