• Re: Concatenated if and preprocessor

    From David Brown@21:1/5 to pozz on Thu Mar 13 16:55:16 2025
    On 13/03/2025 16:44, pozz wrote:
    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    Could you give a short example of what you would want as the result of
    the pre-processing, just with a couple of conditions?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to pozz on Thu Mar 13 16:11:35 2025
    pozz <[email protected]> writes:
    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the >combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    Perhaps using switch instead of a series of if statements would
    make the problem more tractable.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Kaz Kylheku@21:1/5 to pozz on Thu Mar 13 16:30:47 2025
    On 2025-03-13, pozz <[email protected]> wrote:
    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    The best way is not to use the preprocessor to try to conditionally
    generate syntax. Rather, use the preprocessor to control the
    conditions. You can make the conditions appear false at compile
    time, and he compiler will remove the code as dead code.

    #if HAVE_FEATURE_RELATED_TO_COND1
    #define cond1 real->expression[0].fun(arg)
    #else
    #define cond1 0
    #endif

    Thus if the feature is disabled, then if (cond1) becomes if (0).

    There are reasons why this might not work, like the associated
    code not compiling when the feature is disabled, due to missing
    declarations.

    Suppose we have to use the preprocessor to remove any combination of the conditionals.


    Firstly, let's (1) start the if/else ladder with a dummy if that is
    always false, and (2) terminate it with a dummy else.

    That way everything in between is consistenlty an "else if" item.

    if (0) { /* empty */ }
    else if (cond1) { ... code ...}
    else if (cond2) { ... code ...}
    else if (cond3) { ... code ...}
    else { /* empty */ }

    You see where this is going? We can now delete any combination of the conditionals, including all of them.

    if (0) { /* empty */ }
    ##if HAVE_FEATURE_REALTED_TO_COND1
    else if (cond1) { ... code ...}
    #endif
    ##if HAVE_FEATURE_REALTED_TO_COND2
    else if (cond2) { ... code ...}
    #endif
    ##if HAVE_FEATURE_REALTED_TO_COND2
    else if (cond3) { ... code ...}
    #endif
    else { /* empty */ }


    --
    TXR Programming Language: http://nongnu.org/txr
    Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
    Mastodon: @[email protected]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to pozz on Thu Mar 13 12:07:05 2025
    On 3/13/25 11:44, pozz wrote:
    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    The cleanest way to do this involves trusting the compiler to quietly
    remove unused branches:

    #ifdef COND1
    if (cond1) }
    } else
    #endif

    #ifdef COND2
    if (cond2) {
    } else
    #endif

    #ifdef COND3
    if (cond3 ) {
    }
    #else
    ; // Alternatively, use {}
    #endif

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From bart@21:1/5 to pozz on Thu Mar 13 17:29:44 2025
    On 13/03/2025 15:44, pozz wrote:
    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?


    Comment out the macro of the conditions that are not needed:


    #define COND1
    #define COND2
    #define COND3

    if (0) {
    }
    #ifdef COND1
    else if (cond1) {
    }
    #endif

    #ifdef COND2
    else if (cond2) {
    }
    #endif

    #ifdef COND3
    else if (cond3) {
    }
    #endif

    All 8 combinations (for 3 branches) should work including all disabled.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to pozz on Thu Mar 13 14:37:16 2025
    pozz <[email protected]> writes:

    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    if ( ..bypass all further tests.. ) {
    // for a "skip all conditional segments" case (if needed)
    ...

    #if TEST_1
    } else if (cond1) {
    ...
    #endif

    #if TEST_2
    } else if (cond2) {
    ...
    #endif

    #if TEST_3
    } else if (cond3) {
    ...
    #endif

    } else {
    // for a "no conditional segment" ran case (if needed)
    ...
    }


    Having said that, it's hard to imagine a scenario where doing
    something like this is the best way to solve the higher level
    problem. It is almost certainly better to rethink the reasoning
    that resulted in choosing this scheme, and find a way to avoid it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to pozz on Fri Mar 14 14:13:52 2025
    On 14/03/2025 13:02, pozz wrote:
    Il 13/03/2025 16:44, pozz ha scritto:
    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the
    combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    You're right, a real example is better to define my problem.

    I have a project that can be compiled in different ways, depending on
    the final product model (it's an embedded platform, it's a material
    device).
    I have three models with different characteristics: MODEL_A, MODEL_B, MODEL_C. Three different builds that are managed at compile time by
    defining MODEL macro as MODEL_A, MODEL_B or MODEL_C.

    For each model, I could have a different features set. FEATURE_1,
    FUTURE_2, FUTURE_3, ...

    #if MODEL == MODEL_A
    #  define FEATURE_1   1
    #  define FEATURE_2   0
    #  define FEATURE_3   0
    #elif MODEL == MODEL_B
    #  define FEATURE_1   0
    #  define FEATURE_2   1
    #  define FEATURE_3   0
    #elif MODEL == MODEL_C
    #  define FEATURE_1   1
    #  define FEATURE_2   1
    #  define FEATURE_3   1
    #endif

    Now, on the full-featured model (MODEL_C) I could write:

    if (key == 1) {
      ...
    } else if (key == 2) {
      ...
    } else if (key == 3) {
      ...
    } else {
      ...
    }

    However, for MODEL_A I should have:

    if (key == 1) {
      ...
    } else {
      ...
    }

    For MODEL_B I should have:

    if (key == 2) {
      ...
    } else {
      ...
    }

    This is the scenario.

    I thought using if(0) or if(1), but many times I receive some warnings
    from the compiler (condition is always true or condition is always false).


    How about :

    if (FEATURE_1 && key == 1) {
    ...
    } else if (FEATURE_2 && key == 2) {
    ...
    } else {
    ...
    }

    ?

    (You might prefer a switch to a list of if's, but that's a different issue.)

    If you are still suffering from unwanted warnings (and don't want to
    disable the warning in question), can you post a godbolt.org link that
    shows some sample code giving the warning, along with the choice of
    compiler and flags you are using? When people can duplicate the issue,
    it's a lot easier to give help than when your code is approximate, your compiler messages are vague, and we don't know details of the toolchain.
    (Usually it does not matter if the toolchain is for the right target processor - you will generally get the same warnings for code for x86-64
    gcc, and godbolt has most versions of these available.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Purgert@21:1/5 to pozz on Fri Mar 14 13:44:59 2025
    On 2025-03-14, pozz wrote:
    Il 13/03/2025 16:44, pozz ha scritto:
    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the
    combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    You're right, a real example is better to define my problem.

    I have a project that can be compiled in different ways, depending on
    the final product model (it's an embedded platform, it's a material
    device).
    I have three models with different characteristics: MODEL_A, MODEL_B, MODEL_C. Three different builds that are managed at compile time by
    defining MODEL macro as MODEL_A, MODEL_B or MODEL_C.

    For each model, I could have a different features set. FEATURE_1,
    FUTURE_2, FUTURE_3, ...

    #if MODEL == MODEL_A
    # define FEATURE_1 1
    # define FEATURE_2 0
    # define FEATURE_3 0
    #elif MODEL == MODEL_B
    # define FEATURE_1 0
    # define FEATURE_2 1
    # define FEATURE_3 0
    #elif MODEL == MODEL_C
    # define FEATURE_1 1
    # define FEATURE_2 1
    # define FEATURE_3 1
    #endif


    So are you saying that the features are potentially independent of the
    models, or that "Model A" explicitly defines that only "FEATURE_1" is
    available (and will never support the other two) ?

    --
    |_|O|_|
    |_|_|O| Github: https://github.com/dpurgert
    |O|O|O| PGP: DDAB 23FB 19FA 7D85 1CC1 E067 6D65 70E5 4CE7 2860

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Lynn McGuire on Fri Mar 14 09:26:07 2025
    Lynn McGuire <[email protected]> writes:

    On 3/13/2025 4:37 PM, Tim Rentsch wrote:

    pozz <[email protected]> writes:

    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the
    combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    if ( ..bypass all further tests.. ) {
    // for a "skip all conditional segments" case (if needed)
    ...

    #if TEST_1
    } else if (cond1) {
    ...
    #endif

    #if TEST_2
    } else if (cond2) {
    ...
    #endif

    #if TEST_3
    } else if (cond3) {
    ...
    #endif

    } else {
    // for a "no conditional segment" ran case (if needed)
    ...
    }
    >
    Having said that, it's hard to imagine a scenario where doing
    something like this is the best way to solve the higher level
    problem. It is almost certainly better to rethink the reasoning
    that resulted in choosing this scheme, and find a way to avoid it.

    It is code that must run on several platforms.

    Yes, I already understood that. The point of my comment is
    not to eliminate the preprocessor dependencies but to express
    them in a more aesthetically pleasing way.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to pozz on Fri Mar 14 09:44:16 2025
    pozz <[email protected]> writes:

    Il 13/03/2025 16:44, pozz ha scritto:

    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All
    the combinations are possible: only the first, only the second, only
    the third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    You're right, a real example is better to define my problem.

    I have a project that can be compiled in different ways, depending on
    the final product model (it's an embedded platform, it's a material
    device).
    I have three models with different characteristics: MODEL_A, MODEL_B, MODEL_C. Three different builds that are managed at compile time by
    defining MODEL macro as MODEL_A, MODEL_B or MODEL_C.

    For each model, I could have a different features set. FEATURE_1,
    FUTURE_2, FUTURE_3, ...

    #if MODEL == MODEL_A
    # define FEATURE_1 1
    # define FEATURE_2 0
    # define FEATURE_3 0
    #elif MODEL == MODEL_B
    # define FEATURE_1 0
    # define FEATURE_2 1
    # define FEATURE_3 0
    #elif MODEL == MODEL_C
    # define FEATURE_1 1
    # define FEATURE_2 1
    # define FEATURE_3 1
    #endif

    Now, on the full-featured model (MODEL_C) I could write:

    if (key == 1) {
    ...
    } else if (key == 2) {
    ...
    } else if (key == 3) {
    ...
    } else {
    ...
    }

    However, for MODEL_A I should have:

    if (key == 1) {
    ...
    } else {
    ...
    }

    For MODEL_B I should have:

    if (key == 2) {
    ...
    } else {
    ...
    }

    This is the scenario.

    I thought using if(0) or if(1), but many times I receive some
    warnings from the compiler (condition is always true or condition
    is always false).

    So your question is not a language question but how to avoid implemenation-specific warnings? It would have been good to
    explain that at the beginning.

    My first suggestion is to just turn off the damn warning. Any
    compiler that gives a "condition always false" warning on 'if(0)'
    is one best avoided.

    Having said that, here is an alternative:

    for( int just_once = 1; just_once; just_once = 0 ){
    #if FEATURE_1
    if( condition_1 ){
    ...
    break;
    }
    #endif

    #if FEATURE_2
    if( condition_2 ){
    ...
    break;
    }
    #endif

    #if FEATURE_3
    if( condition_3 ){
    ...
    break;
    }
    #endif

    ... default code goes here ...

    }

    Test compiles at optimization level -O1 shows gcc and clang are both
    smart enough to optimize the for(...) out of existence, leaving
    just the enabled if() sections.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Tim Rentsch on Fri Mar 14 18:15:13 2025
    On 14/03/2025 16:44, Tim Rentsch wrote:

    for( int just_once = 1; just_once; just_once = 0 ){

    Any reason not to say ...

    do {
    ...
    } while (0);

    ... ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Richard Harnden on Fri Mar 14 13:40:26 2025
    Richard Harnden <[email protected]d> writes:

    On 14/03/2025 16:44, Tim Rentsch wrote:

    for( int just_once = 1; just_once; just_once = 0 ){

    Any reason not to say ...

    do {
    ...
    } while (0);

    ... ?

    In fact using do/while(0) is what I first wrote. But then
    I thought, oh wait, what if an overzealous compiler gives
    a warning because the while() expression is always false? :-/

    It's because of examples like this that I am wary of rules
    like "enable all warnings" and "treat any warning condition
    as an error." I recently ran across a set of coding standard
    rules that included these rules: not just /some/ warning
    conditions, but ALL warning conditions. I still don't know
    if they were literally serious. (And my understanding is
    clang has a -Weverything option, which enables all warning
    conditions that clang is able to test for, no matter how
    silly.)

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Richard Harnden@21:1/5 to Keith Thompson on Fri Mar 14 21:31:08 2025
    On 14/03/2025 21:10, Keith Thompson wrote:
    Tim Rentsch <[email protected]> writes:
    Richard Harnden <[email protected]d> writes:
    On 14/03/2025 16:44, Tim Rentsch wrote:
    for( int just_once = 1; just_once; just_once = 0 ){

    Any reason not to say ...

    do {
    ...
    } while (0);

    ... ?

    In fact using do/while(0) is what I first wrote. But then
    I thought, oh wait, what if an overzealous compiler gives
    a warning because the while() expression is always false? :-/

    That would break a lot of macros :)


    It's because of examples like this that I am wary of rules
    like "enable all warnings" and "treat any warning condition
    as an error." I recently ran across a set of coding standard
    rules that included these rules: not just /some/ warning
    conditions, but ALL warning conditions. I still don't know
    if they were literally serious. (And my understanding is
    clang has a -Weverything option, which enables all warning
    conditions that clang is able to test for, no matter how
    silly.)

    I've worked under such coding standards. Perhaps surprisingly, I
    haven't found them to be terribly inconvenient. I rarely ran into
    a warning that was inordinately difficult to avoid. I can see that
    "clang -Weverything" would cause problems.

    The most common inconvenience was that if I experimentally commented
    out some code, and it caused some variable not to be referenced,
    the build would fail. (I could just add `(void)foo;` to avoid that.)
    To be clear, this was not code that I intended to commit.

    I can imagine that there could be problems if a newer version of the
    compiler produced new warnings, but we didn't often change compilers.

    (In one obscure case, I wrote a wrapper script that could be
    installed in $PATH as "gcc" that would invoke the real gcc and
    filter out a particular warning. The wrapper was necessary due to
    the behavior of a build script, not to an explicit coding standard.)


    Hmm, clang with -Weverything is okay with:
    do { ... } while (0);

    But not with:
    if ( 0 ) { ... }

    But it's okay with:
    if ( (0) ) { ... }

    I didn't know that was a thing, so I've learnt something new today, thanks.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Keith Thompson on Fri Mar 14 15:57:39 2025
    Keith Thompson <[email protected]> writes:

    Tim Rentsch <[email protected]> writes:

    Richard Harnden <[email protected]d> writes:

    On 14/03/2025 16:44, Tim Rentsch wrote:

    for( int just_once = 1; just_once; just_once = 0 ){

    Any reason not to say ...

    do {
    ...
    } while (0);

    ... ?

    In fact using do/while(0) is what I first wrote. But then
    I thought, oh wait, what if an overzealous compiler gives
    a warning because the while() expression is always false? :-/

    It's because of examples like this that I am wary of rules
    like "enable all warnings" and "treat any warning condition
    as an error." I recently ran across a set of coding standard
    rules that included these rules: not just /some/ warning
    conditions, but ALL warning conditions. I still don't know
    if they were literally serious. (And my understanding is
    clang has a -Weverything option, which enables all warning
    conditions that clang is able to test for, no matter how
    silly.)

    I've worked under such coding standards.

    I'm guessing this comment is an overstatement, and that you have
    worked with similar but not nearly as stringent coding standards.
    The coding standard I was referring to above says "Compile with
    all possible warnings active" (and then also says something about
    addressing them).

    Perhaps surprisingly, I
    haven't found them to be terribly inconvenient. I rarely ran into
    a warning that was inordinately difficult to avoid. I can see that
    "clang -Weverything" would cause problems.

    Yes, exactly my point. "Lots of warnings" is not at all the same as
    "all possible warnings".

    The most common inconvenience was that if I experimentally commented
    out some code, and it caused some variable not to be referenced,
    the build would fail. (I could just add `(void)foo;` to avoid that.)
    To be clear, this was not code that I intended to commit.

    Another question about coding standards is at what point in the
    development process do they apply. The rule in question here
    says to _compile_ with all possible warnings active, presumably
    meaning all compilations, not just those at checkin time.

    I can imagine that there could be problems if a newer version of the
    compiler produced new warnings, but we didn't often change compilers.

    The two cardinal sins for giving error/warning options for a coding
    standard are: one, including an option whose meaning is not well
    defined; and two, including an option whose meaning changes over
    time, either because of using a different compiler or because of
    using a different version of the same compiler. Saying it doesn't
    happen often is no excuse; developers should never agree to
    requirements that mandate moving targets.

    (In one obscure case, I wrote a wrapper script that could be
    installed in $PATH as "gcc" that would invoke the real gcc and
    filter out a particular warning. The wrapper was necessary due to
    the behavior of a build script, not to an explicit coding standard.)

    A reasonable course of action under the circumstances, I expect. At
    the same time, it shows a shortcoming of the coding standard in
    effect, if said standard says builds should not have any warnings
    (and no exception is made for spurious warnings that occur because
    of how builds are done).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Richard Harnden on Fri Mar 14 15:29:36 2025
    Richard Harnden <[email protected]d> writes:

    On 14/03/2025 21:10, Keith Thompson wrote:

    Tim Rentsch <[email protected]> writes:

    Richard Harnden <[email protected]d> writes:

    On 14/03/2025 16:44, Tim Rentsch wrote:

    for( int just_once = 1; just_once; just_once = 0 ){

    Any reason not to say ...

    do {
    ...
    } while (0);

    ... ?

    In fact using do/while(0) is what I first wrote. But then
    I thought, oh wait, what if an overzealous compiler gives
    a warning because the while() expression is always false? :-/

    That would break a lot of macros :)

    [...]

    Hmm, clang with -Weverything is okay with:
    do { ... } while (0);

    But not with:
    if ( 0 ) { ... }

    But it's okay with:
    if ( (0) ) { ... }

    These examples illustrate why I have the reaction I do. That
    plus the lack of clarity as to what the OP's actual requirements
    are explains my decision to use a for() rather than do/while(0).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From James Kuyper@21:1/5 to pozz on Fri Mar 14 23:20:07 2025
    On 3/14/25 08:02, pozz wrote:
    Il 13/03/2025 16:44, pozz ha scritto:
    Consider this code:

    if (cond1) {
    ...
    } else if (cond2) {
    ...
    } else if (cond3) {
    ...
    }

    I want to activate every single if with a macro preprocessor. All the
    combinations are possible: only the first, only the second, only the
    third, the first and second... and so on.

    What's the best method to have a clean code that is always compiled
    without errors?

    You're right, a real example is better to define my problem.

    I have a project that can be compiled in different ways, depending on
    the final product model (it's an embedded platform, it's a material
    device).
    I have three models with different characteristics: MODEL_A, MODEL_B, MODEL_C. Three different builds that are managed at compile time by
    defining MODEL macro as MODEL_A, MODEL_B or MODEL_C.

    For each model, I could have a different features set. FEATURE_1,
    FUTURE_2, FUTURE_3, ...

    #if MODEL == MODEL_A
    # define FEATURE_1 1
    # define FEATURE_2 0
    # define FEATURE_3 0
    #elif MODEL == MODEL_B
    # define FEATURE_1 0
    # define FEATURE_2 1
    # define FEATURE_3 0
    #elif MODEL == MODEL_C
    # define FEATURE_1 1
    # define FEATURE_2 1
    # define FEATURE_3 1
    #endif

    Now, on the full-featured model (MODEL_C) I could write:

    if (key == 1) {
    ...
    } else if (key == 2) {
    ...
    } else if (key == 3) {
    ...
    } else {
    ...
    }

    If all of the if-conditions are tests of the same variable for different values, switch() is the more appropriate control structure t than
    repeated "if() {} else". In that case, the feature macros can simply
    control the cases that exist within the switch statement.
    If switch is not suitable, it must be because of some complication you
    haven't shown us yet.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Richard Harnden on Sat Mar 15 07:03:00 2025
    On Fri, 14 Mar 2025 18:15:13 +0000, Richard Harnden wrote:

    Any reason not to say ...

    do {
    ...
    } while (0);

    ... ?

    do
    {
    ...
    }
    while (false);

    I think makes more sense.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Keith Thompson on Sat Mar 15 15:06:30 2025
    Keith Thompson <[email protected]> writes:
    Tim Rentsch <[email protected]> writes:
    Keith Thompson <[email protected]> writes:
    Tim Rentsch <[email protected]> writes:

    It's because of examples like this that I am wary of rules
    like "enable all warnings" and "treat any warning condition
    as an error." I recently ran across a set of coding standard
    rules that included these rules: not just /some/ warning
    conditions, but ALL warning conditions. I still don't know
    if they were literally serious. (And my understanding is
    clang has a -Weverything option, which enables all warning
    conditions that clang is able to test for, no matter how
    silly.)

    I've worked under such coding standards.

    I'm guessing this comment is an overstatement, and that you have
    worked with similar but not nearly as stringent coding standards.
    The coding standard I was referring to above says "Compile with
    all possible warnings active" (and then also says something about
    addressing them).

    Right, I didn't read closely enough. Some (non-maximal) set of warnings
    were enabled, and any warnings that resulted were treated as fatal errors.

    We build with -Wall. It's been quite successful for us and
    hasn't resulted in significant effort to maintain (granted
    as we switch to newer versions of the compiler suite, we
    run into new warnings, but they're quite easy to address
    either via code changes or #pragma).

    The codebase runs well over two million SLOC and supports
    gcc7 through gcc14.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Tim Rentsch@21:1/5 to Scott Lurndal on Sat Mar 15 08:49:25 2025
    [email protected] (Scott Lurndal) writes:

    Keith Thompson <[email protected]> writes:

    Tim Rentsch <[email protected]> writes:

    Keith Thompson <[email protected]> writes:

    Tim Rentsch <[email protected]> writes:

    It's because of examples like this that I am wary of rules
    like "enable all warnings" and "treat any warning condition
    as an error." I recently ran across a set of coding standard
    rules that included these rules: not just /some/ warning
    conditions, but ALL warning conditions. I still don't know
    if they were literally serious. (And my understanding is
    clang has a -Weverything option, which enables all warning
    conditions that clang is able to test for, no matter how
    silly.)

    I've worked under such coding standards.

    I'm guessing this comment is an overstatement, and that you have
    worked with similar but not nearly as stringent coding standards.
    The coding standard I was referring to above says "Compile with
    all possible warnings active" (and then also says something about
    addressing them).

    Right, I didn't read closely enough. Some (non-maximal) set of
    warnings were enabled, and any warnings that resulted were treated
    as fatal errors.

    We build with -Wall. It's been quite successful for us and
    hasn't resulted in significant effort to maintain (granted
    as we switch to newer versions of the compiler suite, we
    run into new warnings, but they're quite easy to address
    either via code changes or #pragma).

    The codebase runs well over two million SLOC and supports
    gcc7 through gcc14.

    Can you say which new warnings have been addressed via #pragma
    (which I assume effectively means selective disabling)?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Tim Rentsch on Sat Mar 15 17:32:32 2025
    On 14/03/2025 23:29, Tim Rentsch wrote:
    Richard Harnden <[email protected]d> writes:

    On 14/03/2025 21:10, Keith Thompson wrote:

    Tim Rentsch <[email protected]> writes:

    Richard Harnden <[email protected]d> writes:

    On 14/03/2025 16:44, Tim Rentsch wrote:

    for( int just_once = 1; just_once; just_once = 0 ){

    Any reason not to say ...

    do {
    ...
    } while (0);

    ... ?

    In fact using do/while(0) is what I first wrote. But then
    I thought, oh wait, what if an overzealous compiler gives
    a warning because the while() expression is always false? :-/

    That would break a lot of macros :)

    [...]

    Hmm, clang with -Weverything is okay with:
    do { ... } while (0);

    But not with:
    if ( 0 ) { ... }

    But it's okay with:
    if ( (0) ) { ... }

    These examples illustrate why I have the reaction I do. That
    plus the lack of clarity as to what the OP's actual requirements
    are explains my decision to use a for() rather than do/while(0).

    I think your "for" solution would raise far more questions to any reader
    than idiomatic "do ... while (0)" would, or even if ((0)). I really
    don't understand your reactions at all.

    But I fully agree that it would be a lot easier to give the OP a good
    answer if he explained his requirements and situation better.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From David Brown@21:1/5 to Keith Thompson on Sat Mar 15 17:28:24 2025
    On 14/03/2025 22:10, Keith Thompson wrote:
    Tim Rentsch <[email protected]> writes:
    Richard Harnden <[email protected]d> writes:
    On 14/03/2025 16:44, Tim Rentsch wrote:
    for( int just_once = 1; just_once; just_once = 0 ){

    Any reason not to say ...

    do {
    ...
    } while (0);

    ... ?

    In fact using do/while(0) is what I first wrote. But then
    I thought, oh wait, what if an overzealous compiler gives
    a warning because the while() expression is always false? :-/

    It's because of examples like this that I am wary of rules
    like "enable all warnings" and "treat any warning condition
    as an error." I recently ran across a set of coding standard
    rules that included these rules: not just /some/ warning
    conditions, but ALL warning conditions. I still don't know
    if they were literally serious. (And my understanding is
    clang has a -Weverything option, which enables all warning
    conditions that clang is able to test for, no matter how
    silly.)

    I've worked under such coding standards. Perhaps surprisingly, I
    haven't found them to be terribly inconvenient. I rarely ran into
    a warning that was inordinately difficult to avoid. I can see that
    "clang -Weverything" would cause problems.

    It is normal for safety or reliability critical software to insist that
    all warnings are treated as errors. This is essential to avoid missing warnings when using a build system - if you run "make" and you get
    warnings, running "make" again will appear to give a clean warning-free
    build. So you use "warnings as errors" options to the compiler, at
    least once your project is somewhat stable in the development process.

    But it is not normal to insist that /all/ compiler warnings are enabled
    - many compilers support a wide range of warnings, and many will be inapplicable to some code. Coding standards don't usually go into
    enough detail of the use of a particular compiler to specify warnings
    exactly - and it would rarely be a good idea anyway if the standard
    should cover a range of different types of code. More often, they are
    vague about warnings - "enable all standard warnings" or "make good use
    of appropriate compiler warnings", along with insisting that the build
    be warning-free to avoid missing anything.


    The most common inconvenience was that if I experimentally commented
    out some code, and it caused some variable not to be referenced,
    the build would fail. (I could just add `(void)foo;` to avoid that.)
    To be clear, this was not code that I intended to commit.


    This can be an inconvenience, yes - and sometimes during development or testing, it is appropriate to "cheat" temporarily like this, or by
    disabling the "all warnings are errors" flag for a while. A development process should not be /too/ rigid!

    It's common to use "(void) foo;" in final code too. Usually you don't
    want code that creates a variable and then does not use it at all, so
    warnings there can be helpful, and typically mean you should fix
    something in the code (remove the variable, or use it). But for
    function parameters it is not uncommon that the signature must fit a
    particular form even though the implementation does not use all the
    parameters. Casting the unused parameter to void is an idiomatic and
    clear way of indicating that the parameter is not used, without using implementation-specific features like "__attribute__((unused))". (C23
    gives two new alternatives - [[maybe_unused]], and leaving the parameter unnamed in the function definition.)

    It can also be, IMHO, perfectly reasonable to add pragmas to disable
    particular warnings in code. Sometimes you know that a particular bit
    of code will trigger a warning that you normally want enabled, and it
    would be ugly, unclear or inefficient to write the code in a way that
    avoids the warning. Of course, such warning disable pragmas are not
    going to be portable.

    I can imagine that there could be problems if a newer version of the
    compiler produced new warnings, but we didn't often change compilers.

    (In one obscure case, I wrote a wrapper script that could be
    installed in $PATH as "gcc" that would invoke the real gcc and
    filter out a particular warning. The wrapper was necessary due to
    the behavior of a build script, not to an explicit coding standard.)


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Scott Lurndal@21:1/5 to Tim Rentsch on Sat Mar 15 17:28:40 2025
    Tim Rentsch <[email protected]> writes:
    [email protected] (Scott Lurndal) writes:

    Keith Thompson <[email protected]> writes:


    We build with -Wall. It's been quite successful for us and
    hasn't resulted in significant effort to maintain (granted
    as we switch to newer versions of the compiler suite, we
    run into new warnings, but they're quite easy to address
    either via code changes or #pragma).

    The codebase runs well over two million SLOC and supports
    gcc7 through gcc14.

    Can you say which new warnings have been addressed via #pragma
    (which I assume effectively means selective disabling)?

    Most of the new warnings have been due to better detection of unused
    and/or uninitialized variables - all to the good.

    The rest fall into a few catgegories:

    #pragma GCC diagnostic ignored "-Wformat-nonliteral"
    #pragma warning(disable:4996) (related to vsnprintf).

    A few floating point warnings about double->float conversions,
    that are expected in a certain block of code that deals with
    floating point simulation.

    And a handful that are #pragma'd out of third-party source code that we
    cannot modify, and which the third-party won't modify. Mostly related
    to C++14 extensions.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)