Skip to content

Commit 0351926

Browse files
author
Brox Chen
authored
[SYCL] Forbid non-trivially-copyable type in annotated_ptr/ref class (#11798)
1. Explicitly state that use non-trivially-copyable type in annotated_ptr and annotated_ref is not supported and error out if annotated_ptr is constructed with non-trivially-copyable type 2. `void` is allowed on annotated_ptr as an exception 3. Use pass-by-value in annotated_ref operator= now, and updated the spec this fix volatile type not supported in the following code ``` void func(const T& a) { ... } volatile T b; func(b); // this will error out ```
1 parent 338b390 commit 0351926

File tree

4 files changed

+70
-6
lines changed

4 files changed

+70
-6
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_annotated_ptr.asciidoc

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,31 @@ information provided as compile-time constant properties through all uses of the
183183
pointer unless noted otherwise.
184184

185185
.Unsupported Usage Example
186+
[source,c++]
187+
----
188+
using sycl::ext::oneapi::experimental;
189+
struct MyType {
190+
MyType(const MyType& otherM) {
191+
...
192+
}
193+
};
194+
195+
struct MyKernel {
196+
annotated_ptr<MyType, properties<PropA>> a; //non-trivially-copyable type is not allowed
197+
annotated_ptr<void, properties<PropB>> b; //void is legal
198+
...
199+
void operator()() const {
200+
...
201+
*b = ...; //deference is not allowed
202+
}
203+
};
204+
----
205+
It is ill-formed to instantiate`annotated_ptr` and `annotated_ref` for a non-trivially-copyable
206+
type `T`. The only exception is that `annotated_ptr` is allowed to be instantiated with `void`.
207+
208+
In the above example, encapsulating `annotated_ptr` within `MyType` is illegal. Encapsulating
209+
`annotated_ptr` with `void` is legal, but it can not be deferenced.
210+
186211
[source,c++]
187212
----
188213
using sycl::ext::oneapi::experimental;
@@ -524,10 +549,10 @@ class annotated_ref {
524549
public:
525550
annotated_ref(const annotated_ref&) = delete;
526551
operator T() const;
527-
T operator=(const T &) const;
552+
T operator=(T) const;
528553
T operator=(const annotated_ref&) const;
529554
// OP is: +=, -=, *=, /=, %=, <<=, >>=, &=, |=, ^=
530-
T operatorOP(const T &) const;
555+
T operatorOP(T) const;
531556
T operator++() const;
532557
T operator++(int) const;
533558
T operator--() const;
@@ -556,7 +581,7 @@ annotations when the object is loaded from memory.
556581
a|
557582
[source,c++]
558583
----
559-
T operator=(const T &) const;
584+
T operator=(T) const;
560585
----
561586
|
562587
Writes an object of type `T` to the location referenced by this wrapper,
@@ -583,7 +608,7 @@ Does not rebind the reference!
583608
a|
584609
[source,c++]
585610
----
586-
T operatorOP(const T &) const;
611+
T operatorOP(T) const;
587612
----
588613
a|
589614
Where [code]#OP# is: [code]#pass:[+=]#, [code]#-=#,[code]#*=#, [code]#/=#, [code]#%=#, [code]#+<<=+#, [code]#>>=#, [code]#&=#, [code]#\|=#, [code]#^=#.

sycl/include/sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace experimental {
3232

3333
namespace {
3434
#define PROPAGATE_OP(op) \
35-
T operator op##=(const T &rhs) const { \
35+
T operator op##=(T rhs) const { \
3636
T t = *this; \
3737
t op## = rhs; \
3838
*this = t; \
@@ -78,6 +78,10 @@ template <typename T, typename... Props>
7878
class annotated_ref<T, detail::properties_t<Props...>> {
7979
using property_list_t = detail::properties_t<Props...>;
8080

81+
static_assert(
82+
std::is_trivially_copyable_v<T>,
83+
"annotated_ref can only encapsulate a trivially-copyable type!");
84+
8185
private:
8286
T *m_Ptr;
8387
annotated_ref(T *Ptr) : m_Ptr(Ptr) {}
@@ -95,7 +99,7 @@ class annotated_ref<T, detail::properties_t<Props...>> {
9599
#endif
96100
}
97101

98-
T operator=(const T &Obj) const {
102+
T operator=(T Obj) const {
99103
#ifdef __SYCL_DEVICE_ONLY__
100104
*__builtin_intel_sycl_ptr_annotation(
101105
m_Ptr, detail::PropertyMetaInfo<Props>::name...,
@@ -178,6 +182,11 @@ class __SYCL_SPECIAL_CLASS
178182
__SYCL_TYPE(annotated_ptr) annotated_ptr<T, detail::properties_t<Props...>> {
179183
using property_list_t = detail::properties_t<Props...>;
180184

185+
static_assert(std::is_same_v<T, void> || std::is_trivially_copyable_v<T>,
186+
"annotated_ptr can only encapsulate either "
187+
"a trivially-copyable type "
188+
"or void!");
189+
181190
// buffer_location and alignment are allowed for annotated_ref
182191
// Cache controls are allowed for annotated_ptr
183192
using allowed_properties =
@@ -249,6 +258,7 @@ __SYCL_TYPE(annotated_ptr) annotated_ptr<T, detail::properties_t<Props...>> {
249258
template <typename... PropertyValueTs>
250259
explicit annotated_ptr(T *Ptr, const PropertyValueTs &...props) noexcept
251260
: m_Ptr(Ptr) {
261+
252262
static constexpr bool has_same_properties = std::is_same<
253263
property_list_t,
254264
detail::merged_properties_t<property_list_t,

sycl/test-e2e/Annotated_arg_ptr/annotated_ptr.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,17 @@ int main() {
2828

2929
auto *d = malloc_shared<int>(4, Q);
3030
auto d_ptr = annotated_ptr{d};
31+
32+
auto *e1 = malloc_shared<int>(1, Q);
33+
*e1 = 0;
34+
volatile int *e1_vol = e1;
35+
auto e1_ptr = annotated_ptr{e1_vol};
36+
37+
auto *e2 = malloc_shared<int>(1, Q);
38+
*e2 = 5;
39+
const volatile int *e2_vol = e2;
40+
auto e2_ptr = annotated_ptr{e2_vol};
41+
3142
for (int i = 0; i < 4; i++)
3243
d_ptr[i] = i;
3344
Q.single_task([=]() {
@@ -60,6 +71,8 @@ int main() {
6071
};
6172

6273
d_ptr[3] = func(d_ptr[0], d_ptr[1], d_ptr[2]);
74+
75+
e1_ptr[0] = e2_ptr[0];
6376
}).wait();
6477

6578
assert(a_ptr[0] == -1 && "a_ptr[0] value does not match.");
@@ -78,11 +91,15 @@ int main() {
7891

7992
assert(d_ptr[3] == -1 && "d_ptr[3] value does not match.");
8093

94+
assert(e1_ptr[0] == 5 && "e_ptr[0] value does not match.");
95+
8196
free(a, Q);
8297
free(b, Q);
8398
free(c->b, Q);
8499
free(c, Q);
85100
free(d, Q);
101+
free(e1, Q);
102+
free(e2, Q);
86103

87104
return 0;
88105
}

sycl/test/extensions/annotated_ptr/annotated_ptr.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,18 @@ void TestVectorAddWithAnnotatedMMHosts() {
157157
std::cout << raw[i] << std::endl;
158158
}
159159

160+
class test {
161+
int n;
162+
163+
public:
164+
test(int n_) : n(n_) {}
165+
test(const test &t) { n = t.n; }
166+
};
167+
// expected-error-re@sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr.hpp:* {{static assertion failed due to requirement {{.+}}: annotated_ptr can only encapsulate either a trivially-copyable type or void!}}
168+
annotated_ptr<test> non_trivially_copyable;
169+
170+
annotated_ptr<void> void_type;
171+
160172
free(raw, q);
161173
}
162174

0 commit comments

Comments
 (0)