20

Before clang 16.0 I was able to compile all my projects using -Weveything without problems, fixing my code and paying attention to the (useful) warnings that this option gave. However, it seems that the -Wunsafe-buffer-usage was added in version 16 (my system updated to it recently) and then compiling any project is impossible without getting a huge list of useless warnings about any pointer being used, see minimal example below:

$ cat main.c
#include <stdio.h>

int main(int argc, char **argv) {
    if (argc != 2) {
        return 0;
    }
    printf("argv[1] = %s\n", argv[1]);
}

$ clang -Weverything main.c
main.c:3:27: warning: 'argv' is an unsafe pointer used for buffer access [-Wunsafe-buffer-usage]
int main(int argc, char **argv) {
                   ~~~~~~~^~~~
main.c:7:30: note: used in buffer access here
    printf("argv[1] = %s\n", argv[1]);
                             ^~~~
1 warning generated.

One can't possibly reason about his code using this warning.

The clang documentation has the following to say:

Since -Weverything enables every diagnostic, we generally don’t recommend using it. -Wall -Wextra are a better choice for most projects. Using -Weverything means that updating your compiler is more difficult because you’re exposed to experimental diagnostics which might be of lower quality than the default ones. If you do use -Weverything then we advise that you address all new compiler diagnostics as they get added to Clang, either by fixing everything they find or explicitly disabling that diagnostic with its corresponding Wno- option.

In this case, how would I "fix everything they find"?

Setting -Wno-unsafe-buffer-usage works, but it is an ugly solution. It adds clutter to a Makefile and feels like cheating.

22
  • 7
    I'd offer that fighting with -Weverything may not be a battle you want to start. You may be able to make -Weverything happy in this case, but there will be many more warnings you'll need to satisfy, many of which may require making your code worse to "fix". For example, satisfying -Wdeclaration-after-statement would require declaring all local variables at the top of functions instead of as needed. Commented Aug 31, 2023 at 16:27
  • 4
    Where I use -Weverything, I also counter some options with -Wno-xyz variants. One script I use has: -Weverything -Wno-padded -Wno-vla -Wno-reserved-id-macro -Wno-documentation-unknown-command -Wno-poison-system-directories -Wno-format-nonliteral. I build format strings in a number of the programs, hence -Wno-format-nonliteral. I use VLAs in matrix manipulation code (and carefully in other places too), so I need -Wno-vla. I use feature test macros (for POSIX, and also systems like Solaris) to determine how to compile code, so -Wno-reserved-id-macro was necessary. […continued…] Commented Aug 31, 2023 at 16:43
  • 2
    @lucas.mior — undoubtedly: the options I disable warnings about are specific to my needs, based on what I found (back in October 2022 for the latest update to that script), but the principle applies — disable the warnings you regard as unhelpful. I have reasons for rejecting the warnings from each option I disable. You have different code, different problems, different reasons for rejecting (or accepting) the output. But to be practically useful, you'll have to tune the warnings generated by -Weverything. My Mac has Apple's Clang 14.0; the -Wunsafe-buffer-usage option isn't valid. Commented Sep 1, 2023 at 4:19
  • 4
    If -Wno-unsafe-buffer-usage feels like cheating, doesn't -Weverything feel like an unreasonable handicap? -Wall -Wextra is expected to be a useful set of warnings, as your quoted extract states. Commented Sep 1, 2023 at 6:15
  • 3
    @lucas.mior In practice, any codebase will trigger thousands of warnings ... Bull. Every program I'm in charge of is usually completely warning-clean. Right now, the hundred-thousand-or-so-lines of C code I'm in charge of emits all of 7 warnings - only because the code is still internally using a function from the public API that was just marked deprecated in the last release a few weeks ago. That level of correctness needs a disciplined adherence to high standards. A code base that "trigger[s] thousands of warnings" was written to no or very low standards by undisciplined developers. Commented Sep 1, 2023 at 16:43

3 Answers 3

15

I made several attempts at addressing this particular warning with version 16.0.0 at godbolt, i.e. checking argv != NULL && argv[1] != NULL before the call to printf, but was unsuccessful. In fact, even this particular check triggered the warning.

Given that the documentation explicitly recommends not using -Weverything and if you do to use the corresponding -Wno- option for warnings that are not useful, and that it's not clear exactly how this warning could be addressed (I'm unable to find documentation on this option), adding -Wno-unsafe-buffer-usage is probably the best option.

