llvmPackages{12-git}.clang: don't swallow unsupported option errors when compiling + linking

`https://github.com/llvm/llvm-project/issues/116278`

make clang report unsupported option errors / warning when compiling +
linking in the same command.

this works
```
$ clang --target=aarch64 -mpopcnt hello.c
clang: error: unsupported option '-mpopcnt' for target aarch64
```

before change clang swallows the error
```
$ clang --target=aarch64 -mpopcnt hello.c -lc
$ echo $?
0
```

after change error is reported:
```
$ clang --target=aarch64 -mpopcnt hello.c -lc
clang: error: unsupported option '-mpopcnt' for target aarch64
```

Changed files
+81
pkgs
development
compilers
+75
pkgs/development/compilers/llvm/common/clang/clang-unsupported-option.patch
···
+
From 7ef5ed98cc6666f64db2f155ded2077ce038e1e4 Mon Sep 17 00:00:00 2001
+
From: Reno Dakota <paparodeo@proton.me>
+
Date: Sat, 16 Nov 2024 05:57:40 +0000
+
Subject: [PATCH] [Clang][Driver] report unsupported option error regardless of
+
argument order
+
+
This change updates clang to report unsupported option errors regardless
+
of the command line argument order.
+
+
When clang with a source file and without `-c` it will both compile and
+
link. When an unsupported option is also part of the command line clang
+
should generated an error. However, if the source file name comes before
+
an object file, eg: `-lc`, the error is ignored.
+
+
```
+
$ clang --target=x86_64 -lc hello.c -mhtm
+
clang: error: unsupported option '-mhtm' for target 'x86_64'
+
$ echo $?
+
1
+
```
+
+
but if `-lc` comes after `hello.c` the error is dropped
+
+
```
+
$ clang --target=x86_64 hello.c -mhtm -lc
+
$ echo $?
+
0
+
```
+
+
after this change clang will report the error regardless of the command
+
line argument order.
+
---
+
clang/lib/Driver/Driver.cpp | 13 ++++++-------
+
clang/test/Driver/unsupported-option.c | 10 ++++++++++
+
2 files changed, 16 insertions(+), 7 deletions(-)
+
+
diff --git a/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
+
index 93e85f7dffe35a..8e784a7b130ac3 100644
+
--- a/lib/Driver/Driver.cpp
+
+++ b/lib/Driver/Driver.cpp
+
@@ -4064,17 +4064,18 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
+
YcArg = YuArg = nullptr;
+
}
+
+
- unsigned LastPLSize = 0;
+
+ bool LinkOnly = phases::Link == FinalPhase && Inputs.size() > 0;
+
for (auto &I : Inputs) {
+
types::ID InputType = I.first;
+
const Arg *InputArg = I.second;
+
+
auto PL = types::getCompilationPhases(InputType);
+
- LastPLSize = PL.size();
+
+
+
+ phases::ID InitialPhase = PL[0];
+
+ LinkOnly = LinkOnly && phases::Link == InitialPhase && PL.size() == 1;
+
+
// If the first step comes after the final phase we are doing as part of
+
// this compilation, warn the user about it.
+
- phases::ID InitialPhase = PL[0];
+
if (InitialPhase > FinalPhase) {
+
if (InputArg->isClaimed())
+
continue;
+
@@ -4129,10 +4130,8 @@ void Driver::handleArguments(Compilation &C, DerivedArgList &Args,
+
}
+
}
+
+
- // If we are linking, claim any options which are obviously only used for
+
- // compilation.
+
- // FIXME: Understand why the last Phase List length is used here.
+
- if (FinalPhase == phases::Link && LastPLSize == 1) {
+
+ // claim any options which are obviously only used for compilation.
+
+ if (LinkOnly) {
+
Args.ClaimAllArgs(options::OPT_CompileOnly_Group);
+
Args.ClaimAllArgs(options::OPT_cl_compile_Group);
+
}
+6
pkgs/development/compilers/llvm/common/default.nix
···
(metadata.getVersionFile "clang/purity.patch")
# https://reviews.llvm.org/D51899
(metadata.getVersionFile "clang/gnu-install-dirs.patch")
+
+
# https://github.com/llvm/llvm-project/pull/116476
+
# prevent clang ignoring warnings / errors for unsuppored
+
# options when building & linking a source file with trailing
+
# libraries. eg: `clang -munsupported hello.c -lc`
+
./clang/clang-unsupported-option.patch
]
++ lib.optional (lib.versions.major metadata.release_version == "13")
# Revert of https://reviews.llvm.org/D100879