Skip to content

Commit e4ca878

Browse files
yug-intelwangdi4
authored andcommitted
[SYCL] Specific error messages for invalid properties on non pointer types (intel#11843)
This change adds specific error messages for invalid properties that are specified on non pointer types. This change is directly in the header annotated_arg.hpp and these checks are done before the `check_property_list` check which previously accounted for this but had a generic error message. This change adds static asserts so that the error message specifies the invalid property and that it is invalid due to a non pointer type for the underlying data type. For example, if the user tries to declare the following variable: ```cpp annotated_arg<int, decltype(properties{buffer_location<0>})> a; ``` The following error message is outputted: ``` error: static assertion failed due to requirement '!has_buffer_location': Property buffer_location cannot be specified for annotated_arg<T> when T is a non pointer type. 288 | static_assert(!has_buffer_location, | ^~~~~~~~~~~~~~~~~~~~ ``` Prior to this change, the following generic error message was printed with multiple notes: ``` /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/oneapi/experimental/common_annotated_properties/properties.hpp:59:17: error: static assertion failed due to requirement 'is_valid_property_for_given_type': Property is invalid for the given type. 59 | static_assert(is_valid_property_for_given_type, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:307:7: note: in instantiation of template class 'sycl::ext::oneapi::experimental::check_property_list<int, sycl::ext::oneapi::experimental::property_value<sycl::ext::intel::experimental::buffer_location_key, std::integral_constant<int, 0>>>' requested here 307 | check_property_list<T, Props...>::value; | ^ /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:308:17: note: in instantiation of static data member 'sycl::ext::oneapi::experimental::annotated_arg<int, sycl::ext::oneapi::experimental::properties<std::tuple<sycl::ext::oneapi::experimental::property_value<sycl::ext::intel::experimental::buffer_location_key, std::integral_constant<int, 0>>>>>::contains_valid_properties' requested here 308 | static_assert(contains_valid_properties, | ^ temp.cpp:15:66: note: in instantiation of template class 'sycl::ext::oneapi::experimental::annotated_arg<int, sycl::ext::oneapi::experimental::properties<std::tuple<sycl::ext::oneapi::experimental::property_value<sycl::ext::intel::experimental::buffer_location_key, std::integral_constant<int, 0>>>>>' requested here 15 | annotated_arg<int, decltype(properties{buffer_location<0>})> a; | ^ ``` ### Alternate Methods PR intel#11748 adds the same checks but in the `fpga_annotated_properties.hpp` file as a separate check. This PR has the checks directly in the `annotated_arg.hpp` header file so that there are fewer notes printed below the error message. Here is a comparison of how the error message is outputted when the checks are in different files: With error checks in properties header file and using a macro (PR intel#11748): ``` /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/intel/experimental/fpga_annotated_properties.hpp:396:3: error: static assertion failed due to requirement '!has_buffer_location': Property buffer_location cannot be specified for annotated_arg<T> when T is a non pointer type. 396 | CHECK_INVALID_PROPERTY(buffer_location, list) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/intel/experimental/fpga_annotated_properties.hpp:389:17: note: expanded from macro 'CHECK_INVALID_PROPERTY' 389 | static_assert(!has_##property, \ | ^~~~~~~~~~~~~~~ /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:202:25: note: in instantiation of template class 'sycl::ext::oneapi::experimental::detail::checkPropertiesForNonPointerType<sycl::ext::oneapi::experimental::property_value<sycl::ext::intel::experimental::buffer_location_key, std::integral_constant<int, 0>>>' requested here 202 | static_assert(detail::checkPropertiesForNonPointerType<Props...>::value); | ^ temp.cpp:15:66: note: in instantiation of template class 'sycl::ext::oneapi::experimental::annotated_arg<int, sycl::ext::oneapi::experimental::properties<std::tuple<sycl::ext::oneapi::experimental::property_value<sycl::ext::intel::experimental::buffer_location_key, std::integral_constant<int, 0>>>>>' requested here 15 | annotated_arg<int, decltype(properties{buffer_location<0>})> a; | ^ ``` With error check in annotated_arg header and using a macro: ``` /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:292:3: error: static assertion failed due to requirement '!has_buffer_location': Property buffer_location cannot be specified for annotated_arg<T> when T is a non pointer type. 292 | CHECK_INVALID_PROPERTY(buffer_location, property_tuple) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:23:17: note: expanded from macro 'CHECK_INVALID_PROPERTY' 23 | static_assert(!has_##property, \ | ^~~~~~~~~~~~~~~ temp.cpp:15:66: note: in instantiation of template class 'sycl::ext::oneapi::experimental::annotated_arg<int, sycl::ext::oneapi::experimental::properties<std::tuple<sycl::ext::oneapi::experimental::property_value<sycl::ext::intel::experimental::buffer_location_key, std::integral_constant<int, 0>>>>>' requested here 15 | annotated_arg<int, decltype(properties{buffer_location<0>})> a; | ^ ``` ### This Change With error check in annotated_arg header and not using a macro (This PR): ``` /p/psg/swip/w/yugteshs/sycl_include/sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:288:17: error: static assertion failed due to requirement '!has_buffer_location': Property buffer_location cannot be specified for annotated_arg<T> when T is a non pointer type. 288 | static_assert(!has_buffer_location, | ^~~~~~~~~~~~~~~~~~~~ temp.cpp:15:66: note: in instantiation of template class 'sycl::ext::oneapi::experimental::annotated_arg<int, sycl::ext::oneapi::experimental::properties<std::tuple<sycl::ext::oneapi::experimental::property_value<sycl::ext::intel::experimental::buffer_location_key, std::integral_constant<int, 0>>>>>' requested here 15 | annotated_arg<int, decltype(properties{buffer_location<0>})> a; | ^ ``` This version only prints one note and therefore it is more clear for the user.
1 parent a4795f4 commit e4ca878

File tree

5 files changed

+170
-74
lines changed

5 files changed

+170
-74
lines changed

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

Lines changed: 105 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <sycl/detail/defines.hpp>
1212
#include <sycl/ext/intel/experimental/fpga_annotated_properties.hpp>
13+
#include <sycl/ext/oneapi/experimental/annotated_ptr/annotated_ptr_properties.hpp>
1314
#include <sycl/ext/oneapi/experimental/common_annotated_properties/properties.hpp>
1415
#include <sycl/ext/oneapi/properties/properties.hpp>
1516

@@ -79,26 +80,6 @@ __SYCL_TYPE(annotated_arg) annotated_arg<T *, detail::properties_t<Props...>> {
7980
#endif
8081

8182
public:
82-
static constexpr bool is_valid_property_list =
83-
is_property_list<property_list_t>::value;
84-
static_assert(is_valid_property_list, "Property list is invalid.");
85-
static constexpr bool contains_valid_properties =
86-
check_property_list<T *, Props...>::value;
87-
static_assert(contains_valid_properties,
88-
"The property list contains invalid property.");
89-
// check the set if FPGA specificed properties are used
90-
static constexpr bool hasValidFPGAProperties =
91-
detail::checkValidFPGAPropertySet<Props...>::value;
92-
static_assert(hasValidFPGAProperties,
93-
"FPGA Interface properties (i.e. awidth, dwidth, etc.)"
94-
"can only be set with BufferLocation together.");
95-
// check if conduit and register_map properties are specified together
96-
static constexpr bool hasConduitAndRegisterMapProperties =
97-
detail::checkHasConduitAndRegisterMap<Props...>::value;
98-
static_assert(hasConduitAndRegisterMapProperties,
99-
"The properties conduit and register_map cannot be "
100-
"specified at the same time.");
101-
10283
annotated_arg() noexcept = default;
10384
annotated_arg(const annotated_arg &) = default;
10485
annotated_arg &operator=(annotated_arg &) = default;
@@ -185,6 +166,34 @@ __SYCL_TYPE(annotated_arg) annotated_arg<T *, detail::properties_t<Props...>> {
185166
template <typename PropertyT> static constexpr auto get_property() {
186167
return property_list_t::template get_property<PropertyT>();
187168
}
169+
170+
// *************************************************************************
171+
// All static error checking is added here instead of placing inside neat
172+
// functions to minimize the number lines printed out when an assert
173+
// is triggered.
174+
// static constexprs are used to ensure that the triggered assert prints
175+
// a message that is very readable. Without these, the assert will
176+
// print out long templated names
177+
// *************************************************************************
178+
static constexpr bool is_valid_property_list =
179+
is_property_list<property_list_t>::value;
180+
static_assert(is_valid_property_list, "Property list is invalid.");
181+
static constexpr bool contains_valid_properties =
182+
check_property_list<T *, Props...>::value;
183+
static_assert(contains_valid_properties,
184+
"The property list contains invalid property.");
185+
// check the set if FPGA specificed properties are used
186+
static constexpr bool hasValidFPGAProperties =
187+
detail::checkValidFPGAPropertySet<Props...>::value;
188+
static_assert(hasValidFPGAProperties,
189+
"FPGA Interface properties (i.e. awidth, dwidth, etc.) "
190+
"can only be set with BufferLocation together.");
191+
// check if conduit and register_map properties are specified together
192+
static constexpr bool hasConduitAndRegisterMapProperties =
193+
detail::checkHasConduitAndRegisterMap<Props...>::value;
194+
static_assert(hasConduitAndRegisterMapProperties,
195+
"The properties conduit and register_map cannot be "
196+
"specified at the same time.");
188197
};
189198

190199
// Partial specialization for non-pointer type
@@ -206,28 +215,6 @@ __SYCL_TYPE(annotated_arg) annotated_arg<T, detail::properties_t<Props...>> {
206215
#endif
207216

208217
public:
209-
static constexpr bool is_device_copyable = is_device_copyable_v<T>;
210-
static_assert(is_device_copyable, "Type T must be device copyable.");
211-
static constexpr bool is_valid_property_list =
212-
is_property_list<property_list_t>::value;
213-
static_assert(is_valid_property_list, "Property list is invalid.");
214-
static constexpr bool contains_valid_properties =
215-
check_property_list<T, Props...>::value;
216-
static_assert(contains_valid_properties,
217-
"The property list contains invalid property.");
218-
// check the set if FPGA specificed properties are used
219-
static constexpr bool hasValidFPGAProperties =
220-
detail::checkValidFPGAPropertySet<Props...>::value;
221-
static_assert(hasValidFPGAProperties,
222-
"FPGA Interface properties (i.e. awidth, dwidth, etc.)"
223-
"can only be set with BufferLocation together.");
224-
// check if conduit and register_map properties are specified together
225-
static constexpr bool hasConduitAndRegisterMapProperties =
226-
detail::checkHasConduitAndRegisterMap<Props...>::value;
227-
static_assert(hasConduitAndRegisterMapProperties,
228-
"The properties conduit and register_map cannot be "
229-
"specified at the same time.");
230-
231218
annotated_arg() noexcept = default;
232219
annotated_arg(const annotated_arg &) = default;
233220
annotated_arg &operator=(annotated_arg &) = default;
@@ -377,6 +364,82 @@ __SYCL_TYPE(annotated_arg) annotated_arg<T, detail::properties_t<Props...>> {
377364
R operator<<(const annotated_arg<T2, PropertyList2> &other) const {
378365
return obj << other.obj;
379366
}
367+
368+
// *************************************************************************
369+
// All static error checking is added here instead of placing inside neat
370+
// functions to minimize the number lines printed out when an assert
371+
// is triggered.
372+
// static constexprs are used to ensure that the triggered assert prints
373+
// a message that is very readable. Without these, the assert will
374+
// print out long templated names
375+
// *************************************************************************
376+
static constexpr bool is_device_copyable = is_device_copyable_v<T>;
377+
static_assert(is_device_copyable, "Type T must be device copyable.");
378+
379+
// check if invalid properties are specified for non pointer type
380+
static constexpr bool has_buffer_location =
381+
has_property<buffer_location_key>();
382+
static_assert(!has_buffer_location,
383+
"Property buffer_location cannot be specified for "
384+
"annotated_arg<T> when T is a non pointer type.");
385+
386+
static constexpr bool has_awidth = has_property<awidth_key>();
387+
static_assert(!has_awidth, "Property awidth cannot be specified for "
388+
"annotated_arg<T> when T is a non pointer type.");
389+
390+
static constexpr bool has_dwidth = has_property<dwidth_key>();
391+
static_assert(!has_dwidth, "Property dwidth cannot be specified for "
392+
"annotated_arg<T> when T is a non pointer type.");
393+
394+
static constexpr bool has_latency = has_property<latency_key>();
395+
static_assert(!has_latency, "Property latency cannot be specified for "
396+
"annotated_arg<T> when T is a non pointer type.");
397+
398+
static constexpr bool has_read_write_mode =
399+
has_property<read_write_mode_key>();
400+
static_assert(!has_read_write_mode,
401+
"Property read_write_mode cannot be specified for "
402+
"annotated_arg<T> when T is a non pointer type.");
403+
404+
static constexpr bool has_maxburst = has_property<maxburst_key>();
405+
static_assert(!has_maxburst,
406+
"Property maxburst cannot be specified for "
407+
"annotated_arg<T> when T is a non pointer type.");
408+
409+
static constexpr bool has_wait_request = has_property<wait_request_key>();
410+
static_assert(!has_wait_request,
411+
"Property wait_request cannot be specified for "
412+
"annotated_arg<T> when T is a non pointer type.");
413+
414+
static constexpr bool has_alignment = has_property<alignment_key>();
415+
static_assert(!has_alignment,
416+
"Property alignment cannot be specified for "
417+
"annotated_arg<T> when T is a non pointer type.");
418+
419+
static constexpr bool has_usm_kind = has_property<usm_kind_key>();
420+
static_assert(!has_usm_kind,
421+
"Property usm_kind cannot be specified for "
422+
"annotated_arg<T> when T is a non pointer type.");
423+
424+
static constexpr bool is_valid_property_list =
425+
is_property_list<property_list_t>::value;
426+
static_assert(is_valid_property_list, "Property list is invalid.");
427+
static constexpr bool contains_valid_properties =
428+
check_property_list<T, Props...>::value;
429+
static_assert(contains_valid_properties,
430+
"The property list contains invalid property.");
431+
// check the set if FPGA specificed properties are used
432+
static constexpr bool hasValidFPGAProperties =
433+
detail::checkValidFPGAPropertySet<Props...>::value;
434+
static_assert(hasValidFPGAProperties,
435+
"FPGA Interface properties (i.e. awidth, dwidth, etc.) "
436+
"can only be set with BufferLocation together.");
437+
// check if conduit and register_map properties are specified together
438+
static constexpr bool hasConduitAndRegisterMapProperties =
439+
detail::checkHasConduitAndRegisterMap<Props...>::value;
440+
static_assert(hasConduitAndRegisterMapProperties,
441+
"The properties conduit and register_map cannot be "
442+
"specified at the same time.");
380443
};
381444

382445
template <typename T, typename PropertyList, typename T2,

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

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -215,26 +215,6 @@ __SYCL_TYPE(annotated_ptr) annotated_ptr<T, detail::properties_t<Props...>> {
215215
#endif
216216

217217
public:
218-
static constexpr bool is_valid_property_list =
219-
is_property_list<property_list_t>::value;
220-
static_assert(is_valid_property_list, "Property list is invalid.");
221-
static constexpr bool contains_valid_properties =
222-
check_property_list<T *, Props...>::value;
223-
static_assert(contains_valid_properties,
224-
"The property list contains invalid property.");
225-
// check the set if FPGA specificed properties are used
226-
static constexpr bool hasValidFPGAProperties =
227-
detail::checkValidFPGAPropertySet<Props...>::value;
228-
static_assert(hasValidFPGAProperties,
229-
"FPGA Interface properties (i.e. awidth, dwidth, etc.)"
230-
"can only be set with BufferLocation together.");
231-
// check if conduit and register_map properties are specified together
232-
static constexpr bool hasConduitAndRegisterMapProperties =
233-
detail::checkHasConduitAndRegisterMap<Props...>::value;
234-
static_assert(hasConduitAndRegisterMapProperties,
235-
"The properties conduit and register_map cannot be "
236-
"specified at the same time.");
237-
238218
annotated_ptr() noexcept = default;
239219
annotated_ptr(const annotated_ptr &) = default;
240220
annotated_ptr &operator=(const annotated_ptr &) = default;
@@ -356,6 +336,34 @@ __SYCL_TYPE(annotated_ptr) annotated_ptr<T, detail::properties_t<Props...>> {
356336
template <typename PropertyT> static constexpr auto get_property() {
357337
return property_list_t::template get_property<PropertyT>();
358338
}
339+
340+
// *************************************************************************
341+
// All static error checking is added here instead of placing inside neat
342+
// functions to minimize the number lines printed out when an assert
343+
// is triggered.
344+
// static constexprs are used to ensure that the triggered assert prints
345+
// a message that is very readable. Without these, the assert will
346+
// print out long templated names
347+
// *************************************************************************
348+
static constexpr bool is_valid_property_list =
349+
is_property_list<property_list_t>::value;
350+
static_assert(is_valid_property_list, "Property list is invalid.");
351+
static constexpr bool contains_valid_properties =
352+
check_property_list<T *, Props...>::value;
353+
static_assert(contains_valid_properties,
354+
"The property list contains invalid property.");
355+
// check the set if FPGA specificed properties are used
356+
static constexpr bool hasValidFPGAProperties =
357+
detail::checkValidFPGAPropertySet<Props...>::value;
358+
static_assert(hasValidFPGAProperties,
359+
"FPGA Interface properties (i.e. awidth, dwidth, etc.) "
360+
"can only be set with BufferLocation together.");
361+
// check if conduit and register_map properties are specified together
362+
static constexpr bool hasConduitAndRegisterMapProperties =
363+
detail::checkHasConduitAndRegisterMap<Props...>::value;
364+
static_assert(hasConduitAndRegisterMapProperties,
365+
"The properties conduit and register_map cannot be "
366+
"specified at the same time.");
359367
};
360368

361369
} // namespace experimental

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#pragma once
1111

12+
#include <sycl/ext/oneapi/experimental/common_annotated_properties/properties.hpp>
1213
#include <sycl/ext/oneapi/properties/properties.hpp> // for properties_t
1314
#include <sycl/usm/usm_enums.hpp>
1415

sycl/test/extensions/annotated_arg/annotated_arg_negative.cpp

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clangxx -fsycl -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note,warning %s
1+
// RUN: %clangxx -fsycl -ferror-limit=0 -fsycl-targets=%sycl_triple -fsyntax-only -Xclang -verify -Xclang -verify-ignore-unexpected=note,warning %s
22

33
#include "sycl/sycl.hpp"
44
#include <sycl/ext/intel/fpga_extensions.hpp>
@@ -17,7 +17,42 @@ void check_conduit_and_register_map_properties() {
1717
annotated_ptr<int, decltype(properties{conduit, register_map})> c;
1818
}
1919

20+
void check_invalid_properties_on_non_pointer_types() {
21+
// check buffer location property specified on non pointer type
22+
// expected-error@sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:* {{Property buffer_location cannot be specified for annotated_arg<T> when T is a non pointer type.}}
23+
annotated_arg<int, decltype(properties{buffer_location<0>})> a;
24+
25+
// check awidth property specified on non pointer type
26+
// expected-error@sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:* {{Property awidth cannot be specified for annotated_arg<T> when T is a non pointer type.}}
27+
annotated_arg<int, decltype(properties{awidth<32>})> b;
28+
29+
// check dwidth property specified on non pointer type
30+
// expected-error@sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:* {{Property dwidth cannot be specified for annotated_arg<T> when T is a non pointer type.}}
31+
annotated_arg<int, decltype(properties{dwidth<32>})> c;
32+
33+
// check latency property specified on non pointer type
34+
// expected-error@sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:* {{Property latency cannot be specified for annotated_arg<T> when T is a non pointer type.}}
35+
annotated_arg<int, decltype(properties{latency<1>})> d;
36+
37+
// check read_write_mode property specified on non pointer type
38+
// expected-error@sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:* {{Property read_write_mode cannot be specified for annotated_arg<T> when T is a non pointer type.}}
39+
annotated_arg<int, decltype(properties{read_write_mode_readwrite})> e;
40+
41+
// check maxburst property specified on non pointer type
42+
// expected-error@sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:* {{Property maxburst cannot be specified for annotated_arg<T> when T is a non pointer type.}}
43+
annotated_arg<int, decltype(properties{maxburst<1>})> f;
44+
45+
// check wait_request property specified on non pointer type
46+
// expected-error@sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:* {{Property wait_request cannot be specified for annotated_arg<T> when T is a non pointer type.}}
47+
annotated_arg<int, decltype(properties{wait_request_requested})> g;
48+
49+
// check alignment property specified on non pointer type
50+
// expected-error@sycl/ext/oneapi/experimental/annotated_arg/annotated_arg.hpp:* {{Property alignment cannot be specified for annotated_arg<T> when T is a non pointer type.}}
51+
annotated_arg<int, decltype(properties{alignment<256>})> h;
52+
}
53+
2054
int main() {
55+
check_invalid_properties_on_non_pointer_types();
2156
check_conduit_and_register_map_properties();
2257
return 0;
2358
}

sycl/test/extensions/annotated_arg/annotated_arg_properties.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,15 +46,6 @@ template <typename T> void checkIsPropertyOf() {
4646
is_property_value_of<decltype(wait_request_requested), T>::value);
4747
}
4848

49-
// Checks is_property_key_of and is_property_value_of are false for non-pointer
50-
// type T.
51-
template <typename T> void checkIsValidPropertyOfNonPtr() {
52-
static_assert(
53-
is_valid_property<T, decltype(wait_request_not_requested)>::value ==
54-
false);
55-
static_assert(is_valid_property<T, decltype(latency<8>)>::value == false);
56-
}
57-
5849
int main() {
5950
static_assert(is_property_key<register_map_key>::value);
6051
static_assert(is_property_key<buffer_location_key>::value);
@@ -90,7 +81,5 @@ int main() {
9081
static_assert(AnnotatedArg4.get_property<read_write_mode_key>() ==
9182
read_write_mode_read);
9283

93-
// Check if a property is valid for a given type
94-
checkIsValidPropertyOfNonPtr<A>();
9584
return 0;
9685
}

0 commit comments

Comments
 (0)