Skip to content

Commit 52add49

Browse files
Added diagnostic to handle unscoped enums with no fixed underlying type.
Also fixed handling of template argument type - enum type. The prior patch handled only enum values, not the type itself. Signed-off-by: Elizabeth Andrews <elizabeth.andrews@intel.com>
1 parent 0a83e16 commit 52add49

File tree

5 files changed

+120
-23
lines changed

5 files changed

+120
-23
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10761,7 +10761,9 @@ def err_builtin_launder_invalid_arg : Error<
1076110761
// SYCL-specific diagnostics
1076210762
def err_sycl_kernel_incorrectly_named : Error<
1076310763
"kernel %select{name is missing"
10764-
"|needs to have a globally-visible name}0">;
10764+
"|needs to have a globally-visible name"
10765+
"|name cannot be templated using unscoped enum without fixed underlying type"
10766+
"}0">;
1076510767
def err_sycl_restrict : Error<
1076610768
"SYCL kernel cannot "
1076710769
"%select{use a non-const global variable"

clang/lib/AST/Decl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,9 +1594,8 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
15941594
Ctx = Ctx->getParent();
15951595
}
15961596

1597-
if (WithGlobalNsPrefix) {
1597+
if (WithGlobalNsPrefix)
15981598
OS << "::";
1599-
}
16001599

