[clang] [clang][Driver] Fix libc++ include path on FreeBSD (PR #212725)

Rainer Orth via cfe-commits cfe-commits at lists.llvm.org
Sun Aug 2 05:25:13 PDT 2026


https://github.com/rorth updated https://github.com/llvm/llvm-project/pull/212725

>From 6c1e69756696c56672c678a111fdb5b0f4bd2005 Mon Sep 17 00:00:00 2001
From: Rainer Orth <ro at gcc.gnu.org>
Date: Wed, 29 Jul 2026 11:27:31 +0200
Subject: [PATCH 1/3] [clang][Driver] Fix libc++ include path on FreeBSD

`clang++` defaults to `-stdlib=libc++` on FreeBSD.  When building with both
`clang` and `libcxx` included, the freshly built `clang++` uses the system
version of the `libc++` headers.  However, this is from the bundled
`libc++` 19.1.7, thus inconsistent with the `libc++` being built.

Similarly to the NetBSD case, FreeBSD has its own version of
addLibCxxIncludePaths which just includes `/usr/include/c++/v1`.

Rather than replicating the generic version in `Gnu.cpp`, this patch just
calls `Generic_GCC::addLibCxxIncludePaths`.

Tested on `amd64-pc-freebsd15.1`.

This breaks the `Driver/freebsd.cpp` and `Driver/freebsd-include-paths.c`
testcases.  Once it can be confirmed the approach is sound, I'll  update
them accordingly.
---
 clang/lib/Driver/ToolChains/FreeBSD.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 724ccbefd790f..519999a9a5bcf 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -10,6 +10,7 @@
 #include "Arch/ARM.h"
 #include "Arch/Mips.h"
 #include "Arch/Sparc.h"
+#include "Gnu.h"
 #include "clang/Config/config.h"
 #include "clang/Driver/CommonArgs.h"
 #include "clang/Driver/Compilation.h"
@@ -434,8 +435,7 @@ void FreeBSD::AddClangSystemIncludeArgs(
 
 void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                     llvm::opt::ArgStringList &CC1Args) const {
-  addSystemInclude(DriverArgs, CC1Args,
-                   concat(getDriver().SysRoot, "/usr/include/c++/v1"));
+  Generic_GCC::addLibCxxIncludePaths(DriverArgs, CC1Args);
 }
 
 void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,

>From 3cc4ebdf09c0595114044949fef1c37b206b5cb2 Mon Sep 17 00:00:00 2001
From: Rainer Orth <ro at gcc.gnu.org>
Date: Thu, 30 Jul 2026 17:00:50 +0200
Subject: [PATCH 2/3] Remove FreeBSD::addLibCxxIncludePaths. Add testcases.

---
 clang/lib/Driver/ToolChains/FreeBSD.cpp   | 6 ------
 clang/lib/Driver/ToolChains/FreeBSD.h     | 2 --
 clang/test/Driver/freebsd-include-paths.c | 3 ++-
 clang/test/Driver/freebsd.cpp             | 6 ++++--
 4 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index 519999a9a5bcf..dcf2973c364d1 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -10,7 +10,6 @@
 #include "Arch/ARM.h"
 #include "Arch/Mips.h"
 #include "Arch/Sparc.h"
-#include "Gnu.h"
 #include "clang/Config/config.h"
 #include "clang/Driver/CommonArgs.h"
 #include "clang/Driver/Compilation.h"
@@ -433,11 +432,6 @@ void FreeBSD::AddClangSystemIncludeArgs(
                           concat(D.SysRoot, "/usr/include"));
 }
 
-void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
-                                    llvm::opt::ArgStringList &CC1Args) const {
-  Generic_GCC::addLibCxxIncludePaths(DriverArgs, CC1Args);
-}
-
 void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
                                   ArgStringList &CmdArgs) const {
   Generic_ELF::AddCXXStdlibLibArgs(Args, CmdArgs);
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h
index 55400e17b5ea4..a8f4226a88274 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -69,8 +69,6 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
     return ToolChain::CST_Libcxx;
   }
 
