diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 3cde249e286fa..22e60aa9fe312 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1599,8 +1599,15 @@ def CUDAShared : InheritableAttr { } def : MutualExclusions<[CUDAConstant, CUDAShared, HIPManaged]>; +def SYCLKernel : InheritableAttr { + let Spellings = [Clang<"sycl_kernel">]; + let Subjects = SubjectList<[FunctionTmpl]>; + let LangOpts = [SYCLDevice]; + let Documentation = [SYCLKernelDocs]; +} + def DeviceKernel : DeclOrTypeAttr { - let Spellings = [Clang<"device_kernel">, Clang<"sycl_kernel">, + let Spellings = [Clang<"device_kernel">, Clang<"nvptx_kernel">, Clang<"amdgpu_kernel">, CustomKeyword<"__kernel">, CustomKeyword<"kernel">]; let Documentation = [DeviceKernelDocs]; @@ -1624,15 +1631,6 @@ def DeviceKernel : DeclOrTypeAttr { if(!A) return false; return isNVPTXSpelling(*A); } - static inline bool isSYCLSpelling(const AttributeCommonInfo& A) { - return A.getAttributeSpellingListIndex() == GNU_sycl_kernel || - A.getAttributeSpellingListIndex() == CXX11_clang_sycl_kernel || - A.getAttributeSpellingListIndex() == C23_clang_sycl_kernel; - } - static inline bool isSYCLSpelling(const AttributeCommonInfo* A) { - if(!A) return false; - return isSYCLSpelling(*A); - } static inline bool isOpenCLSpelling(const AttributeCommonInfo& A) { // Tablegen trips underscores from spellings to build the spelling // list, but here we have the same spelling with unscores and without, diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 20a52b49a8f10..e0bbda083b5cf 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -396,13 +396,10 @@ any option of a multiversioned function is undefined. }]; } -def DeviceKernelDocs : Documentation { +def SYCLKernelDocs : Documentation { let Category = DocCatFunction; - let Heading = "device_kernel, sycl_kernel, nvptx_kernel, amdgpu_kernel, " - "kernel, __kernel"; + let Heading = "sycl_kernel"; let Content = [{ -These attributes specify that the function represents a kernel for device offloading. -The specific semantics depend on the offloading language, target, and attribute spelling. The ``sycl_kernel`` attribute specifies that a function template will be used to outline device code and to generate an OpenCL kernel. Here is a code example of the SYCL program, which demonstrates the compiler's @@ -476,6 +473,21 @@ The SYCL kernel in the previous code sample meets these expectations. }]; } +def DeviceKernelDocs : Documentation { + let Category = DocCatFunction; + let Heading = "device_kernel, nvptx_kernel, amdgpu_kernel, " + "kernel, __kernel"; + let Content = [{ +These attributes specify that the function represents a kernel for device offloading. +The specific semantics depend on the offloading language, target, and attribute spelling. +Here is a code example using the attribute to mark a function as a kernel: + +.. code-block:: c++ + + [[clang::device_kernel]] int foo(int x) { return ++x; } + }]; +} + def SYCLExternalDocs : Documentation { let Category = DocCatFunction; let Heading = "sycl_external"; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0e83c20b27c22..8ac09c4d30f1a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -20797,7 +20797,7 @@ Sema::FunctionEmissionStatus Sema::getEmissionStatus(const FunctionDecl *FD, // SYCL functions can be template, so we check if they have appropriate // attribute prior to checking if it is a template. - if (LangOpts.SYCLIsDevice && FD->hasAttr()) + if (LangOpts.SYCLIsDevice && FD->hasAttr()) return FunctionEmissionStatus::Emitted; // Templates are emitted when they're instantiated. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 328ccf6694073..3107876565e8e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5204,16 +5204,7 @@ static void handleCallConvAttr(Sema &S, Decl *D, const ParsedAttr &AL) { static void handleDeviceKernelAttr(Sema &S, Decl *D, const ParsedAttr &AL) { const auto *FD = dyn_cast_or_null(D); bool IsFunctionTemplate = FD && FD->getDescribedFunctionTemplate(); - if (S.getLangOpts().SYCLIsDevice) { - if (!IsFunctionTemplate) { - S.Diag(AL.getLoc(), diag::warn_attribute_wrong_decl_type_str) - << AL << AL.isRegularKeywordAttribute() << "function templates"; - } else { - S.SYCL().handleKernelAttr(D, AL); - } - } else if (DeviceKernelAttr::isSYCLSpelling(AL)) { - S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; - } else if (S.getASTContext().getTargetInfo().getTriple().isNVPTX()) { + if (S.getASTContext().getTargetInfo().getTriple().isNVPTX()) { handleGlobalAttr(S, D, AL); } else { // OpenCL C++ will throw a more specific error. @@ -7100,6 +7091,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, case ParsedAttr::AT_EnumExtensibility: handleEnumExtensibilityAttr(S, D, AL); break; + case ParsedAttr::AT_SYCLKernel: + S.SYCL().handleKernelAttr(D, AL); + break; case ParsedAttr::AT_SYCLExternal: handleSimpleAttribute(S, D, AL); break; diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 2f97f6290f0e8..b981c35c8083f 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -199,7 +199,7 @@ void SemaSYCL::handleKernelAttr(Decl *D, const ParsedAttr &AL) { return; } - handleSimpleAttribute(*this, D, AL); + handleSimpleAttribute(*this, D, AL); } void SemaSYCL::handleKernelEntryPointAttr(Decl *D, const ParsedAttr &AL) { diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 3819f775811e5..85e3d207b2cf2 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -710,9 +710,9 @@ static void instantiateDependentAMDGPUMaxNumWorkGroupsAttr( // This doesn't take any template parameters, but we have a custom action that // needs to happen when the kernel itself is instantiated. We need to run the // ItaniumMangler to mark the names required to name this kernel. -static void instantiateDependentDeviceKernelAttr( +static void instantiateDependentSYCLKernelAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, - const DeviceKernelAttr &Attr, Decl *New) { + const SYCLKernelAttr &Attr, Decl *New) { New->addAttr(Attr.clone(S.getASTContext())); } @@ -966,8 +966,8 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, continue; } - if (auto *A = dyn_cast(TmplAttr)) { - instantiateDependentDeviceKernelAttr(*this, TemplateArgs, *A, New); + if (auto *A = dyn_cast(TmplAttr)) { + instantiateDependentSYCLKernelAttr(*this, TemplateArgs, *A, New); continue; } diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index bee613aa5f1c5..a9e7c34de94f4 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -3780,12 +3780,10 @@ static CallingConv getCCForDeclaratorChunk( } } } - if (!S.getLangOpts().isSYCL()) { - for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) { - if (AL.getKind() == ParsedAttr::AT_DeviceKernel) { - CC = CC_DeviceKernel; - break; - } + for (const ParsedAttr &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == ParsedAttr::AT_DeviceKernel) { + CC = CC_DeviceKernel; + break; } } return CC;