Skip to content

Commit 6a61f36

Browse files
committed
[SYCL] add clang diagnostic for illegal data types of kernel free function arguments
1 parent 1a26508 commit 6a61f36

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12969,6 +12969,8 @@ def err_free_function_first_occurrence_missing_attr: Error<
1296912969
"the first occurrence of SYCL kernel free function should be declared with 'sycl-nd-range-kernel' or 'sycl-single-task-kernel' compile time properties">;
1297012970
def err_free_function_class_method : Error<
1297112971
"%select{static |}0class method cannot be used to define a SYCL kernel free function kernel">;
12972+
def err_free_function_virtual_arg : Error<
12973+
"argument type %0 of kernel free function can not %select{be virtually derived |have virtual methods}1">;
1297212974

1297312975

1297412976
// SYCL kernel entry point diagnostics

clang/lib/Sema/SemaSYCL.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5849,6 +5849,43 @@ void SemaSYCL::MarkDevices() {
58495849
}
58505850
}
58515851

5852+
static bool hasVirtuals(Sema &S, ParmVarDecl *Param) {
5853+
const clang::CXXRecordDecl *ParamType =
5854+
Param->getType()->getAsCXXRecordDecl();
5855+
if (!ParamType || !ParamType->isThisDeclarationADefinition())
5856+
return false;
5857+
5858+
llvm::SmallVector<const clang::CXXRecordDecl *, 8> WorkList;
5859+
llvm::SmallPtrSet<const clang::CXXRecordDecl *, 8> Visited;
5860+
WorkList.push_back(ParamType);
5861+
5862+
while (!WorkList.empty()) {
5863+
const clang::CXXRecordDecl *Cur = WorkList.pop_back_val();
5864+
if (!Visited.insert(Cur).second)
5865+
continue;
5866+
5867+
// Check for virtual bases
5868+
for (const clang::CXXBaseSpecifier &Base : Cur->bases()) {
5869+
if (Base.isVirtual())
5870+
return S.Diag(Param->getLocation(), diag::err_free_function_virtual_arg)
5871+
<< ParamType->getNameAsString() << 0 << Param->getSourceRange();
5872+
const clang::CXXRecordDecl *BaseDecl =
5873+
Base.getType()->getAsCXXRecordDecl();
5874+
if (BaseDecl && BaseDecl->isThisDeclarationADefinition())
5875+
WorkList.push_back(BaseDecl);
5876+
}
5877+
5878+
// Check for virtual member functions
5879+
for (const auto *Method : Cur->methods()) {
5880+
if (Method->isVirtual()) {
5881+
return S.Diag(Param->getLocation(), diag::err_free_function_virtual_arg)
5882+
<< ParamType->getNameAsString() << 1 << Param->getSourceRange();
5883+
}
5884+
}
5885+
}
5886+
return false;
5887+
}
5888+
58525889
static bool CheckFreeFunctionDiagnostics(Sema &S, FunctionDecl *FD) {
58535890
if (FD->isVariadic()) {
58545891
return S.Diag(FD->getLocation(), diag::err_free_function_variadic_args);
@@ -5871,6 +5908,8 @@ static bool CheckFreeFunctionDiagnostics(Sema &S, FunctionDecl *FD) {
58715908
diag::err_free_function_with_default_arg)
58725909
<< Param->getSourceRange();
58735910
}
5911+
if (hasVirtuals(S, Param))
5912+
return true;
58745913
}
58755914
return false;
58765915
}

clang/test/SemaSYCL/free_function_negative.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,81 @@ static void StaticsingleTaskKernelMethod(int Value) {
118118
}
119119

120120
};
121+
122+
class Base {};
123+
class Derived : virtual public Base {};
124+
125+
// expected-error@+2 {{argument type Derived of kernel free function can not be virtually derived}}
126+
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]]
127+
void VirtualInheritArg(Derived Value) {
128+
}
129+
130+
// expected-error@+2 {{argument type Derived of kernel free function can not be virtually derived}}
131+
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]]
132+
void VirtualInheritArg1(int a, Derived Value, float b, Derived Value1) {
133+
}
134+
135+
class Derived1 : public Derived {
136+
};
137+
138+
// expected-error@+2 {{argument type Derived1 of kernel free function can not be virtually derived}}
139+
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]]
140+
void VirtualInheritArg2(Derived1 Value) {
141+
}
142+
143+
class Base1 {};
144+
class Derived2 : public Base1, public virtual Base {
145+
};
146+
147+
// expected-error@+2 {{argument type Derived2 of kernel free function can not be virtually derived}}
148+
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]]
149+
void VirtualInheritArg3(Derived2 Value) {
150+
}
151+
152+
struct Derived3 : virtual public Base {
153+
};
154+
155+
// expected-error@+2 {{argument type Derived3 of kernel free function can not be virtually derived}}
156+
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]]
157+
void VirtualInheritArg4(Derived3 Value) {
158+
}
159+
160+
class Class {
161+
public:
162+
virtual void virtualMethod() {}
163+
};
164+
165+
// expected-error@+2 {{argument type Class of kernel free function can not have virtual methods}}
166+
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]]
167+
void VirtualMethodArg1(Class Value) {
168+
}
169+
170+
class Class1: public Class {
171+
public:
172+
void NewMethod() {}
173+
};
174+
175+
// expected-error@+2 {{argument type Class1 of kernel free function can not have virtual methods}}
176+
[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]]
177+
void VirtualMethodArg2(Class1 Value) {
178+
}
179+
180+
class Class2: Base1 {
181+
public:
182+
virtual void virtualMethod() {}
183+
};
184+
185+
// expected-error@+2 {{argument type Class2 of kernel free function can not have virtual methods}}
186+
[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]]
187+
void VirtualMethodArg2(Class2 Value) {
188+
}
189+
190+
class Class3 {
191+
public:
192+
virtual ~Class3() {}
193+
};
194+
195+
// expected-error@+2 {{argument type Class3 of kernel free function can not have virtual methods}}
196+
[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]]
197+
void VirtualMethodArg3(Class3 Value) {
198+
}

0 commit comments

Comments
 (0)