-  void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
-                             llvm::opt::ArgStringList &CC1Args) const override;
   void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
                            llvm::opt::ArgStringList &CmdArgs) const override;
   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
diff --git a/clang/test/Driver/freebsd-include-paths.c b/clang/test/Driver/freebsd-include-paths.c
index 872b2386ce9f1..be8104c9ce7ce 100644
--- a/clang/test/Driver/freebsd-include-paths.c
+++ b/clang/test/Driver/freebsd-include-paths.c
@@ -11,6 +11,7 @@
 // RUN: %clang -### -xc++ %s --target=x86_64-unknown-freebsd13.1 2>&1 \
 // RUN:   | FileCheck %s --check-prefix=DRIVER-PASS-INCLUDES-CXX
 // DRIVER-PASS-INCLUDES-CXX:      "-cc1" {{.*}}"-resource-dir" "[[RESOURCE:[^"]+]]"
-// DRIVER-PASS-INCLUDES-CXX-SAME: "-internal-isystem" "/usr/include/c++/v1"
+// DRIVER-PASS-INCLUDES-CXX-SAME: "-internal-isystem" "{{.*}}bin/../include/c++/v1"
+// DRIVER-PASS-INCLUDES-CXX-NOT:  "-internal-isystem" "/usr/include/c++/v1"
 // DRIVER-PASS-INCLUDES-CXX-SAME: {{^}} "-internal-isystem" "[[RESOURCE]]/include"
 // DRIVER-PASS-INCLUDES-CXX-SAME: {{^}} "-internal-externc-isystem" "/usr/include"
diff --git a/clang/test/Driver/freebsd.cpp b/clang/test/Driver/freebsd.cpp
index e2f76cd013f7f..6b60be0594e9a 100644
--- a/clang/test/Driver/freebsd.cpp
+++ b/clang/test/Driver/freebsd.cpp
@@ -27,7 +27,8 @@
 // RUN:   | FileCheck --check-prefix=CHECK-LIBCXX-SYSROOT %s
 // CHECK-LIBCXX-SYSROOT: "-cc1"
 // CHECK-LIBCXX-SYSROOT-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
-// CHECK-LIBCXX-SYSROOT-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
+// CHECK-LIBCXX-SYSROOT-SAME: "-internal-isystem" "{{.*}}/bin/../include/c++/v1"
+// CHECK-LIBCXX-SYSROOT-NOT:  "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
 
 // Test include paths when the sysroot path ends with `/`.
 // RUN: %clangxx %s -### -fsyntax-only 2>&1 \
@@ -37,4 +38,5 @@
 // RUN:   | FileCheck --check-prefix=CHECK-LIBCXX-SYSROOT-SLASH %s
 // CHECK-LIBCXX-SYSROOT-SLASH: "-cc1"
 // CHECK-LIBCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]"
-// CHECK-LIBCXX-SYSROOT-SLASH-SAME: "-internal-isystem" "[[SYSROOT]]usr/include/c++/v1"
+// CHECK-LIBCXX-SYSROOT-SLASH-SAME: "-internal-isystem" "{{.*}}/bin/../include/c++/v1"
+// CHECK-LIBCXX-SYSROOT-SLASH-NOT:  "-internal-isystem" "[[SYSROOT]]usr/include/c++/v1"

>From 05af7f0de9376917c191e69d6bf49763d4138359 Mon Sep 17 00:00:00 2001
From: Rainer Orth <ro at gcc.gnu.org>
Date: Sun, 2 Aug 2026 13:18:06 +0200
Subject: [PATCH 3/3] Add install_tree_without_libcxx for reproducability. New
 DRIVER-INSTALL-INCLUDES test.

