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 @@ -42,9 +42,9 @@ : Group(Group), Lookup(Lookup), UserEntryIdx(UserEntryIdx) {} }; -/// InitHeaderSearch - This class makes it easier to set the search paths of -/// a HeaderSearch object. InitHeaderSearch stores several search path lists -/// internally, which can be sent to a HeaderSearch object in one swoop. +/// This class makes it easier to set the search paths of a HeaderSearch object. +/// InitHeaderSearch stores several search path lists internally, which can be +/// sent to a HeaderSearch object in one swoop. class InitHeaderSearch { std::vector IncludePath; std::vector > SystemHeaderPrefixes; @@ -58,56 +58,54 @@ : Headers(HS), Verbose(verbose), IncludeSysroot(std::string(sysroot)), HasSysroot(!(sysroot.empty() || sysroot == "/")) {} - /// AddPath - Add the specified path to the specified group list, prefixing - /// the sysroot if used. + /// Add the specified path to the specified group list, prefixing the sysroot + /// if used. /// Returns true if the path exists, false if it was ignored. bool AddPath(const Twine &Path, IncludeDirGroup Group, bool isFramework, Optional UserEntryIdx = None); - /// AddUnmappedPath - Add the specified path to the specified group list, - /// without performing any sysroot remapping. + /// Add the specified path to the specified group list, without performing any + /// sysroot remapping. /// Returns true if the path exists, false if it was ignored. bool AddUnmappedPath(const Twine &Path, IncludeDirGroup Group, bool isFramework, Optional UserEntryIdx = None); - /// AddSystemHeaderPrefix - Add the specified prefix to the system header - /// prefix list. + /// Add the specified prefix to the system header prefix list. void AddSystemHeaderPrefix(StringRef Prefix, bool IsSystemHeader) { SystemHeaderPrefixes.emplace_back(std::string(Prefix), IsSystemHeader); } - /// AddGnuCPlusPlusIncludePaths - Add the necessary paths to support a gnu - /// libstdc++. + /// Add the necessary paths to support a gnu libstdc++. /// Returns true if the \p Base path was found, false if it does not exist. bool AddGnuCPlusPlusIncludePaths(StringRef Base, StringRef ArchDir, StringRef Dir32, StringRef Dir64, const llvm::Triple &triple); - /// AddMinGWCPlusPlusIncludePaths - Add the necessary paths to support a MinGW - /// libstdc++. + /// Add the necessary paths to support a MinGW libstdc++. void AddMinGWCPlusPlusIncludePaths(StringRef Base, StringRef Arch, StringRef Version); - // AddDefaultCIncludePaths - Add paths that should always be searched. + /// Add paths that should always be searched. void AddDefaultCIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); - // AddDefaultCPlusPlusIncludePaths - Add paths that should be searched when - // compiling c++. + /// Add paths that should be searched when compiling c++. void AddDefaultCPlusPlusIncludePaths(const LangOptions &LangOpts, const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); - /// AddDefaultSystemIncludePaths - Adds the default system include paths so - /// that e.g. stdio.h is found. + /// Returns true iff AddDefaultIncludePaths should do anything. If this + /// returns false, include paths should instead be handled in the driver. + bool ShouldAddDefaultIncludePaths(const llvm::Triple &triple); + + /// Adds the default system include paths so that e.g. stdio.h is found. void AddDefaultIncludePaths(const LangOptions &Lang, const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); - /// Realize - Merges all search path lists into one list and send it to - /// HeaderSearch. + /// Merges all search path lists into one list and send it to HeaderSearch. void Realize(const LangOptions &Lang); }; @@ -225,18 +223,15 @@ 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 +275,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 +375,12 @@ 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."); - } + // FIXME: temporary hack: hard-coded paths. + llvm::Triple::OSType os = triple.getOS(); 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 +406,56 @@ } } -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. +bool InitHeaderSearch::ShouldAddDefaultIncludePaths( + const llvm::Triple &triple) { switch (triple.getOS()) { - default: - break; // Everything else continues to use this routine's logic. - + 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; + + default: 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); } @@ -484,9 +475,9 @@ AddDefaultCIncludePaths(triple, HSOpts); } -/// RemoveDuplicates - If there are duplicate directory entries in the specified -/// search list, remove the later (dead) ones. Returns the number of non-system -/// headers removed, which is used to update NumAngled. +/// If there are duplicate directory entries in the specified search list, +/// remove the later (dead) ones. Returns the number of non-system headers +/// removed, which is used to update NumAngled. static unsigned RemoveDuplicates(std::vector &SearchList, unsigned First, bool Verbose) { llvm::SmallPtrSet SeenDirs; 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-SAME: {{^}} "-internal-isystem" "[[RESOURCE]]/include" +// DRIVER-PASS-INCLUDES-SAME: {{^}} "-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-SAME: {{^}} "-internal-isystem" "/usr/include/c++/v1" +// DRIVER-PASS-INCLUDES-SAME: {{^}} "-internal-isystem" "[[RESOURCE]]/include" +// DRIVER-PASS-INCLUDES-SAME: {{^}} "-internal-externc-isystem" "/usr/include"