4

Clang -Wunused-command-line-argument

 1 year ago
source link: https://maskray.me/blog/2023-08-25-clang-wunused-command-line-argument
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Clang -Wunused-command-line-argument

clangDriver is the library implementing the compiler driver for Clang. It utilitizes LLVMOption to process command line options. As options are processed when required, as opposed to use a large switch, Clang gets the ability to detect unused options straightforwardly.

When an option is checked with APIs such as hasArg and getLastArg, its "claimed" bit is set.

template<typename ...OptSpecifiers>
Arg *getLastArg(OptSpecifiers ...Ids) const {
Arg *Res = nullptr;
for (Arg *A : filtered(Ids...)) {
Res = A;
Res->claim();
}
return Res;
}

After all options are processed, Clang reports a -Wunused-command-line-argument diagnostic for each unclaimed option. There are multiple possible messages, but argument unused during compilation is the most common one.

% clang -c a.c -la
clang: warning: -la: 'linker' input unused [-Wunused-command-line-argument]
% clang -c -Werror a.c -la
clang: error: -la: 'linker' input unused [-Werror,-Wunused-command-line-argument]
% clang -c -Werror=unused-command-line-argument a.c -la
clang: error: -la: 'linker' input unused [-Werror,-Wunused-command-line-argument]

There are many heuristics to enhance the desirability of -Wunused-command-line-argument, which can be rather subjective. For instance, options that are relevant only during compilation do not result in -Wunused-command-line-argument diagnostics when linking is performed. This is necessary to support linking actions that utilitize CFLAGS or CXXFLAGS.

% clang -faddrsig -fpic -march=generic a.o

Assembly files

For assembly files that do not need preprocessing (e.g. .s (clang::driver::types::TY_PP_Asm)), the driver selects clang::driver::tools::ClangAs when using the integrated assembler. ClangAs::ConstructJob claims very few options and clangDriver will report many -Wunused-command-line-argument diagnostics.

% gcc -S -fpic -mfpmath=sse a.c
% gcc -c -fpic -mfpmath=sse a.s
% clang-16 -c -fpic -mfpmath=sse a.s
clang-16: warning: argument unused during compilation: '-mfpmath=sse' [-Wunused-command-line-argument]

For assembly files that need preprocessing (e.g. .S (clang::driver::types::TY_Asm)), clangDriver selects clang::driver::tools::Clang. Clang::ConstructJob is where most driver options are handled. Target-specific options are handled by Clang's member function RenderTargetOptions. We will get behaviors similar to compiling a .c file: compilation only options do not lead to diagnostics.

% clang-16 -c -fpic -mfpmath=sse a.S

Default options

There is a tension between -Wunused-command-line-argument and default options. Let's consider a scenario where we specify --rtlib=compiler-rt --unwindlib=libunwind in CFLAGS and CXXFLAGS to utilize compiler-rt and LLVM libunwind. ClangDriver claims --rtlib and --unwindlib in the following code snippet:

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) {
if (!Args.hasArg(options::OPT_nodefaultlibs)) {
// Handle --rtlib and --unwindlib.
}
if (!Args.hasArg(options::OPT_nostartfiles)) {
// Handle --rtlib. Append clang_rt.crtend.o or GCC style crtend{,S,T}.o
}
}

However, if a build target employs -nostdlib or -nodefaultlibs, options such as --rtlib, --unwindlib, and many other linker options (e.g. -static-libstdc++ and -pthread) will not be claimed, resulting in unused argument diagnostics:

% clang --rtlib=compiler-rt --unwindlib=libunwind -stdlib=libstdc++ -static-libstdc++ -pthread -nostdlib a.o
clang: warning: argument unused during compilation: '--rtlib=compiler-rt' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '--unwindlib=libunwind' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-static-libstdc++' [-Wunused-command-line-argument]
clang: warning: argument unused during compilation: '-pthread' [-Wunused-command-line-argument]

While some options like -stdlib= do not trigger a diagnostic, this seems more like a happenstance rather than a deliberate design choice.

To suppress the diagnostics, we can utilitize --start-no-unused-arguments and --end-no-unused-arguments (Clang 14) like the following:

% clang --start-no-unused-arguments --rtlib=compiler-rt --unwindlib=libunwind -stdlib=libstdc++ -static-libstdc++ -pthread --end-no-unused-arguments -nostdlib a.o

There is also a heavy hammer -Qunused-arguments to suppress -Wunused-command-line-argument diagnostics regardless of options' positions:

% clang -Qunused-arguments --rtlib=compiler-rt --unwindlib=libunwind -stdlib=libstdc++ -static-libstdc++ -pthread -nostdlib a.o

-Qunused-arguments is similar to -Wno-unused-command-line-argument.

Conveniently, options specified in a Clang configuration file are automatically claimed.

cat >a.cfg <<e
-stdlib=libstdc++
--rtlib=libgcc
--unwindlib=libgcc
e
clang --config=./a.cfg a.c # no diagnostic
mkdir bin lib
ln -s /usr/bin/clang bin/
cp a.cfg bin/clang.cfg
ln -s /usr/lib/clang lib/
bin/clang -no-canonical-prefixes a.c # no diagnostic

In the last command, I specify -no-canonical-prefixes so that clang will find dirname(clang)/clang.cfg, otherwise Clang would try to find dirname(realname(clang))/clang.cfg.

Target-specific options

GCC has machine-dependent options that usually begin with -m. These options are often referred to as "machine-specific" or sometimes as "target-specific". I am not certain whether there are any distinctions in these terms within the context of GCC. In Clang, we prefer the term "target-specific".

For instance, certain targets implement -mtls-dialect=. This is achieved through files like gcc/config/aarch64/aarch64.opt. If we use such options on unsupported targets, we will encounter an error:

% aarch64-linux-gnu-gcc -c -mtls-dialect=desc a.c
% powerpc64le-linux-gnu-gcc -c -mtls-dialect=desc a.c
powerpc64le-linux-gnu-gcc: error: unrecognized command-line option ‘-mtls-dialect=desc’

However, Clang employs a unified table named clang/include/clang/Driver/Options.td for all options, thereby eliminating the need for maintaining target-specific lists. Historically, an unsupported option merely issued a warning (unless -Werror is used):

% clang-16 -c --target=aarch64 -mavx a.c
clang-16: warning: argument unused during compilation: '-mavx' [-Wunused-command-line-argument]

For Clang 17, I have implemented the TargetSpecific flag in clang/include/clang/Driver/Options.td and annotated numerous options accordingly. If an option is annotated as TargetSpecific, the -Wunused-command-line-argument diagnostic will be elevated to an error

% clang -c --target=aarch64 -mavx a.c
clang: error: unsupported option '-mavx' for target 'aarch64'

For assembler input, marking target-specific options as TargetSpecific without claiming them will lead to errors:

% clang -mfpmath=sse -c a.s
clang: error: unsupported option '-mfpmath=' for target 'x86_64-unknown-linux-gnu'




About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK