Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[clang][Darwin] Remove legacy framework search path logic in the frontend #138234

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

ian-twilightcoder
Copy link
Contributor

@ian-twilightcoder ian-twilightcoder commented May 2, 2025

Move the Darwin framework search path logic from InitHeaderSearch::AddDefaultIncludePaths to DarwinClang::AddClangSystemIncludeArgs. Add a new -internal-iframework cc1 argument to support the tool chain adding these paths.
Now that the tool chain is adding search paths via cc1 flag, they're only added if they exist, so the Preprocessor/cuda-macos-includes.cu test is no longer relevant.
Change Driver/driverkit-path.c and Driver/darwin-subframeworks.c to do -### style testing similar to the darwin-header-search and darwin-embedded-search-paths tests. Rename darwin-subframeworks.c to darwin-framework-search-paths.c and have it test all framework search paths, not just SubFrameworks.
Add a unit test to validate that the myriad of search path flags result in the expected search path list.

Fixes #75638

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" labels May 2, 2025
@llvmbot
Copy link
Member

llvmbot commented May 2, 2025

@llvm/pr-subscribers-clang

Author: Ian Anderson (ian-twilightcoder)

Changes

Move the Darwin framework search path logic from InitHeaderSearch::AddDefaultIncludePaths to DarwinClang::AddClangSystemIncludeArgs. Add a new -internal-iframework cc1 argument to support the tool chain adding these paths. Now that the tool chain is adding search paths via cc1 flag, they're only added if they exist, so the Preprocessor/cuda-macos-includes.cu test is no longer relevant. Change Driver/driverkit-path.c and Driver/darwin-subframeworks.c to do -### style testing similar to the darwin-header-search and darwin-embedded-search-paths tests. Rename darwin-subframeworks.c to darwin-framework-search-paths.c and have it test all framework search paths, not just SubFrameworks. Add a unit test to validate that the myriad of search path flags result in the expected search path list.

Fixes #75638


Patch is 21.07 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138234.diff

17 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+5)
  • (modified) clang/include/clang/Driver/ToolChain.h (+6)
  • (modified) clang/lib/Driver/Job.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChain.cpp (+20)
  • (modified) clang/lib/Driver/ToolChains/Darwin.cpp (+21)
  • (modified) clang/lib/Driver/ToolChains/Darwin.h (+4)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (+4)
  • (modified) clang/lib/Lex/InitHeaderSearch.cpp (+3-16)
  • (added) clang/test/Driver/Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks/.keep ()
  • (added) clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibraryFrameworks/.keep ()
  • (added) clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibrarySubFrameworks/.keep ()
  • (added) clang/test/Driver/darwin-framework-search-paths.c (+23)
  • (removed) clang/test/Driver/darwin-subframeworks.c (-18)
  • (modified) clang/test/Driver/driverkit-path.c (+9-7)
  • (removed) clang/test/Preprocessor/cuda-macos-includes.cu (-13)
  • (modified) clang/unittests/Frontend/CMakeLists.txt (+1)
  • (added) clang/unittests/Frontend/SearchPathTest.cpp (+157)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 561b0498c549c..7d2b847dd3830 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -8413,6 +8413,11 @@ def objc_isystem : Separate<["-"], "objc-isystem">,
 def objcxx_isystem : Separate<["-"], "objcxx-isystem">,
   MetaVarName<"<directory>">,
   HelpText<"Add directory to the ObjC++ SYSTEM include search path">;
+def internal_iframework : Separate<["-"], "internal-iframework">,
+  MetaVarName<"<directory>">,
+  HelpText<"Add directory to the internal system framework search path; these "
+           "are assumed to not be user-provided and are used to model system "
+           "and standard frameworks' paths.">;
 def internal_isystem : Separate<["-"], "internal-isystem">,
   MetaVarName<"<directory>">,
   HelpText<"Add directory to the internal system include search path; these "
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index d0059673d6a67..58edf2b3887b0 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -226,6 +226,9 @@ class ToolChain {
 
   /// \name Utilities for implementing subclasses.
   ///@{
+  static void addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
+                                        llvm::opt::ArgStringList &CC1Args,
+                                        const Twine &Path);
   static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
                                llvm::opt::ArgStringList &CC1Args,
                                const Twine &Path);
@@ -236,6 +239,9 @@ class ToolChain {
       addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs,
                                       llvm::opt::ArgStringList &CC1Args,
                                       const Twine &Path);
+  static void addSystemFrameworkIncludes(const llvm::opt::ArgList &DriverArgs,
+                                         llvm::opt::ArgStringList &CC1Args,
+                                         ArrayRef<StringRef> Paths);
   static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
                                 llvm::opt::ArgStringList &CC1Args,
                                 ArrayRef<StringRef> Paths);
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index 4619b8c1887be..60f219f564abb 100644
--- a/clang/lib/Driver/Job.cpp
+++ b/clang/lib/Driver/Job.cpp
@@ -73,7 +73,7 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
     .Cases("-internal-externc-isystem", "-iprefix", true)
     .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
     .Cases("-isysroot", "-I", "-F", "-resource-dir", true)
-    .Cases("-iframework", "-include-pch", true)
+    .Cases("-internal-iframework", "-iframework", "-include-pch", true)
     .Default(false);
   if (IsInclude)
     return !HaveCrashVFS;
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 5cd5755e01587..d18799016e853 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1366,6 +1366,15 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
   return *cxxStdlibType;
 }
 
+/// Utility function to add a system framework directory to CC1 arguments.
+/*static*/ void
+ToolChain::addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
+                                     llvm::opt::ArgStringList &CC1Args,
+                                     const Twine &Path) {
+  CC1Args.push_back("-internal-iframework");
+  CC1Args.push_back(DriverArgs.MakeArgString(Path));
+}
+
 /// Utility function to add a system include directory to CC1 arguments.
 /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
                                             ArgStringList &CC1Args,
@@ -1396,6 +1405,17 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
     addExternCSystemInclude(DriverArgs, CC1Args, Path);
 }
 
+/// Utility function to add a list of system framework directories to CC1.
+/*static*/ void
+ToolChain::addSystemFrameworkIncludes(const ArgList &DriverArgs,
+                                      ArgStringList &CC1Args,
+                                      ArrayRef<StringRef> Paths) {
+  for (const auto &Path : Paths) {
+    CC1Args.push_back("-internal-iframework");
+    CC1Args.push_back(DriverArgs.MakeArgString(Path));
+  }
+}
+
 /// Utility function to add a list of system include directories to CC1.
 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
                                              ArgStringList &CC1Args,
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 4735dc3ad30ee..76fa2d121db2a 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2577,6 +2577,27 @@ void AppleMachO::AddClangSystemIncludeArgs(
   }
 }
 
+void DarwinClang::AddClangSystemIncludeArgs(
+    const llvm::opt::ArgList &DriverArgs,
+    llvm::opt::ArgStringList &CC1Args) const {
+  AppleMachO::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+
+  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+      DriverArgs.hasArg(options::OPT_nostdlibinc))
+    return;
+
+  llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
+
+  // Add <sysroot>/System/Library/Frameworks
+  // Add <sysroot>/System/Library/SubFrameworks
+  // Add <sysroot>/Library/Frameworks
+  SmallString<128> P1(Sysroot), P2(Sysroot), P3(Sysroot);
+  llvm::sys::path::append(P1, "System", "Library", "Frameworks");
+  llvm::sys::path::append(P2, "System", "Library", "SubFrameworks");
+  llvm::sys::path::append(P3, "Library", "Frameworks");
+  addSystemFrameworkIncludes(DriverArgs, CC1Args, {P1, P2, P3});
+}
+
 bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                               llvm::opt::ArgStringList &CC1Args,
                                               llvm::SmallString<128> Base,
diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index 76523d636ce07..b38bfe6d1e554 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -647,6 +647,10 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
   /// @name Apple ToolChain Implementation
   /// {
 
+  void
+  AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                            llvm::opt::ArgStringList &CC1Args) const override;
+
   RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
 
   void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index c7d11e6027ccf..9ad4324be789b 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3364,6 +3364,8 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
                            : OPT_internal_externc_isystem;
     GenerateArg(Consumer, Opt, It->Path);
   }
