Re: Multi-instructions macro and compiler warning

Discussion in 'C Programming' started by Ian Collins, Oct 16, 2011.

  1. Ian Collins

    Ian Collins Guest

    On 10/16/11 08:09 PM, pozz wrote:
    > I'm trying to increase the warning level during compilation. My goal is
    > to reach the maximum warning level without any warning message after
    > compilation. I think this is a Good Thing to do when programming.
    >
    > After changing warning level from 4 to 5, I received many warning
    > messages of the type
    >
    > W1207C: conditional expression is constant: dowhile
    >
    > Those messages refer to multi-instructions macros defined as below:
    >
    > #define MACRO(a, b) do { foo(a); bar(b); } while(0)
    >
    > Many times I read to use the trick do/while(0) to write
    > multi-instruction macros to avoid other problems during compilation. In
    > this way, I can use MACRO() at any point where I could use a normal
    > function.
    >
    > How can I avoid the warning message W1207C? I'm using an embedded
    > microcontroller C compiler from Fujitsu, named Softune.


    Use a function. Any decent compiler will inline something that trivial.

    --
    Ian Collins
     
    Ian Collins, Oct 16, 2011
    #1
    1. Advertising

  2. Ian Collins

    Ian Collins Guest

    On 10/16/11 08:41 PM, pozz wrote:
    > Il 16/10/2011 09:31, Ian Collins ha scritto:
    >> On 10/16/11 08:09 PM, pozz wrote:
    >>> I'm trying to increase the warning level during compilation. My goal is
    >>> to reach the maximum warning level without any warning message after
    >>> compilation. I think this is a Good Thing to do when programming.
    >>>
    >>> After changing warning level from 4 to 5, I received many warning
    >>> messages of the type
    >>>
    >>> W1207C: conditional expression is constant: dowhile
    >>>
    >>> Those messages refer to multi-instructions macros defined as below:
    >>>
    >>> #define MACRO(a, b) do { foo(a); bar(b); } while(0)
    >>>
    >>> Many times I read to use the trick do/while(0) to write
    >>> multi-instruction macros to avoid other problems during compilation. In
    >>> this way, I can use MACRO() at any point where I could use a normal
    >>> function.
    >>>
    >>> How can I avoid the warning message W1207C? I'm using an embedded
    >>> microcontroller C compiler from Fujitsu, named Softune.

    >>
    >> Use a function. Any decent compiler will inline something that trivial.

    >
    > I have *many* macros of the same type (do/while(0)) in my projects,
    > sparsed over source and include files. The trivial MACRO() macro in my
    > original post is just an example to describe my approach for
    > multi-instructions macros.
    >
    > Should I change a macro for a function just to avoid a warning from
    > compiler? It doesn't make sense to me.


    But changing them because function like macros are an anachronism (or an
    abomination, depending on your point of view) does make sense.

    > And another curiosity. Is a C compiler optimizer able to convert a
    > function call to inline even if the function implementation (its code)
    > is in a different C module file?


    The compiler can't, but some linkers can.

    --
    Ian Collins
     
    Ian Collins, Oct 16, 2011
    #2
    1. Advertising

  3. Ian Collins

    Ian Collins Guest

    On 10/16/11 09:16 PM, pozz wrote:
    > Il 16/10/2011 09:49, Ian Collins ha scritto:
    >> On 10/16/11 08:41 PM, pozz wrote:
    >>> And another curiosity. Is a C compiler optimizer able to convert a
    >>> function call to inline even if the function implementation (its code)
    >>> is in a different C module file?

    >>
    >> The compiler can't, but some linkers can.

    >
    > I tried, the linker I'm using can't. Also the compiler (even with
    > optimization) doesn't transform normal functions to inline functions,
    > without the inline keyword.



    So use it! At least the compiler honours the hint. Embedded compilers
    tend to offer more control over what is and isn't inlined than their
    hosted brethren.

    --
    Ian Collins
     
    Ian Collins, Oct 16, 2011
    #3
  4. Ian Collins

    BartC Guest

    "pozz" <> wrote in message
    news:j7e1qm$7te$...
    > Il 16/10/2011 09:31, Ian Collins ha scritto:


    >> Use a function. Any decent compiler will inline something that trivial.


    > And another curiosity. Is a C compiler optimizer able to convert a
    > function call to inline even if the function implementation (its code) is
    > in a different C module file?


    The body of a macro has to be visible to the program. The same can be done
    with functions.

    But sharing the same function across several modules means putting the
    function definition in an include file, which is usually not done.

    The code will be duplicated in each module, but that will happen many times
    anyway if you want the function to be inlined.

    You also need to put 'static' in front of the function definition to keep
    the name of each one local, otherwise they will all clash with each other.

    --
    Bartc
     
    BartC, Oct 16, 2011
    #4
  5. Ian Collins

    bert Guest

    On Sunday, October 16, 2011 8:41:10 AM UTC+1, pozz wrote:
    > Il 16/10/2011 09:31, Ian Collins ha scritto:
    > > On 10/16/11 08:09 PM, pozz wrote:
    > >> I'm trying to increase the warning level during compilation. My goal is
    > >> to reach the maximum warning level without any warning message after
    > >> compilation. I think this is a Good Thing to do when programming.
    > >>
    > >> After changing warning level from 4 to 5, I received many warning
    > >> messages of the type
    > >>
    > >> W1207C: conditional expression is constant: dowhile
    > >>
    > >> Those messages refer to multi-instructions macros defined as below:
    > >>
    > >> #define MACRO(a, b) do { foo(a); bar(b); } while(0)
    > >>
    > >> Many times I read to use the trick do/while(0) to write
    > >> multi-instruction macros to avoid other problems during compilation. In
    > >> this way, I can use MACRO() at any point where I could use a normal
    > >> function.
    > >>
    > >> How can I avoid the warning message W1207C? I'm using an embedded
    > >> microcontroller C compiler from Fujitsu, named Softune.

    > >
    > > Use a function. Any decent compiler will inline something that trivial.

    >
    > I have *many* macros of the same type (do/while(0)) in my projects,
    > sparsed over source and include files. The trivial MACRO() macro in my
    > original post is just an example to describe my approach for
    > multi-instructions macros.
    >
    > Should I change a macro for a function just to avoid a warning from
    > compiler? It doesn't make sense to me.


    I think he meant an in-lineable function
    something like:

    int never(void)
    { return 0;
    }

    then use while(never()); instead of while(0);
    --
     
    bert, Oct 16, 2011
    #5
  6. Ian Collins

    Jorgen Grahn Guest

    On Sun, 2011-10-16, BartC wrote:
    ....
    > The body of a macro has to be visible to the program. The same can be done
    > with functions.
    >
    > But sharing the same function across several modules means putting the
    > function definition in an include file, which is usually not done.


    Maybe it's usually not done, but it *should* be (if you have a modern
    compiler). Things which don't *have* to be macros should be inline
    functions, for readability and type safety.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
     
    Jorgen Grahn, Oct 16, 2011
    #6
  7. Ian Collins

    pozz Guest

    On 16 Ott, 12:09, Ian Collins <> wrote:
    > On 10/16/11 09:16 PM, pozz wrote:
    > > I tried, the linker I'm using can't.  Also the compiler (even with
    > > optimization) doesn't transform normal functions to inline functions,
    > > without the inline keyword.

    >
    > So use it!  At least the compiler honours the hint.  Embedded compilers
    > tend to offer more control over what is and isn't inlined than their
    > hosted brethren.


    Unfortunately, I have another "warning" problem if I use inline
    functions.

    Suppose I have a macro that activate a relay connected to a
    microcontroller pin:

    #define RELAY_ON() do {PIN_SET_OUTPUT(10); PIN_SET(PIN(10));}
    while(0)

    The first instruction is to configure the pin as an output; the second
    is to set its level to high.

    Transforming this macro to an inline function, I would write:

    #pragma inline relay_on
    void relay_on(void) {
    PIN_SET_OUTPUT(10);
    PIN_SET(PIN(10));
    }

    If this function is accessible just from one compilation module, it is
    simple to use it:

    -- test.c --
    #include "cpu.h"

    #pragma inline relay_on
    static void relay_on(void) {
    PIN_SET_OUTPUT(10);
    PIN_SET(PIN(10));
    }

    void test(void) {
    relay_on();
    /* other things */
    }
    -- test.h --
    #ifndef TEST_H
    #define TEST_H
    #include "test.h"
    void test(void);
    #endif
    --

    The compilation ends without any errors and warnings.

    The problem happens when I try to use this function in more than one
    module,
    so moving the code to include file (I think this is the way to have an
    extern
    inline function):

    -- test.h --
    #ifndef TEST_H
    #define TEST_H

    #pragma inline relay_on
    void relay_on(void) {
    PIN_SET_OUTPUT(10);
    PIN_SET(PIN(10));
    }

    #endif
    --

    If I include test.h in more than one file, the compilation ends with
    the warning

    W1327L: Duplicate symbol definition (_relay_on)

    even if the function relay_on() is never used. So the use of inline
    function to
    avoid a warning has produced another warning :-(
     
    pozz, Oct 17, 2011
    #7
  8. Ian Collins

    pozz Guest

    On 16 Ott, 13:47, "BartC" <> wrote:
    > The body of a macro has to be visible to the program. The same can be done
    > with functions.
    >
    > But sharing the same function across several modules means putting the
    > function definition in an include file, which is usually not done.


    So isn't it possible to share an inline function among several
    modules?


    > The code will be duplicated in each module, but that will happen many times
    > anyway if you want the function to be inlined.
    >
    > You also need to put 'static' in front of the function definition to keep
    > the name of each one local, otherwise they will all clash with each other.


    I tried with:

    -- test.h --
    #ifndef TEST_H
    #define TEST_H

    #pragma inline relay_on
    static void relay_on(void) {
    PIN_SET_OUTPUT(10);
    PIN_SET(PIN(10));
    }

    #endif
    --

    but now I receive a warning message from the compiler if one module
    includes
    test.h without using relay_on() function (and this could be possible,
    because
    I usually have other definitions in the include file):

    W1204C: static symbol `relay_on' unused

    It's a nightmare...
     
    pozz, Oct 17, 2011
    #8
  9. Ian Collins

    Ian Collins Guest

    On 10/17/11 10:37 PM, pozz wrote:
    > On 16 Ott, 12:09, Ian Collins<> wrote:
    >> On 10/16/11 09:16 PM, pozz wrote:
    >>> I tried, the linker I'm using can't. Also the compiler (even with
    >>> optimization) doesn't transform normal functions to inline functions,
    >>> without the inline keyword.

    >>
    >> So use it! At least the compiler honours the hint. Embedded compilers
    >> tend to offer more control over what is and isn't inlined than their
    >> hosted brethren.

    >
    > Unfortunately, I have another "warning" problem if I use inline
    > functions.
    >
    > Suppose I have a macro that activate a relay connected to a
    > microcontroller pin:
    >
    > #define RELAY_ON() do {PIN_SET_OUTPUT(10); PIN_SET(PIN(10));}
    > while(0)
    >
    > The first instruction is to configure the pin as an output; the second
    > is to set its level to high.
    >
    > Transforming this macro to an inline function, I would write:
    >
    > #pragma inline relay_on
    > void relay_on(void) {
    > PIN_SET_OUTPUT(10);
    > PIN_SET(PIN(10));
    > }
    >
    > If this function is accessible just from one compilation module, it is
    > simple to use it:
    >
    > -- test.c --
    > #include "cpu.h"
    >
    > #pragma inline relay_on
    > static void relay_on(void) {
    > PIN_SET_OUTPUT(10);
    > PIN_SET(PIN(10));
    > }
    >
    > void test(void) {
    > relay_on();
    > /* other things */
    > }
    > -- test.h --
    > #ifndef TEST_H
    > #define TEST_H
    > #include "test.h"
    > void test(void);
    > #endif
    > --
    >
    > The compilation ends without any errors and warnings.
    >
    > The problem happens when I try to use this function in more than one
    > module,
    > so moving the code to include file (I think this is the way to have an
    > extern
    > inline function):
    >
    > -- test.h --
    > #ifndef TEST_H
    > #define TEST_H
    >
    > #pragma inline relay_on
    > void relay_on(void) {
    > PIN_SET_OUTPUT(10);
    > PIN_SET(PIN(10));
    > }
    >
    > #endif
    > --
    >
    > If I include test.h in more than one file, the compilation ends with
    > the warning
    >
    > W1327L: Duplicate symbol definition (_relay_on)
    >
    > even if the function relay_on() is never used. So the use of inline
    > function to
    > avoid a warning has produced another warning :-(
    >

    Well your "#pragma inline" doesn't follow the rules for inline
    functions. if the compiler did,

    inline void relay_on(void) {}

    would avoid multiple inclusion.

    Try "static void " rather than "inline void", it should have the same
    effect.

    --
    Ian Collins
     
    Ian Collins, Oct 17, 2011
    #9
  10. pozz <> writes:
    <snip>
    > Unfortunately, I have another "warning" problem if I use inline
    > functions.

    <snip>
    > Transforming this macro to an inline function, I would write:
    >
    > #pragma inline relay_on
    > void relay_on(void) {
    > PIN_SET_OUTPUT(10);
    > PIN_SET(PIN(10));
    > }
    >
    > If this function is accessible just from one compilation module, it is
    > simple to use it:

    <snip>
    > The problem happens when I try to use this function in more than one
    > module,
    > so moving the code to include file (I think this is the way to have an
    > extern
    > inline function):
    >
    > -- test.h --
    > #ifndef TEST_H
    > #define TEST_H
    >
    > #pragma inline relay_on
    > void relay_on(void) {
    > PIN_SET_OUTPUT(10);
    > PIN_SET(PIN(10));
    > }
    >
    > #endif
    > --
    >
    > If I include test.h in more than one file, the compilation ends with
    > the warning
    >
    > W1327L: Duplicate symbol definition (_relay_on)
    >
    > even if the function relay_on() is never used. So the use of inline
    > function to
    > avoid a warning has produced another warning :-(


    Make the function static.

    --
    Ben.
     
    Ben Bacarisse, Oct 17, 2011
    #10
  11. Ian Collins

    pozz Guest

    On 17 Ott, 12:06, Ben Bacarisse <> wrote:
    > pozz <> writes:
    >
    > <snip>
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > Unfortunately, I have another "warning" problem if I use inline
    > > functions.

    > <snip>
    > > Transforming this macro to an inline function, I would write:

    >
    > >   #pragma inline relay_on
    > >   void relay_on(void) {
    > >     PIN_SET_OUTPUT(10);
    > >     PIN_SET(PIN(10));
    > >   }

    >
    > > If this function is accessible just from one compilation module, it is
    > > simple to use it:

    > <snip>
    > > The problem happens when I try to use this function in more than one
    > > module,
    > > so moving the code to include file (I think this is the way to have an
    > > extern
    > > inline function):

    >
    > > -- test.h --
    > > #ifndef TEST_H
    > > #define TEST_H

    >
    > > #pragma inline relay_on
    > > void relay_on(void) {
    > >   PIN_SET_OUTPUT(10);
    > >   PIN_SET(PIN(10));
    > > }

    >
    > > #endif
    > > --

    >
    > > If I include test.h in more than one file, the compilation ends with
    > > the warning

    >
    > >   W1327L: Duplicate symbol definition (_relay_on)

    >
    > > even if the function relay_on() is never used. So the use of inline
    > > function to
    > > avoid a warning has produced another warning :-(

    >
    > Make the function static.


    See my answer to BartC below. If I declare the inline function static,
    I receive
    a warning when I include the file without using the function... :-(
     
    pozz, Oct 17, 2011
    #11
  12. Ian Collins

    BartC Guest

    "pozz" <> wrote in message
    news:...
    > On 16 Ott, 13:47, "BartC" <> wrote:


    >> The code will be duplicated in each module, but that will happen many
    >> times
    >> anyway if you want the function to be inlined.


    > -- test.h --
    > #ifndef TEST_H
    > #define TEST_H
    >
    > #pragma inline relay_on
    > static void relay_on(void) {
    > PIN_SET_OUTPUT(10);
    > PIN_SET(PIN(10));
    > }
    >
    > #endif
    > --
    >
    > but now I receive a warning message from the compiler if one module
    > includes
    > test.h without using relay_on() function (and this could be possible,
    > because
    > I usually have other definitions in the include file):
    >
    > W1204C: static symbol `relay_on' unused
    >
    > It's a nightmare...


    No, it's just a warning, not an error.

    You can ignore the warning. Or find some compiler switch that turns the
    warning off.

    Or create a more complex include file scheme, so that these functions are
    declared in their own header, and included only when used. Or use a dummy
    function that makes use of 'relay_on' (that's assuming that doesn't generate
    yet another warning about not calling the dummy function...)

    --
    Bartc
     
    BartC, Oct 17, 2011
    #12
  13. pozz <> writes:
    [...]
    > Suppose I have a macro that activate a relay connected to a
    > microcontroller pin:
    >
    > #define RELAY_ON() do {PIN_SET_OUTPUT(10); PIN_SET(PIN(10));}
    > while(0)

    [...]

    Are PIN_SET_OUTPUT and PIN_SET functions or macros?

    If they're functions, or if they're macros whose invocations expand to
    valid expressions, then you can just do this:

    #define RELAY_ON() ( PIN_SET_OUTPUT(10), PIN_SET(PIN(10)) )

    There's no need for the "do { ... } while (0)" trick unless you
    need to use control-flow constructs (if, for, while) -- and "if"
    can often be replaced with "?:". Just about anything that doesn't
    require looping can be made into an expression.

    This assumes you really need to make it a macro. If you're able
    to make it a function (inline or not), then of course you can use
    any control-flow you like.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Oct 17, 2011
    #13
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jay Douglas
    Replies:
    2
    Views:
    9,519
    Alvin Bruney [ASP.NET MVP]
    Mar 16, 2005
  2. Michael B Allen

    Suppressing Compiler Warning About Tricky Macro

    Michael B Allen, Jul 22, 2007, in forum: C Programming
    Replies:
    6
    Views:
    357
    Barry Schwarz
    Jul 22, 2007
  3. Tom Anderson
    Replies:
    4
    Views:
    519
    Peter Flynn
    Dec 13, 2008
  4. Jean-Christophe

    Re: Multi-instructions macro and compiler warning

    Jean-Christophe, Oct 16, 2011, in forum: C Programming
    Replies:
    3
    Views:
    404
    Ian Collins
    Oct 16, 2011
  5. ImpalerCore

    Re: Multi-instructions macro and compiler warning

    ImpalerCore, Oct 17, 2011, in forum: C Programming
    Replies:
    4
    Views:
    422
    Keith Thompson
    Oct 18, 2011
Loading...

Share This Page