Home > Software engineering >  How can I add warning feature to the GCC?
How can I add warning feature to the GCC?

Time:04-09

Example of usage:

void closefrom (int lowfd);

int main()
{
    // expected warning
    closefrom(-1);
    return 0;
}

Specifically: I should implement diagnostics (compiler warning) for function calls. Function located in glibc: void closefrom (int lowfd);

If lowfd is negative compiler should issue a warning.

Here is some information about closefrom:

https://sourceware.org/pipermail/libc-alpha/2021-August/129718.html

Maybe attribute of the function will somehow help in this?

CodePudding user response:

You can do it like this, but don’t:

void foo(int x) {}

#define foo(x)  foo(((int [(x) 1]){0}, (x)))

int main(void)
{
    foo(-1);
    return 0;
}

The macro attempts to create a compound literal consisting of an array with (x) 1 elements. If x is negative, (x) 1 will be negative or zero, and the compiler will complain about an improper size for the array. (This may require using compiler switches to disable a zero-length array extension.) If x is zero or positive, the compound literal will be discarded by the comma operator, and foo will be called with argument x. (When a macro name is used in its own replacement, it is not replaced again, so the function foo will be called.)

Note that overflow in (x) 1 is possible. You could add a check against INT_MAX to deal with that.

This requires that x be some compile-time expression, which is implied in your question about how to check at compile time.

With Clang or GCC, you can combine a standard _Static_assert with a non-standard statement expression:

#define foo(x)  ({ _Static_assert((x) >= 0, "Argument to foo must be nonnegative."); foo(x); })

If foo is always void, you can simply use a _Static_assert with the do … while idiom to give it statement form when a semicolon is appended:

#define foo(x)  do { _Static_assert((x) >= 0, "Argument to foo must be nonnegative."); foo(x); } while (0)

If x can be something other than an int, such as a floating-point type, you might want to work on the conditions a bit to deal with issues that arise in the tests and conversions.

CodePudding user response:

want to issue warning only if compiler is able to calculate the value (by optimizations, or if the value is constant). Otherwise just use function without warnin

In short, with GNU extensions:

void foo (int lowfd);

#if defined(__GNUC__) && defined(__OPTIMIZE__)
#define curb(expr, msg) \
     __extension__({ \
          if (__builtin_constant_p(expr)) { \
              if (!(expr)) { \
                    __attribute__((__noinline__, \
                    __warning__(msg))) void warnit() {__asm__("");}; warnit(); \
              } \
           } \
     })
#else
#define curb(expr, msg)  (void)0
#endif

#define foo(x)  (curb(x >= 0, "x is lower than 0"), foo(x))

int main()
{
    // expected warning
    foo(-1);
    return 0;
}

I have this https://gitlab.com/Kamcuk/kamillibc/-/blob/master/libs/curb/src/curb.h#L46 in my tree about the idea of issuing a warning or error if the expression is known at compile time, and if it isn't, failing at runtime or not. The && defined(__OPTIMIZE__) seems not to be needed in this case.

  •  Tags:  
  • c gcc
  • Related