diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index ee8220631af6b..822e283251d57 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -219,6 +219,7 @@ LANGOPT(GPURelocatableDeviceCode, 1, 0, "generate relocatable device code") LANGOPT(SYCLIsDevice , 1, 0, "Generate code for SYCL device") LANGOPT(SYCLUseBitcode , 1, 0, "Generate bitcode for SYCL") +LANGOPT(SYCLAllowFuncPtr , 1, 0, "Allow function pointers in SYCL device code") LANGOPT(SizedDeallocation , 1, 0, "sized deallocation") LANGOPT(AlignedAllocation , 1, 0, "aligned allocation") diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index 17b0dcb109d09..232ffd985f158 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -849,6 +849,9 @@ def fsycl_int_header : Separate<["-"], "fsycl-int-header">, HelpText<"Generate SYCL integration header into this file.">; def fsycl_int_header_EQ : Joined<["-"], "fsycl-int-header=">, Alias; +def fsycl_allow_func_ptr : Flag<["-"], "fsycl-allow-func-ptr">, + HelpText<"Allow function pointers in SYCL device.">; +def fno_sycl_allow_func_ptr : Flag<["-"], "fno-sycl-allow-func-ptr">; } // let Flags = [CC1Option] diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c95cd914ee281..fff11779c5bae 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3550,6 +3550,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_sycl_use_bitcode, true)) { CmdArgs.push_back("-fsycl-use-bitcode"); } + if (Args.hasFlag(options::OPT_fsycl_allow_func_ptr, + options::OPT_fno_sycl_allow_func_ptr, false)) { + CmdArgs.push_back("-fsycl-allow-func-ptr"); + } } if (IsOpenMPDevice) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 1bc5dd83012ff..741154e997823 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2893,6 +2893,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.SYCLIsDevice = Args.hasArg(options::OPT_fsycl_is_device); Opts.SYCLUseBitcode = Args.hasFlag(options::OPT_fsycl_use_bitcode, options::OPT_fno_sycl_use_bitcode, false); + Opts.SYCLAllowFuncPtr = Args.hasFlag(options::OPT_fsycl_allow_func_ptr, + options::OPT_fno_sycl_allow_func_ptr, false); // Set CUDA mode for OpenMP target NVPTX if specified in options Opts.OpenMPCUDAMode = Opts.OpenMPIsDevice && T.isNVPTX() && diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index c7301d5970b6e..471f2c36c4bb1 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -113,10 +113,9 @@ class MarkDeviceFunction : public RecursiveASTVisitor { SemaRef.AddSyclKernel(Def); } } - } else { + } else if (!SemaRef.getLangOpts().SYCLAllowFuncPtr) SemaRef.Diag(e->getExprLoc(), diag::err_sycl_restrict) << KernelCallFunctionPointer; - } return true; } diff --git a/clang/test/SemaSYCL/sycl-restrict.cpp b/clang/test/SemaSYCL/sycl-restrict.cpp index bea75fa2c5431..5daef045b7db9 100644 --- a/clang/test/SemaSYCL/sycl-restrict.cpp +++ b/clang/test/SemaSYCL/sycl-restrict.cpp @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -fcxx-exceptions -fsycl-is-device -Wno-return-type -verify -fsyntax-only -x c++ -emit-llvm-only -std=c++17 %s +// RUN: %clang_cc1 -fcxx-exceptions -fsycl-is-device -fno-sycl-allow-func-ptr -Wno-return-type -verify -fsyntax-only -x c++ -emit-llvm-only -std=c++17 %s +// RUN: %clang_cc1 -fcxx-exceptions -fsycl-is-device -DALLOW_FP=1 -fsycl-allow-func-ptr -Wno-return-type -verify -fsyntax-only -x c++ -emit-llvm-only -std=c++17 %s namespace std { @@ -104,7 +106,11 @@ void usage( myFuncDef functionPtr ) { eh_not_ok(); - // expected-error@+1 {{SYCL kernel cannot call through a function pointer}} +#if ALLOW_FP + // No error message for function pointer. +#else + // expected-error@+2 {{SYCL kernel cannot call through a function pointer}} +#endif if ((*functionPtr)(1,2)) // expected-note@+3{{used here}} // expected-error@+2 {{SYCL kernel cannot use a global variable}}