And based on a link in the comments from the LLVM discussion boards at https://discourse.llvm.org/t/rfc-c-buffer-hardening/65734/85:

this warning currently fires at the one place where (afaict) there is no getting around it. int main(int argc, char const** argv)

It seems it's not possible to silence the warning in this case. So using -Wno-unsafe-buffer-usage looks to be your only option.

Sign up to request clarification or add additional context in comments.

15 Comments

Yes, but the documentation says "either by fixing everything they find or explicitly disabling ..." What is the point of a warning whose code it warns against can't be fixed even in such central aspect of a program?
@lucas.mior I think you may not have an option but to ignore in this case. It also seems you're not the only person to have trouble with this option.
@lucas.mior Re: "What is the point of a warning whose code it warns against can't be fixed even in such central aspect of a program" I think that's part of "experimental diagnostics" .
@lucas.mior: Re “What is the point of a warning whose code it warns against can't be fixed even in such central aspect of a program?”: As the documentation states, the additional warnings in -Weverything are experimental. The purpose of the experiment is to get feedback: The Clang maintainers test warning options to see how useful they are and what problems there might be with them. People using -Weverything should report problems to the Clang maintainers, including sample code that demonstrates the problems, so the Clang maintainers can consider improvements. That is the point.
@yvs2014: So? The fact that it is reported for the argv of main is information that can be fed back to the Clang developers. Additionally, the first item at your link gives another reason for -Weverything: Use it manually once to all the diagnostics it reports, evaluate each of them yourself, fix the ones that are actual problems, but leave it off in your regular builds.
|
8

This warning seems to be essentially undocumented (which perhaps is a sign that it's better disabled). The available information suggests that you haven't missed anything; it's simply not possible to compile a complete C program without triggering it. If you wish to use -Weverything with -Werror when compiling an entire C program (including main), it seems to be mandatory to disable this warning.

Thanks to @yvs2014 for this link from the comments: https://discourse.llvm.org/t/rfc-c-buffer-hardening/65734/85

It's suggested in that discussion thread that (1) this warning is really meant for use with C++ code, which should normally not be handling raw pointers, and not for use with C code; (2) it might theoretically be used for C code which uses some library or API that abstracts away the usage of raw pointers; (but it cannot possibly be used when compiling the implementation of that library); (3) it can never be used when compiling main.

I question the wisdom of this design choice, but it is what it is (and they do pretty explicitly warn against using -Weverything.)

1 Comment

Yes, once again c++ gets in the way of C. In the link you provide, it is suggested that one writing C code should wrap the pointer arithmetic stuff in safe APIs and then use compiler directives to disable the warning in these implementations. Indeed, there is no way to do it without writing in a different language.
0

-Wunsafe-buffer-usage is intended to be used in C++ projects using modern collections and hardened libc++. In these conditions, it's feasible for you to entirely avoid arithmetic on raw pointers. This way, you can ensure that all pointer accesses are bounds-checked.

You should disable -Wunsafe-buffer-usage if you do not meet these conditions (including if your project doesn't use C++ at all).

In general, -Weverything is not meant to be used "permanently". Building successfully with -Weverything should not be a goal of any code base, and it does not prove that you have the highest code quality. -Wunsafe-buffer-usage is not the only un-fixable diagnostic that you can run into; there are also a number of contradictory diagnostics, where fixing one raises another, and fixing the other raises the first one again. You can use -Weverything to find diagnostics that seem relevant to your code and that you think provide value.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.