16011600
for (const DeclContext *DC : llvm::reverse(Contexts)) {
16021601
if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(DC)) {

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,6 +1637,18 @@ static std::string eraseAnonNamespace(std::string S) {
16371637
return S;
16381638
}
16391639

1640+
static bool checkEnumTemplateParameter(const EnumDecl *ED,
1641+
DiagnosticsEngine &Diag,
1642+
SourceLocation KernelLocation) {
1643+
if (!ED->isScoped() && !ED->isFixed()) {
1644+
Diag.Report(KernelLocation, diag::err_sycl_kernel_incorrectly_named) << 2;
1645+
Diag.Report(ED->getSourceRange().getBegin(), diag::note_entity_declared_at)
1646+
<< ED;
1647+
return false;
1648+
}
1649+
return true;
1650+
}
1651+
16401652
// Emits a forward declaration
16411653
void SYCLIntegrationHeader::emitFwdDecl(raw_ostream &O, const Decl *D,
16421654
SourceLocation KernelLocation) {
@@ -1774,8 +1786,20 @@ void SYCLIntegrationHeader::emitForwardClassDecls(
17741786

17751787
switch (Arg.getKind()) {
17761788
case TemplateArgument::ArgKind::Type:
1777-
emitForwardClassDecls(O, Arg.getAsType(), KernelLocation, Printed);
1789+
case TemplateArgument::ArgKind::Integral: {
1790+
QualType T = (Arg.getKind() == TemplateArgument::ArgKind::Type)
1791+
? Arg.getAsType()
1792+
: Arg.getIntegralType();
1793+
1794+
// Handle Kernel Name Type templated using enum type and value.
1795+
if (const auto *ET = T->getAs<EnumType>()) {
1796+
const EnumDecl *ED = ET->getDecl();
1797+
if (checkEnumTemplateParameter(ED, Diag, KernelLocation))
1798+
emitFwdDecl(O, ED, KernelLocation);
1799+
} else if (Arg.getKind() == TemplateArgument::ArgKind::Type)
1800+
emitForwardClassDecls(O, T, KernelLocation, Printed);
17781801
break;
1802+
}
17791803
case TemplateArgument::ArgKind::Pack: {
17801804
ArrayRef<TemplateArgument> Pack = Arg.getPackAsArray();
17811805

@@ -1808,15 +1832,6 @@ void SYCLIntegrationHeader::emitForwardClassDecls(
18081832
}
18091833
break;
18101834
}
1811-
case TemplateArgument::ArgKind::Integral: {
1812-
// Handle Kernel Name Type templated using enum.
1813-
QualType T = Arg.getIntegralType();
1814-
if (const auto *ET = T->getAs<EnumType>()) {
1815-
const EnumDecl *ED = ET->getDecl();
1816-
emitFwdDecl(O, ED, KernelLocation);
1817-
}
1818-
break;
1819-
}
18201835
default:
18211836
break; // nop
18221837
}

clang/test/CodeGenSYCL/kernelname-enum.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,6 @@ enum unscoped_enum : int {
88
val_2
99
};
1010

11-
enum unscoped_enum_no_type_set {
12-
val_3,
13-
val_4
14-
};
15-
1611
enum class no_namespace_int : int {
1712
val_1,
1813
val_2
@@ -78,7 +73,7 @@ class dummy_functor_6 {
7873
void operator()() {}
7974
};
8075

81-
template <unscoped_enum_no_type_set EnumType>
76+
template <typename EnumType>
8277
class dummy_functor_7 {
8378
public:
8479
void operator()() {}
@@ -92,7 +87,8 @@ int main() {
9287
dummy_functor_4<enum_in_anonNS::val_2> f4;
9388
dummy_functor_5<no_type_set::val_1> f5;
9489
dummy_functor_6<unscoped_enum::val_1> f6;
95-
dummy_functor_7<unscoped_enum_no_type_set::val_4> f7;
90+
dummy_functor_7<no_namespace_int> f7;
91+
dummy_functor_7<internal::namespace_short> f8;
9692

9793
cl::sycl::queue q;
9894

@@ -124,6 +120,10 @@ int main() {
124120
cgh.single_task(f7);
125121
});
126122

123+
q.submit([&](cl::sycl::handler &cgh) {
124+
cgh.single_task(f8);
125+
});
126+
127127
return 0;
128128
}
129129

@@ -144,8 +144,7 @@ int main() {
144144
// CHECK: template <no_type_set EnumType> class dummy_functor_5;
145145
// CHECK: enum unscoped_enum : int;
146146
// CHECK: template <unscoped_enum EnumType> class dummy_functor_6;
147-
// CHECK: enum unscoped_enum_no_type_set : unsigned int;
148-
// CHECK: template <unscoped_enum_no_type_set EnumType> class dummy_functor_7;
147+
// CHECK: template <typename EnumType> class dummy_functor_7;
149148

150149
// CHECK: Specializations of KernelInfo for kernel function types:
151150
// CHECK: template <> struct KernelInfo<::dummy_functor_1<(no_namespace_int)0>>
@@ -154,4 +153,5 @@ int main() {
154153
// CHECK: template <> struct KernelInfo<::dummy_functor_4<(enum_in_anonNS)1>>
155154
// CHECK: template <> struct KernelInfo<::dummy_functor_5<(no_type_set)0>>
156155
// CHECK: template <> struct KernelInfo<::dummy_functor_6<(unscoped_enum)0>>
157-
// CHECK: template <> struct KernelInfo<::dummy_functor_7<(unscoped_enum_no_type_set)1>>
156+
// CHECK: template <> struct KernelInfo<::dummy_functor_7<::no_namespace_int>>
157+
// CHECK: template <> struct KernelInfo<::dummy_functor_7<::internal::namespace_short>>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// RUN: %clang_cc1 -I %S/Inputs -fsycl -fsycl-is-device -fsycl-int-header=%t.h -fsyntax-only -verify %s
2+
3+
//#include <sycl.hpp>
4+
5+
#include "sycl.hpp"
6+
7+
enum unscoped_enum_int : int {
8+
val_1,
9+
val_2
10+
};
11+
12+
// expected-note@+1 {{'unscoped_enum_no_type_set' declared here}}
13+
enum unscoped_enum_no_type_set {
14+
val_3,
15+
val_4
16+
};
17+
18+
enum class scoped_enum_int : int {
19+
val_1,
20+
val_2
21+
};
22+
23+
enum class scoped_enum_no_type_set {
24+
val_3,
25+
val_4
26+
};
27+
28+
template <unscoped_enum_int EnumType>
29+
class dummy_functor_1 {
30+
public:
31+
void operator()() {}
32+
};
33+
34+
// expected-error@+2 {{kernel name cannot be templated using unscoped enum without fixed underlying type}}
35+
template <unscoped_enum_no_type_set EnumType>
36+
class dummy_functor_2 {
37+
public:
38+
void operator()() {}
39+
};
40+
41+
template <scoped_enum_int EnumType>
42+
class dummy_functor_3 {
43+
public:
44+
void operator()() {}
45+
};
46+
47+
template <scoped_enum_no_type_set EnumType>
48+
class dummy_functor_4 {
49+
public:
50+
void operator()() {}
51+
};
52+
53+
int main() {
54+
55+
dummy_functor_1<val_1> f1;
56+
dummy_functor_2<val_3> f2;
57+
dummy_functor_3<scoped_enum_int::val_2> f3;
58+
dummy_functor_4<scoped_enum_no_type_set::val_4> f4;
59+
60+
cl::sycl::queue q;
61+
62+
q.submit([&](cl::sycl::handler &cgh) {
63+
cgh.single_task(f1);
64+
});
65+
66+
q.submit([&](cl::sycl::handler &cgh) {
67+
cgh.single_task(f2);
68+
});
69+
70+
q.submit([&](cl::sycl::handler &cgh) {
71+
cgh.single_task(f3);
72+
});
73+
74+
q.submit([&](cl::sycl::handler &cgh) {
75+
cgh.single_task(f4);
76+
});
77+
78+
79+
return 0;
80+
}
81+

0 commit comments

Comments
 (0)