[SYCL] Make sub_group non-user-constructible in preview mode (#23042)
SYCL 2020 section 4.9.1.8 specifies `sycl::sub_group` with a deleted
default
constructor, but the implementation declared it `protected` and
defaulted
instead. That is not equivalent: a constructor that is defaulted on its
first
declaration is not *user-provided*, so in C++17 `sub_group` remained an
aggregate and `sycl::sub_group{}` was a well-formed aggregate
initialization
that bypassed the access check altogether:
```c++
// Compiles today with -std=c++17, which is the default:
auto sg = sycl::sub_group{};
```
This patch deletes the default constructor and adds a `protected` one
taking a
private tag. Being user-provided, it also makes the class a
non-aggregate,
which closes the C++17 loophole. `sub_group` objects are now created
through
that constructor in `nd_item::get_sub_group()` and
`ext::oneapi::this_work_item::get_sub_group()`, both of which are
already
friends.
Applications may rely on the current permissive behavior, so the change
is
guarded by `__INTEL_PREVIEW_BREAKING_CHANGES`.
The deprecated `ext::oneapi::sub_group` also stops initializing its base
through a private default constructor: copy-initializing the base works
in
both modes and needs no guard.
### Testing
New `sycl/test/basic_tests/sub_group_interface.cpp` checks the SYCL 2020
synopsis, the common by-value semantics, and that the class can be
constructed
neither directly nor as an aggregate. It runs in four configurations:
{C++17, C++20} x {default, `-fpreview-breaking-changes`}.
Verified that legitimate ways of obtaining a sub-group still compile in
all
four configurations (`nd_item::get_sub_group()`, the free function
queries,
`khr::this_sub_group()`, copy/assign/compare, implicit conversion to the
deprecated `ext::oneapi::sub_group`, group algorithms), and that
`sycl::sub_group{}` still compiles outside of preview mode.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>