Skip to content

Commit 46c54c6

Browse files
committed
[SYCL] Support or diagnose use of namespace std types as kernel type names
When std::nullptr_t is used as a kernel type, the generated integration header uses 'nullptr_t'. This causes lookup errors. Use 'std::nullptr_t' instead. std::max_align_t is defined (in one implementation) as a typedef of an anonymous struct. This causes errors when attempting to forward declare the type in the integration header. Diagnose such cases earlier. Signed-off-by: Premanand M Rao <[email protected]>
1 parent 8445ee8 commit 46c54c6

File tree

3 files changed

+103
-28
lines changed

3 files changed

+103
-28
lines changed

clang/lib/Sema/SemaSYCL.cpp

+22-23
Original file line numberDiff line numberDiff line change
@@ -1649,30 +1649,27 @@ void SYCLIntegrationHeader::emitFwdDecl(raw_ostream &O, const Decl *D,
16491649
auto *NS = dyn_cast_or_null<NamespaceDecl>(DC);
16501650

16511651
if (!NS) {
1652-
if (!DC->isTranslationUnit()) {
1653-
const TagDecl *TD = isa<ClassTemplateDecl>(D)
1654-
? cast<ClassTemplateDecl>(D)->getTemplatedDecl()
1655-
: dyn_cast<TagDecl>(D);
1656-
1657-
if (TD && !UnnamedLambdaSupport) {
1658-
// defined class constituting the kernel name is not globally
1659-
// accessible - contradicts the spec
1660-
const bool KernelNameIsMissing = TD->getName().empty();
1661-
if (KernelNameIsMissing) {
1652+
const TagDecl *TD = isa<ClassTemplateDecl>(D)
1653+
? cast<ClassTemplateDecl>(D)->getTemplatedDecl()
1654+
: dyn_cast<TagDecl>(D);
1655+
if (!TD)
1656+
break;
1657+
1658+
const bool KernelNameIsMissing = TD->getName().empty();
1659+
if (KernelNameIsMissing)
1660+
Diag.Report(KernelLocation, diag::err_sycl_kernel_incorrectly_named)
1661+
<< /* kernel name is missing */ 0;
1662+
else if (!DC->isTranslationUnit()) {
1663+
// defined class constituting the kernel name is not globally
1664+
// accessible - contradicts the spec
1665+
if (!UnnamedLambdaSupport) {
1666+
if (TD->isCompleteDefinition())
16621667
Diag.Report(KernelLocation, diag::err_sycl_kernel_incorrectly_named)
1663-
<< /* kernel name is missing */ 0;
1664-
// Don't emit note if kernel name was completely omitted
1665-
} else {
1666-
if (TD->isCompleteDefinition())
1667-
Diag.Report(KernelLocation,
1668-
diag::err_sycl_kernel_incorrectly_named)
1669-
<< /* kernel name is not globally-visible */ 1;
1670-
else
1671-
Diag.Report(KernelLocation, diag::warn_sycl_implicit_decl);
1672-
Diag.Report(D->getSourceRange().getBegin(),
1673-
diag::note_previous_decl)
1674-
<< TD->getName();
1675-
}
1668+
<< /* kernel name is not globally-visible */ 1;
1669+
else
1670+
Diag.Report(KernelLocation, diag::warn_sycl_implicit_decl);
1671+
Diag.Report(D->getSourceRange().getBegin(), diag::note_previous_decl)
1672+
<< TD->getName();
16761673
}
16771674
}
16781675
break;
@@ -1826,8 +1823,10 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) {
18261823
O << "// This is auto-generated SYCL integration header.\n";
18271824
O << "\n";
18281825

1826+
O << "#include <cstddef>\n";
18291827
O << "#include <CL/sycl/detail/defines.hpp>\n";
18301828
O << "#include <CL/sycl/detail/kernel_desc.hpp>\n";
1829+
O << "using nullptr_t = std::nullptr_t;\n";
18311830

18321831
O << "\n";
18331832

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsycl-int-header=%t.h %s
2+
// RUN: FileCheck -input-file=%t.h %s
3+
//
4+
// CHECK: #include <cstddef>
5+
// CHECK-NEXT: #include <CL/sycl/detail/defines.hpp>
6+
// CHECK-NEXT: #include <CL/sycl/detail/kernel_desc.hpp>
7+
// CHECK-NEXT: using nullptr_t = std::nullptr_t;
8+
//
9+
// CHECK: static constexpr
10+
// CHECK-NEXT: const char* const kernel_names[] = {
11+
// CHECK-NEXT: "_ZTSDn"
12+
// CHECK-NEXT: "_ZTSSt4byte"
13+
// CHECK-NEXT: "_ZTSm",
14+
// CHECK-NEXT: "_ZTSl"
15+
// CHECK-NEXT: };
16+
//
17+
// CHECK: static constexpr
18+
// CHECK-NEXT: const kernel_param_desc_t kernel_signatures[] = {
19+
// CHECK-NEXT: //--- _ZTSDn
20+
// CHECK-EMPTY:
21+
// CHECK-NEXT: //--- _ZTSSt4byte
22+
// CHECK-EMPTY:
23+
// CHECK-NEXT: //--- _ZTSm
24+
// CHECK-EMPTY:
25+
// CHECK-NEXT: //--- _ZTSl
26+
// CHECK-EMPTY:
27+
// CHECK-NEXT: };
28+
//
29+
// CHECK: static constexpr
30+
// CHECK-NEXT: const unsigned kernel_signature_start[] = {
31+
// CHECK-NEXT: 0, // _ZTSDn
32+
// CHECK-NEXT: 1, // _ZTSSt4byte
33+
// CHECK-NEXT: 2, // _ZTSm
34+
// CHECK-NEXT: 3 // _ZTSl
35+
// CHECK-NEXT: };
36+
37+
// CHECK: template <> struct KernelInfo<nullptr_t> {
38+
// CHECK: template <> struct KernelInfo<::std::byte> {
39+
// CHECK: template <> struct KernelInfo<unsigned long> {
40+
// CHECK: template <> struct KernelInfo<long> {
41+
42+
void usage() {
43+
}
44+
45+
namespace std {
46+
typedef long unsigned int size_t;
47+
typedef long int ptrdiff_t;
48+
typedef decltype(nullptr) nullptr_t;
49+
enum class byte : unsigned char {};
50+
} // namespace std
51+
52+
template <typename name, typename Func>
53+
__attribute__((sycl_kernel)) void kernel_single_task(Func kernelFunc) {
54+
kernelFunc();
55+
}
56+
57+
int main() {
58+
kernel_single_task<std::nullptr_t>([]() { usage(); });
59+
kernel_single_task<std::byte>([=]() {});
60+
kernel_single_task<std::size_t>([=]() {});
61+
kernel_single_task<std::ptrdiff_t>([=]() {});
62+
return 0;
63+
}

clang/test/SemaSYCL/unnamed-kernel.cpp

+18-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -fsycl-int-header=%t.h -fsyntax-only -verify %s
22
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -fsycl-int-header=%t.h -fsycl-unnamed-lambda -fsyntax-only -verify %s
3-
#include <sycl.hpp>
43

54
#ifdef __SYCL_UNNAMED_LAMBDA__
65
// expected-no-diagnostics
76
#endif
87

8+
#include <sycl.hpp>
9+
910
namespace namespace1 {
1011
template <typename T>
1112
class KernelName;
1213
}
1314

15+
namespace std {
16+
typedef struct {
17+
} max_align_t;
18+
} // namespace std
19+
1420
struct MyWrapper {
1521
private:
1622
class InvalidKernelName0 {};
@@ -41,15 +47,15 @@ struct MyWrapper {
4147

4248
#ifndef __SYCL_UNNAMED_LAMBDA__
4349
// expected-error@+4 {{kernel needs to have a globally-visible name}}
44-
// expected-note@16 {{InvalidKernelName0 declared here}}
50+
// expected-note@21 {{InvalidKernelName0 declared here}}
4551
#endif
4652
q.submit([&](cl::sycl::handler &h) {
4753
h.single_task<InvalidKernelName0>([] {});
4854
});
4955

5056
#ifndef __SYCL_UNNAMED_LAMBDA__
5157
// expected-error@+4 {{kernel needs to have a globally-visible name}}
52-
// expected-note@17 {{InvalidKernelName3 declared here}}
58+
// expected-note@22 {{InvalidKernelName3 declared here}}
5359
#endif
5460
q.submit([&](cl::sycl::handler &h) {
5561
h.single_task<namespace1::KernelName<InvalidKernelName3>>([] {});
@@ -60,10 +66,17 @@ struct MyWrapper {
6066
h.single_task<ValidAlias>([] {});
6167
});
6268

69+
#ifndef __SYCL_UNNAMED_LAMBDA__
70+
// expected-error@+3 {{kernel name is missing}}
71+
#endif
72+
q.submit([&](cl::sycl::handler &h) {
73+
h.single_task<std::max_align_t>([] {});
74+
});
75+
6376
using InvalidAlias = InvalidKernelName4;
6477
#ifndef __SYCL_UNNAMED_LAMBDA__
6578
// expected-error@+4 {{kernel needs to have a globally-visible name}}
66-
// expected-note@18 {{InvalidKernelName4 declared here}}
79+
// expected-note@23 {{InvalidKernelName4 declared here}}
6780
#endif
6881
q.submit([&](cl::sycl::handler &h) {
6982
h.single_task<InvalidAlias>([] {});
@@ -72,7 +85,7 @@ struct MyWrapper {
7285
using InvalidAlias1 = InvalidKernelName5;
7386
#ifndef __SYCL_UNNAMED_LAMBDA__
7487
// expected-error@+4 {{kernel needs to have a globally-visible name}}
75-
// expected-note@19 {{InvalidKernelName5 declared here}}
88+
// expected-note@24 {{InvalidKernelName5 declared here}}
7689
#endif
7790
q.submit([&](cl::sycl::handler &h) {
7891
h.single_task<namespace1::KernelName<InvalidAlias1>>([] {});

0 commit comments

Comments
 (0)