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.
1 | template<typename ...OptSpecifiers> |
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.
1 | % clang -c -ftime-trace a.s |
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
.
1 | % clang -faddrsig -fpic -march=generic a.o |
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:
1 | if (!Args.hasArg(options::OPT_nostdlib, options::OPT_r)) { |
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:
1 | % clang --rtlib=compiler-rt --unwindlib=libunwind -stdlib=libstdc++ -static-libstdc++ -pthread -nostdlib a.o |
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:
1 | % 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:
1 | % clang -Qunused-arguments --rtlib=compiler-rt --unwindlib=libunwind -stdlib=libstdc++ -static-libstdc++ -pthread -nostdlib a.o |
Conveniently, options specified in a Clang configuration file are automatically claimed.
1 | cat >a.cfg <<e |
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
.