Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
38f88ab
Enable clang-cl builds of ONNX Runtime on Windows (core shared lib)
Copilot Jul 10, 2026
32c03ae
Make DirectML EP compile with clang-cl on Windows
Jul 10, 2026
949f100
Fix clang-cl build of ONNX Runtime test targets on Windows
Jul 10, 2026
5d13f56
Patch ONNX 1.22.0 scoped_resource.h for clang-cl compatibility
adrastogi Jul 11, 2026
5c81cd1
Merge remote-tracking branch 'origin/main' into adrastogi/clang-windows
adrastogi Jul 18, 2026
4d6091b
Merge remote-tracking branch 'origin/main' into adrastogi/clang-windows
adrastogi Nov 4, 2026
0b36e55
Reject x86 and ARM64X targets with --use_clang_cl
adrastogi Nov 4, 2026
3466c36
Fix clang-cl MLAS flags for AVX2-VNNI split kernels
adrastogi Nov 5, 2026
4e0ed35
Order override objects first so test targets link with lld-link
adrastogi Nov 5, 2026
c00fe2a
Fix clang-cl MLAS flags for the 2-bit packer and AVX2 dequant kernel
adrastogi Nov 5, 2026
5c28986
Order override sources first in the no-exceptions provider bridge test
adrastogi Nov 5, 2026
f181107
Reject non-x64 hosts for --use_clang_cl
adrastogi Nov 5, 2026
1101a88
Do not enable AVX512-VNNI for the non-VNNI AVX-512 SQNBitGemm kernel …
adrastogi Nov 5, 2026
8334be6
Merge commit '0e21de25ea~1' into adityar-microsoft-clang-windows-pr-u…
adrastogi Nov 5, 2026
502cd71
Merge remote-tracking branch 'origin/main' into adrastogi/clang-windows
adrastogi Nov 5, 2026
4e2ced2
Merge remote-tracking branch 'origin/main' into adityar-microsoft-cla…
adrastogi Nov 6, 2026
00e8cd6
Merge remote-tracking branch 'origin/main' into adityar-microsoft-cla…
adrastogi Nov 12, 2026
d44ba71
Fix clang-cl build after merging main
adrastogi Nov 12, 2026
b1bc93c
Link clang-cl builds with MSVC link.exe
adrastogi Nov 14, 2026
f8970e6
Share MLAS x86-64 C++ ISA source groups across compilers
adrastogi Nov 14, 2026
6b3e01a
Address clang-cl review feedback
adrastogi Nov 14, 2026
23b0384
Merge remote-tracking branch 'origin/main' into adityar-microsoft-cla…
adrastogi Nov 14, 2026
89dc240
Forward ClangCL toolset for ARM targets; relax OneCore test timeout
adrastogi Nov 14, 2026
fee6d85
Add missing standard includes to AbstractOperatorDesc.h
adrastogi Nov 14, 2026
077abe3
Address review feedback on comparison operators, math test and Spectr…
adrastogi Nov 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,21 @@ if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_
endif()

include(detect_onnxruntime_target_platform.cmake)

if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
if(NOT WIN32 OR NOT onnxruntime_target_platform STREQUAL "x64")
message(FATAL_ERROR "Building with clang-cl is supported only for Windows x64 targets "
"(target platform: '${onnxruntime_target_platform}').")
endif()
# The Visual Studio ClangCL toolset defaults to lld-link. Link with MSVC link.exe instead, which binary analysis
# tooling such as BinSkim supports.
if(NOT DEFINED CMAKE_LINKER_TYPE)
if(CMAKE_VERSION VERSION_LESS 3.29)
message(FATAL_ERROR "Building with clang-cl requires CMake 3.29 or newer to select the MSVC linker.")
endif()
set(CMAKE_LINKER_TYPE MSVC)
endif()
endif()
include(onnxruntime_msvc_runtime.cmake)

# OneCore builds link the Windows umbrella libraries (onecoreuap.lib, onecoreuap_apiset.lib) instead of CMake's default
Expand Down
271 changes: 155 additions & 116 deletions cmake/onnxruntime_mlas.cmake