---
 clang/lib/Driver/ToolChains/FreeBSD.cpp          |  6 ++++++
 clang/lib/Driver/ToolChains/FreeBSD.h            |  2 ++
 .../Inputs/install_tree_without_libcxx/bin/.keep |  0
 .../install_tree_without_libcxx/include/.keep    |  0
 .../Inputs/install_tree_without_libcxx/lib/.keep |  0
 clang/test/Driver/freebsd-include-paths.c        |  7 ++++---
 clang/test/Driver/freebsd.cpp                    | 16 ++++++++++++----
 7 files changed, 24 insertions(+), 7 deletions(-)
 create mode 100644 clang/test/Driver/Inputs/install_tree_without_libcxx/bin/.keep
 create mode 100644 clang/test/Driver/Inputs/install_tree_without_libcxx/include/.keep
 create mode 100644 clang/test/Driver/Inputs/install_tree_without_libcxx/lib/.keep

diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index dcf2973c364d1..724ccbefd790f 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -432,6 +432,12 @@ void FreeBSD::AddClangSystemIncludeArgs(
                           concat(D.SysRoot, "/usr/include"));
 }
 
+void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+                                    llvm::opt::ArgStringList &CC1Args) const {
+  addSystemInclude(DriverArgs, CC1Args,
+                   concat(getDriver().SysRoot, "/usr/include/c++/v1"));
+}
+
 void FreeBSD::AddCXXStdlibLibArgs(const ArgList &Args,
                                   ArgStringList &CmdArgs) const {
   Generic_ELF::AddCXXStdlibLibArgs(Args, CmdArgs);
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h
index a8f4226a88274..55400e17b5ea4 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.h
+++ b/clang/lib/Driver/ToolChains/FreeBSD.h
@@ -69,6 +69,8 @@ class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF {
     return ToolChain::CST_Libcxx;
   }
 
+  void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
+                             llvm::opt::ArgStringList &CC1Args) const override;
   void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
                            llvm::opt::ArgStringList &CmdArgs) const override;
   void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs,
diff --git a/clang/test/Driver/Inputs/install_tree_without_libcxx/bin/.keep b/clang/test/Driver/Inputs/install_tree_without_libcxx/bin/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/install_tree_without_libcxx/include/.keep b/clang/test/Driver/Inputs/install_tree_without_libcxx/include/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/install_tree_without_libcxx/lib/.keep b/clang/test/Driver/Inputs/install_tree_without_libcxx/lib/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/freebsd-include-paths.c b/clang/test/Driver/freebsd-include-paths.c
index be8104c9ce7ce..96c97d9ea276c 100644
--- a/clang/test/Driver/freebsd-include-paths.c
+++ b/clang/test/Driver/freebsd-include-paths.c
@@ -9,9 +9,10 @@
 
 // Check that the driver passes include paths to cc1 on FreeBSD in C++ mode.
 // RUN: %clang -### -xc++ %s --target=x86_64-unknown-freebsd13.1 2>&1 \
+// RUN:     -ccc-install-dir %S/Inputs/install_tree_without_libcxx/bin \
+// RUN:     --sysroot=%S/Inputs/basic_freebsd_libcxx_tree \
 // RUN:   | FileCheck %s --check-prefix=DRIVER-PASS-INCLUDES-CXX
 // DRIVER-PASS-INCLUDES-CXX:      "-cc1" {{.*}}"-resource-dir" "[[RESOURCE:[^"]+]]"
-// DRIVER-PASS-INCLUDES-CXX-SAME: "-internal-isystem" "{{.*}}bin/../include/c++/v1"
-// DRIVER-PASS-INCLUDES-CXX-NOT:  "-internal-isystem" "/usr/include/c++/v1"
+// DRIVER-PASS-INCLUDES-CXX-SAME: "-internal-isystem" "{{.*}}/usr/include/c++/v1"
 // DRIVER-PASS-INCLUDES-CXX-SAME: {{^}} "-internal-isystem" "[[RESOURCE]]/include"
