diff --git a/clang/lib/Driver/ToolChains/FreeBSD.h b/clang/lib/Driver/ToolChains/FreeBSD.h --- a/clang/lib/Driver/ToolChains/FreeBSD.h +++ b/clang/lib/Driver/ToolChains/FreeBSD.h @@ -58,6 +58,9 @@ bool IsMathErrnoDefault() const override { return false; } bool IsObjCNonFragileABIDefault() const override { return true; } + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; CXXStdlibType GetDefaultCXXStdlibType() const override; void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -11,6 +11,7 @@ #include "Arch/Mips.h" #include "Arch/Sparc.h" #include "CommonArgs.h" +#include "clang/Config/config.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" @@ -408,6 +409,40 @@ return 4; } +void FreeBSD::AddClangSystemIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const { + const Driver &D = getDriver(); + + if (DriverArgs.hasArg(clang::driver::options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> Dir(D.ResourceDir); + llvm::sys::path::append(Dir, "include"); + addSystemInclude(DriverArgs, CC1Args, Dir.str()); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + // Check for configure-time C include directories. + StringRef CIncludeDirs(C_INCLUDE_DIRS); + if (CIncludeDirs != "") { + SmallVector dirs; + CIncludeDirs.split(dirs, ":"); + for (StringRef dir : dirs) { + StringRef Prefix = + llvm::sys::path::is_absolute(dir) ? StringRef(D.SysRoot) : ""; + addExternCSystemInclude(DriverArgs, CC1Args, Prefix + dir); + } + return; + } + + addExternCSystemInclude(DriverArgs, CC1Args, + concat(D.SysRoot, "/usr/include")); +} + void FreeBSD::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const { addSystemInclude(DriverArgs, CC1Args, diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp --- a/clang/lib/Lex/InitHeaderSearch.cpp +++ b/clang/lib/Lex/InitHeaderSearch.cpp @@ -100,6 +100,11 @@ const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); + /// ShouldAddDefaultIncludePaths - Returns true iff AddDefaultIncludePaths + /// should actually do anything. If this returns false, include management + /// should instead be handled in the driver. + bool ShouldAddDefaultIncludePaths(const llvm::Triple &triple); + /// AddDefaultSystemIncludePaths - Adds the default system include paths so /// that e.g. stdio.h is found. void AddDefaultIncludePaths(const LangOptions &Lang, @@ -225,18 +230,16 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { - llvm::Triple::OSType os = triple.getOS(); - - if (triple.isOSDarwin()) { + if (!ShouldAddDefaultIncludePaths(triple)) { llvm_unreachable("Include management is handled in the driver."); } + llvm::Triple::OSType os = triple.getOS(); + if (HSOpts.UseStandardSystemIncludes) { switch (os) { case llvm::Triple::CloudABI: - case llvm::Triple::FreeBSD: case llvm::Triple::NetBSD: - case llvm::Triple::OpenBSD: case llvm::Triple::NaCl: case llvm::Triple::PS4: case llvm::Triple::PS5: @@ -280,12 +283,6 @@ } switch (os) { - case llvm::Triple::Linux: - case llvm::Triple::Hurd: - case llvm::Triple::Solaris: - case llvm::Triple::OpenBSD: - llvm_unreachable("Include management is handled in the driver."); - case llvm::Triple::CloudABI: { // //include SmallString<128> P = StringRef(HSOpts.ResourceDir); @@ -386,20 +383,14 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( const LangOptions &LangOpts, const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { - llvm::Triple::OSType os = triple.getOS(); - // FIXME: temporary hack: hard-coded paths. - - if (triple.isOSDarwin()) { + if (!ShouldAddDefaultIncludePaths(triple)) { llvm_unreachable("Include management is handled in the driver."); } + llvm::Triple::OSType os = triple.getOS(); + + // FIXME: temporary hack: hard-coded paths. switch (os) { - case llvm::Triple::Linux: - case llvm::Triple::Hurd: - case llvm::Triple::Solaris: - case llvm::Triple::AIX: - llvm_unreachable("Include management is handled in the driver."); - break; case llvm::Triple::Win32: switch (triple.getEnvironment()) { default: llvm_unreachable("Include management is handled in the driver."); @@ -425,46 +416,55 @@ } } -void InitHeaderSearch::AddDefaultIncludePaths(const LangOptions &Lang, - const llvm::Triple &triple, - const HeaderSearchOptions &HSOpts) { - // NB: This code path is going away. All of the logic is moving into the - // driver which has the information necessary to do target-specific - // selections of default include paths. Each target which moves there will be - // exempted from this logic here until we can delete the entire pile of code. - switch (triple.getOS()) { - default: - break; // Everything else continues to use this routine's logic. +bool InitHeaderSearch::ShouldAddDefaultIncludePaths( + const llvm::Triple &triple) { + llvm::Triple::OSType os = triple.getOS(); + switch (triple.getOS()) { + case llvm::Triple::AIX: case llvm::Triple::Emscripten: - case llvm::Triple::Linux: + case llvm::Triple::FreeBSD: case llvm::Triple::Hurd: + case llvm::Triple::Linux: case llvm::Triple::OpenBSD: case llvm::Triple::Solaris: case llvm::Triple::WASI: - case llvm::Triple::AIX: - return; + return false; case llvm::Triple::Win32: if (triple.getEnvironment() != llvm::Triple::Cygnus || triple.isOSBinFormatMachO()) - return; + return false; break; case llvm::Triple::UnknownOS: if (triple.isWasm()) - return; + return false; break; } - // All header search logic is handled in the Driver for Darwin. + return true; // Everything else uses AddDefaultIncludePaths(). +} + +void InitHeaderSearch::AddDefaultIncludePaths( + const LangOptions &Lang, const llvm::Triple &triple, + const HeaderSearchOptions &HSOpts) { + // NB: This code path is going away. All of the logic is moving into the + // driver which has the information necessary to do target-specific + // selections of default include paths. Each target which moves there will be + // exempted from this logic in ShouldAddDefaultIncludePaths() until we can + // delete the entire pile of code. + if (!ShouldAddDefaultIncludePaths(triple)) + return; + + // NOTE: some additional header search logic is handled in the driver for + // Darwin. if (triple.isOSDarwin()) { if (HSOpts.UseStandardSystemIncludes) { // Add the default framework include paths on Darwin. if (triple.isDriverKit()) { AddPath("/System/DriverKit/System/Library/Frameworks", System, true); - } - else { + } else { AddPath("/System/Library/Frameworks", System, true); AddPath("/Library/Frameworks", System, true); } diff --git a/clang/test/Driver/freebsd.c b/clang/test/Driver/freebsd.c --- a/clang/test/Driver/freebsd.c +++ b/clang/test/Driver/freebsd.c @@ -213,3 +213,10 @@ // RELOCATABLE-NOT: "-dynamic-linker" // RELOCATABLE-NOT: "-l // RELOCATABLE-NOT: crt{{[^./]+}}.o + +// Check that the driver passes include paths to cc1 on FreeBSD. +// RUN: %clang -### %s --target=x86_64-unknown-freebsd13.1 -r 2>&1 \ +// RUN: | FileCheck %s --check-prefix=DRIVER-PASS-INCLUDES +// DRIVER-PASS-INCLUDES: "-cc1" {{.*}}"-resource-dir" "[[RESOURCE:[^"]+]]" +// DRIVER-PASS-INCLUDES: "-internal-isystem" "[[RESOURCE]]/include" +// DRIVER-PASS-INCLUDES: "-internal-externc-isystem" "/usr/include" diff --git a/clang/test/Driver/freebsd.cpp b/clang/test/Driver/freebsd.cpp --- a/clang/test/Driver/freebsd.cpp +++ b/clang/test/Driver/freebsd.cpp @@ -40,3 +40,11 @@ // 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 that the driver passes include paths to cc1 on FreeBSD. +// RUN: %clang -### %s --target=x86_64-unknown-freebsd13.1 -r 2>&1 \ +// RUN: | FileCheck %s --check-prefix=DRIVER-PASS-INCLUDES +// DRIVER-PASS-INCLUDES: "-cc1" {{.*}}"-resource-dir" "[[RESOURCE:[^"]+]]" +// DRIVER-PASS-INCLUDES: "-internal-isystem" "/usr/include/c++/v1" +// DRIVER-PASS-INCLUDES: "-internal-isystem" "[[RESOURCE]]/include" +// DRIVER-PASS-INCLUDES: "-internal-externc-isystem" "/usr/include"