Large diffs are not rendered by default.

45 changes: 42 additions & 3 deletions cmake/onnxruntime_msvc_runtime.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,50 @@ function(onnxruntime_msvc_spectre_enabled flags result_var)
set(${result_var} ${spectre_enabled} PARENT_SCOPE)
endfunction()

# Returns the MSVC tools root (VC/Tools/MSVC/<version>) that provides the MSVC runtime libraries.
function(onnxruntime_get_msvc_tools_root result_var)
if (NOT (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC"))
# CMAKE_C_COMPILER is <MSVC tools root>/bin/Host<arch>/<arch>/cl.exe.
cmake_path(SET msvc_tools_root NORMALIZE "${CMAKE_C_COMPILER}/../../../..")
set(${result_var} "${msvc_tools_root}" PARENT_SCOPE)
return()
endif()

# clang-cl lives under VC/Tools/Llvm, so the runtime cannot be found relative to it. The VS ClangCL toolset links
# the MSVC runtime of the MSVC tools version MSBuild selects: the generator toolset's version= field if given,
# otherwise the instance's default.
if (NOT CMAKE_GENERATOR_INSTANCE)
message(FATAL_ERROR "Linking the OneCore MSVC runtime with clang-cl requires a Visual Studio generator.")
endif()
set(msvc_tools_dir "${CMAKE_GENERATOR_INSTANCE}/VC/Tools/MSVC")
if (CMAKE_VS_PLATFORM_TOOLSET_VERSION)
file(GLOB msvc_tools_versions LIST_DIRECTORIES true RELATIVE "${msvc_tools_dir}"
"${msvc_tools_dir}/${CMAKE_VS_PLATFORM_TOOLSET_VERSION}*")
list(SORT msvc_tools_versions COMPARE NATURAL ORDER DESCENDING)
if (msvc_tools_versions)
list(GET msvc_tools_versions 0 msvc_tools_version)
endif()
else()
set(msvc_tools_version_file "${CMAKE_GENERATOR_INSTANCE}/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt")
if (EXISTS "${msvc_tools_version_file}")
file(STRINGS "${msvc_tools_version_file}" msvc_tools_version LIMIT_COUNT 1)
string(STRIP "${msvc_tools_version}" msvc_tools_version)
endif()
endif()
if (NOT msvc_tools_version OR NOT IS_DIRECTORY "${msvc_tools_dir}/${msvc_tools_version}")
message(FATAL_ERROR "Unable to locate the MSVC tools for clang-cl under ${msvc_tools_dir} "
"(requested version: '${CMAKE_VS_PLATFORM_TOOLSET_VERSION}').")
endif()
set(${result_var} "${msvc_tools_dir}/${msvc_tools_version}" PARENT_SCOPE)
endfunction()

function(onnxruntime_configure_msvc_onecore_runtime)
# GDK builds are skipped because gdk_toolchain.cmake configures the runtime, WINAPI_FAMILY and related flags.
if (onnxruntime_BUILD_FOR_ONECORE AND NOT GDK_PLATFORM AND NOT CMAKE_CROSSCOMPILING)
# OneCore builds must link the OneCore flavor of the MSVC runtime. Its lib directory is prepended to the
# linker search path below so it takes precedence over the desktop runtime libraries found via LIB.
# CMAKE_C_COMPILER is <MSVC tools root>/bin/Host<arch>/<arch>/cl.exe.
cmake_path(SET msvc_lib_root NORMALIZE "${CMAKE_C_COMPILER}/../../../../lib")
onnxruntime_get_msvc_tools_root(msvc_tools_root)
set(msvc_lib_root "${msvc_tools_root}/lib")
set(msvc_onecore_platform "${onnxruntime_target_platform}")
if (msvc_onecore_platform STREQUAL "ARM64EC")
# MSVC ships no ARM64EC runtime directory; ARM64EC uses the ARM64 hybrid CRT libraries.
Expand All @@ -41,7 +78,9 @@ function(onnxruntime_configure_msvc_onecore_runtime)

onnxruntime_msvc_spectre_enabled("${CMAKE_C_FLAGS}" msvc_c_spectre_enabled)
onnxruntime_msvc_spectre_enabled("${CMAKE_CXX_FLAGS}" msvc_cxx_spectre_enabled)
if (msvc_c_spectre_enabled OR msvc_cxx_spectre_enabled)
# onnxruntime_USE_MSVC_SPECTRE_RUNTIME requests the Spectre-mitigated runtime for compilers such as clang-cl
# that do not implement /Qspectre.
if (msvc_c_spectre_enabled OR msvc_cxx_spectre_enabled OR onnxruntime_USE_MSVC_SPECTRE_RUNTIME)
set(msvc_onecore_lib_dir "${msvc_lib_root}/spectre/onecore/${msvc_onecore_platform}")
# Only the release libraries are required: debug CRT libraries are not Spectre-mitigated by design, and
# BinSkim BA2024 skips modules that link them.
Expand Down
2 changes: 1 addition & 1 deletion cmake/onnxruntime_unittests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2231,7 +2231,7 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP)
file(GLOB onnxruntime_perf_test_src CONFIGURE_DEPENDS
${onnxruntime_perf_test_src_patterns}
)
onnxruntime_add_executable(onnxruntime_perf_test ${onnxruntime_perf_test_src} ${ONNXRUNTIME_ROOT}/core/platform/path_lib.cc)
onnxruntime_add_executable(onnxruntime_perf_test ${onnxruntime_perf_test_src})

# ABSL_FLAGS_STRIP_NAMES is set to 1 by default to disable flag registration when building for Android, iPhone, and "embedded devices".
# See the issue: https://github.com/abseil/abseil-cpp/issues/1875
Expand Down
7 changes: 5 additions & 2 deletions include/onnxruntime/core/common/float16.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,11 @@ struct MLFloat16 : onnxruntime_float16::Float16Impl<MLFloat16> {

operator float() const noexcept { return ToFloat(); }

using Base::operator==;
using Base::operator!=;
// Compare on the derived type (as BFloat16 does). With the inherited Float16Impl-typed operator==, C++20's
// reversed candidates make MLFloat16 == MLFloat16 ambiguous, which clang reports as
// -Wambiguous-reversed-operator. operator< is not rewritten in C++20, so the inherited one is unambiguous.
bool operator==(const MLFloat16& rhs) const noexcept { return Base::operator==(rhs); }
bool operator!=(const MLFloat16& rhs) const noexcept { return Base::operator!=(rhs); }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Out of curiosity, why is this true for integrating clang on windows also? Also why not for <?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

[Agentic Response]: Good questions. I reproduced both with main's header.

  • Why clang: C++20 adds reversed candidates for ==, and != is rewritten in terms of ==. MLFloat16 == MLFloat16 therefore matches the inherited Float16Impl::operator==(const Float16Impl&) both normally and reversed, each needing the same derived-to-base conversion. Clang reports this as -Wambiguous-reversed-operator, a warning that becomes an error under warnings-as-errors. cl.exe doesn't diagnose it, and neither does a C++17 build. So this isn't specific to Windows: any clang C++20 build would warn. A comparison operator taking the derived type, the same pattern BFloat16 already uses, gives an exact match and removes the ambiguity.
  • Why not <: relational operators aren't reversed or rewritten in C++20; only ==/!= are, and <=> is synthesized for the others. The inherited operator< has a single candidate, so it isn't ambiguous.

In 077abe3 I corrected the code comment, which wrongly called this an error, and noted why < is unaffected.

using Base::operator<;
};

Expand Down
3 changes: 2 additions & 1 deletion onnxruntime/contrib_ops/cpu/quantization/gguf_vec_dot_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ inline void QuantizeBlockQ8Scalar(const float* x, GgufQ8Block* blk) noexcept {
blk->bsum = bsum;
}

#if (defined(__x86_64__) || defined(_M_X64)) && (defined(__GNUC__) || defined(__clang__))
// clang-cl is excluded: __builtin_cpu_supports needs compiler-rt's __cpu_model, which clang-cl does not link.
#if (defined(__x86_64__) || defined(_M_X64)) && (defined(__GNUC__) || defined(__clang__)) && !defined(_MSC_VER)
#define ORT_GGUF_CPU_HAS_AVX2_TARGET 1
#else
#define ORT_GGUF_CPU_HAS_AVX2_TARGET 0
Expand Down
24 changes: 22 additions & 2 deletions onnxruntime/core/common/spin_pause.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@
namespace onnxruntime {
namespace concurrency {

// TPAUSE is compiled in on x64 Windows and on other x64 targets built with WAITPKG; it is still used only when
// CPUIDInfo::HasTPAUSE() reports support at runtime.
#if (defined(_M_AMD64) || defined(__x86_64__)) && \
Comment thread
adrastogi marked this conversation as resolved.
Resolved
!defined(_M_ARM64EC) && \
!defined(__ANDROID__) && \
!defined(__APPLE__) && \
(defined(_WIN32) || defined(__WAITPKG__))
#define ORT_USE_TPAUSE

// clang (including clang-cl) refuses to emit _tpause from a function not compiled with the 'waitpkg' target
// feature, so isolate it in a non-inlined helper carrying that feature. MSVC does not feature-gate intrinsics.
#if defined(__clang__)
__attribute__((target("waitpkg"), noinline))
#endif
static void
OrtTPause(uint64_t deadline) {
_tpause(0x0, deadline);
}
#endif

// Intrinsic to use in spin-loops
void SpinPause() {
#if (defined(_M_AMD64) || defined(__x86_64__)) && \
Expand All @@ -35,9 +55,9 @@ void SpinPause() {

static const bool has_tpause = CPUIDInfo::GetCPUIDInfo().HasTPAUSE();
if (has_tpause) {
#if (defined(_WIN32) && !defined(__clang__)) || defined(__WAITPKG__)
#if defined(ORT_USE_TPAUSE)
static constexpr uint64_t tpause_spin_delay_cycles = 1000;
_tpause(0x0, __rdtsc() + tpause_spin_delay_cycles);
OrtTPause(__rdtsc() + tpause_spin_delay_cycles);
#else
_mm_pause();
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,69 +3,111 @@

#pragma once

#include <utility>
#include <vector>

class OperatorField;

struct AbstractOperatorDesc
{
const DML_OPERATOR_SCHEMA* schema = nullptr;
std::vector<OperatorField> fields;

AbstractOperatorDesc() = default;
AbstractOperatorDesc(const DML_OPERATOR_SCHEMA* schema, std::vector<OperatorField>&& fields)
: schema(schema)
, fields(std::move(fields))
{}
// NOTE (clang-cl / two-phase name lookup):
// OperatorField and AbstractOperatorDesc are mutually recursive - OperatorField holds a
// std::optional<AbstractOperatorDesc> (see GeneratedSchemaTypes.h) - so OperatorField is
// necessarily an incomplete type at this point. Any member function that instantiates
// std::vector<OperatorField> operations requiring a complete element type - the special
// member functions (which may need to destroy the vector) and the GetTensors iteration -
// must therefore be declared here and defined out of line below, after OperatorField has
// been completed. MSVC's cl.exe defers these instantiations and tolerates inline
// definitions, but conforming two-phase compilers such as clang-cl instantiate them at
// definition time and fail with "incomplete type 'OperatorField'".
AbstractOperatorDesc();
AbstractOperatorDesc(const DML_OPERATOR_SCHEMA* schema, std::vector<OperatorField>&& fields);
AbstractOperatorDesc(const AbstractOperatorDesc&);
AbstractOperatorDesc(AbstractOperatorDesc&&) noexcept;
AbstractOperatorDesc& operator=(const AbstractOperatorDesc&);
AbstractOperatorDesc& operator=(AbstractOperatorDesc&&) noexcept;
~AbstractOperatorDesc();

std::vector<DmlBufferTensorDesc*> GetInputTensors()
{
return GetTensors<DmlBufferTensorDesc, DML_SCHEMA_FIELD_KIND_INPUT_TENSOR>();
}
std::vector<DmlBufferTensorDesc*> GetInputTensors();
std::vector<const DmlBufferTensorDesc*> GetInputTensors() const;
std::vector<DmlBufferTensorDesc*> GetOutputTensors();
std::vector<const DmlBufferTensorDesc*> GetOutputTensors() const;

std::vector<const DmlBufferTensorDesc*> GetInputTensors() const
{
return GetTensors<const DmlBufferTensorDesc, DML_SCHEMA_FIELD_KIND_INPUT_TENSOR>();
}
private:
template <typename TensorType, DML_SCHEMA_FIELD_KIND Kind>
std::vector<TensorType*> GetTensors() const;
};

std::vector<DmlBufferTensorDesc*> GetOutputTensors()
{
return GetTensors<DmlBufferTensorDesc, DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR>();
}
// Complete OperatorField before defining the members that require it. GeneratedSchemaTypes.h is
// guarded by #pragma once, so its subsequent include from precomp.h is a no-op and the
// established include order is preserved.
#include "GeneratedSchemaTypes.h"

std::vector<const DmlBufferTensorDesc*> GetOutputTensors() const
{
return GetTensors<const DmlBufferTensorDesc, DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR>();
}
inline AbstractOperatorDesc::AbstractOperatorDesc() = default;

private:
template <typename TensorType, DML_SCHEMA_FIELD_KIND Kind>
std::vector<TensorType*> GetTensors() const
inline AbstractOperatorDesc::AbstractOperatorDesc(const DML_OPERATOR_SCHEMA* schema, std::vector<OperatorField>&& fields)
: schema(schema)
, fields(std::move(fields))
{
}

inline AbstractOperatorDesc::AbstractOperatorDesc(const AbstractOperatorDesc&) = default;
inline AbstractOperatorDesc::AbstractOperatorDesc(AbstractOperatorDesc&&) noexcept = default;
inline AbstractOperatorDesc& AbstractOperatorDesc::operator=(const AbstractOperatorDesc&) = default;
inline AbstractOperatorDesc& AbstractOperatorDesc::operator=(AbstractOperatorDesc&&) noexcept = default;
inline AbstractOperatorDesc::~AbstractOperatorDesc() = default;

inline std::vector<DmlBufferTensorDesc*> AbstractOperatorDesc::GetInputTensors()
{
return GetTensors<DmlBufferTensorDesc, DML_SCHEMA_FIELD_KIND_INPUT_TENSOR>();
}

inline std::vector<const DmlBufferTensorDesc*> AbstractOperatorDesc::GetInputTensors() const
{
return GetTensors<const DmlBufferTensorDesc, DML_SCHEMA_FIELD_KIND_INPUT_TENSOR>();
}

inline std::vector<DmlBufferTensorDesc*> AbstractOperatorDesc::GetOutputTensors()
{
return GetTensors<DmlBufferTensorDesc, DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR>();
}

inline std::vector<const DmlBufferTensorDesc*> AbstractOperatorDesc::GetOutputTensors() const
{
return GetTensors<const DmlBufferTensorDesc, DML_SCHEMA_FIELD_KIND_OUTPUT_TENSOR>();
}

template <typename TensorType, DML_SCHEMA_FIELD_KIND Kind>
std::vector<TensorType*> AbstractOperatorDesc::GetTensors() const
{
std::vector<TensorType*> tensors;
for (auto& field : fields)
{
std::vector<TensorType*> tensors;
for (auto& field : fields)
const DML_SCHEMA_FIELD* fieldSchema = field.GetSchema();
if (fieldSchema->Kind != Kind)
{
const DML_SCHEMA_FIELD* fieldSchema = field.GetSchema();
if (fieldSchema->Kind != Kind)
{
continue;
}
continue;
}

if (fieldSchema->Type == DML_SCHEMA_FIELD_TYPE_TENSOR_DESC)
{
auto& tensor = field.AsTensorDesc();
tensors.push_back(tensor ? const_cast<TensorType*>(&*tensor) : nullptr);
}
else if (fieldSchema->Type == DML_SCHEMA_FIELD_TYPE_TENSOR_DESC_ARRAY)
if (fieldSchema->Type == DML_SCHEMA_FIELD_TYPE_TENSOR_DESC)
{
auto& tensor = field.AsTensorDesc();
tensors.push_back(tensor ? const_cast<TensorType*>(&*tensor) : nullptr);
}
else if (fieldSchema->Type == DML_SCHEMA_FIELD_TYPE_TENSOR_DESC_ARRAY)
{
auto& tensorArray = field.AsTensorDescArray();
if (tensorArray)
{
auto& tensorArray = field.AsTensorDescArray();
if (tensorArray)
for (auto& tensor : *tensorArray)
{
for (auto& tensor : *tensorArray)
{
tensors.push_back(const_cast<TensorType*>(&tensor));
}
tensors.push_back(const_cast<TensorType*>(&tensor));
}
}
}
return tensors;
}
};
return tensors;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3148,7 +3148,7 @@ namespace Windows::AI::MachineLearning::Adapter

#define CASE_PROTO(X, Y, Z) \
case ONNX_NAMESPACE::TensorProto_DataType::TensorProto_DataType_##X: { \
size_t elementCount = initializer.##Z(); \
size_t elementCount = initializer.Z(); \
tensorByteSize = elementCount * sizeof(Y); \
unpackedTensor.reset(new std::byte[tensorByteSize]); \
ORT_THROW_HR_IF(E_FAIL, !onnxruntime::utils::UnpackTensor( \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ class GpuDFTOperator : public WRL::Base<IMLOperatorKernel>
return dims;
}

template <typename TConstants, uint32_t TSize>
template <typename TConstants, size_t TSize>
void Dispatch(
std::array<ID3D12Resource*, TSize>& resources,
TConstants& constants,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ class DmlGridSampleOperator : public WRL::Base<IMLOperatorKernel>
return dims;
}

template <typename TConstants, uint32_t TSize>
template <typename TConstants, size_t TSize>
void Dispatch(
std::array<ID3D12Resource*, TSize>& resources,
TConstants& constants,
Expand Down
12 changes: 3 additions & 9 deletions onnxruntime/test/providers/cpu/math/element_wise_ops_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4093,13 +4093,7 @@ TEST(MathOpTest, Mean_8) {
test.Run(OpTester::ExpectResult::kExpectSuccess, "", {kTensorrtExecutionProvider}); // TensorRT: Input batch size is inconsistent
}

#ifdef _LIBCPP_VERSION
#define MATH_NO_EXCEPT
#else
#define MATH_NO_EXCEPT noexcept
#endif

template <float (&op)(float value) MATH_NO_EXCEPT>
template <float (&op)(float value)>
void TrigFloatTest(OpTester& test, std::initializer_list<float> input, float abs_error = -1.0f) {
std::vector<int64_t> dims{static_cast<int64_t>(input.size())};

Expand All @@ -4117,7 +4111,7 @@ void TrigFloatTest(OpTester& test, std::initializer_list<float> input, float abs
test.Run();
}

template <double (&op)(double value) MATH_NO_EXCEPT>
template <double (&op)(double value)>
void TrigDoubleTest(OpTester& test, std::initializer_list<double> input,
const std::unordered_set<std::string> excluded_provider_types = {}) {
std::vector<int64_t> dims{static_cast<int64_t>(input.size())};
Expand All @@ -4131,7 +4125,7 @@ void TrigDoubleTest(OpTester& test, std::initializer_list<double> input,
test.Run(OpTester::ExpectResult::kExpectSuccess, "", excluded_provider_types);
}

template <float (&op)(float value) MATH_NO_EXCEPT>
template <float (&op)(float value)>
void TrigFloat16Test(OpTester& test, std::initializer_list<float> input) {
std::vector<int64_t> dims{static_cast<int64_t>(input.size())};

Expand Down
Loading
Loading