[clang] clang: Do not pass an empty -syslibroot for --sysroot= on Darwin (PR #229421)
Matt Arsenault via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 7 00:54:22 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/229421
>From 3c336adc7b09dfa40487ed35c5af77f138581016 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Tue, 6 Oct 2026 15:15:48 +0200
Subject: [PATCH] clang: Do not pass an empty -syslibroot for --sysroot= on
Darwin
-isysroot and DEFAULT_SYSROOT, but it checked only for the presence
of the option. An empty --sysroot= then produced -syslibroot "",
where previously it fell through to -isysroot. An empty --sysroot= is
the usual way to defeat DEFAULT_SYSROOT, so treat it as absent.
Use this to fix the darwin-static-lib tests when clang is built with
DEFAULT_SYSROOT or CLANG_USE_XCSELECT.
Co-authored-by: Claude Opus 5.5 <noreply at anthropic.com>
---
clang/lib/Driver/ToolChains/Darwin.cpp | 3 ++-
.../test/Driver/darwin-static-lib-universal.c | 2 +-
clang/test/Driver/darwin-static-lib.c | 22 +++++++++----------
clang/test/Driver/sysroot.c | 12 ++++++++++
4 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 0fb94d8712e69f..7eaf2491a02f11 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -213,7 +213,8 @@ static void AddMachOSysLibRoot(Compilation &C, const ArgList &Args,
// --isysroot as the syslibroot.
// We check `OPT__sysroot_EQ` directly instead of `getSysRoot` to make sure we
// prioritise command line arguments over configuration of `DEFAULT_SYSROOT`.
- if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ)) {
+ if (const Arg *A = Args.getLastArg(options::OPT__sysroot_EQ);
+ A && !StringRef(A->getValue()).empty()) {
CmdArgs.push_back("-syslibroot");
CmdArgs.push_back(A->getValue());
} else if (const Arg *A = Args.getLastArg(options::OPT_isysroot)) {
diff --git a/clang/test/Driver/darwin-static-lib-universal.c b/clang/test/Driver/darwin-static-lib-universal.c
index bee9ce28e2fd85..89b4f7cec1b16b 100644
--- a/clang/test/Driver/darwin-static-lib-universal.c
+++ b/clang/test/Driver/darwin-static-lib-universal.c
@@ -5,7 +5,7 @@
// Multiple -arch produces one libtool job per arch plus a lipo. -Xarch_ is only
// forwarded to the matching architecture libtool. --static-lib-target-arch-only
// should pick up the effective triple for each -arch.
-// RUN: %clang -### --emit-static-lib %t1.o %t2.o \
+// RUN: %clang --sysroot= -### --emit-static-lib %t1.o %t2.o \
// RUN: -arch x86_64 -arch arm64 --static-lib-target-arch-only \
// RUN: -Xarch_arm64 --no-static-lib-deterministic \
// RUN: -Xarch_x86_64 --static-lib-warn-no-symbols -o libfoo.a 2>&1 \
diff --git a/clang/test/Driver/darwin-static-lib.c b/clang/test/Driver/darwin-static-lib.c
index 4e16e07851b12c..b24d95d8bc942f 100644
--- a/clang/test/Driver/darwin-static-lib.c
+++ b/clang/test/Driver/darwin-static-lib.c
@@ -1,26 +1,26 @@
// -D and -no_warning_for_no_symbols are on by default.
-// RUN: %clang -target i386-apple-darwin9 %s -### --emit-static-lib 2>&1 | FileCheck %s
+// RUN: %clang -target i386-apple-darwin9 %s --sysroot= -### --emit-static-lib 2>&1 | FileCheck %s
// CHECK: "{{.*}}libtool" "-static" "-D" "-no_warning_for_no_symbols" "-o" "a.out" "{{.*o}}"
-// RUN: %clang -target i386-apple-darwin9 %s -### --emit-static-lib -o libfoo.a 2>&1 | FileCheck %s --check-prefix=OUTPUT
+// RUN: %clang -target i386-apple-darwin9 %s --sysroot= -### --emit-static-lib -o libfoo.a 2>&1 | FileCheck %s --check-prefix=OUTPUT
// OUTPUT: "{{.*}}libtool" "-static" "-D" "-no_warning_for_no_symbols" "-o" "libfoo.a" "{{.*o}}"
// RUN: touch %t1.o %t2.o
// Adding the explicit flags for -D and -no_warning_for_no_symbols doesn't
// double up the arguments passed to libtool.
-// RUN: %clang -target i386-apple-darwin9 -### --emit-static-lib %t1.o %t2.o \
+// RUN: %clang -target i386-apple-darwin9 --sysroot= -### --emit-static-lib %t1.o %t2.o \
// RUN: --static-lib-deterministic --no-static-lib-warn-no-symbols 2>&1 \
// RUN: | FileCheck %s --check-prefix=DEFAULT
// DEFAULT: "{{.*}}libtool" "-static" "-D" "-no_warning_for_no_symbols" "-o" "a.out" "{{.*}}1.o" "{{.*}}2.o"
// Last one wins with contradictory arguments.
-// RUN: %clang -target i386-apple-darwin9 -### --emit-static-lib %t1.o %t2.o \
+// RUN: %clang -target i386-apple-darwin9 --sysroot= -### --emit-static-lib %t1.o %t2.o \
// RUN: --no-static-lib-deterministic --static-lib-deterministic 2>&1 \
// RUN: | FileCheck %s --check-prefix=DEFAULT
// -D and -no_warning_for_no_symbols can be turned off.
-// RUN: %clang -target i386-apple-darwin9 -### --emit-static-lib %t1.o %t2.o \
+// RUN: %clang -target i386-apple-darwin9 --sysroot= -### --emit-static-lib %t1.o %t2.o \
// RUN: --no-static-lib-deterministic --static-lib-warn-no-symbols 2>&1 \
// RUN: | FileCheck %s --check-prefix=NEITHER
// NEITHER: "-static"
@@ -32,18 +32,18 @@
// arch name is used, not the clang one. i.e. the clang driver turns
// armv7k-apple-watchos8.0 into thumbv7k-apple-watchos8.0.0, but -arch_only uses
// the MachO name armv7k. -force_cpusubtype_ALL isn't used by libtool.
-// RUN: %clang -target armv7k-apple-watchos8.0 -### --emit-static-lib %t1.o %t2.o \
+// RUN: %clang -target armv7k-apple-watchos8.0 --sysroot= -### --emit-static-lib %t1.o %t2.o \
// RUN: --static-lib-target-arch-only 2>&1 | FileCheck %s --check-prefix=ARMV7K
// ARMV7K: "-static" "-arch_only" "armv7k" "-D"
// ARMV7K-NOT: "-force_cpusubtype_ALL"
// Firmware uses the full triple.
-// RUN: %clang -target armv7em-apple-firmware1.0 -### --emit-static-lib %t1.o %t2.o \
+// RUN: %clang -target armv7em-apple-firmware1.0 --sysroot= -### --emit-static-lib %t1.o %t2.o \
// RUN: --static-lib-target-arch-only 2>&1 | FileCheck %s --check-prefix=FIRMWARE
// FIRMWARE: "-arch_only" "thumbv7em-apple-firmware1.0.0"
// -arch_only on the clang command line is ignored and not passed on.
-// RUN: %clang -target armv7k-apple-watchos8.0 -### --emit-static-lib %t1.o %t2.o \
+// RUN: %clang -target armv7k-apple-watchos8.0 --sysroot= -### --emit-static-lib %t1.o %t2.o \
// RUN: --static-lib-target-arch-only -arch_only arm32_64 2>&1 | \
// RUN: FileCheck %s --check-prefix=ARCH-ONLY
// ARCH-ONLY: warning: argument unused during compilation: '-arch_only arm32_64'
@@ -63,7 +63,7 @@
// -L and -F are forwarded in joined format. -iframework is forwarded as -F.
// -Xstatic-lib-tool passes through.
-// RUN: %clang -target i386-apple-darwin9 -### --emit-static-lib %t1.o %t2.o \
+// RUN: %clang -target i386-apple-darwin9 --sysroot= -### --emit-static-lib %t1.o %t2.o \
// RUN: -L/tmp/first -L /tmp/second -F/tmp/fw1 -iframework /tmp/ifw -F /tmp/fw2 \
// RUN: -Xstatic-lib-tool -dependency_info -Xstatic-lib-tool deps.dat 2>&1 \
// RUN: | FileCheck %s --check-prefix=PASSTHROUGH
@@ -73,14 +73,14 @@
// PASSTHROUGH-DAG: "{{.*}}1.o" "{{.*}}2.o"
// -filelist, -l, -framework are forwarded (-l in joined format).
-// RUN: %clang -target i386-apple-darwin9 -### --emit-static-lib %t1.o \
+// RUN: %clang -target i386-apple-darwin9 --sysroot= -### --emit-static-lib %t1.o \
// RUN: -l foo -filelist first.txt -framework Foo %t2.o \
// RUN: -filelist second.txt -lBar 2>&1 \
// RUN: | FileCheck %s --check-prefix=LINKER_INPUTS
// LINKER_INPUTS: "-o" "a.out" "{{.*}}1.o" "-lfoo" "-filelist" "first.txt" "-framework" "Foo" "{{.*}}2.o" "-filelist" "second.txt" "-lBar"
// Unsupported linker inputs warn instead of being silently dropped.
-// RUN: %clang -target i386-apple-darwin9 -### --emit-static-lib %t1.o \
+// RUN: %clang -target i386-apple-darwin9 --sysroot= -### --emit-static-lib %t1.o \
// RUN: -weak_framework Bar -Xlinker -all_load \
// RUN: -rpath /tmp -e _main 2>&1 | FileCheck %s --check-prefix=UNSUPPORTED_INPUTS
// UNSUPPORTED_INPUTS-DAG: warning: argument unused during compilation: '-weak_framework Bar'
diff --git a/clang/test/Driver/sysroot.c b/clang/test/Driver/sysroot.c
index 3080f76e031686..13e497093a51f0 100644
--- a/clang/test/Driver/sysroot.c
+++ b/clang/test/Driver/sysroot.c
@@ -16,3 +16,15 @@
// RUN: -isysroot /FOO --sysroot=/BAR -### %t3.o 2> %t3
// RUN: FileCheck --check-prefix=CHECK-APPLE-SYSROOT < %t3 %s
// CHECK-APPLE-SYSROOT: "-arch" "i386"{{.*}} "-syslibroot" "{{[^"]*}}/BAR"
+
+// An empty --sysroot= does not override -isysroot.
+// RUN: %clang -target i386-apple-darwin10 \
+// RUN: -isysroot /FOO --sysroot= -### %t3.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-APPLE-ISYSROOT %s
+
+// An empty --sysroot= alone produces no -syslibroot.
+// RUN: %clang -target i386-apple-darwin10 \
+// RUN: --sysroot= -### %t3.o 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-APPLE-EMPTY-SYSROOT %s
+// CHECK-APPLE-EMPTY-SYSROOT: "-arch" "i386"
+// CHECK-APPLE-EMPTY-SYSROOT-NOT: "-syslibroot"
More information about the cfe-commits
mailing list