diff --git a/sycl/include/sycl/ext/oneapi/properties/properties.hpp b/sycl/include/sycl/ext/oneapi/properties/properties.hpp index 93317fb590b59..80a03c0cba289 100644 --- a/sycl/include/sycl/ext/oneapi/properties/properties.hpp +++ b/sycl/include/sycl/ext/oneapi/properties/properties.hpp @@ -95,7 +95,7 @@ struct ExtractProperties> { using ExtractedPropertiesT = std::tuple<>; template - static ExtractedPropertiesT + static constexpr ExtractedPropertiesT Extract(std::tuple) { return {}; } @@ -112,7 +112,7 @@ struct ExtractProperties> { NextExtractedPropertiesT>::type; template - static ExtractedPropertiesT + static constexpr ExtractedPropertiesT Extract(std::tuple PropertyValues) { PropertyT ThisExtractedProperty = std::get(PropertyValues); NextExtractedPropertiesT NextExtractedProperties = @@ -137,7 +137,7 @@ template class properties { public: template - properties(PropertyValueTs... props) + constexpr properties(PropertyValueTs... props) : Storage(detail::ExtractProperties::Extract( std::tuple{props...})) {} diff --git a/sycl/test/extensions/properties/mock_compile_time_properties.hpp b/sycl/test/extensions/properties/mock_compile_time_properties.hpp index 0bc6a3cf21742..581165b62e521 100644 --- a/sycl/test/extensions/properties/mock_compile_time_properties.hpp +++ b/sycl/test/extensions/properties/mock_compile_time_properties.hpp @@ -31,7 +31,7 @@ struct boo_key { }; struct foo { - foo(int v) : value(v) {} + constexpr foo(int v) : value(v) {} int value; }; @@ -41,9 +41,9 @@ inline bool operator==(const foo &lhs, const foo &rhs) { inline bool operator!=(const foo &lhs, const foo &rhs) { return !(lhs == rhs); } struct foz { - foz(float v1, bool v2) : value1(v1), value2(v2) {} + constexpr foz(float v1, bool v2) : value1(v1), value2(v2) {} // Define copy constructor to make foz non-trivially copyable - foz(const foz &f) { + constexpr foz(const foz &f) { value1 = f.value1; value2 = f.value2; } @@ -57,6 +57,7 @@ inline bool operator==(const foz &lhs, const foz &rhs) { inline bool operator!=(const foz &lhs, const foz &rhs) { return !(lhs == rhs); } struct fir { + // Intentionally not constexpr to test for properties that cannot be constexpr fir(float v1, bool v2) : value1(v1), value2(v2) {} // Define copy constructor to make foz non-trivially copyable fir(const foz &f) { diff --git a/sycl/test/extensions/properties/properties_ctor_constexpr.cpp b/sycl/test/extensions/properties/properties_ctor_constexpr.cpp new file mode 100644 index 0000000000000..efc12f79548f1 --- /dev/null +++ b/sycl/test/extensions/properties/properties_ctor_constexpr.cpp @@ -0,0 +1,73 @@ +// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note,warning %s + +#include + +#include "mock_compile_time_properties.hpp" + +int main() { + // Empty properties + constexpr decltype(sycl::ext::oneapi::experimental::properties{}) + EmptyProps1{}; + constexpr auto EmptyProps2 = sycl::ext::oneapi::experimental::properties{}; + + // Compile-time value properties + constexpr decltype(sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::bar, + sycl::ext::oneapi::experimental::baz<1>, + sycl::ext::oneapi::experimental::boo}) CTProps1{ + sycl::ext::oneapi::experimental::bar, + sycl::ext::oneapi::experimental::baz<1>, + sycl::ext::oneapi::experimental::boo}; + constexpr auto CTProps2 = sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::bar, + sycl::ext::oneapi::experimental::baz<1>, + sycl::ext::oneapi::experimental::boo}; + + // Runtime value properties + constexpr decltype(sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::foo(42), + sycl::ext::oneapi::experimental::foz(3.14, false)}) RTProps1{ + sycl::ext::oneapi::experimental::foo(42), + sycl::ext::oneapi::experimental::foz(3.14, false)}; + constexpr auto RTProps2 = sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::foo(42), + sycl::ext::oneapi::experimental::foz(3.14, false)}; + + // Mixed compile-time and runtime value properties + constexpr decltype(sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::bar, + sycl::ext::oneapi::experimental::baz<1>, + sycl::ext::oneapi::experimental::boo, + sycl::ext::oneapi::experimental::foo(42), + sycl::ext::oneapi::experimental::foz(3.14, false)}) MixProps1{ + sycl::ext::oneapi::experimental::bar, + sycl::ext::oneapi::experimental::baz<1>, + sycl::ext::oneapi::experimental::boo, + sycl::ext::oneapi::experimental::foo(42), + sycl::ext::oneapi::experimental::foz(3.14, false)}; + constexpr auto MixProps2 = sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::bar, + sycl::ext::oneapi::experimental::baz<1>, + sycl::ext::oneapi::experimental::boo, + sycl::ext::oneapi::experimental::foo(42), + sycl::ext::oneapi::experimental::foz(3.14, false)}; + + // Runtime value property without constexpr ctors + // expected-error@+2 {{constexpr variable cannot have non-literal type}} + constexpr decltype(sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::fir(3.14, false)}) NCRTProps1{ + sycl::ext::oneapi::experimental::fir(3.14, false)}; + // expected-error@+1 {{constexpr variable cannot have non-literal type}} + constexpr auto NCRTProps2 = sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::fir(3.14, false)}; + int RTIntValue = 1; + // expected-error@+2 {{constexpr variable 'NCRTProps3' must be initialized by a constant expression}} + constexpr decltype(sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::foo(RTIntValue)}) NCRTProps3{ + sycl::ext::oneapi::experimental::foo(RTIntValue)}; + // expected-error@+1 {{constexpr variable 'NCRTProps4' must be initialized by a constant expressio}} + constexpr auto NCRTProps4 = sycl::ext::oneapi::experimental::properties{ + sycl::ext::oneapi::experimental::foo(RTIntValue)}; + + return 0; +}