-// DRIVER-PASS-INCLUDES-CXX-SAME: {{^}} "-internal-externc-isystem" "/usr/include"
+// DRIVER-PASS-INCLUDES-CXX-SAME: {{^}} "-internal-externc-isystem" "{{.*}}/usr/include"
diff --git a/clang/test/Driver/freebsd.cpp b/clang/test/Driver/freebsd.cpp
index 6b60be0594e9a..0fe7bbd9c219c 100644
--- a/clang/test/Driver/freebsd.cpp
+++ b/clang/test/Driver/freebsd.cpp
@@ -19,24 +19,32 @@
 // CHECK-PG-FOURTEEN: "-lc++" "-lm"
 // CHECK-PG-TEN: "-lc++_p" "-lm_p"
 
+// Test that FreeBSD prefers install tree libc++ headers over system ones.
+// RUN: %clang -### %s --target=amd64-unknown-freebsd -r 2>&1 \
+// RUN:     -ccc-install-dir %S/Inputs/install_tree_with_libcxx/bin \
+// RUN:     --sysroot=%S/Inputs/basic_freebsd_libcxx_tree \
+// RUN:   | FileCheck %s --check-prefix=DRIVER-INSTALL-INCLUDES
+// DRIVER-INSTALL-INCLUDES:      "-internal-isystem" "{{.*}}bin[[SEP:/|\\\\]]..[[SEP]]include[[SEP]]c++[[SEP]]v1"
+// DRIVER-INSTALL-INCLUDES-NOT:  "-internal-isystem" "{{.*}}[[SEP]]/usr[[SEP]]include[[SEP]]c++[[SEP]]v1"
+
 // Test include paths with a sysroot.
 // RUN: %clangxx %s -### -fsyntax-only 2>&1 \
 // RUN:     --target=amd64-unknown-freebsd \
+// RUN:     -ccc-install-dir %S/Inputs/install_tree_without_libcxx/bin \
 // RUN:     --sysroot=%S/Inputs/basic_openbsd_libcxx_tree \
 // RUN:     -resource-dir=%S/Inputs/resource_dir \
 // RUN:   | FileCheck --check-prefix=CHECK-LIBCXX-SYSROOT %s
 // CHECK-LIBCXX-SYSROOT: "-cc1"
 // CHECK-LIBCXX-SYSROOT-SAME: "-isysroot" "[[SYSROOT:[^"]+]]"
-// CHECK-LIBCXX-SYSROOT-SAME: "-internal-isystem" "{{.*}}/bin/../include/c++/v1"
-// CHECK-LIBCXX-SYSROOT-NOT:  "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
+// CHECK-LIBCXX-SYSROOT-SAME: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
 
 // Test include paths when the sysroot path ends with `/`.
 // RUN: %clangxx %s -### -fsyntax-only 2>&1 \
 // RUN:     --target=amd64-unknown-freebsd \
+// RUN:     -ccc-install-dir %S/Inputs/install_tree_without_libcxx/bin \
 // RUN:     --sysroot=%S/Inputs/basic_openbsd_libcxx_tree/ \
 // RUN:     -resource-dir=%S/Inputs/resource_dir \
 // RUN:   | FileCheck --check-prefix=CHECK-LIBCXX-SYSROOT-SLASH %s
 // CHECK-LIBCXX-SYSROOT-SLASH: "-cc1"
 // CHECK-LIBCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]"
-// CHECK-LIBCXX-SYSROOT-SLASH-SAME: "-internal-isystem" "{{.*}}/bin/../include/c++/v1"
-// CHECK-LIBCXX-SYSROOT-SLASH-NOT:  "-internal-isystem" "[[SYSROOT]]usr/include/c++/v1"
+// CHECK-LIBCXX-SYSROOT-SLASH-SAME: "-internal-isystem" "[[SYSROOT]]usr/include/c++/v1"



More information about the cfe-commits mailing list