Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a gcc warning for "conditional expression is constant"?

I've inherited a sizeable codebase where someone, somehow, has written several conditionals like so:

enum
{
    FOO_TYPE_A,
    FOO_TYPE_B,
    FOO_TYPE_C,
    FOO_TYPE_D
};

void bar(int fooType)
{
    if (fooType == FOO_TYPE_A || FOO_TYPE_B) // <-- This will always be true, since FOO_TYPE_B is nonzero!
    {
        // Do something intended for only type A or B
    }

    // Do things general to A,B,C,D
}

where the condition check should clearly be:

    if (fooType == FOO_TYPE_A || fooType  == FOO_TYPE_B)

Is there a warning in gcc I can turn on to find them all, similar to MSDN's C4127?

Specifically, I'm using the Android NDK r9d.

If not, why not? It seems like a useful catch-all for unintentional assignment, unsigned > 0 as well as the above foolishness.

EDIT: Made the code more verbose to illustrate the problem.

like image 602
etheranger Avatar asked Nov 11 '22 10:11

etheranger


1 Answers

I do not see a warning that corresponds to MSDN C4127. GCC does have a warning that is somewhat similar in intent, but not to address your problem: -Wtype-limits

Warn if a comparison is always true or always false due to the limited range of the data type, but do not warn for constant expressions. For example, warn if an unsigned variable is compared against zero with < or >=. This warning is also enabled by -Wextra.

As you can see, GCC explicitly states it does not warn about constant expressions. The motivation for this may be due to the common use of constant expressions to leverage the compiler's dead code elimination so that macros (or portions of it) can be optimized away by using a compile time constant. It would be used as an alternative to conditional compilation (#if defined() and #if X == Y), as the macro reads more naturally like a regular function. As a hypothetical example:

#define VERIFY(E) \
do { \
    if (NO_VERIFY) break; \
    if (!(E) && (VERIFY_LOG_LEVEL >= log_level() || VERIFY_LOG_ALWAYS)) { \
        log("validation error for: " #E); \
    } \
} while (0)
like image 164
jxh Avatar answered Nov 15 '22 08:11

jxh