+  for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
+    GenerateArg(Consumer, OPT_internal_iframework, It->Path);
 
   assert(It == End && "Unhandled HeaderSearchOption::Entry.");
 
@@ -3496,6 +3498,8 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
       Group = frontend::ExternCSystem;
     Opts.AddPath(A->getValue(), Group, false, true);
   }
+  for (const auto *A : Args.filtered(OPT_internal_iframework))
+    Opts.AddPath(A->getValue(), frontend::System, true, true);
 
   // Add the path prefixes which are implicitly treated as being system headers.
   for (const auto *A :
diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp
index bb2a21356fa8f..df45c96725fe3 100644
--- a/clang/lib/Lex/InitHeaderSearch.cpp
+++ b/clang/lib/Lex/InitHeaderSearch.cpp
@@ -321,6 +321,9 @@ bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
     break;
   }
 
+  if (triple.isOSDarwin())
+    return false;
+
   return true; // Everything else uses AddDefaultIncludePaths().
 }
 
@@ -335,22 +338,6 @@ void InitHeaderSearch::AddDefaultIncludePaths(
   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 {
-        AddPath("/System/Library/Frameworks", System, true);
-        AddPath("/System/Library/SubFrameworks", System, true);
-        AddPath("/Library/Frameworks", System, true);
-      }
-    }
-    return;
-  }
-
   if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
       HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
     if (HSOpts.UseLibcxx) {
diff --git a/clang/test/Driver/Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks/.keep b/clang/test/Driver/Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibraryFrameworks/.keep b/clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibraryFrameworks/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibrarySubFrameworks/.keep b/clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibrarySubFrameworks/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/darwin-framework-search-paths.c b/clang/test/Driver/darwin-framework-search-paths.c
new file mode 100644
index 0000000000000..1cb4dc420c536
--- /dev/null
+++ b/clang/test/Driver/darwin-framework-search-paths.c
@@ -0,0 +1,23 @@
+// UNSUPPORTED: system-windows
+//   Windows is unsupported because we use the Unix path separator `/` in the test.
+
+// RUN: %clang %s -target arm64-apple-macosx15.1 -isysroot %S/Inputs/MacOSX15.1.sdk -c %s -### 2>&1 \
+// RUN: | FileCheck -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+//
+// CHECK: "-cc1"
+// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]"
+// CHECK-SAME: "-internal-iframework" "[[SDKROOT]]/System/Library/Frameworks"
+// CHECK-SAME: "-internal-iframework" "[[SDKROOT]]/System/Library/SubFrameworks"
+// CHECK-SAME: "-internal-iframework" "[[SDKROOT]]/Library/Frameworks"
+
+// Verify that -nostdlibinc and -nostdinc removes the default search paths.
+//
+// RUN: %clang %s -target arm64-apple-macosx15.1 -isysroot %S/Inputs/MacOSX15.1.sdk -nostdinc -c %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NOSTD -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+//
+// RUN: %clang %s -target arm64-apple-macosx15.1 -isysroot %S/Inputs/MacOSX15.1.sdk -nostdlibinc -c %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NOSTD -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+//
+// CHECK-NOSTD: "-cc1"
+// CHECK-NOSTD: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]"
+// CHECK-NOSTD-NOT: "-internal-iframework"
diff --git a/clang/test/Driver/darwin-subframeworks.c b/clang/test/Driver/darwin-subframeworks.c
deleted file mode 100644
index 1a7a095c64292..0000000000000
--- a/clang/test/Driver/darwin-subframeworks.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// UNSUPPORTED: system-windows
-//   Windows is unsupported because we use the Unix path separator `\`.
-
-// Add default directories before running clang to check default 
-// search paths. 
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: cp -R %S/Inputs/MacOSX15.1.sdk %t/
-// RUN: mkdir -p %t/MacOSX15.1.sdk/System/Library/Frameworks
-// RUN: mkdir -p %t/MacOSX15.1.sdk/System/Library/SubFrameworks
-// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/include
-
-// RUN: %clang %s -target arm64-apple-darwin13.0 -isysroot %t/MacOSX15.1.sdk -E -v 2>&1 | FileCheck %s
-
-// CHECK:    -isysroot [[PATH:[^ ]*/MacOSX15.1.sdk]]
-// CHECK:    #include <...> search starts here:
-// CHECK:    [[PATH]]/usr/include
-// CHECK:    [[PATH]]/System/Library/Frameworks (framework directory)
-// CHECK:    [[PATH]]/System/Library/SubFrameworks (framework directory)
diff --git a/clang/test/Driver/driverkit-path.c b/clang/test/Driver/driverkit-path.c
index 3caae382d65bb..32f0a6721ab77 100644
--- a/clang/test/Driver/driverkit-path.c
+++ b/clang/test/Driver/driverkit-path.c
@@ -21,13 +21,15 @@ int main() { return 0; }
 // LD64-NEW: "-isysroot" "[[PATH:[^"]*]]Inputs/DriverKit19.0.sdk"
 // LD64-NEW-NOT: "-L[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/usr/lib"
 // LD64-NEW-NOT: "-F[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/Frameworks"
+// LD64-NEW-NOT: "-F[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks"
 
 
-// RUN: %clang %s -target x86_64-apple-driverkit19.0 -isysroot %S/Inputs/DriverKit19.0.sdk -E -v -x c++ 2>&1 | FileCheck %s --check-prefix=INC
+// RUN: %clang %s -target x86_64-apple-driverkit19.0 -isysroot %S/Inputs/DriverKit19.0.sdk -x c++ -### 2>&1 \
+// RUN: | FileCheck %s -DSDKROOT=%S/Inputs/DriverKit19.0.sdk --check-prefix=INC
 //
-// INC:       -isysroot [[PATH:[^ ]*/Inputs/DriverKit19.0.sdk]]
-// INC-LABEL: #include <...> search starts here:
-// INC:       [[PATH]]/System/DriverKit/usr/local/include
-// INC:       /lib{{(64)?}}/clang/{{[^/ ]+}}/include
-// INC:       [[PATH]]/System/DriverKit/usr/include
-// INC:       [[PATH]]/System/DriverKit/System/Library/Frameworks (framework directory)
+// INC: "-isysroot" "[[SDKROOT]]"
+// INC: "-internal-isystem" "[[SDKROOT]]/System/DriverKit/usr/local/include"
+// INC: "-internal-isystem" "{{.+}}/lib{{(64)?}}/clang/{{[^/ ]+}}/include"
+// INC: "-internal-externc-isystem" "[[SDKROOT]]/System/DriverKit/usr/include"
+// INC: "-internal-iframework" "[[SDKROOT]]/System/DriverKit/System/Library/Frameworks"
+// INC: "-internal-iframework" "[[SDKROOT]]/System/DriverKit/System/Library/SubFrameworks"
diff --git a/clang/test/Preprocessor/cuda-macos-includes.cu b/clang/test/Preprocessor/cuda-macos-includes.cu
deleted file mode 100644
index 6ef94b0e45352..0000000000000
--- a/clang/test/Preprocessor/cuda-macos-includes.cu
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %clang -cc1 -fcuda-is-device -isysroot /var/empty \
-// RUN:   -triple nvptx-nvidia-cuda -aux-triple i386-apple-macosx \
-// RUN:   -E -fcuda-is-device -v -o /dev/null -x cuda %s 2>&1 | FileCheck %s
-
-// RUN: %clang -cc1 -isysroot /var/empty \
-// RUN:   -triple i386-apple-macosx -aux-triple nvptx-nvidia-cuda \
-// RUN:   -E -fcuda-is-device -v -o /dev/null -x cuda %s 2>&1 | FileCheck %s
-
-// Check that when we do CUDA host and device compiles on MacOS, we check for
-// includes in /System/Library/Frameworks and /Library/Frameworks.
-
-// CHECK-DAG: ignoring nonexistent directory "/var/empty/System/Library/Frameworks"
-// CHECK-DAG: ignoring nonexistent directory "/var/empty/Library/Frameworks"
diff --git a/clang/unittests/Frontend/CMakeLists.txt b/clang/unittests/Frontend/CMakeLists.txt
index bbf0396014fa9..0d9fc714212d5 100644
--- a/clang/unittests/Frontend/CMakeLists.txt
+++ b/clang/unittests/Frontend/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_unittest(FrontendTests
   PCHPreambleTest.cpp
   ReparseWorkingDirTest.cpp
   OutputStreamTest.cpp
+  SearchPathTest.cpp
   TextDiagnosticTest.cpp
   UtilsTest.cpp
   CLANG_LIBS
diff --git a/clang/unittests/Frontend/SearchPathTest.cpp b/clang/unittests/Frontend/SearchPathTest.cpp
new file mode 100644
index 0000000000000..5d382a4ee20a8
--- /dev/null
+++ b/clang/unittests/Frontend/SearchPathTest.cpp
@@ -0,0 +1,157 @@
+//====-- unittests/Frontend/SearchPathTest.cpp - FrontendAction tests -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include "gtest/gtest.h"
+
+#include <memory>
+#include <optional>
+#include <tuple>
+#include <vector>
+
+namespace clang {
+namespace {
+
+class SearchPathTest : public ::testing::Test {
+protected:
+  SearchPathTest()
+      : Diags(new DiagnosticIDs(), new DiagnosticOptions,
+              new IgnoringDiagConsumer()),
+        VFS(new llvm::vfs::InMemoryFileSystem),
+        FileMgr(FileSystemOptions(), VFS), SourceMgr(Diags, FileMgr),
+        Invocation(std::make_unique<CompilerInvocation>()) {}
+
+  DiagnosticsEngine Diags;
+  IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS;
+  FileManager FileMgr;
+  SourceManager SourceMgr;
+  std::unique_ptr<CompilerInvocation> Invocation;
+
+  void addDirectories(ArrayRef<StringRef> Dirs) {
+    for (StringRef Dir : Dirs) {
+      VFS->addFile(Dir, 0, llvm::MemoryBuffer::getMemBuffer(""),
+                   /*User=*/std::nullopt, /*Group=*/std::nullopt,
+                   llvm::sys::fs::file_type::directory_file);
+    }
+  }
+
+  std::unique_ptr<HeaderSearch>
+  makeHeaderSearchFromCC1Args(llvm::opt::ArgStringList Args) {
+    CompilerInvocation::CreateFromArgs(*Invocation, Args, Diags);
+    HeaderSearchOptions HSOpts = Invocation->getHeaderSearchOpts();
+    LangOptions LangOpts = Invocation->getLangOpts();
+    TargetInfo *Target =
+        TargetInfo::CreateTargetInfo(Diags, Invocation->getTargetOpts());
+    auto HeaderInfo = std::make_unique<HeaderSearch>(HSOpts, SourceMgr, Diags,
+                                                     LangOpts, Target);
+    ApplyHeaderSearchOptions(*HeaderInfo, HSOpts, LangOpts,
+                             Target->getTriple());
+    return HeaderInfo;
+  }
+};
+
+TEST_F(SearchPathTest, SearchPathOrder) {
+  addDirectories({"One", "Two", "Three", "Four", "Five", "Six", "Seven",
+                  "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+                  "Fourteen", "Fifteen", "Sixteen", "Seventeen"});
+  llvm::opt::ArgStringList Args = {
+      // Make sure to use a triple and language that don't automatically add any
+      // search paths.
+      "-triple", "arm64-apple-darwin24.4.0", "-x", "c",
+
+      // clang-format off
+      "-internal-isystem", "One",
+      "-iwithsysroot", "Two",
+      "-c-isystem", "Three",
+      "-IFour",
+      "-idirafter", "Five",
+      "-internal-externc-isystem", "Six",
+      "-iwithprefix", "Seven",
+      "-FEight",
+      "-idirafter", "Nine",
+      "-iframeworkwithsysroot", "Ten",
+      "-internal-iframework", "Eleven",
+      "-iframework", "Twelve",
+      "-iwithprefixbefore", "Thirteen",
+      "-internal-isystem", "Fourteen",
+      "-isystem", "Fifteen",
+      "-ISixteen",
+      "-iwithsysroot", "Seventeen",
+      // clang-format on
+  };
+
+  // The search path arguments get categorized by IncludeDirGroup, but
+  // ultimately are sorted with some groups mixed together and some flags sorted
+  // very specifically within their group. The conceptual groups below don't
+  // exactly correspond to IncludeDirGroup.
+  const std::vector<StringRef> expected = {
+      // User paths: -I and -F mixed together, -iwithprefixbefore.
+      /*-I*/ "Four",
+      /*-F*/ "Eight",
+      /*-I*/ "Sixteen",
+      /*-iwithprefixbefore*/ "Thirteen",
+
+      // System paths: -isystem and -iwithsysroot, -iframework,
+      // -iframeworkwithsysroot, one of {-c-isystem, -cxx-isystem,
+      // -objc-isystem, -objcxx-isystem}
+      /*-iwithsysroot*/ "Two",
+      /*-isystem*/ "Fifteen",
+      /*-iwithsysroot*/ "Seventeen",
+      /*-iframework*/ "Twelve",
+      /*...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented May 2, 2025

@llvm/pr-subscribers-clang-driver

Author: Ian Anderson (ian-twilightcoder)

Changes

Move the Darwin framework search path logic from InitHeaderSearch::AddDefaultIncludePaths to DarwinClang::AddClangSystemIncludeArgs. Add a new -internal-iframework cc1 argument to support the tool chain adding these paths. Now that the tool chain is adding search paths via cc1 flag, they're only added if they exist, so the Preprocessor/cuda-macos-includes.cu test is no longer relevant. Change Driver/driverkit-path.c and Driver/darwin-subframeworks.c to do -### style testing similar to the darwin-header-search and darwin-embedded-search-paths tests. Rename darwin-subframeworks.c to darwin-framework-search-paths.c and have it test all framework search paths, not just SubFrameworks. Add a unit test to validate that the myriad of search path flags result in the expected search path list.

Fixes #75638


Patch is 21.07 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138234.diff

17 Files Affected:

  • (modified) clang/include/clang/Driver/Options.td (+5)
  • (modified) clang/include/clang/Driver/ToolChain.h (+6)
  • (modified) clang/lib/Driver/Job.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChain.cpp (+20)
  • (modified) clang/lib/Driver/ToolChains/Darwin.cpp (+21)
  • (modified) clang/lib/Driver/ToolChains/Darwin.h (+4)
  • (modified) clang/lib/Frontend/CompilerInvocation.cpp (+4)
  • (modified) clang/lib/Lex/InitHeaderSearch.cpp (+3-16)
  • (added) clang/test/Driver/Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks/.keep ()
  • (added) clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibraryFrameworks/.keep ()
  • (added) clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibrarySubFrameworks/.keep ()
  • (added) clang/test/Driver/darwin-framework-search-paths.c (+23)
  • (removed) clang/test/Driver/darwin-subframeworks.c (-18)
  • (modified) clang/test/Driver/driverkit-path.c (+9-7)
  • (removed) clang/test/Preprocessor/cuda-macos-includes.cu (-13)
  • (modified) clang/unittests/Frontend/CMakeLists.txt (+1)
  • (added) clang/unittests/Frontend/SearchPathTest.cpp (+157)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 561b0498c549c..7d2b847dd3830 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -8413,6 +8413,11 @@ def objc_isystem : Separate<["-"], "objc-isystem">,
 def objcxx_isystem : Separate<["-"], "objcxx-isystem">,
   MetaVarName<"<directory>">,
   HelpText<"Add directory to the ObjC++ SYSTEM include search path">;
+def internal_iframework : Separate<["-"], "internal-iframework">,
+  MetaVarName<"<directory>">,
+  HelpText<"Add directory to the internal system framework search path; these "
+           "are assumed to not be user-provided and are used to model system "
+           "and standard frameworks' paths.">;
 def internal_isystem : Separate<["-"], "internal-isystem">,
   MetaVarName<"<directory>">,
   HelpText<"Add directory to the internal system include search path; these "
diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h
index d0059673d6a67..58edf2b3887b0 100644
--- a/clang/include/clang/Driver/ToolChain.h
+++ b/clang/include/clang/Driver/ToolChain.h
@@ -226,6 +226,9 @@ class ToolChain {
 
   /// \name Utilities for implementing subclasses.
   ///@{
+  static void addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
+                                        llvm::opt::ArgStringList &CC1Args,
+                                        const Twine &Path);
   static void addSystemInclude(const llvm::opt::ArgList &DriverArgs,
                                llvm::opt::ArgStringList &CC1Args,
                                const Twine &Path);
@@ -236,6 +239,9 @@ class ToolChain {
       addExternCSystemIncludeIfExists(const llvm::opt::ArgList &DriverArgs,
                                       llvm::opt::ArgStringList &CC1Args,
                                       const Twine &Path);
+  static void addSystemFrameworkIncludes(const llvm::opt::ArgList &DriverArgs,
+                                         llvm::opt::ArgStringList &CC1Args,
+                                         ArrayRef<StringRef> Paths);
   static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
                                 llvm::opt::ArgStringList &CC1Args,
                                 ArrayRef<StringRef> Paths);
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index 4619b8c1887be..60f219f564abb 100644
--- a/clang/lib/Driver/Job.cpp
+++ b/clang/lib/Driver/Job.cpp
@@ -73,7 +73,7 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum,
     .Cases("-internal-externc-isystem", "-iprefix", true)
     .Cases("-iwithprefixbefore", "-isystem", "-iquote", true)
     .Cases("-isysroot", "-I", "-F", "-resource-dir", true)
-    .Cases("-iframework", "-include-pch", true)
+    .Cases("-internal-iframework", "-iframework", "-include-pch", true)
     .Default(false);
   if (IsInclude)
     return !HaveCrashVFS;
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 5cd5755e01587..d18799016e853 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -1366,6 +1366,15 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{
   return *cxxStdlibType;
 }
 
+/// Utility function to add a system framework directory to CC1 arguments.
+/*static*/ void
+ToolChain::addSystemFrameworkInclude(const llvm::opt::ArgList &DriverArgs,
+                                     llvm::opt::ArgStringList &CC1Args,
+                                     const Twine &Path) {
+  CC1Args.push_back("-internal-iframework");
+  CC1Args.push_back(DriverArgs.MakeArgString(Path));
+}
+
 /// Utility function to add a system include directory to CC1 arguments.
 /*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs,
                                             ArgStringList &CC1Args,
@@ -1396,6 +1405,17 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
     addExternCSystemInclude(DriverArgs, CC1Args, Path);
 }
 
+/// Utility function to add a list of system framework directories to CC1.
+/*static*/ void
+ToolChain::addSystemFrameworkIncludes(const ArgList &DriverArgs,
+                                      ArgStringList &CC1Args,
+                                      ArrayRef<StringRef> Paths) {
+  for (const auto &Path : Paths) {
+    CC1Args.push_back("-internal-iframework");
+    CC1Args.push_back(DriverArgs.MakeArgString(Path));
+  }
+}
+
 /// Utility function to add a list of system include directories to CC1.
 /*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs,
                                              ArgStringList &CC1Args,
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 4735dc3ad30ee..76fa2d121db2a 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -2577,6 +2577,27 @@ void AppleMachO::AddClangSystemIncludeArgs(
   }
 }
 
+void DarwinClang::AddClangSystemIncludeArgs(
+    const llvm::opt::ArgList &DriverArgs,
+    llvm::opt::ArgStringList &CC1Args) const {
+  AppleMachO::AddClangSystemIncludeArgs(DriverArgs, CC1Args);
+
+  if (DriverArgs.hasArg(options::OPT_nostdinc) ||
+      DriverArgs.hasArg(options::OPT_nostdlibinc))
+    return;
+
+  llvm::SmallString<128> Sysroot = GetEffectiveSysroot(DriverArgs);
+
+  // Add <sysroot>/System/Library/Frameworks
+  // Add <sysroot>/System/Library/SubFrameworks
+  // Add <sysroot>/Library/Frameworks
+  SmallString<128> P1(Sysroot), P2(Sysroot), P3(Sysroot);
+  llvm::sys::path::append(P1, "System", "Library", "Frameworks");
+  llvm::sys::path::append(P2, "System", "Library", "SubFrameworks");
+  llvm::sys::path::append(P3, "Library", "Frameworks");
+  addSystemFrameworkIncludes(DriverArgs, CC1Args, {P1, P2, P3});
+}
+
 bool DarwinClang::AddGnuCPlusPlusIncludePaths(const llvm::opt::ArgList &DriverArgs,
                                               llvm::opt::ArgStringList &CC1Args,
                                               llvm::SmallString<128> Base,
diff --git a/clang/lib/Driver/ToolChains/Darwin.h b/clang/lib/Driver/ToolChains/Darwin.h
index 76523d636ce07..b38bfe6d1e554 100644
--- a/clang/lib/Driver/ToolChains/Darwin.h
+++ b/clang/lib/Driver/ToolChains/Darwin.h
@@ -647,6 +647,10 @@ class LLVM_LIBRARY_VISIBILITY DarwinClang : public Darwin {
   /// @name Apple ToolChain Implementation
   /// {
 
+  void
+  AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+                            llvm::opt::ArgStringList &CC1Args) const override;
+
   RuntimeLibType GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
 
   void AddLinkRuntimeLibArgs(const llvm::opt::ArgList &Args,
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index c7d11e6027ccf..9ad4324be789b 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -3364,6 +3364,8 @@ static void GenerateHeaderSearchArgs(const HeaderSearchOptions &Opts,
                            : OPT_internal_externc_isystem;
     GenerateArg(Consumer, Opt, It->Path);
   }
+  for (; It < End && Matches(*It, {frontend::System}, true, true); ++It)
+    GenerateArg(Consumer, OPT_internal_iframework, It->Path);
 
   assert(It == End && "Unhandled HeaderSearchOption::Entry.");
 
@@ -3496,6 +3498,8 @@ static bool ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args,
       Group = frontend::ExternCSystem;
     Opts.AddPath(A->getValue(), Group, false, true);
   }
+  for (const auto *A : Args.filtered(OPT_internal_iframework))
+    Opts.AddPath(A->getValue(), frontend::System, true, true);
 
   // Add the path prefixes which are implicitly treated as being system headers.
   for (const auto *A :
diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp
index bb2a21356fa8f..df45c96725fe3 100644
--- a/clang/lib/Lex/InitHeaderSearch.cpp
+++ b/clang/lib/Lex/InitHeaderSearch.cpp
@@ -321,6 +321,9 @@ bool InitHeaderSearch::ShouldAddDefaultIncludePaths(
     break;
   }
 
+  if (triple.isOSDarwin())
+    return false;
+
   return true; // Everything else uses AddDefaultIncludePaths().
 }
 
@@ -335,22 +338,6 @@ void InitHeaderSearch::AddDefaultIncludePaths(
   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 {
-        AddPath("/System/Library/Frameworks", System, true);
-        AddPath("/System/Library/SubFrameworks", System, true);
-        AddPath("/Library/Frameworks", System, true);
-      }
-    }
-    return;
-  }
-
   if (Lang.CPlusPlus && !Lang.AsmPreprocessor &&
       HSOpts.UseStandardCXXIncludes && HSOpts.UseStandardSystemIncludes) {
     if (HSOpts.UseLibcxx) {
diff --git a/clang/test/Driver/Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks/.keep b/clang/test/Driver/Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibraryFrameworks/.keep b/clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibraryFrameworks/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibrarySubFrameworks/.keep b/clang/test/Driver/Inputs/MacOSX15.1.sdk/System/LibrarySubFrameworks/.keep
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/clang/test/Driver/darwin-framework-search-paths.c b/clang/test/Driver/darwin-framework-search-paths.c
new file mode 100644
index 0000000000000..1cb4dc420c536
--- /dev/null
+++ b/clang/test/Driver/darwin-framework-search-paths.c
@@ -0,0 +1,23 @@
+// UNSUPPORTED: system-windows
+//   Windows is unsupported because we use the Unix path separator `/` in the test.
+
+// RUN: %clang %s -target arm64-apple-macosx15.1 -isysroot %S/Inputs/MacOSX15.1.sdk -c %s -### 2>&1 \
+// RUN: | FileCheck -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+//
+// CHECK: "-cc1"
+// CHECK: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]"
+// CHECK-SAME: "-internal-iframework" "[[SDKROOT]]/System/Library/Frameworks"
+// CHECK-SAME: "-internal-iframework" "[[SDKROOT]]/System/Library/SubFrameworks"
+// CHECK-SAME: "-internal-iframework" "[[SDKROOT]]/Library/Frameworks"
+
+// Verify that -nostdlibinc and -nostdinc removes the default search paths.
+//
+// RUN: %clang %s -target arm64-apple-macosx15.1 -isysroot %S/Inputs/MacOSX15.1.sdk -nostdinc -c %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NOSTD -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+//
+// RUN: %clang %s -target arm64-apple-macosx15.1 -isysroot %S/Inputs/MacOSX15.1.sdk -nostdlibinc -c %s -### 2>&1 \
+// RUN: | FileCheck --check-prefix=CHECK-NOSTD -DSDKROOT=%S/Inputs/MacOSX15.1.sdk %s
+//
+// CHECK-NOSTD: "-cc1"
+// CHECK-NOSTD: "-resource-dir" "[[RESOURCE_DIR:[^"]*]]"
+// CHECK-NOSTD-NOT: "-internal-iframework"
diff --git a/clang/test/Driver/darwin-subframeworks.c b/clang/test/Driver/darwin-subframeworks.c
deleted file mode 100644
index 1a7a095c64292..0000000000000
--- a/clang/test/Driver/darwin-subframeworks.c
+++ /dev/null
@@ -1,18 +0,0 @@
-// UNSUPPORTED: system-windows
-//   Windows is unsupported because we use the Unix path separator `\`.
-
-// Add default directories before running clang to check default 
-// search paths. 
-// RUN: rm -rf %t && mkdir -p %t
-// RUN: cp -R %S/Inputs/MacOSX15.1.sdk %t/
-// RUN: mkdir -p %t/MacOSX15.1.sdk/System/Library/Frameworks
-// RUN: mkdir -p %t/MacOSX15.1.sdk/System/Library/SubFrameworks
-// RUN: mkdir -p %t/MacOSX15.1.sdk/usr/include
-
-// RUN: %clang %s -target arm64-apple-darwin13.0 -isysroot %t/MacOSX15.1.sdk -E -v 2>&1 | FileCheck %s
-
-// CHECK:    -isysroot [[PATH:[^ ]*/MacOSX15.1.sdk]]
-// CHECK:    #include <...> search starts here:
-// CHECK:    [[PATH]]/usr/include
-// CHECK:    [[PATH]]/System/Library/Frameworks (framework directory)
-// CHECK:    [[PATH]]/System/Library/SubFrameworks (framework directory)
diff --git a/clang/test/Driver/driverkit-path.c b/clang/test/Driver/driverkit-path.c
index 3caae382d65bb..32f0a6721ab77 100644
--- a/clang/test/Driver/driverkit-path.c
+++ b/clang/test/Driver/driverkit-path.c
@@ -21,13 +21,15 @@ int main() { return 0; }
 // LD64-NEW: "-isysroot" "[[PATH:[^"]*]]Inputs/DriverKit19.0.sdk"
 // LD64-NEW-NOT: "-L[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/usr/lib"
 // LD64-NEW-NOT: "-F[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/Frameworks"
+// LD64-NEW-NOT: "-F[[PATH]]Inputs/DriverKit19.0.sdk/System/DriverKit/System/Library/SubFrameworks"
 
 
-// RUN: %clang %s -target x86_64-apple-driverkit19.0 -isysroot %S/Inputs/DriverKit19.0.sdk -E -v -x c++ 2>&1 | FileCheck %s --check-prefix=INC
+// RUN: %clang %s -target x86_64-apple-driverkit19.0 -isysroot %S/Inputs/DriverKit19.0.sdk -x c++ -### 2>&1 \
+// RUN: | FileCheck %s -DSDKROOT=%S/Inputs/DriverKit19.0.sdk --check-prefix=INC
 //
-// INC:       -isysroot [[PATH:[^ ]*/Inputs/DriverKit19.0.sdk]]
-// INC-LABEL: #include <...> search starts here:
-// INC:       [[PATH]]/System/DriverKit/usr/local/include
-// INC:       /lib{{(64)?}}/clang/{{[^/ ]+}}/include
-// INC:       [[PATH]]/System/DriverKit/usr/include
-// INC:       [[PATH]]/System/DriverKit/System/Library/Frameworks (framework directory)
+// INC: "-isysroot" "[[SDKROOT]]"
+// INC: "-internal-isystem" "[[SDKROOT]]/System/DriverKit/usr/local/include"
+// INC: "-internal-isystem" "{{.+}}/lib{{(64)?}}/clang/{{[^/ ]+}}/include"
+// INC: "-internal-externc-isystem" "[[SDKROOT]]/System/DriverKit/usr/include"
+// INC: "-internal-iframework" "[[SDKROOT]]/System/DriverKit/System/Library/Frameworks"
+// INC: "-internal-iframework" "[[SDKROOT]]/System/DriverKit/System/Library/SubFrameworks"
diff --git a/clang/test/Preprocessor/cuda-macos-includes.cu b/clang/test/Preprocessor/cuda-macos-includes.cu
deleted file mode 100644
index 6ef94b0e45352..0000000000000
--- a/clang/test/Preprocessor/cuda-macos-includes.cu
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: %clang -cc1 -fcuda-is-device -isysroot /var/empty \
-// RUN:   -triple nvptx-nvidia-cuda -aux-triple i386-apple-macosx \
-// RUN:   -E -fcuda-is-device -v -o /dev/null -x cuda %s 2>&1 | FileCheck %s
-
-// RUN: %clang -cc1 -isysroot /var/empty \
-// RUN:   -triple i386-apple-macosx -aux-triple nvptx-nvidia-cuda \
-// RUN:   -E -fcuda-is-device -v -o /dev/null -x cuda %s 2>&1 | FileCheck %s
-
-// Check that when we do CUDA host and device compiles on MacOS, we check for
-// includes in /System/Library/Frameworks and /Library/Frameworks.
-
-// CHECK-DAG: ignoring nonexistent directory "/var/empty/System/Library/Frameworks"
-// CHECK-DAG: ignoring nonexistent directory "/var/empty/Library/Frameworks"
diff --git a/clang/unittests/Frontend/CMakeLists.txt b/clang/unittests/Frontend/CMakeLists.txt
index bbf0396014fa9..0d9fc714212d5 100644
--- a/clang/unittests/Frontend/CMakeLists.txt
+++ b/clang/unittests/Frontend/CMakeLists.txt
@@ -10,6 +10,7 @@ add_clang_unittest(FrontendTests
   PCHPreambleTest.cpp
   ReparseWorkingDirTest.cpp
   OutputStreamTest.cpp
+  SearchPathTest.cpp
   TextDiagnosticTest.cpp
   UtilsTest.cpp
   CLANG_LIBS
diff --git a/clang/unittests/Frontend/SearchPathTest.cpp b/clang/unittests/Frontend/SearchPathTest.cpp
new file mode 100644
index 0000000000000..5d382a4ee20a8
--- /dev/null
+++ b/clang/unittests/Frontend/SearchPathTest.cpp
@@ -0,0 +1,157 @@
+//====-- unittests/Frontend/SearchPathTest.cpp - FrontendAction tests -----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "clang/Basic/DiagnosticOptions.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/HeaderSearchOptions.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include "gtest/gtest.h"
+
+#include <memory>
+#include <optional>
+#include <tuple>
+#include <vector>
+
+namespace clang {
+namespace {
+
+class SearchPathTest : public ::testing::Test {
+protected:
+  SearchPathTest()
+      : Diags(new DiagnosticIDs(), new DiagnosticOptions,
+              new IgnoringDiagConsumer()),
+        VFS(new llvm::vfs::InMemoryFileSystem),
+        FileMgr(FileSystemOptions(), VFS), SourceMgr(Diags, FileMgr),
+        Invocation(std::make_unique<CompilerInvocation>()) {}
+
+  DiagnosticsEngine Diags;
+  IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> VFS;
+  FileManager FileMgr;
+  SourceManager SourceMgr;
+  std::unique_ptr<CompilerInvocation> Invocation;
+
+  void addDirectories(ArrayRef<StringRef> Dirs) {
+    for (StringRef Dir : Dirs) {
+      VFS->addFile(Dir, 0, llvm::MemoryBuffer::getMemBuffer(""),
+                   /*User=*/std::nullopt, /*Group=*/std::nullopt,
+                   llvm::sys::fs::file_type::directory_file);
+    }
+  }
+
+  std::unique_ptr<HeaderSearch>
+  makeHeaderSearchFromCC1Args(llvm::opt::ArgStringList Args) {
+    CompilerInvocation::CreateFromArgs(*Invocation, Args, Diags);
+    HeaderSearchOptions HSOpts = Invocation->getHeaderSearchOpts();
+    LangOptions LangOpts = Invocation->getLangOpts();
+    TargetInfo *Target =
+        TargetInfo::CreateTargetInfo(Diags, Invocation->getTargetOpts());
+    auto HeaderInfo = std::make_unique<HeaderSearch>(HSOpts, SourceMgr, Diags,
+                                                     LangOpts, Target);
+    ApplyHeaderSearchOptions(*HeaderInfo, HSOpts, LangOpts,
+                             Target->getTriple());
+    return HeaderInfo;
+  }
+};
+
+TEST_F(SearchPathTest, SearchPathOrder) {
+  addDirectories({"One", "Two", "Three", "Four", "Five", "Six", "Seven",
+                  "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen",
+                  "Fourteen", "Fifteen", "Sixteen", "Seventeen"});
+  llvm::opt::ArgStringList Args = {
+      // Make sure to use a triple and language that don't automatically add any
+      // search paths.
+      "-triple", "arm64-apple-darwin24.4.0", "-x", "c",
+
+      // clang-format off
+      "-internal-isystem", "One",
+      "-iwithsysroot", "Two",
+      "-c-isystem", "Three",
+      "-IFour",
+      "-idirafter", "Five",
+      "-internal-externc-isystem", "Six",
+      "-iwithprefix", "Seven",
+      "-FEight",
+      "-idirafter", "Nine",
+      "-iframeworkwithsysroot", "Ten",
+      "-internal-iframework", "Eleven",
+      "-iframework", "Twelve",
+      "-iwithprefixbefore", "Thirteen",
+      "-internal-isystem", "Fourteen",
+      "-isystem", "Fifteen",
+      "-ISixteen",
+      "-iwithsysroot", "Seventeen",
+      // clang-format on
+  };
+
+  // The search path arguments get categorized by IncludeDirGroup, but
+  // ultimately are sorted with some groups mixed together and some flags sorted
+  // very specifically within their group. The conceptual groups below don't
+  // exactly correspond to IncludeDirGroup.
+  const std::vector<StringRef> expected = {
+      // User paths: -I and -F mixed together, -iwithprefixbefore.
+      /*-I*/ "Four",
+      /*-F*/ "Eight",
+      /*-I*/ "Sixteen",
+      /*-iwithprefixbefore*/ "Thirteen",
+
+      // System paths: -isystem and -iwithsysroot, -iframework,
+      // -iframeworkwithsysroot, one of {-c-isystem, -cxx-isystem,
+      // -objc-isystem, -objcxx-isystem}
+      /*-iwithsysroot*/ "Two",
+      /*-isystem*/ "Fifteen",
+      /*-iwithsysroot*/ "Seventeen",
+      /*-iframework*/ "Twelve",
+      /*...
[truncated]

@ian-twilightcoder
Copy link
Contributor Author

This is a takeover of #120149 because Louis is out, I'm not a maintainer so I can't push to his fork, and I redid most of it anyway.

Copy link
Collaborator

@cachemeifyoucan cachemeifyoucan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

I would remove the newly added commented /* static */

@ian-twilightcoder
Copy link
Contributor Author

LGTM.

I would remove the newly added commented /* static */

Alright well it's going to bother me that they don't match the other ones, so I'll get rid of them all.

…tend

Move the Darwin framework search path logic from InitHeaderSearch::AddDefaultIncludePaths to DarwinClang::AddClangSystemIncludeArgs. Add a new -internal-iframework cc1 argument to support the tool chain adding these paths.
Now that the tool chain is adding search paths via cc1 flag, they're only added if they exist, so the Preprocessor/cuda-macos-includes.cu test is no longer relevant.
Change Driver/driverkit-path.c and Driver/darwin-subframeworks.c to do -### style testing similar to the darwin-header-search and darwin-embedded-search-paths tests. Rename darwin-subframeworks.c to darwin-framework-search-paths.c and have it test all framework search paths, not just SubFrameworks.
Add a unit test to validate that the myriad of search path flags result in the expected search path list.

Fixes llvm#75638
@ian-twilightcoder ian-twilightcoder force-pushed the darwin-framework-search-paths branch from 6c55939 to ba40d11 Compare May 8, 2025 03:11
@ian-twilightcoder ian-twilightcoder merged commit 515b4a4 into llvm:main May 8, 2025
11 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 8, 2025

LLVM Buildbot has detected a new failure on builder sanitizer-aarch64-linux-bootstrap-hwasan running on sanitizer-buildbot12 while building clang at step 2 "annotate".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/55/builds/11054

Here is the relevant piece of the build log for the reference
Step 2 (annotate) failure: 'python ../sanitizer_buildbot/sanitizers/zorg/buildbot/builders/sanitizers/buildbot_selector.py' (failure)
...
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 87134 tests, 72 workers --
Testing:  0.. 10.. 20
FAIL: Clang-Unit :: ./AllClangUnitTests/67/96 (21674 of 87134)
******************** TEST 'Clang-Unit :: ./AllClangUnitTests/67/96' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/unittests/./AllClangUnitTests-Clang-Unit-2795272-67-96.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=96 GTEST_SHARD_INDEX=67 /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/unittests/./AllClangUnitTests
--


Note: This is test shard 68 of 96.
[==========] Running 255 tests from 61 test suites.
[----------] Global test environment set-up.
[----------] 1 test from HeaderSearchTest
[ RUN      ] HeaderSearchTest.SdkFramework
[       OK ] HeaderSearchTest.SdkFramework (0 ms)
[----------] 1 test from HeaderSearchTest (0 ms total)

[----------] 1 test from ToolChainTest
[ RUN      ] ToolChainTest.DefaultDriverMode
[       OK ] ToolChainTest.DefaultDriverMode (1 ms)
[----------] 1 test from ToolChainTest (1 ms total)

[----------] 1 test from ExprMutationAnalyzerTest
[ RUN      ] ExprMutationAnalyzerTest.TemplateWithArrayToPointerDecay
[       OK ] ExprMutationAnalyzerTest.TemplateWithArrayToPointerDecay (11 ms)
[----------] 1 test from ExprMutationAnalyzerTest (11 ms total)

[----------] 1 test from ArenaTest
[ RUN      ] ArenaTest.GetOrCreateNegationReturnsSameExprOnSubsequentCalls
[       OK ] ArenaTest.GetOrCreateNegationReturnsSameExprOnSubsequentCalls (0 ms)
[----------] 1 test from ArenaTest (0 ms total)

[----------] 3 tests from TransferTest
[ RUN      ] TransferTest.StructVarDecl
[       OK ] TransferTest.StructVarDecl (8 ms)
[ RUN      ] TransferTest.VarDeclInDoWhile
[       OK ] TransferTest.VarDeclInDoWhile (8 ms)
[ RUN      ] TransferTest.LambdaCaptureByCopy
[       OK ] TransferTest.LambdaCaptureByCopy (8 ms)
[----------] 3 tests from TransferTest (25 ms total)
Step 11 (stage2/hwasan check) failure: stage2/hwasan check (failure)
...
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using lld-link: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/lld-link
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using ld64.lld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/ld64.lld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/llvm/config.py:520: note: using wasm-ld: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/bin/wasm-ld
llvm-lit: /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/utils/lit/lit/main.py:72: note: The test suite configuration requested an individual test timeout of 0 seconds but a timeout of 900 seconds was requested on the command line. Forcing timeout to be 900 seconds.
-- Testing: 87134 tests, 72 workers --
Testing:  0.. 10.. 20
FAIL: Clang-Unit :: ./AllClangUnitTests/67/96 (21674 of 87134)
******************** TEST 'Clang-Unit :: ./AllClangUnitTests/67/96' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/unittests/./AllClangUnitTests-Clang-Unit-2795272-67-96.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=96 GTEST_SHARD_INDEX=67 /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/unittests/./AllClangUnitTests
--


Note: This is test shard 68 of 96.
[==========] Running 255 tests from 61 test suites.
[----------] Global test environment set-up.
[----------] 1 test from HeaderSearchTest
[ RUN      ] HeaderSearchTest.SdkFramework
[       OK ] HeaderSearchTest.SdkFramework (0 ms)
[----------] 1 test from HeaderSearchTest (0 ms total)

[----------] 1 test from ToolChainTest
[ RUN      ] ToolChainTest.DefaultDriverMode
[       OK ] ToolChainTest.DefaultDriverMode (1 ms)
[----------] 1 test from ToolChainTest (1 ms total)

[----------] 1 test from ExprMutationAnalyzerTest
[ RUN      ] ExprMutationAnalyzerTest.TemplateWithArrayToPointerDecay
[       OK ] ExprMutationAnalyzerTest.TemplateWithArrayToPointerDecay (11 ms)
[----------] 1 test from ExprMutationAnalyzerTest (11 ms total)

[----------] 1 test from ArenaTest
[ RUN      ] ArenaTest.GetOrCreateNegationReturnsSameExprOnSubsequentCalls
[       OK ] ArenaTest.GetOrCreateNegationReturnsSameExprOnSubsequentCalls (0 ms)
[----------] 1 test from ArenaTest (0 ms total)

[----------] 3 tests from TransferTest
[ RUN      ] TransferTest.StructVarDecl
[       OK ] TransferTest.StructVarDecl (8 ms)
[ RUN      ] TransferTest.VarDeclInDoWhile
[       OK ] TransferTest.VarDeclInDoWhile (8 ms)
[ RUN      ] TransferTest.LambdaCaptureByCopy
[       OK ] TransferTest.LambdaCaptureByCopy (8 ms)
[----------] 3 tests from TransferTest (25 ms total)

@llvm-ci
Copy link
Collaborator

llvm-ci commented May 8, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-x86_64-darwin running on doug-worker-3 while building clang at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/23/builds/10107

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'Clang-Unit :: ./AllClangUnitTests/13/48' FAILED ********************
Script(shard):
--
GTEST_OUTPUT=json:/Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/tools/clang/unittests/./AllClangUnitTests-Clang-Unit-12168-13-48.json GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=48 GTEST_SHARD_INDEX=13 /Volumes/RAMDisk/buildbot-root/x86_64-darwin/build/tools/clang/unittests/./AllClangUnitTests
--

Note: This is test shard 14 of 48.
[==========] Running 510 tests from 106 test suites.
[----------] Global test environment set-up.
[----------] 1 test from MinimizeSourceToDependencyDirectivesTest
[ RUN      ] MinimizeSourceToDependencyDirectivesTest.DefineMultilineArgsCarriageReturn
[       OK ] MinimizeSourceToDependencyDirectivesTest.DefineMultilineArgsCarriageReturn (0 ms)
[----------] 1 test from MinimizeSourceToDependencyDirectivesTest (0 ms total)

[----------] 1 test from HeaderSearchTest
[ RUN      ] HeaderSearchTest.ShortenWithWorkingDir
[       OK ] HeaderSearchTest.ShortenWithWorkingDir (0 ms)
[----------] 1 test from HeaderSearchTest (0 ms total)

[----------] 1 test from ModuleDeclStateTest
[ RUN      ] ModuleDeclStateTest.ModuleNameWithDot
[       OK ] ModuleDeclStateTest.ModuleNameWithDot (1 ms)
[----------] 1 test from ModuleDeclStateTest (1 ms total)

[----------] 1 test from DxcModeTest
[ RUN      ] DxcModeTest.DefaultEntry
warning: argument unused during compilation: '-S'
warning: argument unused during compilation: '-S'
[       OK ] DxcModeTest.DefaultEntry (4 ms)
[----------] 1 test from DxcModeTest (4 ms total)

[----------] 1 test from MultilibTest
[ RUN      ] MultilibTest.SelectMultiple
[       OK ] MultilibTest.SelectMultiple (0 ms)
[----------] 1 test from MultilibTest (0 ms total)

[----------] 2 tests from ExprMutationAnalyzerTest
[ RUN      ] ExprMutationAnalyzerTest.ReturnAsNonConstRef
input.cc:1:26: warning: reference to stack memory associated with local variable 'x' returned [-Wreturn-stack-address]
    1 | int& f() { int x; return x; }
      |                          ^
[       OK ] ExprMutationAnalyzerTest.ReturnAsNonConstRef (9 ms)
[ RUN      ] ExprMutationAnalyzerTest.NotUnevaluatedExpressions
input.cc:1:19: warning: expression result unused [-Wunused-value]
    1 | void f() { int x; sizeof(int[x++]); }
      |                   ^~~~~~~~~~~~~~~~
input.cc:1:126: warning: expression with side effects will be evaluated despite being used as an operand to 'typeid' [-Wpotentially-evaluated-expression]
    1 | namespace std { class type_info; }struct A { virtual ~A(); }; struct B : A {};struct X { A& f(); }; void f() { X x; typeid(x.f()); }
      |                                                                                                                              ^
input.cc:1:117: warning: expression result unused [-Wunused-value]
...

@vitalybuka
Copy link
Collaborator

@ian-twilightcoder
Copy link
Contributor Author

This one is still broken https://lab.llvm.org/buildbot/#/builders/55/builds/11054/steps/11/logs/stdio

I can't figure how this change would affect that, but let me give BuildSyntaxTreeTest a try.

@ian-twilightcoder
Copy link
Contributor Author

That passes for me. I can't even figure out which unit test is failing, they all say OK and not FAILED. The one error in there looks like it's expected since its test still returns OK. Are we totally sure this isn't an infrastructure issue?

@vitalybuka
Copy link
Collaborator

That passes for me. I can't even figure out which unit test is failing, they all say OK and not FAILED. The one error in there looks like it's expected since its test still returns OK. Are we totally sure this isn't an infrastructure issue?

Unlikely.
Process exits with -6 - abort, and "libc++abi: Pure virtual function called!" does not look right

@ian-twilightcoder
Copy link
Contributor Author

I tried GTEST_SHUFFLE=0 GTEST_TOTAL_SHARDS=96 GTEST_SHARD_INDEX=67 ./AllClangUnitTests and that also passes. There's a leak from the new SearchPathTest, maybe that's making the address sanitizer mad?

@vitalybuka
Copy link
Collaborator

=================================================================
==3963603==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 576 byte(s) in 1 object(s) allocated from:
    #0 0xb3001e6d179c in operator new(unsigned long) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/hwasan_new_delete.cpp:64:3
    #1 0xb300271bb420 in make_unique<clang::targets::DarwinAArch64TargetInfo, const llvm::Triple &, const clang::TargetOptions &, 0> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__memory/unique_ptr.h:759:26
    #2 0xb300271bb420 in clang::targets::AllocateTarget(llvm::Triple const&, clang::TargetOptions const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets.cpp
    #3 0xb300271cdc84 in clang::TargetInfo::CreateTargetInfo(clang::DiagnosticsEngine&, clang::TargetOptions&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets.cpp:784:40
    #4 0xb300214df800 in makeHeaderSearchFromCC1Args /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/unittests/Frontend/SearchPathTest.cpp:69:9
    #5 0xb300214df800 in clang::(anonymous namespace)::SearchPathTest_SearchPathOrder_Test::TestBody() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/unittests/Frontend/SearchPathTest.cpp:142:21
    #6 0xb30025b53884 in HandleExceptionsInMethodIfSupported<testing::Test, void> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc
    #7 0xb30025b53884 in testing::Test::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:2687:5
    #8 0xb30025b56bd0 in testing::TestInfo::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:2836:11
    #9 0xb30025b589e4 in testing::TestSuite::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:3015:30
    #10 0xb30025b7c93c in testing::internal::UnitTestImpl::RunAllTests() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:5920:44
    #11 0xb30025b7b310 in HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc
    #12 0xb30025b7b310 in testing::UnitTest::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:5484:10
    #13 0xb30025b2a1e8 in RUN_ALL_TESTS /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:2317:73
    #14 0xb30025b2a1e8 in main /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/UnitTestMain/TestMain.cpp:55:10
    #15 0xe02b3b1884c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 1d7249a4f207d07166ff4be43acdc68a01faaa04)
    #16 0xe02b3b188594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 1d7249a4f207d07166ff4be43acdc68a01faaa04)
    #17 0xb3001e6962ec in _start (/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/unittests/AllClangUnitTests+0x67d62ec)

Indirect leak of 72 byte(s) in 1 object(s) allocated from:
    #0 0xb3001e6d179c in operator new(unsigned long) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/hwasan_new_delete.cpp:64:3
    #1 0xb300271b00e8 in __libcpp_operator_new<unsigned long> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__new/allocate.h:37:10
    #2 0xb300271b00e8 in __libcpp_allocate<char> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__new/allocate.h:64:28
    #3 0xb300271b00e8 in allocate /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__memory/allocator.h:105:14
    #4 0xb300271b00e8 in __allocate_at_least<std::__1::allocator<char> > /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__memory/allocate_at_least.h:41:19
    #5 0xb300271b00e8 in __init /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/string:2545:25
    #6 0xb300271b00e8 in basic_string /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/string:1070:5
    #7 0xb300271b00e8 in str /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/include/llvm/ADT/StringRef.h:232:14
    #8 0xb300271b00e8 in clang::TargetInfo::resetDataLayout(llvm::StringRef, char const*) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/TargetInfo.cpp:194:25
    #9 0xb30027235e7c in clang::targets::AArch64TargetInfo::handleTargetFeatures(std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>>>&, clang::DiagnosticsEngine&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets/AArch64.cpp:1203:3
    #10 0xb300271cf63c in clang::TargetInfo::CreateTargetInfo(clang::DiagnosticsEngine&, clang::TargetOptions&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets.cpp:845:16
    #11 0xb300214df800 in makeHeaderSearchFromCC1Args /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/unittests/Frontend/SearchPathTest.cpp:69:9
    #12 0xb300214df800 in clang::(anonymous namespace)::SearchPathTest_SearchPathOrder_Test::TestBody() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/unittests/Frontend/SearchPathTest.cpp:142:21
    #13 0xb30025b53884 in HandleExceptionsInMethodIfSupported<testing::Test, void> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc
    #14 0xb30025b53884 in testing::Test::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:2687:5
    #15 0xb30025b56bd0 in testing::TestInfo::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:2836:11
    #16 0xb30025b589e4 in testing::TestSuite::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:3015:30
    #17 0xb30025b7c93c in testing::internal::UnitTestImpl::RunAllTests() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:5920:44
    #18 0xb30025b7b310 in HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc
    #19 0xb30025b7b310 in testing::UnitTest::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:5484:10
    #20 0xb30025b2a1e8 in RUN_ALL_TESTS /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:2317:73
    #21 0xb30025b2a1e8 in main /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/UnitTestMain/TestMain.cpp:55:10
    #22 0xe02b3b1884c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 1d7249a4f207d07166ff4be43acdc68a01faaa04)
    #23 0xe02b3b188594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 1d7249a4f207d07166ff4be43acdc68a01faaa04)
    #24 0xb3001e6962ec in _start (/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/unittests/AllClangUnitTests+0x67d62ec)

Indirect leak of 32 byte(s) in 1 object(s) allocated from:
    #0 0xb3001e6d179c in operator new(unsigned long) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/compiler-rt/lib/hwasan/hwasan_new_delete.cpp:64:3
    #1 0xb3001e6d2768 in __libcpp_operator_new<unsigned long> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__new/allocate.h:37:10
    #2 0xb3001e6d2768 in __libcpp_allocate<char> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__new/allocate.h:64:28
    #3 0xb3001e6d2768 in allocate /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__memory/allocator.h:105:14
    #4 0xb3001e6d2768 in __allocate_at_least<std::__1::allocator<char> > /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__memory/allocate_at_least.h:41:19
    #5 0xb3001e6d2768 in std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>::__init_copy_ctor_external(char const*, unsigned long) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/string:2570:25
    #6 0xb300271af148 in basic_string /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/string:997:7
    #7 0xb300271af148 in Triple /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/llvm/include/llvm/TargetParser/Triple.h:44:7
    #8 0xb300271af148 in clang::TargetInfo::TargetInfo(llvm::Triple const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/TargetInfo.cpp:56:49
    #9 0xb300272222f8 in clang::targets::AArch64TargetInfo::AArch64TargetInfo(llvm::Triple const&, clang::TargetOptions const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets/AArch64.cpp:204:7
    #10 0xb3002723a27c in AArch64leTargetInfo /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets/AArch64.cpp:1617:7
    #11 0xb3002723a27c in OSTargetInfo /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets/OSTargets.h:28:9
    #12 0xb3002723a27c in AppleMachOTargetInfo /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets/OSTargets.h:55:9
    #13 0xb3002723a27c in clang::targets::DarwinTargetInfo<clang::targets::AArch64leTargetInfo>::DarwinTargetInfo(llvm::Triple const&, clang::TargetOptions const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets/OSTargets.h:79:9
    #14 0xb30027239fa0 in clang::targets::DarwinAArch64TargetInfo::DarwinAArch64TargetInfo(llvm::Triple const&, clang::TargetOptions const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets/AArch64.cpp:1769:7
    #15 0xb300271bb430 in make_unique<clang::targets::DarwinAArch64TargetInfo, const llvm::Triple &, const clang::TargetOptions &, 0> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/libcxx_install_hwasan/include/c++/v1/__memory/unique_ptr.h:759:30
    #16 0xb300271bb430 in clang::targets::AllocateTarget(llvm::Triple const&, clang::TargetOptions const&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets.cpp
    #17 0xb300271cdc84 in clang::TargetInfo::CreateTargetInfo(clang::DiagnosticsEngine&, clang::TargetOptions&) /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/lib/Basic/Targets.cpp:784:40
    #18 0xb300214df800 in makeHeaderSearchFromCC1Args /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/unittests/Frontend/SearchPathTest.cpp:69:9
    #19 0xb300214df800 in clang::(anonymous namespace)::SearchPathTest_SearchPathOrder_Test::TestBody() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/clang/unittests/Frontend/SearchPathTest.cpp:142:21
    #20 0xb30025b53884 in HandleExceptionsInMethodIfSupported<testing::Test, void> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc
    #21 0xb30025b53884 in testing::Test::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:2687:5
    #22 0xb30025b56bd0 in testing::TestInfo::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:2836:11
    #23 0xb30025b589e4 in testing::TestSuite::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:3015:30
    #24 0xb30025b7c93c in testing::internal::UnitTestImpl::RunAllTests() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:5920:44
    #25 0xb30025b7b310 in HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool> /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc
    #26 0xb30025b7b310 in testing::UnitTest::Run() /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/src/gtest.cc:5484:10
    #27 0xb30025b2a1e8 in RUN_ALL_TESTS /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h:2317:73
    #28 0xb30025b2a1e8 in main /home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm-project/third-party/unittest/UnitTestMain/TestMain.cpp:55:10
    #29 0xe02b3b1884c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 1d7249a4f207d07166ff4be43acdc68a01faaa04)
    #30 0xe02b3b188594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 1d7249a4f207d07166ff4be43acdc68a01faaa04)
    #31 0xb3001e6962ec in _start (/home/b/sanitizer-aarch64-linux-bootstrap-hwasan/build/llvm_build_hwasan/tools/clang/unittests/AllClangUnitTests+0x67d62ec)

SUMMARY: HWAddressSanitizer: 680 byte(s) leaked in 3 allocation(s).

@ian-twilightcoder
Copy link
Contributor Author

Yeah that's the one, #139335. Hopefully that'll take care of the buildbot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Driver][Darwin] Move the remaining bits for header path handling over to the Driver.
6 participants