Skip to content

Commit e47dbad

Browse files
[SYCL] Allow kernel names in anonymous namespace (#3649)
1 parent 3351916 commit e47dbad

File tree

5 files changed

+96
-37
lines changed

5 files changed

+96
-37
lines changed

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3272,9 +3272,6 @@ class SYCLKernelNameTypeVisitor
32723272
* declared within namespace 'std' (at any level)
32733273
e.g., namespace std { namespace literals { class Whatever; } }
32743274
h.single_task<std::literals::Whatever>([]() {});
3275-
* declared within an anonymous namespace (at any level)
3276-
e.g., namespace foo { namespace { class Whatever; } }
3277-
h.single_task<foo::Whatever>([]() {});
32783275
* declared within a function
32793276
e.g., void foo() { struct S { int i; };
32803277
h.single_task<S>([]() {}); }
@@ -3298,7 +3295,7 @@ class SYCLKernelNameTypeVisitor
32983295
if (DeclCtx && !UnnamedLambdaEnabled) {
32993296

33003297
// Check if the kernel name declaration is declared within namespace
3301-
// "std" or "anonymous" namespace (at any level).
3298+
// "std" (at any level).
33023299
while (!DeclCtx->isTranslationUnit() && isa<NamespaceDecl>(DeclCtx)) {
33033300
const auto *NSDecl = cast<NamespaceDecl>(DeclCtx);
33043301
if (NSDecl->isStdNamespace()) {
@@ -3308,14 +3305,6 @@ class SYCLKernelNameTypeVisitor
33083305
IsInvalid = true;
33093306
return;
33103307
}
3311-
if (NSDecl->isAnonymousNamespace()) {
3312-
S.Diag(KernelInvocationFuncLoc,
3313-
diag::err_sycl_kernel_incorrectly_named)
3314-
<< /* kernel name should be globally visible */ 0
3315-
<< KernelNameType;
3316-
IsInvalid = true;
3317-
return;
3318-
}
33193308
DeclCtx = DeclCtx->getParent();
33203309
}
33213310

clang/test/CodeGenSYCL/int_header1.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
// RUN: %clang_cc1 -fsycl-is-device -internal-isystem %S/Inputs -sycl-std=2020 -fsycl-int-header=%t.h %s -o %t.out
22
// RUN: FileCheck -input-file=%t.h %s
33

4+
// Check if forward declarations of kernel names in anonymous namespace are in
5+
// anonymous namespace in the integration header as well.
6+
// CHECK:namespace {
7+
// CHECK-NEXT:class ClassInAnonNS;
8+
// CHECK-NEXT:}
9+
10+
// CHECK:namespace { namespace NestedInAnon {
11+
// CHECK-NEXT:struct StructInAnonymousNS;
12+
// CHECK-NEXT:}}
13+
14+
// CHECK:namespace Named { namespace {
15+
// CHECK-NEXT:struct IsThisValid;
16+
// CHECK-NEXT:}}
17+
418
// CHECK:template <> struct KernelInfo<class KernelName> {
519
// CHECK:template <> struct KernelInfo<::nm1::nm2::KernelName0> {
620
// CHECK:template <> struct KernelInfo<::nm1::KernelName1> {
@@ -9,6 +23,7 @@
923
// CHECK:template <> struct KernelInfo<::nm1::KernelName4<::nm1::nm2::KernelName0>> {
1024
// CHECK:template <> struct KernelInfo<::nm1::KernelName4<::nm1::KernelName1>> {
1125
// CHECK:template <> struct KernelInfo<::nm1::KernelName8<::nm1::nm2::C>> {
26+
// CHECK:template <> struct KernelInfo<::TmplClassInAnonNS<ClassInAnonNS>> {
1227
// CHECK:template <> struct KernelInfo<::nm1::KernelName9<char>> {
1328
// CHECK:template <> struct KernelInfo<::nm1::KernelName3<const volatile ::nm1::KernelName3<const volatile char>>> {
1429

@@ -51,6 +66,18 @@ namespace {
5166
template <typename T> class TmplClassInAnonNS;
5267
}
5368

69+
namespace {
70+
namespace NestedInAnon {
71+
struct StructInAnonymousNS {};
72+
} // namespace NestedInAnon
73+
} // namespace
74+
75+
namespace Named {
76+
namespace {
77+
struct IsThisValid {};
78+
} // namespace
79+
} // namespace Named
80+
5481
struct MyWrapper {
5582
class KN101 {};
5683

@@ -113,6 +140,22 @@ struct MyWrapper {
113140
kernel_single_task<nm1::KernelName8<nm1::nm2::C>>(
114141
[=]() { acc.use(); });
115142

143+
// kernel name type is a templated class, both the top-level class and the
144+
// template argument are declared in the anonymous namespace
145+
kernel_single_task<TmplClassInAnonNS<class ClassInAnonNS>>(
146+
[=]() { acc.use(); });
147+
148+
// kernel name type is a class, declared in the anonymous namespace
149+
kernel_single_task<ClassInAnonNS>(
150+
[=]() { acc.use(); });
151+
152+
// kernel name types declared in nested anonymous namespace
153+
kernel_single_task<NestedInAnon::StructInAnonymousNS>(
154+
[=]() { acc.use(); });
155+
156+
kernel_single_task<Named::IsThisValid>(
157+
[=]() { acc.use(); });
158+
116159
// Kernel name type is a templated specialization class with empty template pack argument
117160
kernel_single_task<nm1::KernelName9<char>>(
118161
[=]() { acc.use(); });

clang/test/CodeGenSYCL/kernelname-enum.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ enum class namespace_short : short {
2525
};
2626
}
2727

28+
namespace {
29+
enum class enum_in_anonNS : short {
30+
val_1,
31+
val_2
32+
};
33+
}
34+
2835
enum class no_type_set {
2936
val_1,
3037
val_2
@@ -48,6 +55,12 @@ class dummy_functor_3 {
4855
void operator()() const {}
4956
};
5057

58+
template <enum_in_anonNS EnumType>
59+
class dummy_functor_4 {
60+
public:
61+
void operator()() const {}
62+
};
63+
5164
template <no_type_set EnumType>
5265
class dummy_functor_5 {
5366
public:
@@ -100,6 +113,7 @@ int main() {
100113
dummy_functor_1<no_namespace_int::val_1> f1;
101114
dummy_functor_2<no_namespace_short::val_2> f2;
102115
dummy_functor_3<internal::namespace_short::val_2> f3;
116+
dummy_functor_4<enum_in_anonNS::val_2> f4;
103117
dummy_functor_5<no_type_set::val_1> f5;
104118
dummy_functor_6<unscoped_enum::val_1> f6;
105119
dummy_functor_7<no_namespace_int> f7;
@@ -120,6 +134,10 @@ int main() {
120134
cgh.single_task(f3);
121135
});
122136

137+
q.submit([&](cl::sycl::handler &cgh) {
138+
cgh.single_task(f4);
139+
});
140+
123141
q.submit([&](cl::sycl::handler &cgh) {
124142
cgh.single_task(f5);
125143
});
@@ -160,6 +178,10 @@ int main() {
160178
// CHECK-NEXT: enum class namespace_short : short;
161179
// CHECK-NEXT: }
162180
// CHECK: template <internal::namespace_short EnumType> class dummy_functor_3;
181+
// CHECK: namespace {
182+
// CHECK-NEXT: enum class enum_in_anonNS : short;
183+
// CHECK-NEXT: }
184+
// CHECK: template <enum_in_anonNS EnumType> class dummy_functor_4;
163185
// CHECK: enum class no_type_set : int;
164186
// CHECK: template <no_type_set EnumType> class dummy_functor_5;
165187
// CHECK: enum unscoped_enum : int;
@@ -178,6 +200,7 @@ int main() {
178200
// CHECK: template <> struct KernelInfo<::dummy_functor_1<static_cast<::no_namespace_int>(0)>>
179201
// CHECK: template <> struct KernelInfo<::dummy_functor_2<static_cast<::no_namespace_short>(1)>>
180202
// CHECK: template <> struct KernelInfo<::dummy_functor_3<static_cast<::internal::namespace_short>(1)>>
203+
// CHECK: template <> struct KernelInfo<::dummy_functor_4<static_cast<::enum_in_anonNS>(1)>>
181204
// CHECK: template <> struct KernelInfo<::dummy_functor_5<static_cast<::no_type_set>(0)>>
182205
// CHECK: template <> struct KernelInfo<::dummy_functor_6<static_cast<::unscoped_enum>(0)>>
183206
// CHECK: template <> struct KernelInfo<::dummy_functor_7<::no_namespace_int>>

clang/test/SemaSYCL/nested-anon-and-std-ns.cpp

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,6 @@ struct NestedStruct {};
1010
}; // namespace NestedInStd
1111
}; // namespace std
1212

13-
namespace {
14-
namespace NestedInAnon {
15-
struct StructInAnonymousNS {};
16-
} // namespace NestedInAnon
17-
} // namespace
18-
19-
namespace Named {
20-
namespace {
21-
struct IsThisValid {};
22-
} // namespace
23-
} // namespace Named
24-
2513
namespace ValidNS {
2614
struct StructinValidNS {};
2715
} // namespace ValidNS
@@ -44,18 +32,6 @@ struct MyWrapper {
4432
h.single_task<std::NestedInStd::NestedStruct>([] {});
4533
});
4634

47-
// expected-error@#KernelSingleTask {{'Named::(anonymous namespace)::IsThisValid' should be globally visible}}
48-
// expected-note@+2{{in instantiation of function template specialization}}
49-
q.submit([&](cl::sycl::handler &h) {
50-
h.single_task<Named::IsThisValid>([] {});
51-
});
52-
53-
// expected-error@#KernelSingleTask {{'(anonymous namespace)::NestedInAnon::StructInAnonymousNS' should be globally visible}}
54-
// expected-note@+2{{in instantiation of function template specialization}}
55-
q.submit([&](cl::sycl::handler &h) {
56-
h.single_task<NestedInAnon::StructInAnonymousNS>([] {});
57-
});
58-
5935
// no error for valid ns
6036
q.submit([&](cl::sycl::handler &h) {
6137
h.single_task<ValidNS::StructinValidNS>([] {});

sycl/test/functor/kernel_functor.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,27 @@
1818
constexpr auto sycl_read_write = cl::sycl::access::mode::read_write;
1919
constexpr auto sycl_global_buffer = cl::sycl::access::target::global_buffer;
2020

21+
// Case 1:
22+
// - functor class is defined in an anonymous namespace
23+
// - the '()' operator:
24+
// * does not have parameters (to be used in 'single_task').
25+
// * has the 'const' qualifier
26+
namespace {
27+
class Functor1 {
28+
public:
29+
Functor1(
30+
int X_,
31+
cl::sycl::accessor<int, 1, sycl_read_write, sycl_global_buffer> &Acc_)
32+
: X(X_), Acc(Acc_) {}
33+
34+
void operator()() const { Acc[0] += X; }
35+
36+
private:
37+
int X;
38+
cl::sycl::accessor<int, 1, sycl_read_write, sycl_global_buffer> Acc;
39+
};
40+
} // namespace
41+
2142
// Case 1:
2243
// - functor class is defined in a namespace
2344
// - the '()' operator:
@@ -83,6 +104,13 @@ int foo(int X) {
83104
cl::sycl::queue Q;
84105
cl::sycl::buffer<int, 1> Buf(A, 1);
85106

107+
Q.submit([&](cl::sycl::handler &cgh) {
108+
auto Acc = Buf.get_access<sycl_read_write, sycl_global_buffer>(cgh);
109+
Functor1 F(X, Acc);
110+
111+
cgh.single_task(F);
112+
});
113+
86114
Q.submit([&](cl::sycl::handler &cgh) {
87115
auto Acc = Buf.get_access<sycl_read_write, sycl_global_buffer>(cgh);
88116
ns::Functor2 F(X, Acc);
@@ -141,7 +169,7 @@ template <typename T> T bar(T X) {
141169
int main() {
142170
const int Res1 = foo(10);
143171
const int Res2 = bar(10);
144-
const int Gold1 = 30;
172+
const int Gold1 = 40;
145173
const int Gold2 = 80;
146174

147175
assert(Res1 == Gold1);

0 commit comments

Comments
 (0)