-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[InstallAPI] Capture & compare load commands that may differ per arch slice #87674
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
Conversation
cyndyishida
commented
Apr 4, 2024
- Capture reexported libraries, allowable clients, rpaths, shared cache eligibility.
- Add support for select Xarch options.
- Add diagnostics related to capturing these options.
- Add support for verifying these attributes against what is encoded in the dylib.B
@llvm/pr-subscribers-clang Author: Cyndy Ishida (cyndyishida) Changes
Patch is 93.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/87674.diff 19 Files Affected:
diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 3d86f7510bde20..fdce4f3f9d9a60 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -663,6 +663,7 @@ def warn_drv_darwin_sdk_invalid_settings : Warning<
"SDK settings were ignored as 'SDKSettings.json' could not be parsed">,
InGroup<DiagGroup<"darwin-sdk-settings">>;
+def err_missing_sysroot : Error<"no such sysroot directory: '%0'">;
def err_drv_darwin_sdk_missing_arclite : Error<
"SDK does not contain 'libarclite' at the path '%0'; try increasing the minimum deployment target">;
diff --git a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
index e3263fe9ccb9d4..0a477da7186b09 100644
--- a/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
+++ b/clang/include/clang/Basic/DiagnosticInstallAPIKinds.td
@@ -19,9 +19,11 @@ def err_no_such_header_file : Error<"no such %select{public|private|project}1 he
def warn_no_such_excluded_header_file : Warning<"no such excluded %select{public|private}0 header file: '%1'">, InGroup<InstallAPIViolation>;
def warn_glob_did_not_match: Warning<"glob '%0' did not match any header file">, InGroup<InstallAPIViolation>;
def err_no_such_umbrella_header_file : Error<"%select{public|private|project}1 umbrella header file not found in input: '%0'">;
+def err_cannot_find_reexport : Error<"cannot find re-exported %select{framework|library}0: '%1'">;
} // end of command line category.
let CategoryName = "Verification" in {
+// Diagnostics about symbols.
def warn_target: Warning<"violations found for %0">, InGroup<InstallAPIViolation>;
def err_library_missing_symbol : Error<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">;
def warn_library_missing_symbol : Warning<"declaration has external linkage, but dynamic library doesn't have symbol '%0'">, InGroup<InstallAPIViolation>;
@@ -43,6 +45,25 @@ def err_dylib_symbol_flags_mismatch : Error<"dynamic library symbol '%0' is "
"%select{weak defined|thread local}1, but its declaration is not">;
def err_header_symbol_flags_mismatch : Error<"declaration '%0' is "
"%select{weak defined|thread local}1, but symbol is not in dynamic library">;
+
+// Diagnostics about load commands.
+def err_architecture_mismatch : Error<"architectures do not match: '%0' (provided) vs '%1' (found)">;
+def warn_platform_mismatch : Warning<"platform does not match: '%0' (provided) vs '%1' (found)">, InGroup<InstallAPIViolation>;
+def err_platform_mismatch : Error<"platform does not match: '%0' (provided) vs '%1' (found)">;
+def err_install_name_mismatch : Error<"install_name does not match: '%0' (provided) vs '%1' (found)">;
+def err_current_version_mismatch : Error<"current_version does not match: '%0' (provided) vs '%1' (found)">;
+def err_compatibility_version_mismatch : Error<"compatibility_version does not match: '%0' (provided) vs '%1' (found)">;
+def err_appextension_safe_mismatch : Error<"ApplicationExtensionSafe flag does not match: '%0' (provided) vs '%1' (found)">;
+def err_shared_cache_eligiblity_mismatch : Error<"NotForDyldSharedCache flag does not match: '%0' (provided) vs '%1' (found)">;
+def err_no_twolevel_namespace : Error<"flat namespace libraries are not supported">;
+def err_parent_umbrella_missing: Error<"parent umbrella missing from %0: '%1'">;
+def err_parent_umbrella_mismatch : Error<"parent umbrella does not match: '%0' (provided) vs '%1' (found)">;
+def err_reexported_libraries_missing : Error<"re-exported library missing from %0: '%1'">;
+def err_reexported_libraries_mismatch : Error<"re-exported libraries do not match: '%0' (provided) vs '%1' (found)">;
+def err_allowable_clients_missing : Error<"allowable client missing from %0: '%1'">;
+def err_allowable_clients_mismatch : Error<"allowable clients do not match: '%0' (provided) vs '%1' (found)">;
+def warn_rpaths_missing : Warning<"runpath search paths missing from %0: '%1'">, InGroup<InstallAPIViolation>;
+def warn_rpaths_mismatch : Warning<"runpath search paths do not match: '%0' (provided) vs '%1' (found)">, InGroup<InstallAPIViolation>;
} // end of Verification category.
} // end of InstallAPI component
diff --git a/clang/include/clang/InstallAPI/Context.h b/clang/include/clang/InstallAPI/Context.h
index 54e517544b8edf..3ad3dc43677db2 100644
--- a/clang/include/clang/InstallAPI/Context.h
+++ b/clang/include/clang/InstallAPI/Context.h
@@ -28,6 +28,9 @@ struct InstallAPIContext {
/// Library attributes that are typically passed as linker inputs.
BinaryAttrs BA;
+ /// Install names of reexported libraries of a library.
+ LibAttrs Reexports;
+
/// All headers that represent a library.
HeaderSeq InputHeaders;
@@ -80,6 +83,20 @@ struct InstallAPIContext {
llvm::DenseMap<StringRef, HeaderType> KnownIncludes;
};
+/// Lookup the dylib or TextAPI file location for a system library or framework.
+/// The search paths provided are searched in order.
+/// @rpath based libraries are not supported.
+///
+/// \param InstallName The install name for the library.
+/// \param FrameworkSearchPaths Search paths to look up frameworks with.
+/// \param LibrarySearchPaths Search paths to look up dylibs with.
+/// \param SearchPaths Fallback search paths if library was not found in earlier
+/// paths.
+/// \return The full path of the library.
+std::string findLibrary(StringRef InstallName, FileManager &FM,
+ ArrayRef<std::string> FrameworkSearchPaths,
+ ArrayRef<std::string> LibrarySearchPaths,
+ ArrayRef<std::string> SearchPaths);
} // namespace installapi
} // namespace clang
diff --git a/clang/include/clang/InstallAPI/DylibVerifier.h b/clang/include/clang/InstallAPI/DylibVerifier.h
index 22cdc234486cf3..4d396341732f78 100644
--- a/clang/include/clang/InstallAPI/DylibVerifier.h
+++ b/clang/include/clang/InstallAPI/DylibVerifier.h
@@ -24,6 +24,9 @@ enum class VerificationMode {
Pedantic,
};
+using LibAttrs = llvm::StringMap<ArchitectureSet>;
+using ReexportedInterfaces = llvm::SmallVector<llvm::MachO::InterfaceFile, 8>;
+
/// Service responsible to tracking state of verification across the
/// lifetime of InstallAPI.
/// As declarations are collected during AST traversal, they are
@@ -63,11 +66,12 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
DylibVerifier() = default;
- DylibVerifier(llvm::MachO::Records &&Dylib, DiagnosticsEngine *Diag,
- VerificationMode Mode, bool Demangle, StringRef DSYMPath)
- : Dylib(std::move(Dylib)), Mode(Mode), Demangle(Demangle),
- DSYMPath(DSYMPath), Exports(std::make_unique<SymbolSet>()),
- Ctx(VerifierContext{Diag}) {}
+ DylibVerifier(llvm::MachO::Records &&Dylib, ReexportedInterfaces &&Reexports,
+ DiagnosticsEngine *Diag, VerificationMode Mode, bool Demangle,
+ StringRef DSYMPath)
+ : Dylib(std::move(Dylib)), Reexports(std::move(Reexports)), Mode(Mode),
+ Demangle(Demangle), DSYMPath(DSYMPath),
+ Exports(std::make_unique<SymbolSet>()), Ctx(VerifierContext{Diag}) {}
Result verify(GlobalRecord *R, const FrontendAttrs *FA);
Result verify(ObjCInterfaceRecord *R, const FrontendAttrs *FA);
@@ -77,6 +81,14 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
// Scan through dylib slices and report any remaining missing exports.
Result verifyRemainingSymbols();
+ /// Compare and report the attributes represented as
+ /// load commands in the dylib to the attributes provided via options.
+ bool verifyBinaryAttrs(const ArrayRef<Target> ProvidedTargets,
+ const BinaryAttrs &ProvidedBA,
+ const LibAttrs &ProvidedReexports,
+ const LibAttrs &ProvidedClients,
+ const LibAttrs &ProvidedRPaths, const FileType &FT);
+
/// Initialize target for verification.
void setTarget(const Target &T);
@@ -154,6 +166,9 @@ class DylibVerifier : llvm::MachO::RecordVisitor {
// Symbols in dylib.
llvm::MachO::Records Dylib;
+ // Reexported interfaces apart of the library.
+ ReexportedInterfaces Reexports;
+
// Controls what class of violations to report.
VerificationMode Mode = VerificationMode::Invalid;
diff --git a/clang/include/clang/InstallAPI/MachO.h b/clang/include/clang/InstallAPI/MachO.h
index 827220dbf39fb8..854399f54ba6c8 100644
--- a/clang/include/clang/InstallAPI/MachO.h
+++ b/clang/include/clang/InstallAPI/MachO.h
@@ -23,6 +23,8 @@
#include "llvm/TextAPI/TextAPIWriter.h"
#include "llvm/TextAPI/Utils.h"
+using Architecture = llvm::MachO::Architecture;
+using ArchitectureSet = llvm::MachO::ArchitectureSet;
using SymbolFlags = llvm::MachO::SymbolFlags;
using RecordLinkage = llvm::MachO::RecordLinkage;
using Record = llvm::MachO::Record;
diff --git a/clang/lib/InstallAPI/CMakeLists.txt b/clang/lib/InstallAPI/CMakeLists.txt
index e0bc8d969ecb3a..b36493942300b6 100644
--- a/clang/lib/InstallAPI/CMakeLists.txt
+++ b/clang/lib/InstallAPI/CMakeLists.txt
@@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
)
add_clang_library(clangInstallAPI
+ DiagnosticBuilderWrappers.cpp
DylibVerifier.cpp
FileList.cpp
Frontend.cpp
diff --git a/clang/lib/InstallAPI/DiagnosticBuilderWrappers.cpp b/clang/lib/InstallAPI/DiagnosticBuilderWrappers.cpp
new file mode 100644
index 00000000000000..9ab221040a56bf
--- /dev/null
+++ b/clang/lib/InstallAPI/DiagnosticBuilderWrappers.cpp
@@ -0,0 +1,111 @@
+//===- DiagnosticBuilderWrappers.cpp ----------------------------*- C++-*-===//
+//
+// 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 "DiagnosticBuilderWrappers.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TextAPI/Platform.h"
+
+using clang::DiagnosticBuilder;
+
+namespace llvm {
+namespace MachO {
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const Architecture &Arch) {
+ DB.AddString(getArchitectureName(Arch));
+ return DB;
+}
+
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const ArchitectureSet &ArchSet) {
+ DB.AddString(std::string(ArchSet));
+ return DB;
+}
+
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const PlatformType &Platform) {
+ DB.AddString(getPlatformName(Platform));
+ return DB;
+}
+
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const PlatformVersionSet &Platforms) {
+ std::string PlatformAsString;
+ raw_string_ostream Stream(PlatformAsString);
+
+ Stream << "[ ";
+ bool NeedsComma = false;
+ for (auto &[Platform, Version] : Platforms) {
+ if (NeedsComma)
+ Stream << ", ";
+ else
+ NeedsComma = true;
+ Stream << getPlatformName(Platform);
+ if (!Version.empty())
+ Stream << Version.getAsString();
+ }
+ Stream << " ]";
+ DB.AddString(Stream.str());
+ return DB;
+}
+
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const FileType &Type) {
+ switch (Type) {
+ case FileType::MachO_Bundle:
+ DB.AddString("mach-o bundle");
+ return DB;
+ case FileType::MachO_DynamicLibrary:
+ DB.AddString("mach-o dynamic library");
+ return DB;
+ case FileType::MachO_DynamicLibrary_Stub:
+ DB.AddString("mach-o dynamic library stub");
+ return DB;
+ case FileType::TBD_V1:
+ DB.AddString("tbd-v1");
+ return DB;
+ case FileType::TBD_V2:
+ DB.AddString("tbd-v2");
+ return DB;
+ case FileType::TBD_V3:
+ DB.AddString("tbd-v3");
+ return DB;
+ case FileType::TBD_V4:
+ DB.AddString("tbd-v4");
+ return DB;
+ case FileType::TBD_V5:
+ DB.AddString("tbd-v5");
+ return DB;
+ case FileType::Invalid:
+ case FileType::All:
+ llvm_unreachable("Unexpected file type for diagnostics.");
+ }
+}
+
+const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+ const PackedVersion &Version) {
+ std::string VersionString;
+ raw_string_ostream OS(VersionString);
+ OS << Version;
+ DB.AddString(OS.str());
+ return DB;
+}
+
+const clang::DiagnosticBuilder &
+operator<<(const clang::DiagnosticBuilder &DB,
+ const StringMapEntry<ArchitectureSet> &LibAttr) {
+ std::string IFAsString;
+ raw_string_ostream OS(IFAsString);
+
+ OS << LibAttr.getKey() << " [ " << LibAttr.getValue() << " ]";
+ DB.AddString(OS.str());
+ return DB;
+}
+
+} // namespace MachO
+} // namespace llvm
diff --git a/clang/lib/InstallAPI/DiagnosticBuilderWrappers.h b/clang/lib/InstallAPI/DiagnosticBuilderWrappers.h
new file mode 100644
index 00000000000000..48cfefbf65e6bc
--- /dev/null
+++ b/clang/lib/InstallAPI/DiagnosticBuilderWrappers.h
@@ -0,0 +1,49 @@
+//===- DiagnosticBuilderWrappers.h -----------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+/// Diagnostic wrappers for TextAPI types for error reporting.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INSTALLAPI_DIAGNOSTICBUILDER_WRAPPER_H
+#define LLVM_CLANG_INSTALLAPI_DIAGNOSTICBUILDER_WRAPPER_H
+
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/TextAPI/Architecture.h"
+#include "llvm/TextAPI/ArchitectureSet.h"
+#include "llvm/TextAPI/InterfaceFile.h"
+#include "llvm/TextAPI/Platform.h"
+
+namespace llvm {
+namespace MachO {
+
+const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
+ const PlatformType &Platform);
+
+const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
+ const PlatformVersionSet &Platforms);
+
+const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
+ const Architecture &Arch);
+
+const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
+ const ArchitectureSet &ArchSet);
+
+const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
+ const FileType &Type);
+
+const clang::DiagnosticBuilder &operator<<(const clang::DiagnosticBuilder &DB,
+ const PackedVersion &Version);
+
+const clang::DiagnosticBuilder &
+operator<<(const clang::DiagnosticBuilder &DB,
+ const StringMapEntry<ArchitectureSet> &LibAttr);
+
+} // namespace MachO
+} // namespace llvm
+#endif // LLVM_CLANG_INSTALLAPI_DIAGNOSTICBUILDER_WRAPPER_H
diff --git a/clang/lib/InstallAPI/DylibVerifier.cpp b/clang/lib/InstallAPI/DylibVerifier.cpp
index c0eda1d81b9b98..a8f6170518feaf 100644
--- a/clang/lib/InstallAPI/DylibVerifier.cpp
+++ b/clang/lib/InstallAPI/DylibVerifier.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/InstallAPI/DylibVerifier.h"
+#include "DiagnosticBuilderWrappers.h"
#include "clang/InstallAPI/FrontendRecords.h"
#include "clang/InstallAPI/InstallAPIDiagnostic.h"
#include "llvm/Demangle/Demangle.h"
@@ -702,5 +703,179 @@ DylibVerifier::Result DylibVerifier::verifyRemainingSymbols() {
return getState();
}
+bool DylibVerifier::verifyBinaryAttrs(const ArrayRef<Target> ProvidedTargets,
+ const BinaryAttrs &ProvidedBA,
+ const LibAttrs &ProvidedReexports,
+ const LibAttrs &ProvidedClients,
+ const LibAttrs &ProvidedRPaths,
+ const FileType &FT) {
+ assert(!Dylib.empty() && "Need dylib to verify.");
+
+ // Pickup any load commands that can differ per slice to compare.
+ TargetList DylibTargets;
+ LibAttrs DylibReexports;
+ LibAttrs DylibClients;
+ LibAttrs DylibRPaths;
+ for (const std::shared_ptr<RecordsSlice> &RS : Dylib) {
+ DylibTargets.push_back(RS->getTarget());
+ const BinaryAttrs &BinInfo = RS->getBinaryAttrs();
+ for (const StringRef LibName : BinInfo.RexportedLibraries)
+ DylibReexports[LibName].set(DylibTargets.back().Arch);
+ for (const StringRef LibName : BinInfo.AllowableClients)
+ DylibClients[LibName].set(DylibTargets.back().Arch);
+ // Compare attributes that are only representable in >= TBD_V5.
+ if (FT >= FileType::TBD_V5)
+ for (const StringRef Name : BinInfo.RPaths)
+ DylibRPaths[Name].set(DylibTargets.back().Arch);
+ }
+
+ // Check targets first.
+ ArchitectureSet ProvidedArchs = mapToArchitectureSet(ProvidedTargets);
+ ArchitectureSet DylibArchs = mapToArchitectureSet(DylibTargets);
+ if (ProvidedArchs != DylibArchs) {
+ Ctx.Diag->Report(diag::err_architecture_mismatch)
+ << ProvidedArchs << DylibArchs;
+ return false;
+ }
+ auto ProvidedPlatforms = mapToPlatformVersionSet(ProvidedTargets);
+ auto DylibPlatforms = mapToPlatformVersionSet(DylibTargets);
+ if (ProvidedPlatforms != DylibPlatforms) {
+ const bool DiffMinOS =
+ mapToPlatformSet(ProvidedTargets) == mapToPlatformSet(DylibTargets);
+ if (DiffMinOS)
+ Ctx.Diag->Report(diag::warn_platform_mismatch)
+ << ProvidedPlatforms << DylibPlatforms;
+ else {
+ Ctx.Diag->Report(diag::err_platform_mismatch)
+ << ProvidedPlatforms << DylibPlatforms;
+ return false;
+ }
+ }
+
+ // Because InstallAPI requires certain attributes to match across architecture
+ // slices, take the first one to compare those with.
+ const BinaryAttrs &DylibBA = (*Dylib.begin())->getBinaryAttrs();
+
+ if (ProvidedBA.InstallName != DylibBA.InstallName) {
+ Ctx.Diag->Report(diag::err_install_name_mismatch)
+ << ProvidedBA.InstallName << DylibBA.InstallName;
+ return false;
+ }
+
+ if (ProvidedBA.CurrentVersion != DylibBA.CurrentVersion) {
+ Ctx.Diag->Report(diag::err_current_version_mismatch)
+ << ProvidedBA.CurrentVersion << DylibBA.CurrentVersion;
+ return false;
+ }
+
+ if (ProvidedBA.CompatVersion != DylibBA.CompatVersion) {
+ Ctx.Diag->Report(diag::err_compatibility_version_mismatch)
+ << ProvidedBA.CompatVersion << DylibBA.CompatVersion;
+ return false;
+ }
+
+ if (ProvidedBA.AppExtensionSafe != DylibBA.AppExtensionSafe) {
+ Ctx.Diag->Report(diag::err_appextension_safe_mismatch)
+ << (ProvidedBA.AppExtensionSafe ? "true" : "false")
+ << (DylibBA.AppExtensionSafe ? "true" : "false");
+ return false;
+ }
+
+ if (!DylibBA.TwoLevelNamespace) {
+ Ctx.Diag->Report(diag::err_no_twolevel_namespace);
+ return false;
+ }
+
+ if (ProvidedBA.OSLibNotForSharedCache != DylibBA.OSLibNotForSharedCache) {
+ Ctx.Diag->Report(diag::err_shared_cache_eligiblity_mismatch)
+ << (ProvidedBA.OSLibNotForSharedCache ? "true" : "false")
+ << (DylibBA.OSLibNotForSharedCache ? "true" : "false");
+ return false;
+ }
+
+ if (ProvidedBA.ParentUmbrella.empty() && !DylibBA.ParentUmbrella.empty()) {
+ Ctx.Diag->Report(diag::err_parent_umbrella_missing)
+ << "installAPI option" << DylibBA.ParentUmbrella;
+ return false;
+ }
+
+ if (!ProvidedBA.ParentUmbrella.empty() && !DylibBA.ParentUmbrella.empty()) {
+ Ctx.Diag->Report(diag::err_parent_umbrella_missing)
+ << "binary file" << ProvidedBA.ParentUmbrella;
+ return false;
+ }
+
+ if ((!ProvidedBA.ParentUmbrella.empty()) &&
+ (ProvidedBA.ParentUmbrella != DylibBA.ParentUmbrella)) {
+ Ctx.Diag->Report(diag::err_parent_umbrella_mismatch)
+ << ProvidedBA.ParentUmbrella << DylibBA.ParentUmbrella;
+ return false;
+ }
+
+ auto CompareLibraries = [&](const LibAttrs &Provided, const LibAttrs &Dylib,
+ unsigned DiagID...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
ba40f8f
to
a7e6758
Compare
slice * Capture reexported libraries, allowable clients, rpaths, shared cache eligiblity. * Add support for select Xarch options. * Add diagnostics related to capturing these options. * Add support for verifying these attributes against what is encoded in the dylib.
52186d6
to
7ef1a80
Compare
Thanks for reviewing @zixu-w ! |
It looks like this is causing failures on the reverse-iteration buildbot (https://lab.llvm.org/buildbot/#/builders/54/builds/9683) |
Thanks for the heads up, should be fixed by #89270 |