Clang defaults override user-specified warning flags

Clang apparently adds some default flags to every run, and sometimes these take precedence over user-specified flags.

For example, I compiled the following program with clang -Wgnu main.c:

/* main.c */
int main(int argc, char *argv[]) {
    const int foo = 42;
    switch (argc) { case foo: return 5; }
    return 0;
}

Using foo in the switch case is illegal because it isn't a constant expression, but gcc has a feature so that it is. The -Wgnu flag enables warnings when any of these GNU features are used, including the one being used here: constant folding (-Wgnu-folding-constant).

I expected to see the warning, "expression is not an integer constant expression; folding it to a constant is a GNU extension". However, I don't see any warning at all, despite passing the -Wgnu flag. Even with the -Weverything flag, the warning still does not show.

Only when explicitly specifying the -Wgnu-folding-constant flag does the warning show, which sort of defeats the purpose of having -Wgnu at all.

Running clang with the verbose flag (-v) sheds more light on the issue (large portions of uninteresting output elided):

$ clang -v -Wgnu main.c
Apple clang version 13.1.6 (clang-1316.0.21.2.3)
Target: arm64-apple-darwin21.4.0
...
 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple arm64-apple-macosx12.0.0 -Wundef-prefix=TARGET_OS_ -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -emit-obj -mrelax-all ... -v ... -Wgnu -Wno-reorder-init-list -Wno-implicit-int-float-conversion -Wno-c99-designator -Wno-final-dtor-non-final-class -Wno-extra-semi-stmt -Wno-misleading-indentation -Wno-quoted-include-in-framework-header -Wno-implicit-fallthrough -Wno-enum-enum-conversion -Wno-enum-float-conversion -Wno-elaborated-enum-base -Wno-reserved-identifier -Wno-gnu-folding-constant ... -x c main.c
...

The output above shows the final command being passed to the frontend. You can find the -v and -Wgnu injected amidst a bunch of ceremony, and you'll also notice that eventually following the -Wgnu is a -Wno-gnu-folding-constant, the culprit for why this particular warning is hidden.

If you specify -Wgnu-folding-constant, the disable mysteriously disappears from the end of the command.

I'd like to know where these default flags are coming from, and how to disable them if possible.

This question is tied to Clang itself, rather than Apple’s use of it. If no one else chimes in here, I recommend that you ask this via Clang’s support channel.

https://clang.llvm.org/get_involved.html

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks, that was my next stop. However, at the very least, I think this is specific to Apple's build of Clang, rather than something with Clang in general.

If you add -v to various builds of Clang using a tool like Godbolt, those -Wno flags aren't present.

So I dug into this a little bit more.

I downloaded Apple's branch of LLVM, opened the best release branch for the version of Clang in question (swift-5.6-RELEASE, more on this later), and scoured the source code for any leads on the bad behavior; I didn't find anything, everything looked ok. To confirm, I built Clang at this revision, ran it, and indeed found no problems. Here is the relevant output:

# git show
commit 900c3b6b832d1d0e7d6e1220f6ba001802cbe0cc (HEAD, tag: swift-5.6-RELEASE)
# ./build/bin/clang -v -Wgnu -L/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib /tmp/main.c
clang version 13.0.0 (https://github.com/apple/llvm-project.git 900c3b6b832d1d0e7d6e1220f6ba001802cbe0cc)
Target: arm64-apple-darwin21.4.0
 ".../llvm-project/build/bin/clang-13" -cc1 -triple arm64-apple-macosx12.0.0 -Wundef-prefix=TARGET_OS_ -Werror=undef-prefix -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all ... -v ... -Wgnu -fdebug-compilation-dir=... -ferror-limit 19 ... -x c /tmp/main.c
...

So from the publicly available source code, everything is correct. The problem isn't with LLVM in general, or Apple's public modifications to LLVM.

I say this is the "best release branch" because it appears that Apple has a private codebase for building the actual version of Clang they ship with Xcode. I'm guessing this private codebase introduces the bug.

Furthermore, I discovered that the latest version of Clang shipping with Xcode, Apple clang version 14.0.3 (clang-1403.0.22.14.1), has the same buggy behavior of injecting those -Wno flags. That means every project using Xcode is currently having these warning flags manipulated against the user's intentions, and this has been happening for a while now.

Older versions of Xcode don't have this behavior (that's how I discovered this bug in the first place). Xcode 10.1 (10B61) ships with Apple LLVM version 10.0.0 (clang-1000.11.45.5), and this version works correctly. I haven't bisected the releases to find precisely when the bug was introduced.

Regardless, unless Apple also added a flag that disables this behavior, it doesn't look like this is something I can fix.

Clang defaults override user-specified warning flags
 
 
Q