From ad6c477ce0d594ea22977c009fc7ef7bd16925ce Mon Sep 17 00:00:00 2001 From: "Kornev, Nikita" Date: Fri, 13 Feb 2026 19:28:46 +0100 Subject: [PATCH] [SYCL] Forward decl free func kernel template args --- clang/lib/Sema/SemaSYCL.cpp | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 8cba9ce845ddc..c318880ee2ab3 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -6929,6 +6929,38 @@ class FreeFunctionPrinter { /// \param ParmList The parameter list of the function. void printFreeFunctionShim(const FunctionDecl *FD, const unsigned ShimCounter, const std::string &ParmList) { + // If a free function kernel is a template, where a template parameter is a + // class template instantiation, then we need to forward declare this type + // before __sycl_shim. + if (FD->getPrimaryTemplate()) { + auto TAL = FD->getTemplateSpecializationArgs(); + for (unsigned i = 0; i < TAL->size(); ++i) { + auto arg = TAL->get(i); + if (arg.getKind() != clang::TemplateArgument::Type) + continue; + clang::QualType QT = arg.getAsType().getCanonicalType(); + auto RT = QT->getAs(); + if (!RT) + continue; + const clang::RecordDecl *RD = RT->getDecl(); + if (RD && RD->isStruct()) { + const clang::TagType *TT = QT->getAs(); + if (!TT) { + return; + }; + const clang::TagDecl *TD = TT->getDecl()->getFirstDecl(); + if (!TD) { + return; + } + if (auto *CTD = llvm::dyn_cast(TD)) + if (auto *CTpl = CTD->getSpecializedTemplate()) + CTpl->getTemplateParameters()->print(O, Context, false); + + O << TD->getKindName() << " " << TD->getName() << ";\n"; + } + } + } + // Generate a shim function that returns the address of the free function. O << "static constexpr auto __sycl_shim" << ShimCounter << "() {\n"; O << " return (void (*)(" << ParmList << "))";