如何向 GCC 添加警告功能?

How can I add warning feature to the GCC?

用法示例:

void closefrom (int lowfd);

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

具体来说:我应该为函数调用实施诊断(编译器警告)。位于 glibc 中的函数: void closefrom (int lowfd);

如果 lowfd 为负编译器应该发出警告。

这里有一些关于 closefrom 的信息:

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

也许函数的 属性 会以某种方式帮助解决这个问题?

你可以这样做,但不要这样做:

void foo(int x) {}

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

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

该宏试图创建一个由具有 (x)+1 个元素的数组组成的复合文字。如果 x 为负数,(x)+1 将为负数或零,编译器将抱怨数组大小不正确。 (这可能需要使用编译器开关来禁用 zero-length 数组扩展。)如果 x 为零或正数,复合文字将被逗号运算符丢弃,并调用 foo带有参数 x。 (当一个宏名被用在它自己的替换中时,它不会被再次替换,所以函数foo会被调用。)

请注意 (x)+1 中的溢出是可能的。您可以添加针对 INT_MAX 的检查来处理该问题。

这要求 x 是一些 compile-time 表达式,这在您有关如何在编译时检查的问题中暗示。

使用 Clang 或 GCC,您可以将标准 _Static_assert 与 non-standard 语句表达式结合起来:

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

如果 foo 始终是 void,您可以简单地使用带有 do … while 习语的 _Static_assert 在附加分号时为其提供语句形式:

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

如果 x 可以是 int 以外的其他类型,例如 floating-point 类型,您可能需要稍微处理一下条件以处理出现的问题测试和转换。

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

简而言之,使用 GNU 扩展:

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;
}

我的树中有这个 https://gitlab.com/Kamcuk/kamillibc/-/blob/master/libs/curb/src/curb.h#L46 关于如果表达式在编译时已知则发出警告或错误的想法,如果不是,则在运行时失败与否。在这种情况下似乎不需要 && defined(__OPTIMIZE__)