Skip to content
7 changes: 7 additions & 0 deletions sycl/include/sycl/functional.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ template <typename T = void> using bit_xor = std::bit_xor<T>;

// std:logical_and/std::logical_or with a non-void type returns bool,
// sycl requires returning T.
#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
template <typename T = void> struct logical_and : std::logical_and<T> {};
template <typename T = void> struct logical_or : std::logical_or<T> {};

#else
template <typename T = void> struct logical_and {
T operator()(const T &lhs, const T &rhs) const { return lhs && rhs; }
};
Expand All @@ -35,6 +40,8 @@ template <typename T = void> struct logical_or {

template <> struct logical_or<void> : std::logical_or<void> {};

#endif

// sycl::minimum definition should be consistent with std::min
template <typename T = void> struct minimum {
T operator()(const T &lhs, const T &rhs) const {
Expand Down
19 changes: 19 additions & 0 deletions sycl/test/basic_tests/logical_operations.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang -fpreview-breaking-changes -fsycl -o - %s
Copy link
Contributor

Choose a reason for hiding this comment

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

@steffenlarsen , do we have a reasonable use-case for a build without preview enabled?

Copy link
Contributor

Choose a reason for hiding this comment

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

Not really, I don't think. Since we can do -fsyntax-only (and maybe -fsycl-host-only?), the compilation should be somewhat cheap, so a benefit of doing both is that we ensure the return type is preserved until preview-promotion. Additionally, it makes the distinction between preview and non-preview behavior clearer.

Copy link
Contributor

Choose a reason for hiding this comment

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

What I meant is that we have this:

with test_env():
sp = subprocess.getstatusoutput(
config.dpcpp_compiler
+ " -fsycl -fpreview-breaking-changes "
+ check_preview_breaking_changes_file
)
if sp[0] == 0:
config.available_features.add("preview-breaking-changes-supported")

We should either guard the entire RUN-line here, or make sure that we always build with preview enabled and it's always supported.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, thank you for clarifying. I think either solution is fine. Doing REQUIRE: preview-breaking-changes-supported would be the cleaner option IMO.

// RUN: %clang -fsycl -o - %s

#include <cassert>
#include <sycl/functional.hpp>
#include <type_traits>

int main() {
const auto logicalAnd = sycl::logical_and<int>();
const auto logicalOr = sycl::logical_or<int>();
#ifdef __INTEL_PREVIEW_BREAKING_CHANGES
static_assert(std::is_same_v<decltype(logicalAnd(1, 2)), bool> == true);
static_assert(std::is_same_v<decltype(logicalOr(1, 2)), bool> == true);
#else
static_assert(std::is_same_v<decltype(logicalAnd(1, 2)), int> == true);
static_assert(std::is_same_v<decltype(logicalOr(1, 2)), int> == true);
#endif
return 0;
}
19 changes: 19 additions & 0 deletions sycl/test/basic_tests/logical_operations_void_types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

// RUN: %clangxx -fsycl -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note %s
// RUN: %clangxx -fsycl -fpreview-breaking-changes -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note %s

#include <cassert>
#include <sycl/functional.hpp>
#include <type_traits>

const auto logicalAndVoid = sycl::logical_and<void>();
const auto logicalOrVoid = sycl::logical_or<void>();

// expected-error@+1 {{}}
static_assert(std::is_same_v<decltype(logicalAndVoid(static_cast<void>(1),
static_cast<void>(2))),
bool> == true);
// expected-error@+1 {{}}
static_assert(std::is_same_v<decltype(logicalOrVoid(static_cast<void>(1),
static_cast<void>(2))),
bool> == true);
Loading