diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 93f67c6a6c46..4594c55382b1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12670,8 +12670,13 @@ def err_registered_kernels_name_already_registered : Error< "free function kernel has already been registered with '%0'; cannot register with '%1'">; def err_not_sycl_free_function : Error< "attempting to register a function that is not a SYCL free function as '%0'">; -def err_free_function_variadic_args: Error< +def err_free_function_with_default_arg : Error< + "a function with a default argument value cannot be used to define SYCL free function kernel">; +def err_free_function_variadic_args : Error< "free function kernel cannot be a variadic function">; +def err_free_function_return_type : Error< + "SYCL free function kernel should have return type 'void'">; + // SYCL kernel entry point diagnostics def err_sycl_entry_point_invalid : Error< diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 8264529e4952..ab0864aaf41f 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -1159,8 +1159,6 @@ static target getAccessTarget(QualType FieldTy, AccTy->getTemplateArgs()[3].getAsIntegral().getExtValue()); } -// FIXME: Free functions must have void return type and be declared at file -// scope, outside any namespaces. bool SemaSYCL::isFreeFunction(const FunctionDecl *FD) { for (auto *IRAttr : FD->specific_attrs()) { SmallVector, 4> NameValuePairs = @@ -1168,12 +1166,6 @@ bool SemaSYCL::isFreeFunction(const FunctionDecl *FD) { for (const auto &NameValuePair : NameValuePairs) { if (NameValuePair.first == "sycl-nd-range-kernel" || NameValuePair.first == "sycl-single-task-kernel") { - if (!FD->getReturnType()->isVoidType()) { - llvm::report_fatal_error( - "Only functions at file scope with void return " - "type are permitted as free functions"); - return false; - } return true; } } @@ -5791,12 +5783,29 @@ void SemaSYCL::MarkDevices() { } } +static bool CheckFreeFunctionDiagnostics(Sema &S, FunctionDecl *FD) { + if (FD->isVariadic()) { + return S.Diag(FD->getLocation(), diag::err_free_function_variadic_args); + } + + if (!FD->getReturnType()->isVoidType()) { + return S.Diag(FD->getLocation(), diag::err_free_function_return_type); + } + + for (ParmVarDecl *Param : FD->parameters()) { + if (Param->hasDefaultArg()) { + return S.Diag(Param->getLocation(), + diag::err_free_function_with_default_arg) + << Param->getSourceRange(); + } + } + return false; +} + void SemaSYCL::ProcessFreeFunction(FunctionDecl *FD) { if (isFreeFunction(FD)) { - if (FD->isVariadic()) { - Diag(FD->getLocation(), diag::err_free_function_variadic_args); + if (CheckFreeFunctionDiagnostics(SemaRef, FD)) return; - } SyclKernelDecompMarker DecompMarker(*this); SyclKernelFieldChecker FieldChecker(*this); SyclKernelUnionChecker UnionChecker(*this); diff --git a/clang/test/SemaSYCL/free_function_negative.cpp b/clang/test/SemaSYCL/free_function_negative.cpp index 4e2bfe001143..3c8e5a07851b 100644 --- a/clang/test/SemaSYCL/free_function_negative.cpp +++ b/clang/test/SemaSYCL/free_function_negative.cpp @@ -9,3 +9,33 @@ foo(int start, ...) { // expected-error {{free function kernel cannot be a varia [[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]] void foo1(int start, ...) { // expected-error {{free function kernel cannot be a variadic function}} } + +// expected-error@+2 {{a function with a default argument value cannot be used to define SYCL free function kernel}} +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]] void +singleTaskKernelDefaultValues(int Value = 1) { +} + +// expected-error@+2 {{a function with a default argument value cannot be used to define SYCL free function kernel}} +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] void +ndRangeKernelDefaultValues(int Value = 1) { +} + +// expected-error@+2 {{a function with a default argument value cannot be used to define SYCL free function kernel}} +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]] void +singleTaskKernelDefaultValues(int Ivalue = 1, unsigned int Uvalue = 3) { +} + +// expected-error@+2 {{a function with a default argument value cannot be used to define SYCL free function kernel}} +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] void +ndRangeKernelDefaultValues(int Ivalue = 1, unsigned int Uvalue = 3) { +} + +// expected-error@+2 {{SYCL free function kernel should have return type 'void'}} +[[__sycl_detail__::add_ir_attributes_function("sycl-single-task-kernel", 2)]] int +singleTaskKernelReturnType(int Value) { +} + +// expected-error@+2 {{SYCL free function kernel should have return type 'void'}} +[[__sycl_detail__::add_ir_attributes_function("sycl-nd-range-kernel", 2)]] int +ndRangeKernelReturnType(int Value) { +} diff --git a/sycl/test/extensions/free_function_kernels/free_function_kernels_diagnostics.cpp b/sycl/test/extensions/free_function_kernels/free_function_kernels_diagnostics.cpp index 88df7cc9776e..b2cd6b07003e 100644 --- a/sycl/test/extensions/free_function_kernels/free_function_kernels_diagnostics.cpp +++ b/sycl/test/extensions/free_function_kernels/free_function_kernels_diagnostics.cpp @@ -18,11 +18,3 @@ SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(syclexp::single_task_kernel) SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(syclexp::nd_range_kernel<3>) void ndRangeKernelVariadic( // expected-error {{free function kernel cannot be a variadic function}} ...) {} - -// TODO: Add expected error when it will be implemented. -SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(syclexp::single_task_kernel) -void singleTaskKernelDefaultValues(int Value = 1) {} - -// TODO: Add expected error when it will be implemented. -SYCL_EXT_ONEAPI_FUNCTION_PROPERTY(syclexp::nd_range_kernel<1>) -void ndRangeKernelDefaultValues(int Value = 1) {}